Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add text-to-quarto-ast quarto API entries #6215

Merged
merged 5 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/changelog-1.4.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
- ([#5242](https://github.com/quarto-dev/quarto-cli/issues/5242)): Add line numbers to error messages.
- Add support `quarto.doc.add_resource` and `quarto.doc.add_supporting`. `add_resource` will add a resource file to the current render, copying that file to the same relative location in the output directory. `add_supporting` will add a supporting file to the current render, moving that file file to the same relative location in the output directory.
- ([#6211](https://github.com/quarto-dev/quarto-cli/pull/6211)): Improve error message when a JSON filter (or a potentially misspelled Lua filter from an extension) is not found.
- ([#6215](https://github.com/quarto-dev/quarto-cli/issues/6215)): Add `quarto.utils.string_to_inlines` and `quarto.utils.string_to_blocks` to Lua API to convert a string to a list of inlines or blocks taking into account quarto's AST structure.

## Books

Expand Down
24 changes: 23 additions & 1 deletion src/resources/filters/common/pandoc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ end
-- read attribute w/ default
function attribute(el, name, default)
-- FIXME: Doesn't attributes respond to __index?
for k,v in pairs(el.attr.attributes) do
for k,v in pairs(el.attributes) do
if k == name then
return v
end
Expand Down Expand Up @@ -170,3 +170,25 @@ function compileTemplate(template, meta)
end
end

local md_shortcode = require("lpegshortcode")

-- FIXME pick a better name for this.
function string_to_quarto_ast_blocks(text)
local after_shortcodes = md_shortcode.md_shortcode:match(text) or ""
local after_reading = pandoc.read(after_shortcodes, "markdown")

-- FIXME we should run the whole normalization pipeline here
local after_parsing = after_reading:walk(parse_extended_nodes()):walk(compute_flags())
return after_parsing.blocks
end

function string_to_quarto_ast_inlines(text)
local blocks = string_to_quarto_ast_blocks(text)
if #blocks ~= 1 then
fail("Expected a single block, got " .. #blocks)
end
if blocks[1].t ~= "Para" and blocks[1].t ~= "Plain" then
fail("Expected a Para or Plain block, got " .. blocks[1].t)
end
return blocks[1].content
end
16 changes: 5 additions & 11 deletions src/resources/filters/normalize/extractquartodom.lua
Original file line number Diff line number Diff line change
@@ -1,32 +1,26 @@
local md_shortcode = require("lpegshortcode")

local function process_quarto_markdown_input_element(el)
if el.attributes.qmd == nil and el.attributes["qmd-base64"] == nil then
error("process_quarto_markdown_input_element called with element that does not have qmd or qmd-base64 attribute")
return el
end
local text = el.attributes.qmd or quarto.base64.decode(el.attributes["qmd-base64"])
local after_shortcodes = md_shortcode.md_shortcode:match(text) or ""
local after_reading = pandoc.read(after_shortcodes, "markdown")
local after_parsing = after_reading:walk(parse_extended_nodes()):walk(compute_flags())
return after_parsing
return string_to_quarto_ast_blocks(text)
end

function parse_md_in_html_rawblocks()
return {
Div = function(div)
if div.attributes.qmd ~= nil or div.attributes["qmd-base64"] ~= nil then
local doc = process_quarto_markdown_input_element(div)
return doc.blocks
return process_quarto_markdown_input_element(div)
end
end,
Span = function(span)
if span.attributes.qmd ~= nil or span.attributes["qmd-base64"] ~= nil then
local doc = process_quarto_markdown_input_element(span)
if #doc.blocks < 1 then
local blocks = process_quarto_markdown_input_element(span)
if #blocks < 1 then
return pandoc.Span({})
end
return doc.blocks[1].content
return blocks[1].content
end
end
}
Expand Down
15 changes: 15 additions & 0 deletions src/resources/lua-types/quarto/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,18 @@ not be visible to the user.
---@return string
function quarto.utils.resolve_path(path) end

--[[
Converts a string to a list of Pandoc Inlines, processing any Quarto custom
syntax in the string.
]]
---@param path string String to be converted
---@return pandoc.Inlines
function quarto.utils.string_to_inlines(path) end

--[[
Converts a string to a list of Pandoc Blocks, processing any Quarto custom
syntax in the string.
]]
---@param path string String to be converted
---@return pandoc.Blocks
function quarto.utils.string_to_blocks(path) end
19 changes: 16 additions & 3 deletions src/resources/pandoc/datadir/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1293,7 +1293,6 @@ local json = require '_json'
local utils = require '_utils'
local logging = require 'logging'


-- determines whether a path is a relative path
local function isRelativeRef(ref)
return ref:find("^/") == nil and
Expand Down Expand Up @@ -1897,7 +1896,19 @@ _quarto = {
exists = file_exists,
remove = remove_file
}
}
}

-- this injection here is ugly but gets around
-- a hairy order-of-import issue that would otherwise happen
-- because string_to_inlines requires some filter code that is only
-- later imported

_quarto.utils.string_to_inlines = function(s)
return string_to_quarto_ast_inlines(s)
end
_quarto.utils.string_to_blocks = function(s)
return string_to_quarto_ast_blocks(s)
end

-- The main exports of the quarto module
quarto = {
Expand Down Expand Up @@ -2058,7 +2069,9 @@ quarto = {
resolve_path = resolvePathExt,
resolve_path_relative_to_document = resolvePath,
as_inlines = utils.as_inlines,
as_blocks = utils.as_blocks
as_blocks = utils.as_blocks,
string_to_blocks = utils.string_to_blocks,
string_to_inlines = utils.string_to_inlines,
},
json = json,
base64 = base64,
Expand Down
5 changes: 5 additions & 0 deletions tests/docs/smoke-all/lua/6215/test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function Pandoc(doc)
quarto.utils.dump(quarto.utils)
doc.blocks:extend(quarto.utils.string_to_blocks("Some markdown.\n\n[{{< meta test_key >}}]{#test_span}"))
return doc
end
15 changes: 15 additions & 0 deletions tests/docs/smoke-all/lua/6215/test.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
filters:
- test.lua
test_key: _test_value_
_quarto:
_tests:
html:
ensureHtmlElements:
- ["span#test_span em"] # checks for emph to ensure shortcode was executed.
- []
---

## A header

Some content.