Skip to content

Commit

Permalink
feat: Customizable strike, underline, insertion, deletion and mark
Browse files Browse the repository at this point in the history
First, make all these inline elements from Djot or Markdown all
equivalent to a corresponding span with certain classes, so both
cases are implemented identically. We thus have a consistent
mapping in all cases.
Then, use styles, if available, to render them. So for instance,
Markdown ~~xxx~~ is strictly equivalent to [xxx]{.strike}, and
to [xxx]{custom-style=md-strikethrough} in resilient context if
that style exists, for complete customization.
  • Loading branch information
Omikhleia authored and Didier Willis committed Feb 13, 2024
1 parent f4d91d3 commit 798d8e9
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 48 deletions.
18 changes: 6 additions & 12 deletions inputters/djot.lua
Original file line number Diff line number Diff line change
Expand Up @@ -552,23 +552,17 @@ function Renderer:mark (node)
end

function Renderer:insert (node)
local options = node.attr or {}
local content = self:render_children(node)
local out = { "", content, "" }
if node.attr then
-- Add a div when containing attributes
return createCommand("markdown:internal:span", node.attr, out, node_pos(node))
end
return out
djotast.insert_attribute(options, "class", "insertion")
return createCommand("markdown:internal:span", options, content, node_pos(node))
end

function Renderer:delete (node)
local options = node.attr or {}
local content = self:render_children(node)
local out = { "{", content, "}" }
if node.attr then
-- Add a div when containing attributes
return createCommand("markdown:internal:span", node.attr, out, node_pos(node))
end
return out
djotast.insert_attribute(options, "class", "deletion")
return createCommand("markdown:internal:span", options, content, node_pos(node))
end

local function extractAttrValue (attr, key)
Expand Down
5 changes: 4 additions & 1 deletion inputters/markdown.lua
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ local function SileAstWriter (writerOps, renderOps)
writer.paragraph = simpleCommandWrapper("markdown:internal:paragraph")
writer.code = simpleCommandWrapper("code")
writer.emphasis = simpleCommandWrapper("em")
writer.strikeout = simpleCommandWrapper("strikethrough")
writer.subscript = simpleCommandWrapper("textsubscript")
writer.superscript = simpleCommandWrapper("textsuperscript")
writer.blockquote = simpleCommandWrapper("markdown:internal:blockquote")
Expand Down Expand Up @@ -156,6 +155,10 @@ local function SileAstWriter (writerOps, renderOps)
return createCommand("markdown:internal:span" , attr, content)
end

writer.strikeout = function (content)
return createCommand("markdown:internal:span" , { class = "strike" }, content)
end

writer.div = function (content, attr)
return createCommand("markdown:internal:div" , attr, content)
end
Expand Down
15 changes: 8 additions & 7 deletions inputters/pandocast.lua
Original file line number Diff line number Diff line change
Expand Up @@ -427,22 +427,23 @@ function Renderer:Emph (inlines)
local content = self:render(inlines)
return createCommand("em", {}, content)
end
-- Underline [Inline]
function Renderer:Underline (inlines)
local content = self:render(inlines)
return createCommand("underline", {}, content)
end

-- Strong [Inline]
function Renderer:Strong (inlines)
local content = self:render(inlines)
return createCommand("strong", {}, content)
end

-- Underline [Inline]
function Renderer:Underline (inlines)
local content = self:render(inlines)
return createCommand("markdown:internal:span", { class = "underline" }, content)
end

-- Strikeout [Inline]
function Renderer:Strikeout (inlines)
local content = self:render(inlines)
return createCommand("strikethrough", {}, content)
return createCommand("markdown:internal:span" , { class = "strike" }, content)
end

-- Superscript [Inline]
Expand All @@ -460,7 +461,7 @@ end
-- SmallCaps [Inline]
function Renderer:SmallCaps (inlines)
local content = self:render(inlines)
return createCommand("font", { features = "+smcp" }, content)
return createCommand("markdown:internal:span", { class = "smallcaps" }, content)
end

-- Quoted QuoteType [Inline]
Expand Down
12 changes: 6 additions & 6 deletions packages/markdown/cmbase.lua
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ end
---@param pack string The package name.
function package:loadOptPackage (pack)
local ok, _ = pcall(function () return self:loadPackage(pack) end)
SU.debug("markdown", "Optional package "..pack.. (ok and " loaded" or " not loaded"))
SU.debug("markdown.commands", "Optional package "..pack.. (ok and " loaded" or " not loaded"))
end

--- Feature detection, so we can see e.g. with self.hasPackageSupport.xxx if
Expand All @@ -74,19 +74,19 @@ function package:_init (_)

