Skip to content

Commit

Permalink
[Filter] refactor rewritelinks to improve readability (#139)
Browse files Browse the repository at this point in the history
  • Loading branch information
cagix authored Aug 22, 2023
1 parent cfd927e commit 4ab2ea2
Showing 1 changed file with 42 additions and 37 deletions.
79 changes: 42 additions & 37 deletions filters/hugo_rewritelinks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ transformed into 'file/_index.md' (see 'hugo_makedeps.lua').
This filter will adapt the image sources (1) and the link targets (2) in a Markdown file so that
Hugo can build a web page from it.
(1) The Hugo Relearn Theme expects all resources on the same level as the '_index.md' for a page.
Thus all local images will be copied to the respective folders (via 'hugo_makedeps.lua' and some
Makefile magic). Here we just need to adjust all image sources and remove any path elements:
replace `![](img/b.png)` with `![](b.png)` for all local image files.
(2) Hugo's ref shortcode tries to resolve paths without a leading '/' first relative to the current
page, then to the rest of the site. As long as all pages have a _unique name_, we can also simply
use the name of the page. Index pages ('_index.md') must be referenced via their toplevel folder.
Expand Down Expand Up @@ -45,52 +43,59 @@ Caveats:
]]--


-- vars
INDEX_MD = "readme" -- name of the readme.md files (w/o extension)


-- helper
local function _is_relative (target)
return pandoc.path.is_relative(target)
local function _is_local_path (path)
return pandoc.path.is_relative(path) and -- is relative path
not path:match('https?://.*') -- is not http(s)
end

local function _is_local_markdown_file_link (inline)
return inline and
inline.t and
inline.t == "Link" and -- is pandoc.Link
inline.target:match('.*%.md') and -- is markdown
_is_local_path(inline.target) -- is relative & not http(s)
end

local function _is_markdown (target)
return target:match('.*%.md')

-- filter: replace `![](img/b.png)` with `![](b.png)`
local function _fix_img_src (img)
if _is_local_path(img.src) then
img.src = pandoc.path.filename(img.src)
return img
end
end

local function _is_url (target)
return target:match('https?://.*')
-- filter: replace `[Y](subdir/file-a.md)` with `[Y]({{< ref "file-a" >}})`
-- filter: replace `[Y](subdir/readme.md)` with `[Y]({{< ref "subdir" >}})`
local function _process_links (link)
local target = link.target
local content = pandoc.utils.stringify(link.content)

if _is_local_markdown_file_link(link) then
local dir = pandoc.path.split(pandoc.path.directory(target)) -- 'foo.md' => {'.'}; 'sub/foo.md' => {'sub'}; './sub/foo.md' => {'.', 'sub'};
local name, _ = pandoc.path.split_extension(pandoc.path.filename(target))

if name == INDEX_MD then
target = (#dir >= 1 and dir[#dir] ~= ".") and dir[#dir] or "/" -- readme.md: use parent folder or '/'
else
target = name -- ordinary file: use it's name w/o extension
end

return pandoc.RawInline('markdown', '[' .. content .. ']({{< ref "' .. target .. '" >}})')
end
end


-- main filter function
function Pandoc (doc)
-- name of the readme.md files (w/o extension): meta.indexMD
local INDEX_MD = doc.meta.indexMD or "readme"
INDEX_MD = doc.meta.indexMD or "readme"

-- process all images and links
return pandoc.Pandoc(doc.blocks:walk({
Image = function (image)
-- replace `![](img/b.png)` with `![](b.png)`
if _is_relative(image.src) and not _is_url(image.src) then
image.src = pandoc.path.filename(image.src)
return image
end
end,
Link = function (link)
-- replace `[Y](subdir/file-a.md)` with `[Y]({{< ref "file-a" >}})`
-- replace `[Y](subdir/readme.md)` with `[Y]({{< ref "subdir" >}})`
local target = link.target
local content = pandoc.utils.stringify(link.content)

if _is_markdown(target) and _is_relative(target) and not _is_url(target) then
local dir = pandoc.path.split(pandoc.path.directory(target)) -- 'foo.md' => {'.'}; 'sub/foo.md' => {'sub'}; './sub/foo.md' => {'.', 'sub'};
local name, _ = pandoc.path.split_extension(pandoc.path.filename(target))

if name == INDEX_MD then
target = (#dir >= 1 and dir[#dir] ~= ".") and dir[#dir] or "/" -- readme.md: use parent folder or '/'
else
target = name -- ordinary file: use it's name w/o extension
end

return pandoc.RawInline('markdown', '[' .. content .. ']({{< ref "' .. target .. '" >}})')
end
end
}), doc.meta)
return pandoc.Pandoc(doc.blocks:walk({ Image = _fix_img_src, Link = _process_links }), doc.meta)
end

0 comments on commit 4ab2ea2

Please sign in to comment.