Skip to content
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
6 changes: 5 additions & 1 deletion crates/qmd-syntax-helper/src/conversions/div_whitespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,11 @@ impl DivWhitespaceConverter {
}

/// Convert byte offset to row/column (1-indexed)
fn byte_offset_to_location(&self, content: &str, byte_offset: usize) -> crate::rule::SourceLocation {
fn byte_offset_to_location(
&self,
content: &str,
byte_offset: usize,
) -> crate::rule::SourceLocation {
let mut row = 1;
let mut column = 1;
let mut current_offset = 0;
Expand Down
6 changes: 5 additions & 1 deletion crates/qmd-syntax-helper/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ fn main() -> Result<()> {
for result in results {
all_results.push(result.clone());
if !json && result.has_issue {
println!(" {} {}", "✗".red(), result.message.unwrap_or_default());
println!(
" {} {}",
"✗".red(),
result.message.unwrap_or_default()
);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
"column": 17,
"row": 0,
"state": 1284,
"state": 1283,
"sym": "end",
"errorInfo": {
"title": "Unclosed Span",
Expand Down Expand Up @@ -30,23 +30,23 @@
{
"column": 20,
"row": 0,
"state": 2633,
"state": 2678,
"sym": "class_specifier",
"errorInfo": {
"title": "Key-value Pair Before Class Specifier in Attribute",
"message": "This class specifier appears after the key-value pair.",
"captures": [
{
"column": 10,
"lrState": 2743,
"lrState": 2720,
"row": 0,
"size": 3,
"sym": "key_value_key",
"label": "key-value-begin"
},
{
"column": 14,
"lrState": 2548,
"lrState": 2600,
"row": 0,
"size": 5,
"sym": "key_value_value_token1",
Expand All @@ -67,15 +67,15 @@
{
"column": 18,
"row": 0,
"state": 2050,
"state": 2020,
"sym": "_error",
"errorInfo": {
"title": "Mismatched Delimiter in Attribute Specifier",
"message": "I expected a '}', language specifier, an identifier, a class specifier, or a key-value pair.",
"captures": [
{
"column": 17,
"lrState": 2050,
"lrState": 2020,
"row": 0,
"size": 1,
"sym": "{",
Expand Down
2 changes: 1 addition & 1 deletion crates/quarto-markdown-pandoc/src/pandoc/treesitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ fn native_visitor<T: Write>(
"attribute" => process_attribute(children, context),
"commonmark_attribute" => process_commonmark_attribute(children, context),
"class_specifier" | "id_specifier" => create_specifier_base_text(node, input_bytes),
"shortcode_naked_string" | "shortcode_name" => {
"shortcode_naked_string" | "shortcode_name" | "shortcode_key_name_and_equals" => {
process_shortcode_string_arg(node, input_bytes, context)
}
"shortcode_string" => process_shortcode_string(&string_as_base_text, node, context),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,8 @@ pub fn postprocess<E: ErrorCollector>(doc: Pandoc, error_collector: &mut E) -> R
while i < inlines.len() {
if let Inline::Math(math) = &inlines[i] {
// Check if followed by Space then Attr, or just Attr
let has_space = i + 1 < inlines.len() && matches!(inlines[i + 1], Inline::Space(_));
let has_space =
i + 1 < inlines.len() && matches!(inlines[i + 1], Inline::Space(_));
let attr_idx = if has_space { i + 2 } else { i + 1 };

if attr_idx < inlines.len() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,24 @@ pub fn process_shortcode_keyword_param<T: Write>(
let mut name = String::new();
for (node, child) in children {
match node.as_str() {
"shortcode_key_name_and_equals" => {
// This is the new external token that includes "identifier = "
// We need to extract just the identifier part
let PandocNativeIntermediate::IntermediateShortcodeArg(
ShortcodeArg::String(text),
_,
) = child
else {
panic!(
"Expected ShortcodeArg::String in shortcode_key_name_and_equals, got {:?}",
child
)
};
// Remove the trailing '=' and any whitespace before it
name = text.trim_end_matches('=').trim_end().to_string();
}
"shortcode_name" => {
// This handles legacy case or value side of key-value
let PandocNativeIntermediate::IntermediateShortcodeArg(
ShortcodeArg::String(text),
_,
Expand Down
Binary file added crates/quarto-markdown-pandoc/tests/.DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions crates/quarto-markdown-pandoc/tests/smoke/022.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{< meta my-key >}}
1 change: 1 addition & 0 deletions crates/quarto-markdown-pandoc/tests/smoke/023.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{< include file.qmd section >}}
1 change: 1 addition & 0 deletions crates/quarto-markdown-pandoc/tests/smoke/024.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{< pagebreak >}}
1 change: 1 addition & 0 deletions crates/quarto-markdown-pandoc/tests/smoke/025.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{< video src="https://example.com" >}}
1 change: 1 addition & 0 deletions crates/quarto-markdown-pandoc/tests/smoke/026.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{< video src="url" width=500 >}}
1 change: 1 addition & 0 deletions crates/quarto-markdown-pandoc/tests/smoke/027.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{< meta key=value >}}
1 change: 1 addition & 0 deletions crates/quarto-markdown-pandoc/tests/smoke/028.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{< video "url" width=500 autoplay=true >}}
1 change: 1 addition & 0 deletions crates/quarto-markdown-pandoc/tests/smoke/029.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{{< include file.qmd key=value >}}
15 changes: 12 additions & 3 deletions crates/quarto-markdown-pandoc/tests/test_warnings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ Some content
);

// Parsing should succeed (warnings are not errors)
assert!(result.is_ok(), "Document should parse successfully despite warning");
assert!(
result.is_ok(),
"Document should parse successfully despite warning"
);

// TODO: Once the fix is implemented, we need to verify that the warning
// "Caption found without a preceding table" was actually output.
Expand Down Expand Up @@ -56,13 +59,19 @@ fn test_caption_with_table_no_warning() {
);

// Parsing should succeed and no warnings should be emitted
assert!(result.is_ok(), "Document with valid table caption should parse successfully");
assert!(
result.is_ok(),
"Document with valid table caption should parse successfully"
);

let (pandoc, _context) = result.unwrap();

// Verify we have a table in the output
assert!(
pandoc.blocks.iter().any(|b| matches!(b, quarto_markdown_pandoc::pandoc::Block::Table(_))),
pandoc
.blocks
.iter()
.any(|b| matches!(b, quarto_markdown_pandoc::pandoc::Block::Table(_))),
"Should have a table in the output"
);
}
16 changes: 14 additions & 2 deletions crates/tree-sitter-qmd/tree-sitter-markdown-inline/grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ module.exports = grammar(add_inline_rules({
$._shortcode_open,
$._shortcode_close,

// External token for keyword parameter keys with equals sign (e.g. "key=" or "key =")
// This disambiguates positional args from keyword params at lexical level
$._key_name_and_equals,

// Token emitted when encountering opening delimiters for a leaf span
// e.g. a code span, that does not have a matching closing span
$._unclosed_span,
Expand All @@ -102,7 +106,8 @@ module.exports = grammar(add_inline_rules({
[$._link_text, $._inline_element_no_tilde],
[$.link_destination, $.link_title],
[$._link_destination_parenthesis, $.link_title],
[$._shortcode_value, $.shortcode_keyword_param],
// Removed: [$._shortcode_value, $.shortcode_keyword_param]
// No longer needed - external token _key_name_and_equals eliminates ambiguity
],
extras: $ => [],

Expand Down Expand Up @@ -285,7 +290,14 @@ module.exports = grammar(add_inline_rules({
// // shortcode booleans are true or false
shortcode_boolean: $ => choice(token(prec(2, "true")), token(prec(2, "false"))),

shortcode_keyword_param: $ => prec.left(prec(2, seq($.shortcode_name, optional($._whitespace), "=", optional($._whitespace), $._shortcode_value))),
// Key-value parameter using external token that includes the "=" to eliminate ambiguity
// The key_name_and_equals token matches: identifier [whitespace] =
// Example: "key=", "key =", "my-key="
shortcode_keyword_param: $ => prec.left(prec(2, seq(
alias($._key_name_and_equals, $.shortcode_key_name_and_equals),
optional($._whitespace),
$._shortcode_value
))),

note_reference: $ => seq(
alias('[^', $.note_reference_delimiter),
Expand Down
33 changes: 11 additions & 22 deletions crates/tree-sitter-qmd/tree-sitter-markdown-inline/src/grammar.json
Original file line number Diff line number Diff line change
Expand Up @@ -3020,24 +3020,13 @@
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "shortcode_name"
},
{
"type": "CHOICE",
"members": [
{
"type": "SYMBOL",
"name": "_whitespace"
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "="
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "_key_name_and_equals"
},
"named": true,
"value": "shortcode_key_name_and_equals"
},
{
"type": "CHOICE",
Expand Down Expand Up @@ -5001,10 +4990,6 @@
"_link_destination_parenthesis",
"link_title"
],
[
"_shortcode_value",
"shortcode_keyword_param"
],
[
"_emphasis_star",
"_inline_element"
Expand Down Expand Up @@ -5285,6 +5270,10 @@
"type": "SYMBOL",
"name": "_shortcode_close"
},
{
"type": "SYMBOL",
"name": "_key_name_and_equals"
},
{
"type": "SYMBOL",
"name": "_unclosed_span"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1721,6 +1721,10 @@
"type": "shortcode_boolean",
"named": true
},
{
"type": "shortcode_key_name_and_equals",
"named": true
},
{
"type": "shortcode_naked_string",
"named": true
Expand Down Expand Up @@ -2492,6 +2496,10 @@
"type": "shortcode_delimiter",
"named": true
},
{
"type": "shortcode_key_name_and_equals",
"named": true
},
{
"type": "shortcode_name",
"named": true
Expand Down
Loading