diff --git a/README.md b/README.md index 2df8f58..c93c3c4 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ # Critic-markup Extension For Quarto -This extension provide a filter for processing [critic markup](https://github.com/CriticMarkup/CriticMarkup-toolkit) syntax when rendering to html. The rendered html provide a flexible interface with +This extension provide a filter for processing [critic markup](https://github.com/CriticMarkup/CriticMarkup-toolkit) syntax when rendering to html or pdf. The rendered html provide a flexible interface with - The markup document with changes highlighted - The original version - The updated version with the changes applied - This extension was inspired by the critic markup processing for [ScholarlyMarkdown](http://scholarlymarkdown.com/) available under MIT license as well [ScholarlyMarkdown.git](https://github.com/slimgroup/ScholarlyMarkdown) ## Installing @@ -33,4 +32,29 @@ filters: Here is a minimal example showing the critic markup syntax and its rendering: [example.qmd](example.qmd). -This is the output of [example.qmd](https://mloubout.github.io/critic-markup/). \ No newline at end of file +This is the output of [example.qmd](https://mloubout.github.io/critic-markup/). + + +## Multi-format example + +Here is a minimal example showing the critic markup syntax and its rendering: [example-multiformat.qmd](example-multiformat.qmd). + +## Usage + +This filter reads the Quarto meta variable `critic-markup-version`. Valid values are `all` (default), `markup`, `edited` or `original`. + +The default `all` shows all three version of the document. + +- `markup` shows changes highlighted. +- `edited` shows the updated version of document with applied changes. +- `original` shows the original document. + + +## Supported formats + +Formats other than html and pdf simply show the raw critic markup syntax. + +Support for pdf relies on the following LaTeX packages (included in TinyTeX and therefore Quarto by default): + +- [pdfcomment](https://ctan.org/pkg/pdfcomment) +- [draftwatermark](https://ctan.org/pkg/draftwatermark) diff --git a/_extensions/critic-markup/critic-markup.lua b/_extensions/critic-markup/critic-markup.lua index 761606f..e85cbb7 100644 --- a/_extensions/critic-markup/critic-markup.lua +++ b/_extensions/critic-markup/critic-markup.lua @@ -2,7 +2,21 @@ local maybesubs = false local stk_end = false -if FORMAT:match 'html' then +local valid_versions = {all=true, markup=true, edited=true, original=true} +local modifier = PANDOC_STATE.output_file:match("%+([^.]+)%..+$") +if modifier then + for s in modifier:gmatch("[^-]+") do + if valid_versions[s] then + CRITIC_VERSION_default = s + end + end +end + +if not valid_versions[CRITIC_VERSION_default] then + CRITIC_VERSION_default = "all" +end + +if quarto.doc.is_format('html') then add = pandoc.RawInline('html', "") adde = pandoc.RawInline('html', "") @@ -15,7 +29,7 @@ if FORMAT:match 'html' then comm = pandoc.RawInline('html', [[]]) comme = pandoc.RawInline('html', "") -elseif FORMAT:match 'latex' then +elseif quarto.doc.is_format('latex') then add = pandoc.RawInline('latex', "\\criticmarkupadd{") adde = pandoc.RawInline('latex', "}") @@ -28,9 +42,17 @@ elseif FORMAT:match 'latex' then comm = pandoc.RawInline('latex', "\\criticmarkupcomm{") comme = pandoc.RawInline('latex', "}") +else + unsupported = true + adde = pandoc.Str("++}") + rm = pandoc.Str("{--") +end +if unsupported then + ruless = {} +else + ruless = {['{%+%+']=add, ['{\u{2013}']=rm, ['{==']=mark, ['{>>']=comm, ['{~~']=rm, + ['%+%+}']=adde, ['\u{2013}}']=rme, ['==}']=marke, ['<<}']=comme, ['~~}']=rme, ['~>']=rmeadd} end -ruless = {['{%+%+']=add, ['{\u{2013}']=rm, ['{==']=mark, ['{>>']=comm, ['{~~']=rm, - ['%+%+}']=adde, ['\u{2013}}']=rme, ['==}']=marke, ['<<}']=comme, ['~~}']=rme, ['~>']=rmeadd} -- Strikeout before/after st_b = '{' @@ -90,14 +112,15 @@ local scriptcode = [[ var e = document.getElementById("edited-button"); var m = document.getElementById("markup-button"); - window.onload = critic(); + window.addEventListener('load', critic) o.onclick = original; e.onclick = edited; m.onclick = markup; ]] -local latexcode = [[ +local latexcode = {} +latexcode.header = [[ \IfFileExists{pdfcomment.sty} { \usepackage{pdfcomment} @@ -112,6 +135,57 @@ local latexcode = [[ \newcommand{\criticmarkupmark}[1]{\{=={##1}==\}} \newcommand{\criticmarkupcomm}[1]{\{>{}>{##1}<{}<\}} } +\IfFileExists{draftwatermark.sty} +{ + \usepackage{draftwatermark} + \DraftwatermarkOptions{% + pos={5mm,5mm}, + anchor=lt, + alignment=l, + fontsize=10mm, + angle=0 + } + \DraftwatermarkOptions{text=Markup} +} + +\newcounter{criticmarkupfirstpage} + +]] + +latexcode.edited = [[ + \renewcommand{\criticmarkupadd}[1]{#1} + \renewcommand{\criticmarkuprm}[1]{} + \renewcommand{\criticmarkupmark}[1]{#1} + \renewcommand{\criticmarkupcomm}[1]{} + \IfFileExists{draftwatermark.sty} + { + \DraftwatermarkOptions{text=Edited} + } +]] + +latexcode.original = [[ + \renewcommand{\criticmarkupadd}[1]{} + \renewcommand{\criticmarkuprm}[1]{#1} + \renewcommand{\criticmarkupmark}[1]{#1} + \renewcommand{\criticmarkupcomm}[1]{} + \IfFileExists{draftwatermark.sty} + { + \DraftwatermarkOptions{text=Original} + } +]] + +latexcode.reset = [[ + +\clearpage + +]] + +latexcode.newpage = [[ + +\maketitle + +\setcounter{page}{\value{criticmarkupfirstpage}} + ]] function cirtiblock(blocks, k, v) @@ -189,18 +263,63 @@ end function criticheader (meta) - if FORMAT:match 'html' then + local version = meta["critic-markup-version"] + CRITIC_VERSION = version and pandoc.utils.stringify(version) or CRITIC_VERSION_default + if not valid_versions[CRITIC_VERSION] then + error("Invalid critic-markup-version: " .. CRITIC_VERSION) + end + if quarto.doc.is_format('html') then quarto.doc.add_html_dependency({ name = 'critic', scripts = {'critic.min.js'}, stylesheets = {'critic.css'} }) -- inject the rendering code - quarto.doc.include_text("after-body", scriptcode) - else - quarto.doc.include_text("in-header", latexcode) + quarto.doc.include_text("in-header", scriptcode) + if CRITIC_VERSION == "all" then + return + end + -- inject the code selecting a specific version. + local activate = [[ + + ]] + activate = activate:gsub("CRITIC_VERSION", CRITIC_VERSION) + quarto.doc.include_text("in-header", activate) + elseif quarto.doc.is_format('latex') then + quarto.doc.include_text("in-header", latexcode.header) + quarto.doc.include_text("before-body", "\\setcounter{criticmarkupfirstpage}{\\value{page}}") + end +end + +if quarto.doc.is_format('latex') then + function Pandoc(doc) + local n = #doc.blocks + + if CRITIC_VERSION == "all" then + -- Insert edited version of document. + local code = latexcode.reset .. latexcode.edited .. latexcode.newpage + table.insert(doc.blocks, pandoc.RawInline('latex', code)) + for i = 0,n-1 do -- TODO: maybe this should be 1 to n. + table.insert(doc.blocks, doc.blocks[i]) + end + + -- Insert original version of document. + code = latexcode.reset .. latexcode.original .. latexcode.newpage + table.insert(doc.blocks, pandoc.RawInline('latex', code)) + for i = 0,n-1 do + table.insert(doc.blocks, doc.blocks[i]) + end + elseif CRITIC_VERSION == "edited" then + quarto.doc.include_text("in-header", latexcode.edited) + elseif CRITIC_VERSION == "original" then + quarto.doc.include_text("in-header", latexcode.original) + end + return doc end end -- All pass with Meta first -return {{Meta = criticheader}, {Inlines = Inlines}, {Strikeout = Strikeout}, {Str = Str}} +return {{Meta = criticheader}, {Inlines = Inlines}, {Strikeout = Strikeout}, {Str = Str}, {Pandoc = Pandoc}} diff --git a/_extensions/critic-markup/critic.css b/_extensions/critic-markup/critic.css index e10cab9..20ff422 100644 --- a/_extensions/critic-markup/critic.css +++ b/_extensions/critic-markup/critic.css @@ -1,4 +1,4 @@ -.fullcontent { +#quarto-content { padding-top: 30px !important; } diff --git a/example-multiformat.qmd b/example-multiformat.qmd new file mode 100644 index 0000000..01ae68f --- /dev/null +++ b/example-multiformat.qmd @@ -0,0 +1,65 @@ +--- +title: "Critic-markdown multi-format example" +format: + html: default + html+markup: + output-file: example-multiformat+markup.html + html+edited: + output-file: example-multiformat+edited.html + html+original: + output-file: example-multiformat+original.html + pdf: default + pdf+markup: default + pdf+edited: default + pdf+original: default +filters: + - critic-markup +format-links: + - text: HTML + href: ./example-multiformat.html + - text: HTML+markup + href: ./example-multiformat+markup.html + - text: HTML+edited + href: ./example-multiformat+edited.html + - text: HTML+original + href: ./example-multiformat+original.html + - pdf + - format: pdf+edited + text: PDF+edited + - format: pdf+original + text: PDF+original + - format: pdf+markup + text: PDF+markup + +--- + + +## Critic Markdown + +This filter adds processing of critic markdown syntax. Below are examples of usage. + +## Highlighting + +`{==Highlighted text==}` {==Highlighted text==} + +`{== Highlighted text with a comment==}{>>First comment<<}` {== Highlighted text with a comment==}{>>First comment<<} + +`{>>Single comment <<}` {>>Single comment <<} + + +## Addition + +`{++This is added text++}` {++This is added text++} + +`{++This is added text with some removed++}{-- removed--}` {++This is added text with some removed++}{-- removed--} + + +## Deletion + +`{--This is removed text--}` {--This is removed text--} + +`{--This is removed text with some added--}{++added ++}` {--This is removed text with some added--}{++added ++} + +## Replacement + +`{~~This is original text~> this is the replacement~~}` {~~This is original text~> this is the replacement~~}