-- Check if document class is a resilient class or derived from one
self.isResilient = isResilientClass(self.class)
SU.debug("markdown", "Feature detection:",
SU.debug("markdown.commands", "Feature detection:",
self.isResilient and "used in a resilient class" or "used in a non-resilient class")

self.hasPackageSupport = self:_createSupportProxy(function (_, name)
local pack = self.class.packages[name]
SU.debug("markdown", "Feature detection: package", name,
SU.debug("markdown.commands", "Feature detection: package", name,
pack and "supported" or "not supported")
return pack
end)

self.styles = self.hasPackageSupport["resilient.styles"]
if self.styles then
SU.debug("markdown", "Feature detection: hooking our custom styles")
SU.debug("markdown.commands", "Feature detection: registering custom styles")
self:registerStyles()
end

Expand All @@ -95,7 +95,7 @@ function package:_init (_)
-- SILE was refactor to have loadPackage() etc. methods, a lot of boilerplate
-- if at the end we still need to tap into low-level internals.
local cmd = SILE.Commands[name]
SU.debug("markdown", "Feature detection: command", name,
SU.debug("markdown.commands", "Feature detection: command", name,
cmd and "supported" or "not supported")
return cmd
end)
Expand All @@ -109,7 +109,7 @@ function package:_init (_)
-- non-existing style, so is not very handy here.
-- But it's a chicken and egg problem, between resilient and us.
and SILE.scratch.styles.specs[name] -- HACK
SU.debug("markdown", "Feature detection: style", name,
SU.debug("markdown.commands", "Feature detection: style", name,
style and "supported" or "not supported")
return style
end)
Expand Down
78 changes: 56 additions & 22 deletions packages/markdown/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -395,16 +395,45 @@ Please consider using a resilient-compatible class!]])
cascade:call("font", { features = "+smcp" })
end
if hasClass(options, "mark") then
cascade:call("markdown:fallback:mark") -- FIXME Better that before... but be more generic and style-aware
cascade:call("markdown:custom-style:hook", {
name = "md-mark",
alt = "markdown:fallback:mark",
scope = "inline"
})
end
if hasClass(options, "strike") then
cascade:call("strikethrough")
cascade:call("markdown:custom-style:hook", {
name = "md-strikethrough",
alt = "strikethrough",
scope = "inline"
})
end
if hasClass(options, "underline") then
cascade:call("underline")
cascade:call("markdown:custom-style:hook", {
name = "md-underline",
alt = "underline",
scope = "inline"
})
end
if hasClass(options, "insertion") then
cascade:call("markdown:custom-style:hook", {
name = "md-insertion",
alt = "underline",
scope = "inline"
})
end
if hasClass(options, "deletion") then
cascade:call("markdown:custom-style:hook", {
name = "md-deletion",
alt = "strikethrough",
scope = "inline"
})
end
if options["custom-style"] then
cascade:call("markdown:custom-style:hook", { name = options["custom-style"], scope = "inline" })
cascade:call("markdown:custom-style:hook", {
name = options["custom-style"],
scope = "inline"
})
end
if hasClass(options, "nobreak") then
cascade:call("hbox")
Expand Down Expand Up @@ -849,7 +878,7 @@ Please consider using a resilient-compatible class!]])
end
)
else
SU.debug("markdown", "Feature detection: No liner, using a simpler fallback for mark")
SU.debug("markdown.commands", "Feature detection: no liner, using a simpler fallback for mark")
-- Liners are introduced in SILE 0.15.
-- Resilient (with the silex compatibility layer) has them too for SILE 0.14.
-- For now, also support older versions of SILE when used in a non-resilient context.
Expand Down Expand Up @@ -877,34 +906,39 @@ Please consider using a resilient-compatible class!]])
-- C. Customizable hooks

self:registerCommand("markdown:custom-style:hook", function (options, content)
-- Default implementation for the custom-style hook:
-- If we are in the context of a resilient-compatible class and there's
-- an existing style going by that name, use it.
-- Otherwise, tf there is a corresponding SILE command, we invoke it.
-- otherwise, we just ignore the style and process the content.
-- It allows us, e.g. to already
-- - Use resilient styles in proper context
-- Default/standard implementation for the custom-style hook:
-- 1. If we are in the context of a resilient-compatible class and there's
-- an existing style going by that name, we apply it.
-- 2. Otherwise, if there is a corresponding SILE command, going by the
-- optional "alt" command name or if unspecified, the style name itself,
-- we invoke it.
-- 3. Otherwise, we just silently ignore the style and process the content.
--
-- It allows us to;
-- - Use resilient styling paradigm if applicable
-- - Use some alternate fallback command if provided
-- - Use some interesting commands, such as "custom-style=raggedleft".
-- Package or class designers MAY override this hook to support any other
-- styling mechanism they may have or want.
-- The available options are the custom-style "name" and a "scope" which
-- can be "inline" (for inline character-level styling) or "block" (for
-- block paragraph-level styling).
-- The available options are the custom-style "name", an optional "alt"
-- command name, and a "scope" which can be "inline" (for inline
-- character-level styling) or "block" (for block paragraph-level styling).
local name = SU.required(options, "name", "markdown custom style hook")
local scope = SU.required(options, "scope", "markdown custom style hook")
local alt = options.alt or name

if self.hasStyleSupport[name] then
SU.debug("markdown", "Feature detection: Applying actual custom style:", name)
if options.scope == "block" then
if scope == "block" then
SILE.call("style:apply:paragraph", { name = name }, content)
else
SILE.call("style:apply", { name = name }, content)
end
elseif self.hasCommandSupport[name] then
SU.debug("markdown", "Feature detection: Applying command for custom style:", name)
SILE.call(name, {}, content)
elseif self.hasCommandSupport[alt] then
SILE.call(alt, {}, content)
else
SU.debug("markdown", "Feature detection: Ignoring unknown custom style:", name)
SU.debug("markdown.commands", "Feature detection: ignoring unknown custom style:", name)
SILE.process(content)
if options.scope == "block" then
if scope == "block" then
SILE.call("par")
end
end
Expand Down

0 comments on commit 798d8e9

Please sign in to comment.