diff --git a/src/info.ts b/src/info.ts index e2a340a92..f3e0b417e 100644 --- a/src/info.ts +++ b/src/info.ts @@ -33,14 +33,21 @@ export function parseInfo(input: string): Info { let attributeName: string | undefined; let attributeNameStart: number | undefined; let attributeValueStart: number | undefined; + let tagStart = 0; const attributes = {}; - for (let i = 0, n = input.length; i <= n; ++i) { + + // Skip leading whitespace + while (tagStart < input.length && isSpaceCode(input.charCodeAt(tagStart))) { + tagStart++; + } + + for (let i = tagStart, n = input.length; i <= n; ++i) { const code = input.charCodeAt(i); // note: inclusive upper bound; code may be NaN! switch (state) { case STATE_TAG_NAME: { if (isSpaceCode(code) || isNaN(code)) { state = STATE_BEFORE_ATTRIBUTE_NAME; - tag = lower(input, 0, i); + tag = lower(input, tagStart, i); } break; } diff --git a/test/input/fenced-code-space-after-backticks.md b/test/input/fenced-code-space-after-backticks.md new file mode 100644 index 000000000..404a36df6 --- /dev/null +++ b/test/input/fenced-code-space-after-backticks.md @@ -0,0 +1,13 @@ +# Fenced code with space after backticks + +This should work according to CommonMark but currently fails: + +``` sql +SELECT 1 + 2 AS result; +``` + +This works without the space: + +```sql +SELECT 3 + 4 AS result; +``` \ No newline at end of file diff --git a/test/output/fenced-code-space-after-backticks.html b/test/output/fenced-code-space-after-backticks.html new file mode 100644 index 000000000..0d39e5ef4 --- /dev/null +++ b/test/output/fenced-code-space-after-backticks.html @@ -0,0 +1,5 @@ +

Fenced code with space after backticks

+

This should work according to CommonMark but currently fails:

+
+

This works without the space:

+
diff --git a/test/output/fenced-code-space-after-backticks.md.json b/test/output/fenced-code-space-after-backticks.md.json new file mode 100644 index 000000000..06f8f2ed9 --- /dev/null +++ b/test/output/fenced-code-space-after-backticks.md.json @@ -0,0 +1,306 @@ +{ + "data": {}, + "title": "Fenced code with space after backticks", + "style": null, + "code": [ + { + "id": "853e4a25", + "node": { + "body": { + "type": "Program", + "start": 0, + "end": 75, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 75, + "expression": { + "type": "CallExpression", + "start": 0, + "end": 74, + "callee": { + "type": "Identifier", + "start": 0, + "end": 7, + "name": "display" + }, + "arguments": [ + { + "type": "CallExpression", + "start": 8, + "end": 73, + "callee": { + "type": "MemberExpression", + "start": 8, + "end": 20, + "object": { + "type": "Identifier", + "start": 8, + "end": 14, + "name": "Inputs" + }, + "property": { + "type": "Identifier", + "start": 15, + "end": 20, + "name": "table" + }, + "computed": false, + "optional": false + }, + "arguments": [ + { + "type": "AwaitExpression", + "start": 21, + "end": 55, + "argument": { + "type": "TaggedTemplateExpression", + "start": 27, + "end": 55, + "tag": { + "type": "Identifier", + "start": 27, + "end": 30, + "name": "sql" + }, + "quasi": { + "type": "TemplateLiteral", + "start": 30, + "end": 55, + "expressions": [], + "quasis": [ + { + "type": "TemplateElement", + "start": 31, + "end": 54, + "value": { + "raw": "SELECT 1 + 2 AS result;", + "cooked": "SELECT 1 + 2 AS result;" + }, + "tail": true + } + ] + } + } + }, + { + "type": "ObjectExpression", + "start": 57, + "end": 72, + "properties": [ + { + "type": "Property", + "start": 58, + "end": 71, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 58, + "end": 64, + "name": "select" + }, + "value": { + "type": "Literal", + "start": 66, + "end": 71, + "value": false, + "raw": "false" + }, + "kind": "init" + } + ] + } + ], + "optional": false + } + ], + "optional": false + } + } + ], + "sourceType": "module" + }, + "declarations": [], + "references": [ + { + "type": "Identifier", + "start": 0, + "end": 7, + "name": "display" + }, + { + "type": "Identifier", + "start": 8, + "end": 14, + "name": "Inputs" + }, + { + "type": "Identifier", + "start": 27, + "end": 30, + "name": "sql" + } + ], + "files": [], + "imports": [], + "expression": false, + "async": true, + "input": "display(Inputs.table(await sql`SELECT 1 + 2 AS result;`, {select: false}));" + }, + "mode": "block" + }, + { + "id": "5472e671", + "node": { + "body": { + "type": "Program", + "start": 0, + "end": 75, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 75, + "expression": { + "type": "CallExpression", + "start": 0, + "end": 74, + "callee": { + "type": "Identifier", + "start": 0, + "end": 7, + "name": "display" + }, + "arguments": [ + { + "type": "CallExpression", + "start": 8, + "end": 73, + "callee": { + "type": "MemberExpression", + "start": 8, + "end": 20, + "object": { + "type": "Identifier", + "start": 8, + "end": 14, + "name": "Inputs" + }, + "property": { + "type": "Identifier", + "start": 15, + "end": 20, + "name": "table" + }, + "computed": false, + "optional": false + }, + "arguments": [ + { + "type": "AwaitExpression", + "start": 21, + "end": 55, + "argument": { + "type": "TaggedTemplateExpression", + "start": 27, + "end": 55, + "tag": { + "type": "Identifier", + "start": 27, + "end": 30, + "name": "sql" + }, + "quasi": { + "type": "TemplateLiteral", + "start": 30, + "end": 55, + "expressions": [], + "quasis": [ + { + "type": "TemplateElement", + "start": 31, + "end": 54, + "value": { + "raw": "SELECT 3 + 4 AS result;", + "cooked": "SELECT 3 + 4 AS result;" + }, + "tail": true + } + ] + } + } + }, + { + "type": "ObjectExpression", + "start": 57, + "end": 72, + "properties": [ + { + "type": "Property", + "start": 58, + "end": 71, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 58, + "end": 64, + "name": "select" + }, + "value": { + "type": "Literal", + "start": 66, + "end": 71, + "value": false, + "raw": "false" + }, + "kind": "init" + } + ] + } + ], + "optional": false + } + ], + "optional": false + } + } + ], + "sourceType": "module" + }, + "declarations": [], + "references": [ + { + "type": "Identifier", + "start": 0, + "end": 7, + "name": "display" + }, + { + "type": "Identifier", + "start": 8, + "end": 14, + "name": "Inputs" + }, + { + "type": "Identifier", + "start": 27, + "end": 30, + "name": "sql" + } + ], + "files": [], + "imports": [], + "expression": false, + "async": true, + "input": "display(Inputs.table(await sql`SELECT 3 + 4 AS result;`, {select: false}));" + }, + "mode": "block" + } + ], + "path": "fenced-code-space-after-backticks.md" +} \ No newline at end of file