From b07c3608ba128ae893164852a329a85182ff6190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Fri, 28 Mar 2025 16:19:45 +0100 Subject: [PATCH 01/11] feat: allow GitHub mentions co-authored-by: Carlos Scheidegger --- _extensions/github/github.lua | 21 +++++++++------------ example.qmd | 10 ++++++++++ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/_extensions/github/github.lua b/_extensions/github/github.lua index a9c1a4b..fcb632d 100644 --- a/_extensions/github/github.lua +++ b/_extensions/github/github.lua @@ -126,16 +126,16 @@ function commits(elem) return github_uri(text, uri) end -function mentions(elem) - local uri = nil - local text = nil +function mentions_old(elem) if elem.text:match("^@(%w+)$") then - local mention = elem.text:match("^@(%w+)$") - uri = "https://github.com/" .. mention - text = pandoc.utils.stringify(elem.text) + return github_uri(pandoc.utils.stringify(elem.text), "https://github.com/" .. elem.text:match("^@(%w+)$")) end - return github_uri(text, uri) + return elem +end + +function mentions(cite) + return pandoc.Link(cite.content, "https://github.com/" .. cite.content[1].text:sub(2)) end function github(elem) @@ -147,10 +147,6 @@ function github(elem) if is_empty(link) then link = commits(elem) end - - -- if is_empty(link) then - -- link = mentions(elem) - -- end if is_empty(link) then return elem @@ -161,5 +157,6 @@ end return { {Meta = get_repository}, - {Str = github} + {Str = github}, + {Cite = mentions} } diff --git a/example.qmd b/example.qmd index 6c78e1f..577ae6b 100644 --- a/example.qmd +++ b/example.qmd @@ -29,6 +29,16 @@ Some references require to define the default repository via `repository-name` Y repository-name: jlord/sheetsee.js ``` +## Mentioning users + ++-------------------+---------------+------------+ +| User/Organisation | Raw reference | Short link | ++===================+===============+============+ +| | ```txt | | +| User mention | @mcanouil | @mcanouil | +| | ``` | | ++-------------------+---------------+------------+ + ## Issues and pull requests +-------------------------------------------------------------------------------+------------------------------------------------+------------------------------------------------+ From 1c2d3450e51361a64a6ebaf1351d16bfb31822e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Fri, 28 Mar 2025 16:26:26 +0100 Subject: [PATCH 02/11] docs: add organisation --- example.qmd | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/example.qmd b/example.qmd index 577ae6b..07e617f 100644 --- a/example.qmd +++ b/example.qmd @@ -31,13 +31,17 @@ repository-name: jlord/sheetsee.js ## Mentioning users -+-------------------+---------------+------------+ -| User/Organisation | Raw reference | Short link | -+===================+===============+============+ -| | ```txt | | -| User mention | @mcanouil | @mcanouil | -| | ``` | | -+-------------------+---------------+------------+ ++----------------------+----------------+-------------+ +| User/Organisation | Raw reference | Short link | ++======================+================+=============+ +| | ```txt | | +| User mention | @mcanouil | @mcanouil | +| | ``` | | ++----------------------+----------------+-------------+ +| | ```txt | | +| Organisation mention | @quarto-dev | @quarto-dev | +| | ``` | | ++----------------------+----------------+-------------+ ## Issues and pull requests From 1fdcc64d867eab607d6c5f6e2bb3b2229cdac24a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Fri, 28 Mar 2025 17:09:21 +0100 Subject: [PATCH 03/11] feat: automatic repository detection via git remote --- _extensions/github/github.lua | 24 +++++++++- example.qmd | 89 +++++++++++++++++------------------ 2 files changed, 66 insertions(+), 47 deletions(-) diff --git a/_extensions/github/github.lua b/_extensions/github/github.lua index fcb632d..f8a5858 100644 --- a/_extensions/github/github.lua +++ b/_extensions/github/github.lua @@ -22,6 +22,8 @@ # SOFTWARE. ]] +local io = require 'io' + local function is_empty(s) return s == nil or s == '' end @@ -36,9 +38,27 @@ local github_repository = nil function get_repository(meta) local meta_github_repository = nil - if not is_empty(meta['repository-name']) then + if is_empty(meta['repository-name']) then + local is_windows = package.config:sub(1, 1) == "\\" + if is_windows then + remote_repository_command = "(git remote get-url origin) -replace '.*[:/](.+?)(\\.git)?$', '$1'" + else + remote_repository_command = "git remote get-url origin 2>/dev/null | sed -E 's|.*[:/]([^/]+/[^/.]+)(\\.git)?$|\\1|'" + end + + local handle = io.popen(remote_repository_command) + + if handle then + local git_repo = handle:read("*a"):gsub("%s+$", "") + handle:close() + if not is_empty(git_repo) then + meta_github_repository = git_repo + end + end + else meta_github_repository = pandoc.utils.stringify(meta['repository-name']) end + github_repository = meta_github_repository return meta end @@ -143,7 +163,7 @@ function github(elem) if is_empty(link) then link = issues(elem) end - + if is_empty(link) then link = commits(elem) end diff --git a/example.qmd b/example.qmd index 07e617f..aa121be 100644 --- a/example.qmd +++ b/example.qmd @@ -5,7 +5,6 @@ description: | page-layout: full filters: - github -repository-name: jlord/sheetsee.js format: html: output-file: index @@ -23,10 +22,10 @@ filters: - github ``` -Some references require to define the default repository via `repository-name` YAML key. +Some references require to define the default repository via `repository-name` YAML key or have an `origin` remote set in your Git configuration. ```yml -repository-name: jlord/sheetsee.js +repository-name: mcanouil/quarto-github ``` ## Mentioning users @@ -45,48 +44,48 @@ repository-name: jlord/sheetsee.js ## Issues and pull requests -+-------------------------------------------------------------------------------+------------------------------------------------+------------------------------------------------+ -| Reference type | Raw reference | Short link | -+===============================================================================+================================================+================================================+ -| | ```txt | | -| Issue, discussion, or pull request URL | https://github.com/jlord/sheetsee.js/issues/26 | https://github.com/jlord/sheetsee.js/issues/26 | -| ***`repository-name` is optional!*** | ``` | | -+-------------------------------------------------------------------------------+------------------------------------------------+------------------------------------------------+ -| | ```txt | | -| `#` and issue, discussion, or pull request number \ | #26 | #26 | -| ***`repository-name` is required!*** | ``` | | -+-------------------------------------------------------------------------------+------------------------------------------------+------------------------------------------------+ -| | ```txt | | -| `GH-` and issue, discussion, or pull request number \ | GH-26 | GH-26 | -| ***`repository-name` is required!*** | ``` | | -+-------------------------------------------------------------------------------+------------------------------------------------+------------------------------------------------+ -| | ```txt | | -| `Username/Repository#` and issue, discussion, or pull request number | jlord/sheetsee.js#26 | jlord/sheetsee.js#26 | -| | ``` | | -+-------------------------------------------------------------------------------+------------------------------------------------+------------------------------------------------+ -| | ```txt | | -| `Organization_name/Repository#` and issue, discussion, or pull request number | github-linguist/linguist#4039 | github-linguist/linguist#4039 | -| | ``` | | -+-------------------------------------------------------------------------------+------------------------------------------------+------------------------------------------------+ ++-------------------------------------------------------------------------------+----------------------------------------------------+----------------------------------------------------+ +| Reference type | Raw reference | Short link | ++===============================================================================+====================================================+====================================================+ +| | ```txt | | +| Issue, discussion, or pull request URL | https://github.com/mcanouil/quarto-github/issues/3 | https://github.com/mcanouil/quarto-github/issues/3 | +| ***`repository-name` is optional!*** | ``` | | ++-------------------------------------------------------------------------------+----------------------------------------------------+----------------------------------------------------+ +| | ```txt | | +| `#` and issue, discussion, or pull request number \ | #3 | #3 | +| ***`repository-name` is required!*** | ``` | | ++-------------------------------------------------------------------------------+----------------------------------------------------+----------------------------------------------------+ +| | ```txt | | +| `GH-` and issue, discussion, or pull request number \ | GH-3 | GH-3 | +| ***`repository-name` is required!*** | ``` | | ++-------------------------------------------------------------------------------+----------------------------------------------------+----------------------------------------------------+ +| | ```txt | | +| `Username/Repository#` and issue, discussion, or pull request number | mcanouil/quarto-github#3 | mcanouil/quarto-github#3 | +| | ``` | | ++-------------------------------------------------------------------------------+----------------------------------------------------+----------------------------------------------------+ +| | ```txt | | +| `Organization_name/Repository#` and issue, discussion, or pull request number | github-linguist/linguist#4039 | github-linguist/linguist#4039 | +| | ``` | | ++-------------------------------------------------------------------------------+----------------------------------------------------+----------------------------------------------------+ ## Commit SHAs -+--------------------------------------+--------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+ -| Reference type | Raw reference | Short link | -+======================================+======================================================================================+======================================================================================+ -| | ```txt | | -| Commit URL | https://github.com/jlord/sheetsee.js/commit/a5c3785ed8d6a35868bc169f07e40e889087fd2e | https://github.com/jlord/sheetsee.js/commit/a5c3785ed8d6a35868bc169f07e40e889087fd2e | -| ***`repository-name` is optional!*** | ``` | | -+--------------------------------------+--------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+ -| | ```txt | | -| SHA \ | a5c3785ed8d6a35868bc169f07e40e889087fd2e | a5c3785ed8d6a35868bc169f07e40e889087fd2e | -| ***`repository-name` is required!*** | ``` | | -+--------------------------------------+--------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+ -| | ```txt | | -| `User@SHA` \ | jlord@a5c3785ed8d6a35868bc169f07e40e889087fd2e | ***Not supported!*** | -| ***Not supported!*** | ``` | | -+--------------------------------------+--------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+ -| | ```txt | | -| `Username/Repository@SHA` | jlord/sheetsee.js@a5c3785ed8d6a35868bc169f07e40e889087fd2e | jlord/sheetsee.js@a5c3785ed8d6a35868bc169f07e40e889087fd2e | -| | ``` | | -+--------------------------------------+--------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+ ++--------------------------------------+-------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +| Reference type | Raw reference | Short link | ++======================================+===========================================================================================+===========================================================================================+ +| | ```txt | | +| Commit URL | https://github.com/mcanouil/quarto-github/commit/0b2eb553779f0a7cd56d59c2ec102b8bb643e9c3 | https://github.com/mcanouil/quarto-github/commit/0b2eb553779f0a7cd56d59c2ec102b8bb643e9c3 | +| | ``` | | ++--------------------------------------+-------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +| | ```txt | | +| SHA \ | 0b2eb553779f0a7cd56d59c2ec102b8bb643e9c3 | 0b2eb553779f0a7cd56d59c2ec102b8bb643e9c3 | +| ***`repository-name` is required!*** | ``` | | ++--------------------------------------+-------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +| | ```txt | | +| `User@SHA` \ | mcanouil@0b2eb553779f0a7cd56d59c2ec102b8bb643e9c3 | ***Not supported!*** | +| ***Not supported!*** | ``` | | ++--------------------------------------+-------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ +| | ```txt | | +| `Username/Repository@SHA` | mcanouil/quarto-github@0b2eb553779f0a7cd56d59c2ec102b8bb643e9c3 | mcanouil/quarto-github@0b2eb553779f0a7cd56d59c2ec102b8bb643e9c3 | +| | ``` | | ++--------------------------------------+-------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------+ From 24aa59ed9eb13e369fde5ac1c30ade222a684d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Sat, 29 Mar 2025 19:27:42 +0100 Subject: [PATCH 04/11] feat: prevent references from being processed --- _extensions/github/github.lua | 37 +++++++++++++++++++++-------------- example.qmd | 6 ++++-- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/_extensions/github/github.lua b/_extensions/github/github.lua index f8a5858..4d3e407 100644 --- a/_extensions/github/github.lua +++ b/_extensions/github/github.lua @@ -22,7 +22,8 @@ # SOFTWARE. ]] -local io = require 'io' +local github_repository = nil +local references_ids_set = {} local function is_empty(s) return s == nil or s == '' @@ -34,8 +35,6 @@ local function github_uri(text, uri) end end -local github_repository = nil - function get_repository(meta) local meta_github_repository = nil if is_empty(meta['repository-name']) then @@ -63,6 +62,25 @@ function get_repository(meta) return meta end +function get_references(doc) + local references = pandoc.utils.references(doc) + + for _, reference in ipairs(references) do + if reference.id then + references_ids_set[reference.id] = true + end + end + return doc +end + +function mentions(cite) + if references_ids_set[cite.citations[1].id] then + return cite + else + return github_uri(cite.content, "https://github.com/" .. cite.content[1].text:sub(2)) + end +end + function issues(elem) local user_repo = nil local issue_number = nil @@ -146,18 +164,6 @@ function commits(elem) return github_uri(text, uri) end -function mentions_old(elem) - if elem.text:match("^@(%w+)$") then - return github_uri(pandoc.utils.stringify(elem.text), "https://github.com/" .. elem.text:match("^@(%w+)$")) - end - - return elem -end - -function mentions(cite) - return pandoc.Link(cite.content, "https://github.com/" .. cite.content[1].text:sub(2)) -end - function github(elem) local link = nil if is_empty(link) then @@ -176,6 +182,7 @@ function github(elem) end return { + {Pandoc = get_references}, {Meta = get_repository}, {Str = github}, {Cite = mentions} diff --git a/example.qmd b/example.qmd index aa121be..b2e48f6 100644 --- a/example.qmd +++ b/example.qmd @@ -4,7 +4,8 @@ description: | References to GitHub issues, pull requests, and commits are automatically shortened and converted into links. page-layout: full filters: - - github + - path: github + at: post-quarto format: html: output-file: index @@ -19,7 +20,8 @@ This Quarto extension automatically shortens and converts GitHub references into ```yml filters: - - github + - path: github + at: post-quarto ``` Some references require to define the default repository via `repository-name` YAML key or have an `origin` remote set in your Git configuration. From 40ca899f3ef6ea8727bd09b97baf33b5072a74c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Wed, 2 Apr 2025 23:42:44 +0200 Subject: [PATCH 05/11] ci(dependabot): set proper label --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a780c73 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + labels: + - "Type: Dependencies :arrow_up:" From 1d8f59bf32154b06763020ed30693a5fafbc30e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 14 Jul 2025 12:26:35 +0200 Subject: [PATCH 06/11] refactor: use "extensions" scope configuration --- README.md | 27 +++++++++++++++++++++++---- _extensions/github/github.lua | 28 +++++++++++++++++++++++----- example.qmd | 14 +++++++++++++- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 91b4bfb..d66d09d 100644 --- a/README.md +++ b/README.md @@ -18,21 +18,40 @@ This Quarto extension automatically shortens and converts GitHub references into To activate the filter, add the following to your YAML front matter: -```yaml +```yml filters: - - github + - path: github + at: post-quarto ``` -Some references require a default repository to be set via the `repository-name` YAML key. +Some references require a default repository to be set. Use the extension configuration structure: ```yml -repository-name: jlord/sheetsee.js +extensions: + github: + repository-name: jlord/sheetsee.js ``` +> [!WARNING] +> +> The old top-level `repository-name` syntax is deprecated but still supported: +> +> ```yml +> repository-name: jlord/sheetsee.js # deprecated +> ``` + ## References Source: [Autolinked references and URLs - GitHub Docs](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/autolinked-references-and-urls). +### Mentioning users + +| User/Organisation | Raw reference | Short link | +|----------------------|----------------|---------------| +| User mention | `@mcanouil` | `@mcanouil` | +|----------------------|----------------|---------------| +| Organisation mention | `@quarto-dev` | `@quarto-dev` | + ### Issues and pull requests | Reference type | Raw reference | Short link | diff --git a/_extensions/github/github.lua b/_extensions/github/github.lua index 4d3e407..6dc5d10 100644 --- a/_extensions/github/github.lua +++ b/_extensions/github/github.lua @@ -35,9 +35,29 @@ local function github_uri(text, uri) end end +local function get_metadata_value(meta, key) + -- Check for the new nested structure first: extensions.github.key + if meta['extensions'] and meta['extensions']['github'] and meta['extensions']['github'][key] then + return pandoc.utils.stringify(meta['extensions']['github'][key]) + end + + -- Check for deprecated top-level key and warn + if meta[key] then + quarto.log.warning("Using '" .. key .. "' directly in metadata is deprecated. " .. + "Please use the following structure instead:\n" .. + "extensions:\n" .. + " github:\n" .. + " " .. key .. ": value") + return pandoc.utils.stringify(meta[key]) + end + + return nil +end + function get_repository(meta) - local meta_github_repository = nil - if is_empty(meta['repository-name']) then + local meta_github_repository = get_metadata_value(meta, 'repository-name') + + if is_empty(meta_github_repository) then local is_windows = package.config:sub(1, 1) == "\\" if is_windows then remote_repository_command = "(git remote get-url origin) -replace '.*[:/](.+?)(\\.git)?$', '$1'" @@ -54,8 +74,6 @@ function get_repository(meta) meta_github_repository = git_repo end end - else - meta_github_repository = pandoc.utils.stringify(meta['repository-name']) end github_repository = meta_github_repository @@ -155,7 +173,7 @@ function commits(elem) local uri = nil local text = nil if not is_empty(short_link) and not is_empty(commit_sha) and not is_empty(user_repo) and not is_empty(type) then - if type == "commit" and commit_sha:len() == 40 then + if type == "commit" and commit_sha and commit_sha:len() == 40 then uri = "https://github.com/" .. user_repo .. '/' .. type .. '/' .. commit_sha text = pandoc.utils.stringify(short_link) end diff --git a/example.qmd b/example.qmd index b2e48f6..f8eac56 100644 --- a/example.qmd +++ b/example.qmd @@ -24,11 +24,23 @@ filters: at: post-quarto ``` -Some references require to define the default repository via `repository-name` YAML key or have an `origin` remote set in your Git configuration. +Some references require to define the default repository via the extension configuration or have an `origin` remote set in your Git configuration. + +```yml +extensions: + github: + repository-name: mcanouil/quarto-github +``` + +:::: {.callout-warning} +## Deprecated + +The old top-level `repository-name` syntax is deprecated but still supported: ```yml repository-name: mcanouil/quarto-github ``` +::: ## Mentioning users From 1b4ae89d315eef9827d45cbcebb3f1e22323e5ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 14 Jul 2025 12:26:55 +0200 Subject: [PATCH 07/11] style: trim trailing spaces --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d66d09d..ed9b545 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ extensions: > [!WARNING] > > The old top-level `repository-name` syntax is deprecated but still supported: -> +> > ```yml > repository-name: jlord/sheetsee.js # deprecated > ``` From b94f9f67ee750d2338c289e2917aef4fa2cdf2ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 14 Jul 2025 12:29:11 +0200 Subject: [PATCH 08/11] style: reformat --- _extensions/github/github.lua | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/_extensions/github/github.lua b/_extensions/github/github.lua index 6dc5d10..4afc280 100644 --- a/_extensions/github/github.lua +++ b/_extensions/github/github.lua @@ -40,33 +40,36 @@ local function get_metadata_value(meta, key) if meta['extensions'] and meta['extensions']['github'] and meta['extensions']['github'][key] then return pandoc.utils.stringify(meta['extensions']['github'][key]) end - + -- Check for deprecated top-level key and warn if meta[key] then - quarto.log.warning("Using '" .. key .. "' directly in metadata is deprecated. " .. - "Please use the following structure instead:\n" .. - "extensions:\n" .. - " github:\n" .. - " " .. key .. ": value") + quarto.log.warning( + "Using '" .. key .. "' directly in metadata is deprecated. " .. + "Please use the following structure instead:\n" .. + "extensions:\n" .. + " github:\n" .. + " " .. key .. ": value" + ) return pandoc.utils.stringify(meta[key]) end - + return nil end function get_repository(meta) local meta_github_repository = get_metadata_value(meta, 'repository-name') - + if is_empty(meta_github_repository) then local is_windows = package.config:sub(1, 1) == "\\" if is_windows then remote_repository_command = "(git remote get-url origin) -replace '.*[:/](.+?)(\\.git)?$', '$1'" else - remote_repository_command = "git remote get-url origin 2>/dev/null | sed -E 's|.*[:/]([^/]+/[^/.]+)(\\.git)?$|\\1|'" + remote_repository_command = + "git remote get-url origin 2>/dev/null | sed -E 's|.*[:/]([^/]+/[^/.]+)(\\.git)?$|\\1|'" end - + local handle = io.popen(remote_repository_command) - + if handle then local git_repo = handle:read("*a"):gsub("%s+$", "") handle:close() @@ -82,7 +85,7 @@ end function get_references(doc) local references = pandoc.utils.references(doc) - + for _, reference in ipairs(references) do if reference.id then references_ids_set[reference.id] = true @@ -200,8 +203,8 @@ function github(elem) end return { - {Pandoc = get_references}, - {Meta = get_repository}, - {Str = github}, - {Cite = mentions} + { Pandoc = get_references }, + { Meta = get_repository }, + { Str = github }, + { Cite = mentions } } From 7898762cd16272b2a422dd436966d2f1ab1a906e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 14 Jul 2025 12:33:58 +0200 Subject: [PATCH 09/11] docs: add documentation and types --- _extensions/github/github.lua | 69 ++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/_extensions/github/github.lua b/_extensions/github/github.lua index 4afc280..0cd777b 100644 --- a/_extensions/github/github.lua +++ b/_extensions/github/github.lua @@ -22,19 +22,34 @@ # SOFTWARE. ]] +--- @type string|nil The GitHub repository name (e.g., "owner/repo") local github_repository = nil + +--- @type table Set of reference IDs from the document local references_ids_set = {} +--- Check if a string is empty or nil +--- @param s string|nil The string to check +--- @return boolean true if the string is nil or empty local function is_empty(s) return s == nil or s == '' end +--- Create a GitHub URI link element +--- @param text string|nil The link text +--- @param uri string|nil The URI to link to +--- @return pandoc.Link|nil A Pandoc Link element or nil if text or uri is empty local function github_uri(text, uri) if not is_empty(uri) and not is_empty(text) then - return pandoc.Link(text, uri) + return pandoc.Link({pandoc.Str(text --[[@as string]])}, uri --[[@as string]]) end + return nil end +--- Extract metadata value from document meta, supporting both new nested structure and deprecated top-level keys +--- @param meta table The document metadata table +--- @param key string The metadata key to retrieve +--- @return string|nil The metadata value as a string, or nil if not found local function get_metadata_value(meta, key) -- Check for the new nested structure first: extensions.github.key if meta['extensions'] and meta['extensions']['github'] and meta['extensions']['github'][key] then @@ -56,6 +71,11 @@ local function get_metadata_value(meta, key) return nil end +--- Get repository name from metadata or git remote +--- This function extracts the GitHub repository name either from document metadata +--- or by querying the git remote origin URL +--- @param meta table The document metadata table +--- @return table The metadata table (unchanged) function get_repository(meta) local meta_github_repository = get_metadata_value(meta, 'repository-name') @@ -83,6 +103,11 @@ function get_repository(meta) return meta end +--- Extract and store reference IDs from the document +--- This function collects all reference IDs from the document to distinguish +--- between actual citations and GitHub mentions +--- @param doc pandoc.Pandoc The Pandoc document +--- @return pandoc.Pandoc The document (unchanged) function get_references(doc) local references = pandoc.utils.references(doc) @@ -94,14 +119,29 @@ function get_references(doc) return doc end +--- Process GitHub mentions in citations +--- Distinguishes between actual bibliography citations and GitHub @mentions +--- @param cite pandoc.Cite The citation element +--- @return pandoc.Cite|pandoc.Link The original citation or a GitHub mention link function mentions(cite) if references_ids_set[cite.citations[1].id] then return cite else - return github_uri(cite.content, "https://github.com/" .. cite.content[1].text:sub(2)) + local mention_text = pandoc.utils.stringify(cite.content) + local github_link = github_uri(mention_text, "https://github.com/" .. mention_text:sub(2)) + return github_link or cite end end +--- Process GitHub issues, pull requests, and discussions +--- Converts various GitHub reference formats into clickable links +--- Supported formats: +--- - #123 (issue in current repo) +--- - owner/repo#123 (issue in specific repo) +--- - GH-123 (issue in current repo) +--- - https://github.com/owner/repo/issues/123 (full URL) +--- @param elem pandoc.Str The string element to process +--- @return pandoc.Link|nil A GitHub link or nil if no valid pattern found function issues(elem) local user_repo = nil local issue_number = nil @@ -143,6 +183,15 @@ function issues(elem) return github_uri(text, uri) end +--- Process GitHub commit references +--- Converts various commit reference formats into clickable links +--- Supported formats: +--- - 40-character SHA (commit in current repo) +--- - owner/repo@sha (commit in specific repo) +--- - username@40-character-sha (commit by user) +--- - https://github.com/owner/repo/commit/sha (full URL) +--- @param elem pandoc.Str The string element to process +--- @return pandoc.Link|nil A GitHub commit link or nil if no valid pattern found function commits(elem) local user_repo = nil local commit_sha = nil @@ -185,23 +234,33 @@ function commits(elem) return github_uri(text, uri) end +--- Main GitHub processing function +--- Attempts to convert string elements into GitHub links by trying different patterns +--- @param elem pandoc.Str The string element to process +--- @return pandoc.Str|pandoc.Link The original element or a GitHub link function github(elem) local link = nil - if is_empty(link) then + if link == nil then link = issues(elem) end - if is_empty(link) then + if link == nil then link = commits(elem) end - if is_empty(link) then + if link == nil then return elem else return link end end +--- Pandoc filter configuration +--- Defines the order of filter execution: +--- 1. Extract references from the document +--- 2. Get repository information from metadata +--- 3. Process string elements for GitHub patterns +--- 4. Process citations for GitHub mentions return { { Pandoc = get_references }, { Meta = get_repository }, From e9b2022c5066622eb1ba545a6e8b24f11ecb2a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Mon, 14 Jul 2025 13:02:53 +0200 Subject: [PATCH 10/11] fix: avoid multiple displaying of deprecation warning --- _extensions/github/github.lua | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/_extensions/github/github.lua b/_extensions/github/github.lua index 0cd777b..5636f71 100644 --- a/_extensions/github/github.lua +++ b/_extensions/github/github.lua @@ -22,6 +22,10 @@ # SOFTWARE. ]] +--- Flag to track if deprecation warning has been shown +--- @type boolean +local deprecation_warning_shown = false + --- @type string|nil The GitHub repository name (e.g., "owner/repo") local github_repository = nil @@ -58,13 +62,16 @@ local function get_metadata_value(meta, key) -- Check for deprecated top-level key and warn if meta[key] then - quarto.log.warning( - "Using '" .. key .. "' directly in metadata is deprecated. " .. - "Please use the following structure instead:\n" .. - "extensions:\n" .. - " github:\n" .. - " " .. key .. ": value" - ) + if not deprecation_warning_shown then + quarto.log.warning( + "Using '" .. key .. "' directly in metadata is deprecated. " .. + "Please use the following structure instead:\n" .. + "extensions:\n" .. + " github:\n" .. + " " .. key .. ": value" + ) + deprecation_warning_shown = true + end return pandoc.utils.stringify(meta[key]) end From 2ea2fe483e3fe3bdddc5e776a9a2382c3ebbacc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Canouil?= <8896044+mcanouil@users.noreply.github.com> Date: Tue, 15 Jul 2025 14:56:38 +0200 Subject: [PATCH 11/11] docs: add note about filter order --- README.md | 3 +++ example.qmd | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/README.md b/README.md index ed9b545..4b1d0ea 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,9 @@ filters: at: post-quarto ``` +> [!IMPORTANT] +> The extension must be run after Quarto's processing (*i.e.*, `at: post-quarto`) to ensure that references (*e.g.*, `@fig-my-beautiful-figure`) are processed first by Quarto, then by the GitHub filter to avoid conflicts. + Some references require a default repository to be set. Use the extension configuration structure: ```yml diff --git a/example.qmd b/example.qmd index f8eac56..9fc3036 100644 --- a/example.qmd +++ b/example.qmd @@ -24,6 +24,10 @@ filters: at: post-quarto ``` +:::: {.callout-important} +The extension must be run after Quarto's processing (*i.e.*, `at: post-quarto`) to ensure that references (*e.g.*, `@fig-my-beautiful-figure`) are processed first by Quarto, then by the GitHub filter to avoid conflicts. +::: + Some references require to define the default repository via the extension configuration or have an `origin` remote set in your Git configuration. ```yml