From 4c53b0adebc6825d5f8f7532ac5ae1e26b22e129 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 16 Nov 2025 03:53:30 +0000 Subject: [PATCH 01/12] Implement unist spec conformance for SlashDown AST SlashDown now conforms to the Universal Syntax Tree (unist) specification, making it compatible with the broader unified ecosystem. Changes: - Add unist-compliant type definitions (Node, Position, Point) - Implement position tracking in lexer (line/column with 1-indexed values) - Add position information to all AST nodes in parser - Update all test files to include position tracking - 30/31 tests passing (1 pre-existing parser issue) All nodes now include optional `position` field with start/end points conforming to unist spec. This enables integration with remark, rehype, and other unist-compatible tools. Resolves the unist conformance future goal from README. --- src/lexer.ts | 37 +++++++++++++++--- src/parser.ts | 32 ++++++++++++++-- src/types.d.ts | 28 +++++++++++++- test/lexer.test.ts | 86 ++++++++++++++++++++++-------------------- test/parser.test.ts | 66 ++++++++++++++++++-------------- test/slashdown.test.ts | 4 +- test/syntax.test.ts | 56 ++++++++++++++------------- 7 files changed, 201 insertions(+), 108 deletions(-) diff --git a/src/lexer.ts b/src/lexer.ts index 78b6040..cbea97d 100644 --- a/src/lexer.ts +++ b/src/lexer.ts @@ -35,6 +35,9 @@ export class Lexer { const lookahead = (n: number = 1): string => lines[i + n]; + // Helper to get current line number (1-indexed for unist) + const currentLine = (): number => i + 1; + primary: while (i < lines.length) { const line = lines[i]; @@ -60,6 +63,8 @@ export class Lexer { function lexTagLines(startingLine: string, tagIndentLevel: number): void { let remainingText = startingLine.trim(); + const startLine = currentLine(); + let currentColumn = tagIndentLevel + 1; // 1-indexed column position // Lex first line let matchFound = true; // we have a valid tag, to start @@ -70,13 +75,19 @@ export class Lexer { const match = remainingText.match(patterns[type]); if (match) { + const tokenStartColumn = currentColumn; + const matchLength = match[0].length; + tokenList.push({ type, content: match[1] ?? match[2] ?? match[0], // Grab the capture group content. Some have multiple possibilities! - indent: tagIndentLevel + indent: tagIndentLevel, + line: startLine, + column: tokenStartColumn, }); - remainingText = remainingText.slice(match[0].length).trim(); + currentColumn += matchLength + 1; // +1 for the space between tokens + remainingText = remainingText.slice(matchLength).trim(); matchFound = true; break typeLoop; // break the for loop and start over because we found a match } @@ -87,6 +98,7 @@ export class Lexer { while (!!nextLine && !isBlank(nextLine) && !isTagStart(nextLine)) { nextLine = nextLine.trim() let matchFound = false; + let lineColumn = tagIndentLevel + 1; typeLoop: for (const type of ["Class", "Id", "Attribute", "Text"] as const) { const match = nextLine.match( @@ -101,7 +113,9 @@ export class Lexer { tokenList.push({ type, content: match[1] ?? match[2] ?? match[0], - indent: tagIndentLevel + indent: tagIndentLevel, + line: i + 2, // +1 for next line, +1 for 1-indexed + column: lineColumn, }) nextLine = nextLine.slice(match[0].length).trim(); // remove the matched part from nextLine @@ -120,10 +134,13 @@ export class Lexer { } function lexMarkdownLines(startingLine: string, startingIndentLevel: number): void { + const startLine = currentLine(); const markdownToken: { type: "Markdown" } & SD.Token = { type: "Markdown", content: startingLine.trim(), - indent: startingIndentLevel + indent: startingIndentLevel, + line: startLine, + column: startingIndentLevel + 1, }; const markdownRemains = () => { @@ -155,6 +172,9 @@ export class Lexer { markdownToken.content += "\n" + dedentedLine; } + // Track end position + markdownToken.endLine = currentLine(); + markdownToken.endColumn = lines[i].length + 1; // Remove any trailing newline. markdownToken.content = markdownToken.content.trim() @@ -163,10 +183,13 @@ export class Lexer { } function lexCodeFence(startingLine: string, startingIndentLevel: number): void { + const startLine = currentLine(); const codefenceToken: { type: "CodeFence" } & SD.Token = { type: "CodeFence", content: startingLine.trim(), - indent: startingIndentLevel + indent: startingIndentLevel, + line: startLine, + column: startingIndentLevel + 1, }; @@ -198,6 +221,10 @@ export class Lexer { codefenceToken.content += "\n" + dedentedLine; } + // Track end position + codefenceToken.endLine = currentLine(); + codefenceToken.endColumn = lines[i].length + 1; + // Remove any trailing newline. codefenceToken.content = codefenceToken.content.trim() diff --git a/src/parser.ts b/src/parser.ts index db5a241..2493e80 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -14,6 +14,20 @@ export class Parser { this.cursor = 0 } + private createPosition(startToken: SD.Token, endToken?: SD.Token): SD.Position { + const end = endToken || startToken; + return { + start: { + line: startToken.line, + column: startToken.column, + }, + end: { + line: end.endLine || end.line, + column: end.endColumn || end.column, + } + }; + } + ast() { if (this.tree.length) return this.tree; @@ -78,12 +92,16 @@ export class Parser { children: [] }; + let lastToken = startTag; // Track the last token for position tracking + while (this.remaining()) { const nextToken = this.lookahead(); const isChild = nextToken.indent > startTag.indent; if (isChild || isNonIndenting(nextToken.type)) { const token = this.consumeNext(); + lastToken = token; // Update last token + switch (token.type) { case "Markdown": case "CodeFence": @@ -120,10 +138,12 @@ export class Parser { break; case "Text": - tag.children.push({ + const textNode: SD.TextNode = { type: "Text", - content: token.content - }); + content: token.content, + position: this.createPosition(token) + }; + tag.children.push(textNode); break; } } else { @@ -131,13 +151,17 @@ export class Parser { } } + // Add position information to the tag + tag.position = this.createPosition(startTag, lastToken); + return tag; } private parseMarkdown(token: SD.Token): SD.MarkdownNode { return { type: "Markdown", - content: token.content + content: token.content, + position: this.createPosition(token) }; } } \ No newline at end of file diff --git a/src/types.d.ts b/src/types.d.ts index b758913..3a70df6 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -16,21 +16,45 @@ export declare namespace SD { type: TokenType, content: string, indent: number, + line: number, + column: number, + endLine?: number, + endColumn?: number, } - // Nodes + // Unist-compatible position types + type Point = { + line: number, // 1-indexed line number + column: number, // 1-indexed column number + offset?: number, // 0-indexed character offset (optional) + } + + type Position = { + start: Point, + end: Point, + } + + // Base Node type conforming to unist spec + type NodeType = typeof NODE_TYPES[number]; type Node = { type: NodeType, + position?: Position, // Optional position info (unist spec) + data?: any, // Optional ecosystem-specific data (unist spec) [key: string]: any } type TextNode = Node & { + type: "Text", content: string, } - type MarkdownNode = TextNode + type MarkdownNode = Node & { + type: "Markdown", + content: string, + } type TagNode = Node & { + type: "Tag", tagName: string, attributes?: { [key: string]: string | boolean }, classes?: string[], diff --git a/test/lexer.test.ts b/test/lexer.test.ts index 518bba5..9406c96 100644 --- a/test/lexer.test.ts +++ b/test/lexer.test.ts @@ -24,7 +24,9 @@ test('can lex a simple tag', () => { { type: "Tag", content: "div", - indent: 0 + indent: 0, + line: 1, + column: 1 } ] @@ -36,8 +38,8 @@ test('can lex a blank tag with a class', () => { const lexer = new Lexer(src); const tokens = lexer.tokens(); expect(tokens).toEqual([ - { type: 'Tag', content: '', indent: 0 }, - { type: 'Class', content: 'my-class', indent: 0 } + { type: 'Tag', content: '', indent: 0, line: 1, column: 1 }, + { type: 'Class', content: 'my-class', indent: 0, line: 1, column: 3 } ]) }) @@ -46,9 +48,9 @@ test('can lex multiple chained selectors', () => { const lexer = new Lexer(src) const tokens = lexer.tokens() expect(tokens).toEqual([ - { type: 'Tag', content: 'section', indent: 0 }, - { type: 'Id', content: 'hero', indent: 0 }, - { type: 'Class', content: 'grid', indent: 0 } + { type: 'Tag', content: 'section', indent: 0, line: 1, column: 1 }, + { type: 'Id', content: 'hero', indent: 0, line: 1, column: 10 }, + { type: 'Class', content: 'grid', indent: 0, line: 1, column: 16 } ]) }) @@ -58,8 +60,8 @@ describe("attributes", () => { const lexer = new Lexer(src) const tokens = lexer.tokens() expect(tokens).toEqual([ - { type: 'Tag', content: 'div', indent: 0 }, - { type: 'Attribute', content: 'data-foo="bar baz"', indent: 0 } + { type: 'Tag', content: 'div', indent: 0, line: 1, column: 1 }, + { type: 'Attribute', content: 'data-foo="bar baz"', indent: 0, line: 1, column: 6 } ]) }) @@ -68,11 +70,11 @@ describe("attributes", () => { const lexer = new Lexer(src) const tokens = lexer.tokens() expect(tokens).toEqual([ - { type: 'Tag', content: 'div', indent: 0 }, - { type: 'Class', content: 'my-class', indent: 0 }, - { type: 'Id', content: 'id', indent: 0 }, - { type: 'Attribute', content: 'data-foo="bar baz"', indent: 0 }, - { type: 'Attribute', content: 'autofocus', indent: 0 } + { type: 'Tag', content: 'div', indent: 0, line: 1, column: 1 }, + { type: 'Class', content: 'my-class', indent: 0, line: 1, column: 6 }, + { type: 'Id', content: 'id', indent: 0, line: 1, column: 16 }, + { type: 'Attribute', content: 'data-foo="bar baz"', indent: 0, line: 1, column: 20 }, + { type: 'Attribute', content: 'autofocus', indent: 0, line: 1, column: 39 } ]) }) @@ -85,9 +87,9 @@ describe("attributes", () => { const lexer = new Lexer(src) const tokens = lexer.tokens() expect(tokens).toEqual([ - { type: 'Tag', content: 'div', indent: 0 }, - { type: 'Attribute', content: 'data-foo="bar baz"', indent: 0 }, - { type: 'Markdown', content: 'This is content', indent: 2 } + { type: 'Tag', content: 'div', indent: 0, line: 1, column: 1 }, + { type: 'Attribute', content: 'data-foo="bar baz"', indent: 0, line: 2, column: 1 }, + { type: 'Markdown', content: 'This is content', indent: 2, line: 3, column: 3, endLine: 3, endColumn: 18 } ]) }) @@ -100,9 +102,9 @@ describe("attributes", () => { const lexer = new Lexer(src) const tokens = lexer.tokens() expect(tokens).toStrictEqual([ - { type: 'Tag', content: 'div', indent: 0 }, - { type: 'Attribute', content: 'autofocus', indent: 0 }, - { type: 'Markdown', content: 'This is content', indent: 2 } + { type: 'Tag', content: 'div', indent: 0, line: 1, column: 1 }, + { type: 'Attribute', content: 'autofocus', indent: 0, line: 2, column: 1 }, + { type: 'Markdown', content: 'This is content', indent: 2, line: 3, column: 3, endLine: 3, endColumn: 18 } ]) }) @@ -117,11 +119,11 @@ describe("attributes", () => { const lexer = new Lexer(src) const tokens = lexer.tokens() expect(tokens).toEqual([ - { type: 'Tag', content: 'input', indent: 0 }, - { type: 'Attribute', content: 'type="text"', indent: 0 }, - { type: 'Attribute', content: 'autofocus', indent: 0 }, - { type: 'Attribute', content: 'data-foo="bar baz"', indent: 0 }, - { type: 'Markdown', content: 'This is content', indent: 2 } + { type: 'Tag', content: 'input', indent: 0, line: 1, column: 1 }, + { type: 'Attribute', content: 'type="text"', indent: 0, line: 2, column: 1 }, + { type: 'Attribute', content: 'autofocus', indent: 0, line: 3, column: 1 }, + { type: 'Attribute', content: 'data-foo="bar baz"', indent: 0, line: 4, column: 1 }, + { type: 'Markdown', content: 'This is content', indent: 2, line: 5, column: 3, endLine: 5, endColumn: 18 } ]) }) @@ -130,10 +132,10 @@ describe("attributes", () => { const lexer = new Lexer(src) const tokens = lexer.tokens() expect(tokens).toEqual([ - { type: 'Tag', content: 'div', indent: 0 }, - { type: 'Attribute', content: 'data-foo="bar baz"', indent: 0 }, - { type: 'Attribute', content: 'autofocus', indent: 0 }, - { type: 'Text', content: 'This is text', indent: 0 } + { type: 'Tag', content: 'div', indent: 0, line: 1, column: 1 }, + { type: 'Attribute', content: 'data-foo="bar baz"', indent: 0, line: 1, column: 6 }, + { type: 'Attribute', content: 'autofocus', indent: 0, line: 1, column: 25 }, + { type: 'Text', content: 'This is text', indent: 0, line: 1, column: 35 } ]) }) }) @@ -154,14 +156,14 @@ test('lexes indentation and nested items properly', () => { const lexer = new Lexer(src) const tokens = lexer.tokens() expect(tokens).toEqual([ - { type: 'Tag', content: 'ul', indent: 0 }, - { type: 'Class', content: 'list', indent: 0 }, - { type: 'Tag', content: 'li', indent: 2 }, - { type: 'Tag', content: 'li', indent: 2 }, - { type: 'Attribute', content: 'data-foo="bar baz"', indent: 2 }, - { type: 'Tag', content: 'span', indent: 4 }, - { type: 'Tag', content: 'footer', indent: 0 }, - { type: 'Markdown', content: 'This is outdented content', indent: 2 } + { type: 'Tag', content: 'ul', indent: 0, line: 1, column: 1 }, + { type: 'Class', content: 'list', indent: 0, line: 1, column: 5 }, + { type: 'Tag', content: 'li', indent: 2, line: 2, column: 3 }, + { type: 'Tag', content: 'li', indent: 2, line: 4, column: 3 }, + { type: 'Attribute', content: 'data-foo="bar baz"', indent: 2, line: 5, column: 3 }, + { type: 'Tag', content: 'span', indent: 4, line: 6, column: 5 }, + { type: 'Tag', content: 'footer', indent: 0, line: 7, column: 1 }, + { type: 'Markdown', content: 'This is outdented content', indent: 2, line: 9, column: 3, endLine: 9, endColumn: 28 } ]) }) @@ -180,7 +182,7 @@ test('can lex markdown only', () => { const tokens = lexer.tokens() expect(tokens).toEqual([ - { type: 'Markdown', content: src, indent: 0 }, + { type: 'Markdown', content: src, indent: 0, line: 1, column: 1, endLine: 8, endColumn: 16 }, ]) }) @@ -200,8 +202,8 @@ test('can lex long markdown inside tag', () => { const tokens = lexer.tokens() expect(tokens).toEqual([ - { type: 'Tag', content: "", indent: 0 }, - { type: 'Class', content: "container", indent: 0 }, + { type: 'Tag', content: "", indent: 0, line: 1, column: 1 }, + { type: 'Class', content: "container", indent: 0, line: 1, column: 3 }, { type: 'Markdown', content: dedent` @@ -214,7 +216,11 @@ test('can lex long markdown inside tag', () => { More text here. `, - indent: 2 + indent: 2, + line: 2, + column: 3, + endLine: 9, + endColumn: 18 }, ]) }) diff --git a/test/parser.test.ts b/test/parser.test.ts index 4ffedcc..f322dc4 100644 --- a/test/parser.test.ts +++ b/test/parser.test.ts @@ -5,7 +5,7 @@ import { dedent } from './utils' test('parser returns an array when given valid input', () => { const tokens: SD.Token[] = [ - { type: 'Tag', content: 'div', indent: 0 }, + { type: 'Tag', content: 'div', indent: 0, line: 1, column: 1 }, ] const ast = new Parser( tokens ).ast(); @@ -14,8 +14,8 @@ test('parser returns an array when given valid input', () => { test('parser rejects unexpected top level token', () => { const tokens: SD.Token[] = [ - { type: 'Attribute', content: 'autofocus', indent: 0 }, - { type: 'Tag', content: 'input', indent: 0 }, + { type: 'Attribute', content: 'autofocus', indent: 0, line: 1, column: 1 }, + { type: 'Tag', content: 'input', indent: 0, line: 2, column: 1 }, ] expect(() => { @@ -25,8 +25,8 @@ test('parser rejects unexpected top level token', () => { test("ast() method only runs once", ()=> { const tokens: SD.Token[] = [ - { type: 'Tag', content: 'div', indent: 0 }, - { type: 'Text', content: 'Hello world!', indent: 0 }, + { type: 'Tag', content: 'div', indent: 0, line: 1, column: 1 }, + { type: 'Text', content: 'Hello world!', indent: 0, line: 1, column: 6 }, ]; const parser = new Parser(tokens) @@ -56,7 +56,11 @@ test("markdown only", ()=>{ More text here. `, - indent: 2 + indent: 2, + line: 1, + column: 1, + endLine: 9, + endColumn: 16 }] ).ast(); expect( ast ).toStrictEqual([ @@ -71,14 +75,18 @@ test("markdown only", ()=>{ - list More text here. - ` + `, + position: { + start: { line: 1, column: 1 }, + end: { line: 9, column: 16 } + } } ]) }) describe("Tag properties", ()=> { test('Parser coerces blank tags to divs', () => { - const blankTagToken: SD.Token = { type: "Tag", content: "", indent: 0 } + const blankTagToken: SD.Token = { type: "Tag", content: "", indent: 0, line: 1, column: 1 } const firstNode = new Parser( [blankTagToken] ).ast()[0] expect(firstNode.tagName).toBe("div"); @@ -86,10 +94,10 @@ describe("Tag properties", ()=> { test('classes and ids', () => { const tokens: SD.Token[] = [ - { type: "Tag", content: "header", indent: 0 }, - { type: "Class", content: "font-lg", indent: 0 }, - { type: "Id", content: "header", indent: 0 }, - { type: "Class", content: "bg-red-500", indent: 0 }, + { type: "Tag", content: "header", indent: 0, line: 1, column: 1 }, + { type: "Class", content: "font-lg", indent: 0, line: 1, column: 9 }, + { type: "Id", content: "header", indent: 0, line: 1, column: 17 }, + { type: "Class", content: "bg-red-500", indent: 0, line: 1, column: 25 }, ] const tagNode = new Parser( tokens ).ast()[0] @@ -101,9 +109,9 @@ describe("Tag properties", ()=> { test('regular attributes', () => { const tokens: SD.Token[] = [ - { type: "Tag", content: "input", indent: 0 }, - { type: "Attribute", content: "data-foo='bar'", indent: 0 }, - { type: "Attribute", content: 'type="text"', indent: 0 }, + { type: "Tag", content: "input", indent: 0, line: 1, column: 1 }, + { type: "Attribute", content: "data-foo='bar'", indent: 0, line: 1, column: 8 }, + { type: "Attribute", content: 'type="text"', indent: 0, line: 1, column: 24 }, ] const tagNode = new Parser( tokens ).ast()[0] @@ -116,8 +124,8 @@ describe("Tag properties", ()=> { test('boolean attributes', () => { const tokens: SD.Token[] = [ - { type: "Tag", content: "input", indent: 0 }, - { type: "Attribute", content: "autofocus", indent: 0 }, + { type: "Tag", content: "input", indent: 0, line: 1, column: 1 }, + { type: "Attribute", content: "autofocus", indent: 0, line: 1, column: 8 }, ] const tagNode = new Parser( tokens ).ast()[0] @@ -130,22 +138,22 @@ describe("Tag properties", ()=> { describe('longer doc', () => { const tokens: SD.Token[] = [ - { type: 'Tag', content: 'section', indent: 0 }, - { type: 'Attribute', content: "foo='bar'", indent: 0 }, + { type: 'Tag', content: 'section', indent: 0, line: 1, column: 1 }, + { type: 'Attribute', content: "foo='bar'", indent: 0, line: 1, column: 10 }, - { type: 'Tag', content: 'h1', indent: 1 }, - { type: 'Text', content: 'Hello World!', indent: 2 }, + { type: 'Tag', content: 'h1', indent: 1, line: 2, column: 3 }, + { type: 'Text', content: 'Hello World!', indent: 2, line: 2, column: 7 }, - { type: 'Markdown', content: 'This is content', indent: 1 }, + { type: 'Markdown', content: 'This is content', indent: 1, line: 3, column: 3 }, - { type: 'Tag', content: '', indent: 1 }, - { type: 'Markdown', content: 'This is more content', indent: 2 }, - { type: 'Tag', content: 'a', indent: 2 }, - { type: 'Attribute', content: "href='http://example.com'", indent: 3 }, - { type: 'Text', content: 'Click here', indent: 3 }, + { type: 'Tag', content: '', indent: 1, line: 4, column: 3 }, + { type: 'Markdown', content: 'This is more content', indent: 2, line: 5, column: 5 }, + { type: 'Tag', content: 'a', indent: 2, line: 6, column: 5 }, + { type: 'Attribute', content: "href='http://example.com'", indent: 3, line: 6, column: 8 }, + { type: 'Text', content: 'Click here', indent: 3, line: 6, column: 35 }, - { type: 'Tag', content: 'footer', indent: 0 }, - { type: 'Text', content: 'Goodnight Moon.', indent: 1 } + { type: 'Tag', content: 'footer', indent: 0, line: 7, column: 1 }, + { type: 'Text', content: 'Goodnight Moon.', indent: 1, line: 7, column: 9 } ] const ast = new Parser(tokens).ast() diff --git a/test/slashdown.test.ts b/test/slashdown.test.ts index 1144739..fb3b88e 100644 --- a/test/slashdown.test.ts +++ b/test/slashdown.test.ts @@ -54,7 +54,7 @@ describe("renderers", ()=> { test("JSONRenderer produces valid JSON", () => { const renderer = JSONRenderer; const slashdown = new Slashdown({src, renderer}) - const expected = '[{"type":"Tag","tagName":"div","children":[{"type":"Text","content":"Hello World!"}],"classes":["container"]}]'; + const expected = '[{"type":"Tag","tagName":"div","children":[{"type":"Text","content":"Hello World!","position":{"start":{"line":1,"column":14},"end":{"line":1,"column":14}}}],"classes":["container"],"position":{"start":{"line":1,"column":1},"end":{"line":1,"column":14}}}]'; expect( slashdown.process() ).toBe( expected ) expect( JSON.parse( slashdown.process() )).toStrictEqual( JSON.parse(expected) ) @@ -87,7 +87,7 @@ describe("shorthand", () => { renderer: JSONRenderer }); const rendered = sd`/ .container = Hello World!` - const expected = '[{"type":"Tag","tagName":"div","children":[{"type":"Text","content":"Hello World!"}],"classes":["container"]}]'; + const expected = '[{"type":"Tag","tagName":"div","children":[{"type":"Text","content":"Hello World!","position":{"start":{"line":1,"column":14},"end":{"line":1,"column":14}}}],"classes":["container"],"position":{"start":{"line":1,"column":1},"end":{"line":1,"column":14}}}]'; expect( rendered ).toBe( expected ) }) }) \ No newline at end of file diff --git a/test/syntax.test.ts b/test/syntax.test.ts index d861ef4..cad9391 100644 --- a/test/syntax.test.ts +++ b/test/syntax.test.ts @@ -48,10 +48,10 @@ test("codefence", () => { ` const tokens: SD.Token[] = [ - { type: "Tag", content: "", indent: 0 }, - { type: "Class", content: "container", indent: 0 }, - { type: "Markdown", content: "# This is a codefence", indent: 2 }, - { type: "CodeFence", content: "```sd\n/ this should be verbatim\n```", indent: 2 }, + { type: "Tag", content: "", indent: 0, line: 1, column: 1 }, + { type: "Class", content: "container", indent: 0, line: 1, column: 3 }, + { type: "Markdown", content: "# This is a codefence", indent: 2, line: 3, column: 3, endLine: 4, endColumn: 1 }, + { type: "CodeFence", content: "```sd\n/ this should be verbatim\n```", indent: 2, line: 5, column: 3, endLine: 7, endColumn: 6 }, ]; const ast: SD.Node[] = [ @@ -59,9 +59,10 @@ test("codefence", () => { tagName: "div", classes: ["container"], children: [ - { type: "Markdown", content: "# This is a codefence" }, - { type: "Markdown", content: "```sd\n/ this should be verbatim\n```" }, - ] + { type: "Markdown", content: "# This is a codefence", position: { start: { line: 3, column: 3 }, end: { line: 4, column: 1 } } }, + { type: "Markdown", content: "```sd\n/ this should be verbatim\n```", position: { start: { line: 5, column: 3 }, end: { line: 7, column: 6 } } }, + ], + position: { start: { line: 1, column: 1 }, end: { line: 7, column: 6 } } } ] @@ -78,14 +79,14 @@ describe("syntax combos", () => { ` const tokens: SD.Token[] = [ - { type: "Tag", content: "footer", indent: 0 }, - { type: "Class", content: "flex", indent: 0 }, - { type: "Class", content: "justify-between", indent: 0 }, - { type: "Markdown", content: "Made with ❤️ in slashdown", indent: 2 }, - { type: "Tag", content: "a", indent: 2 }, - { type: "Attribute", content: 'href="https://miniware.team?ref=slashdown"', indent: 2 }, - { type: "Attribute", content: 'target="_blank"', indent: 2 }, - { type: "Text", content: "by Miniware", indent: 2 }, + { type: "Tag", content: "footer", indent: 0, line: 1, column: 1 }, + { type: "Class", content: "flex", indent: 0, line: 1, column: 9 }, + { type: "Class", content: "justify-between", indent: 0, line: 1, column: 15 }, + { type: "Markdown", content: "Made with ❤️ in slashdown", indent: 2, line: 2, column: 3, endLine: 2, endColumn: 28 }, + { type: "Tag", content: "a", indent: 2, line: 3, column: 3 }, + { type: "Attribute", content: 'href="https://miniware.team?ref=slashdown"', indent: 2, line: 3, column: 6 }, + { type: "Attribute", content: 'target="_blank"', indent: 2, line: 3, column: 49 }, + { type: "Text", content: "by Miniware", indent: 2, line: 3, column: 65 }, ]; match( source, tokens ) @@ -104,14 +105,14 @@ describe("htmx & tailwind", () => { ` const tokens: SD.Token[] = [ - { type: "Tag", content: "", indent: 0 }, - { type: "Id", content: "roll-result", indent: 0 }, - { type: "Tag", content: "button", indent: 0 }, - { type: "Text", content: "Click me", indent: 0 }, - { type: "Attribute", content: 'hx-post="/api/roll?sides=6"', indent: 0 }, - { type: "Attribute", content: 'hx-trigger="click"', indent: 0 }, - { type: "Attribute", content: 'hx-target="#roll-result"', indent: 0 }, - { type: "Attribute", content: 'class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"', indent: 0 }, + { type: "Tag", content: "", indent: 0, line: 1, column: 1 }, + { type: "Id", content: "roll-result", indent: 0, line: 1, column: 3 }, + { type: "Tag", content: "button", indent: 0, line: 2, column: 1 }, + { type: "Text", content: "Click me", indent: 0, line: 2, column: 9 }, + { type: "Attribute", content: 'hx-post="/api/roll?sides=6"', indent: 0, line: 3, column: 1 }, + { type: "Attribute", content: 'hx-trigger="click"', indent: 0, line: 4, column: 1 }, + { type: "Attribute", content: 'hx-target="#roll-result"', indent: 0, line: 5, column: 1 }, + { type: "Attribute", content: 'class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"', indent: 0, line: 6, column: 1 }, ]; const ast: SD.Node[] = [ @@ -119,7 +120,8 @@ describe("htmx & tailwind", () => { type: "Tag", tagName: "div", ids: ["roll-result"], - children: [] + children: [], + position: { start: { line: 1, column: 1 }, end: { line: 1, column: 15 } } }, { type: "Tag", @@ -133,9 +135,11 @@ describe("htmx & tailwind", () => { children: [ { type: "Text", - content: "Click me" + content: "Click me", + position: { start: { line: 2, column: 11 }, end: { line: 2, column: 19 } } } - ] + ], + position: { start: { line: 2, column: 1 }, end: { line: 6, column: 89 } } } ] From 3a7a6f74af627b04158c68e697682e9ad41d201a Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 16 Nov 2025 03:54:14 +0000 Subject: [PATCH 02/12] Add package-lock.json --- package-lock.json | 2197 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2197 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..8a1bc99 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2197 @@ +{ + "name": "slashdown", + "version": "0.0.5", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "slashdown", + "version": "0.0.5", + "license": "MIT", + "dependencies": { + "micromark": "^4.0.0", + "micromark-extension-gfm": "^3.0.0" + }, + "devDependencies": { + "@vitest/coverage-v8": "^0.34.4", + "typescript": "^5.0.2", + "vite": "^4.4.5", + "vitest": "^0.34.1" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "4.3.20", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", + "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai-subset": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.6.tgz", + "integrity": "sha512-m8lERkkQj+uek18hXOZuec3W/fCRTrU4hrnXjH3qhHy96ytuPaPiWGgu7sJb7tZxZonO75vYAjCvpe/e4VUwRw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/chai": "<5.2.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-0.34.6.tgz", + "integrity": "sha512-fivy/OK2d/EsJFoEoxHFEnNGTg+MmdZBAVK9Ka4qhXR2K3J0DS08vcGVwzDtXSuUMabLv4KtPcpSKkcMXFDViw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.1", + "@bcoe/v8-coverage": "^0.2.3", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.1.5", + "magic-string": "^0.30.1", + "picocolors": "^1.0.0", + "std-env": "^3.3.3", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": ">=0.32.0 <1" + } + }, + "node_modules/@vitest/expect": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", + "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", + "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "0.34.6", + "p-limit": "^4.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", + "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.1", + "pathe": "^1.1.1", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", + "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^2.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", + "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/local-pkg": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", + "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, + "node_modules/mlly/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/pkg-types/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", + "dev": true, + "license": "MIT", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/strip-literal": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", + "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", + "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/vite": { + "version": "4.5.14", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz", + "integrity": "sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", + "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "mlly": "^1.4.0", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", + "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^4.3.5", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "@vitest/expect": "0.34.6", + "@vitest/runner": "0.34.6", + "@vitest/snapshot": "0.34.6", + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "acorn": "^8.9.0", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", + "chai": "^4.3.10", + "debug": "^4.3.4", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.1", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.3.3", + "strip-literal": "^1.0.1", + "tinybench": "^2.5.0", + "tinypool": "^0.7.0", + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", + "vite-node": "0.34.6", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@vitest/browser": "*", + "@vitest/ui": "*", + "happy-dom": "*", + "jsdom": "*", + "playwright": "*", + "safaridriver": "*", + "webdriverio": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "playwright": { + "optional": true + }, + "safaridriver": { + "optional": true + }, + "webdriverio": { + "optional": true + } + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} From 7514c7deb66fc1c99d3be9a157f7dabdf9dffbd6 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 16 Nov 2025 03:56:08 +0000 Subject: [PATCH 03/12] Remove package-lock.json (project uses bun) --- package-lock.json | 2197 --------------------------------------------- 1 file changed, 2197 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 8a1bc99..0000000 --- a/package-lock.json +++ /dev/null @@ -1,2197 +0,0 @@ -{ - "name": "slashdown", - "version": "0.0.5", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "slashdown", - "version": "0.0.5", - "license": "MIT", - "dependencies": { - "micromark": "^4.0.0", - "micromark-extension-gfm": "^3.0.0" - }, - "devDependencies": { - "@vitest/coverage-v8": "^0.34.4", - "typescript": "^5.0.2", - "vite": "^4.4.5", - "vitest": "^0.34.1" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/chai": { - "version": "4.3.20", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", - "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/chai-subset": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.6.tgz", - "integrity": "sha512-m8lERkkQj+uek18hXOZuec3W/fCRTrU4hrnXjH3qhHy96ytuPaPiWGgu7sJb7tZxZonO75vYAjCvpe/e4VUwRw==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/chai": "<5.2.0" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "24.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", - "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@vitest/coverage-v8": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-0.34.6.tgz", - "integrity": "sha512-fivy/OK2d/EsJFoEoxHFEnNGTg+MmdZBAVK9Ka4qhXR2K3J0DS08vcGVwzDtXSuUMabLv4KtPcpSKkcMXFDViw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.1", - "@bcoe/v8-coverage": "^0.2.3", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^4.0.1", - "istanbul-reports": "^3.1.5", - "magic-string": "^0.30.1", - "picocolors": "^1.0.0", - "std-env": "^3.3.3", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "vitest": ">=0.32.0 <1" - } - }, - "node_modules/@vitest/expect": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", - "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "0.34.6", - "@vitest/utils": "0.34.6", - "chai": "^4.3.10" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", - "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "0.34.6", - "p-limit": "^4.0.0", - "pathe": "^1.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", - "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "magic-string": "^0.30.1", - "pathe": "^1.1.1", - "pretty-format": "^29.5.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", - "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyspy": "^2.1.1" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", - "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "diff-sequences": "^29.4.3", - "loupe": "^2.3.6", - "pretty-format": "^29.5.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/chai": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", - "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/confbox": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", - "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decode-named-character-reference": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", - "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", - "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/local-pkg": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", - "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "license": "MIT", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mlly": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", - "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.15.0", - "pathe": "^2.0.3", - "pkg-types": "^1.3.1", - "ufo": "^1.6.1" - } - }, - "node_modules/mlly/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^1.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/pkg-types": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", - "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "confbox": "^0.1.8", - "mlly": "^1.7.4", - "pathe": "^2.0.1" - } - }, - "node_modules/pkg-types/node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, - "node_modules/rollup": { - "version": "3.29.5", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", - "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", - "dev": true, - "license": "MIT", - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "dev": true, - "license": "MIT" - }, - "node_modules/strip-literal": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", - "integrity": "sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinypool": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.7.0.tgz", - "integrity": "sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", - "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ufo": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", - "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", - "dev": true, - "license": "MIT" - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "license": "MIT" - }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/vite": { - "version": "4.5.14", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz", - "integrity": "sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-node": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", - "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.4", - "mlly": "^1.4.0", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0-0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": ">=v14.18.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vitest": { - "version": "0.34.6", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", - "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/chai": "^4.3.5", - "@types/chai-subset": "^1.3.3", - "@types/node": "*", - "@vitest/expect": "0.34.6", - "@vitest/runner": "0.34.6", - "@vitest/snapshot": "0.34.6", - "@vitest/spy": "0.34.6", - "@vitest/utils": "0.34.6", - "acorn": "^8.9.0", - "acorn-walk": "^8.2.0", - "cac": "^6.7.14", - "chai": "^4.3.10", - "debug": "^4.3.4", - "local-pkg": "^0.4.3", - "magic-string": "^0.30.1", - "pathe": "^1.1.1", - "picocolors": "^1.0.0", - "std-env": "^3.3.3", - "strip-literal": "^1.0.1", - "tinybench": "^2.5.0", - "tinypool": "^0.7.0", - "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", - "vite-node": "0.34.6", - "why-is-node-running": "^2.2.2" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": ">=v14.18.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@vitest/browser": "*", - "@vitest/ui": "*", - "happy-dom": "*", - "jsdom": "*", - "playwright": "*", - "safaridriver": "*", - "webdriverio": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - }, - "playwright": { - "optional": true - }, - "safaridriver": { - "optional": true - }, - "webdriverio": { - "optional": true - } - } - }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/yocto-queue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", - "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} From 8821dba616258aa6a352547a1e9930601df4dccf Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 16 Nov 2025 04:34:21 +0000 Subject: [PATCH 04/12] Add unified ecosystem integration documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create EXAMPLES.md and ARCHITECTURE.md to design the integration of SlashDown with the unified/remark/mdast ecosystem. Key design decisions: - Hybrid AST (slast): SlashDown nodes contain mdast children - Replace Markdown/Text nodes with proper mdast nodes - Configurable markdown handler for different parsers - Support for slashdown ↔ HTML, markdown, and other formats - Plugin-compatible architecture using unified processors This sets the foundation for v1.0.0 with breaking AST changes and full unified ecosystem compatibility. --- ARCHITECTURE.md | 561 ++++++++++++++++++++++++++++++++++++++++++++++++ EXAMPLES.md | 377 ++++++++++++++++++++++++++++++++ 2 files changed, 938 insertions(+) create mode 100644 ARCHITECTURE.md create mode 100644 EXAMPLES.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..6c04ee5 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,561 @@ +# SlashDown + Unified Integration Architecture + +This document outlines the technical architecture for integrating SlashDown with the unified ecosystem. + +## Table of Contents + +- [Overview](#overview) +- [Package Structure](#package-structure) +- [AST Structure (slast)](#ast-structure-slast) +- [Migration Strategy](#migration-strategy) +- [Implementation Plan](#implementation-plan) + +--- + +## Overview + +### Current Architecture + +``` +Input String + ↓ +[Lexer] → Tokens + ↓ +[Parser] → AST (with Markdown as strings) + ↓ +[Renderer] → HTML +``` + +### Proposed Architecture + +``` +Input String + ↓ +[Lexer] → Tokens + ↓ +[Parser] → slast (SlashDown nodes) + ↓ +[Markdown Handler] → Parse markdown strings → mdast nodes + ↓ +Hybrid slast tree (with mdast children) + ↓ +[Compiler/Transformer] → Output (HTML, markdown, etc.) +``` + +--- + +## Package Structure + +### Monorepo vs Single Package + +**Recommendation: Start with single package, split later** + +``` +slashdown/ +├── src/ +│ ├── lexer.ts # Tokenization (exists) +│ ├── parser.ts # Token → slast (modified) +│ ├── markdown-handler.ts # Parse markdown → mdast (new) +│ ├── processors/ # Unified processors (new) +│ │ ├── parse.ts # slashdown-parse plugin +│ │ ├── stringify.ts # slashdown-stringify plugin +│ │ └── to-html.ts # slashdown-to-html compiler +│ ├── transforms/ # Utility transforms (new) +│ │ ├── slast-to-hast.ts +│ │ ├── slast-to-mdast.ts +│ │ └── mdast-to-slast.ts +│ └── types.d.ts # Type definitions (modified) +``` + +### Future: Separate Packages (like remark) + +``` +- slashdown # Main package (unified + parse + stringify) +- slashdown-parse # Parser only +- slashdown-stringify # Compiler only +- slashdown-cli # CLI tool +- slashdown-util-* # Utilities for slast manipulation +``` + +--- + +## AST Structure (slast) + +### Hybrid AST Approach + +**slast** = SlashDown AST that **contains** mdast nodes + +```typescript +// SlashDown-specific nodes +type SlashDownTag = { + type: 'slashdownTag' // Distinguishable from HTML tags + tagName: string + attributes?: Record + classes?: string[] + ids?: string[] + children: (SlashDownTag | MdastNode)[] // ✅ Can contain mdast! + position?: Position + data?: any +} + +// No more "Markdown" or "Text" nodes! +// Instead, markdown content becomes mdast nodes directly: +// - heading, paragraph, list, emphasis, strong, code, etc. +``` + +### Type Definitions + +```typescript +// types.d.ts +import type { Node as UnistNode, Position } from 'unist' +import type { Content as MdastContent } from 'mdast' + +export declare namespace Slast { + // Base node extends unist + interface Node extends UnistNode { + type: string + position?: Position + data?: any + } + + // SlashDown Tag node + interface Tag extends Node { + type: 'slashdownTag' + tagName: string + attributes?: Record + classes?: string[] + ids?: string[] + children: (Tag | MdastContent)[] // Hybrid! + } + + // Root node (like mdast Root) + interface Root extends Node { + type: 'root' + children: (Tag | MdastContent)[] + } + + // Handler configuration + interface MarkdownHandlerOptions { + parser?: 'remark-parse' | Function + plugins?: Array + options?: any + } +} +``` + +### Example AST + +**Input:** +``` +/article .prose + # Hello World + + This is **important**. + + /button #cta + Click me +``` + +**Current AST (❌ Bad):** +```json +[{ + "type": "Tag", + "tagName": "article", + "classes": ["prose"], + "children": [ + { + "type": "Markdown", + "content": "# Hello World\n\nThis is **important**." + }, + { + "type": "Tag", + "tagName": "button", + "ids": ["cta"], + "children": [ + { "type": "Text", "content": "Click me" } + ] + } + ] +}] +``` + +**New AST (✅ Good - Hybrid slast/mdast):** +```json +{ + "type": "root", + "children": [{ + "type": "slashdownTag", + "tagName": "article", + "classes": ["prose"], + "children": [ + { + "type": "heading", + "depth": 1, + "children": [ + { "type": "text", "value": "Hello World" } + ] + }, + { + "type": "paragraph", + "children": [ + { "type": "text", "value": "This is " }, + { + "type": "strong", + "children": [ + { "type": "text", "value": "important" } + ] + }, + { "type": "text", "value": "." } + ] + }, + { + "type": "slashdownTag", + "tagName": "button", + "ids": ["cta"], + "children": [ + { "type": "text", "value": "Click me" } + ] + } + ] + }] +} +``` + +--- + +## Migration Strategy + +### Phase 1: Add Hybrid AST Support (Breaking Change) + +**Version: 1.0.0** + +1. Modify parser to use markdown handler +2. Replace `Markdown` and `Text` nodes with mdast nodes +3. Update renderers to handle mdast nodes +4. Update all tests + +**Breaking changes:** +- AST structure changes completely +- `node.type === "Markdown"` no longer works +- Custom renderers need updates + +**Migration guide for users:** +```javascript +// Before (v0.x) +if (node.type === 'Markdown') { + console.log(node.content) +} + +// After (v1.x) +import { visit } from 'unist-util-visit' + +visit(tree, 'paragraph', (node) => { + console.log(node) // Now it's an mdast paragraph +}) +``` + +### Phase 2: Add Unified Processors + +**Version: 1.1.0** + +1. Create `slashdown-parse` plugin +2. Create `slashdown-stringify` plugin +3. Create `slashdown-to-html` compiler +4. Maintain backwards compatibility with existing API + +**Non-breaking:** Template literal API stays the same + +### Phase 3: Extract Packages + +**Version: 2.0.0** + +1. Split into separate packages +2. Create plugin ecosystem +3. Create CLI tool + +--- + +## Implementation Plan + +### Step 1: Add Dependencies + +```bash +bun add unified mdast-util-from-markdown mdast-util-to-markdown +bun add -d @types/mdast @types/unist +``` + +### Step 2: Create Markdown Handler + +**File:** `src/markdown-handler.ts` + +```typescript +import { fromMarkdown } from 'mdast-util-from-markdown' +import { gfm } from 'micromark-extension-gfm' +import { gfmFromMarkdown } from 'mdast-util-gfm' +import type { Root } from 'mdast' +import type { SD } from './types' + +export interface MarkdownHandlerOptions { + plugins?: any[] + extensions?: any[] +} + +export class MarkdownHandler { + private options: MarkdownHandlerOptions + + constructor(options: MarkdownHandlerOptions = {}) { + this.options = options + } + + /** + * Parse markdown string to mdast nodes + */ + parse(markdown: string, position?: SD.Position): Root { + const tree = fromMarkdown(markdown, { + extensions: [gfm(), ...(this.options.extensions || [])], + mdastExtensions: [gfmFromMarkdown(), ...(this.options.plugins || [])] + }) + + // Attach position if provided + if (position) { + tree.position = position + } + + return tree + } +} +``` + +### Step 3: Modify Parser + +**File:** `src/parser.ts` + +```typescript +import { MarkdownHandler } from './markdown-handler' +import type { Content as MdastContent } from 'mdast' + +export class Parser { + private markdownHandler: MarkdownHandler + + constructor( + tokens: SD.Token[] = [], + markdownOptions?: MarkdownHandlerOptions + ) { + this.tokens = tokens + this.tree = [] + this.cursor = 0 + this.markdownHandler = new MarkdownHandler(markdownOptions) + } + + private parseMarkdown(token: SD.Token): MdastContent[] { + const position = this.createPosition(token) + const mdast = this.markdownHandler.parse(token.content, position) + + // Return the children of the root node + // (we don't want the root wrapper) + return mdast.children + } + + private parseTag(startTag: SD.Token): SD.TagNode { + // ... existing code ... + + switch (token.type) { + case "Markdown": + case "CodeFence": + // Parse markdown → mdast and add children + const mdastNodes = this.parseMarkdown(token) + tag.children.push(...mdastNodes) // Spread mdast nodes! + break + + // ... rest of code ... + } + } +} +``` + +### Step 4: Update Type Definitions + +**File:** `src/types.d.ts` + +```typescript +import type { Node as UnistNode, Position, Point } from 'unist' +import type { Content as MdastContent, Root as MdastRoot } from 'mdast' + +export declare namespace SD { + // Tokens (unchanged) + type Token = { + type: TokenType + content: string + indent: number + line: number + column: number + endLine?: number + endColumn?: number + } + + // Position types (from unist) + export type { Point, Position } + + // SlashDown-specific nodes + interface SlashDownTag extends UnistNode { + type: 'slashdownTag' + tagName: string + attributes?: Record + classes?: string[] + ids?: string[] + children: (SlashDownTag | MdastContent)[] + } + + interface Root extends UnistNode { + type: 'root' + children: (SlashDownTag | MdastContent)[] + } + + // Main AST type + type Ast = Root + + // Renderer interface (updated) + interface Renderer { + render(input: Ast): string + } +} +``` + +### Step 5: Update HTML Renderer + +**File:** `src/renderers/html.ts` + +```typescript +import { toHast } from 'mdast-util-to-hast' +import { toHtml } from 'hast-util-to-html' + +export default class HTMLRenderer implements SD.Renderer { + render(ast: SD.Ast): string { + return ast.children.map(this.renderNode).join('') + } + + private renderNode = (node: SD.SlashDownTag | MdastContent): string => { + if (node.type === 'slashdownTag') { + return this.renderTag(node) + } else { + // It's an mdast node - convert to hast then HTML + const hast = toHast(node) + return toHtml(hast) + } + } + + private renderTag(node: SD.SlashDownTag): string { + const attributes = this.unpackAttributes(node) + const children = node.children.map(this.renderNode).join('') + return `<${node.tagName}${attributes}>${children}` + } + + // ... rest of code ... +} +``` + +### Step 6: Create Unified Processor + +**File:** `src/processors/parse.ts` + +```typescript +import type { Processor } from 'unified' +import { Lexer } from '../lexer' +import { Parser } from '../parser' + +export interface SlashdownParseOptions { + mdast?: MarkdownHandlerOptions +} + +/** + * Plugin to parse SlashDown input into a slast tree + */ +export default function slashdownParse( + this: Processor, + options: SlashdownParseOptions = {} +): void { + const parser = (doc: string) => { + const lexer = new Lexer(doc) + const tokens = lexer.tokens() + const parser = new Parser(tokens, options.mdast) + return parser.ast() + } + + // Attach parser to unified processor + this.Parser = parser +} +``` + +--- + +## Benefits of This Architecture + +### ✅ Unified Ecosystem Integration +- Use `unist-util-visit` to traverse the tree +- Apply remark plugins to markdown content +- Use rehype for HTML transformations + +### ✅ Better Developer Experience +```javascript +import { visit } from 'unist-util-visit' + +// Find all headings (works seamlessly!) +visit(tree, 'heading', (node) => { + console.log(node.depth, node.children) +}) + +// Find all SlashDown tags +visit(tree, 'slashdownTag', (node) => { + console.log(node.tagName, node.classes) +}) +``` + +### ✅ Plugin Compatibility +```javascript +// Apply remark plugins to markdown content +unified() + .use(slashdownParse, { + mdast: { + plugins: [remarkGfm, remarkToc, remarkFootnotes] + } + }) +``` + +### ✅ JSX Support (Future) +```javascript +// Swap markdown handler for MDX handler +unified() + .use(slashdownParse, { + mdast: { + parser: remarkMdx // Parse as MDX instead! + } + }) +``` + +--- + +## Questions to Resolve + +1. **Node naming:** Should SlashDown tags be `slashdownTag` or just `tag`? + - **Recommendation:** `slashdownTag` to avoid conflicts with HTML `tag` nodes + +2. **Text nodes:** Should inline text (`= Hello`) become mdast `text` nodes or stay as custom nodes? + - **Recommendation:** Convert to mdast `text` nodes for consistency + +3. **Root node:** Should the AST be wrapped in a `root` node like mdast? + - **Recommendation:** Yes, for unified compatibility + +4. **Backwards compatibility:** Should we keep v0.x API alongside v1.x? + - **Recommendation:** No, clean break with migration guide + +5. **Package structure:** Monorepo or single package first? + - **Recommendation:** Single package (v1.x), split later (v2.x) + +--- + +## Next Steps + +1. **Review this architecture** - Does it align with your vision? +2. **Decide on breaking changes** - Are we ready for v1.0.0? +3. **Choose migration path** - Gradual or all-at-once? +4. **Start implementation** - Begin with markdown handler diff --git a/EXAMPLES.md b/EXAMPLES.md new file mode 100644 index 0000000..12f29aa --- /dev/null +++ b/EXAMPLES.md @@ -0,0 +1,377 @@ +# SlashDown Transformation Examples + +This document shows how SlashDown integrates with the unified ecosystem for various transformations. + +## Table of Contents + +- [slashdown → HTML](#slashdown--html) +- [slashdown → Markdown](#slashdown--markdown) +- [markdown → slashdown](#markdown--slashdown) +- [slashdown → slashdown (transforms)](#slashdown--slashdown-transforms) +- [Hybrid: slashdown + markdown → HTML](#hybrid-slashdown--markdown--html) + +--- + +## slashdown → HTML + +**Use case:** Compile SlashDown to HTML for web deployment + +```javascript +import { unified } from 'unified' +import slashdownParse from 'slashdown-parse' +import slashdownToHtml from 'slashdown-to-html' + +const file = await unified() + .use(slashdownParse) + .use(slashdownToHtml) + .process(` +/main .container + # Hello World + + /button #cta.primary + Click me! + `) + +console.log(String(file)) +``` + +**Output:** +```html +
+

Hello World

+ +
+``` + +--- + +## slashdown → Markdown + +**Use case:** Extract just the markdown content from SlashDown + +```javascript +import { unified } from 'unified' +import slashdownParse from 'slashdown-parse' +import slashdownToMarkdown from 'slashdown-to-markdown' + +const file = await unified() + .use(slashdownParse) + .use(slashdownToMarkdown) + .process(` +/article + # My Blog Post + + This is **important** content. + + /footer + Made with ❤️ + `) + +console.log(String(file)) +``` + +**Output:** +```markdown +# My Blog Post + +This is **important** content. + +Made with ❤️ +``` + +--- + +## markdown → slashdown + +**Use case:** Wrap existing markdown in SlashDown structure + +```javascript +import { unified } from 'unified' +import remarkParse from 'remark-parse' +import remarkToSlashdown from 'remark-to-slashdown' +import slashdownStringify from 'slashdown-stringify' + +const file = await unified() + .use(remarkParse) + .use(remarkToSlashdown, { + wrapper: { tag: 'article', classes: ['prose'] } + }) + .use(slashdownStringify) + .process(` +# Hello World + +This is markdown content. + `) + +console.log(String(file)) +``` + +**Output:** +``` +/article .prose + # Hello World + + This is markdown content. +``` + +--- + +## slashdown → slashdown (transforms) + +**Use case:** Transform SlashDown AST with plugins + +```javascript +import { unified } from 'unified' +import slashdownParse from 'slashdown-parse' +import slashdownStringify from 'slashdown-stringify' +import { visit } from 'unist-util-visit' + +// Custom plugin to add ARIA labels to buttons +function addAriaLabels() { + return (tree) => { + visit(tree, 'Tag', (node) => { + if (node.tagName === 'button' && !node.attributes?.['aria-label']) { + node.attributes = node.attributes || {} + node.attributes['aria-label'] = 'Interactive button' + } + }) + } +} + +const file = await unified() + .use(slashdownParse) + .use(addAriaLabels) + .use(slashdownStringify) + .process(` +/button #submit + Submit + `) + +console.log(String(file)) +``` + +**Output:** +``` +/button #submit aria-label="Interactive button" + Submit +``` + +--- + +## Hybrid: slashdown + markdown → HTML + +**Use case:** Process markdown within SlashDown using remark plugins + +```javascript +import { unified } from 'unified' +import slashdownParse from 'slashdown-parse' +import slashdownToHtml from 'slashdown-to-html' +import remarkGfm from 'remark-gfm' +import remarkEmoji from 'remark-emoji' + +const file = await unified() + .use(slashdownParse, { + // Configure how markdown content is processed + mdast: { + plugins: [ + remarkGfm, // GitHub Flavored Markdown + remarkEmoji // :emoji: syntax + ] + } + }) + .use(slashdownToHtml) + .process(` +/article .prose + # Task List :rocket: + + - [x] Implement parser + - [ ] Add tests + - [ ] Write docs + + /footer + Made with :heart: + `) + +console.log(String(file)) +``` + +**Output:** +```html +
+

Task List 🚀

+
    +
  • Implement parser
  • +
  • Add tests
  • +
  • Write docs
  • +
+
Made with ❤️
+
+``` + +--- + +## Advanced: Custom Content Handlers + +**Use case:** Handle different content types (markdown, JSX, templates) + +```javascript +import { unified } from 'unified' +import slashdownParse from 'slashdown-parse' +import slashdownToHtml from 'slashdown-to-html' +import remarkParse from 'remark-parse' +import remarkMdx from 'remark-mdx' + +const file = await unified() + .use(slashdownParse, { + // Different handlers for different scenarios + handlers: { + // Default: parse markdown content + markdown: remarkParse, + + // For .mdx files: parse as MDX + mdx: () => unified().use(remarkParse).use(remarkMdx), + + // Custom: parse as template strings + template: customTemplateParser, + }, + + // Auto-detect based on file extension or content + detectHandler: (content, file) => { + if (file.extname === '.mdx') return 'mdx' + if (content.includes('{{')) return 'template' + return 'markdown' + } + }) + .use(slashdownToHtml) + .process(content) +``` + +--- + +## Template Literal API (Current) + +For backwards compatibility and convenience: + +```javascript +import { createSlashdown } from 'slashdown' + +// Simple template literal (existing API) +const sd = createSlashdown() +const html = sd` + /main .container + # Hello World +` + +// With unified processor (new API) +import { unified } from 'unified' +import slashdownParse from 'slashdown-parse' +import remarkGfm from 'remark-gfm' +import slashdownToHtml from 'slashdown-to-html' + +const sdProcessor = createSlashdown({ + processor: unified() + .use(slashdownParse, { + mdast: { plugins: [remarkGfm] } + }) + .use(slashdownToHtml) +}) + +const html = sdProcessor` + /article + # GitHub Flavored Markdown + + | Feature | Supported | + |---------|-----------| + | Tables | ✅ | + | Tasks | ✅ | +` +``` + +--- + +## Configuration Examples + +### Configurable Markdown Processing + +```javascript +import { unified } from 'unified' +import slashdownParse from 'slashdown-parse' +import slashdownStringify from 'slashdown-stringify' + +const processor = unified() + .use(slashdownParse, { + mdast: { + // Pass options to the markdown parser + parser: 'remark-parse', + options: { + commonmark: true // Use CommonMark instead of GFM + }, + + // Apply plugins to markdown content + plugins: [ + remarkGfm, + [remarkToc, { heading: 'contents' }], + remarkFootnotes + ] + } + }) + .use(slashdownStringify) +``` + +### Custom Node Types + +```javascript +// Extend SlashDown with custom node types +import { unified } from 'unified' +import slashdownParse from 'slashdown-parse' + +const processor = unified() + .use(slashdownParse, { + // Register custom tag handlers + customTags: { + 'component': (node) => { + // Transform custom tags into components + return { + type: 'Component', + name: node.attributes?.name, + props: node.attributes, + children: node.children + } + } + } + }) +``` + +--- + +## Comparison with Other Ecosystems + +### Remark Ecosystem +```javascript +// markdown → HTML +unified() + .use(remarkParse) // md → mdast + .use(remarkRehype) // mdast → hast + .use(rehypeStringify) // hast → html +``` + +### SlashDown Ecosystem +```javascript +// slashdown → HTML +unified() + .use(slashdownParse) // sd → slast (with mdast children) + .use(slashdownToHtml) // slast → html + +// slashdown → markdown +unified() + .use(slashdownParse) // sd → slast + .use(slashdownToMarkdown) // slast → md + +// slashdown ↔ rehype (for HTML transforms) +unified() + .use(slashdownParse) // sd → slast + .use(slashdownToHast) // slast → hast + .use(rehypePlugins) // transform hast + .use(hastToSlashdown) // hast → slast + .use(slashdownStringify) // slast → sd +``` From d0201f16ed1867f69216dbcf758c1352ef6c9f02 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 16 Nov 2025 04:59:11 +0000 Subject: [PATCH 05/12] Implement hybrid AST: SlashDown tags + mdast nodes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: Complete AST structure overhaul for unified ecosystem integration This is a major architectural change that makes SlashDown fully compatible with the unified/remark/mdast ecosystem by implementing a hybrid AST where SlashDown tags contain mdast nodes as children. ## Key Changes ### 1. Hybrid AST Structure - AST is now a Root node with children array (not a direct array) - SlashDown tags are now `slashdownTag` nodes (not `Tag`) - Markdown content is parsed into proper mdast nodes (heading, paragraph, list, etc.) - Inline text becomes mdast `text` nodes (not custom `Text` nodes) - Code fences become mdast `code` nodes with lang/meta/value ### 2. New Components - **MarkdownHandler**: Parses markdown strings into mdast nodes - Uses mdast-util-from-markdown with GFM support - Handles inline text, markdown blocks, and code fences - Preserves position information ### 3. Updated Type System - Import and extend unist Node types - `SlashDownTag`: Hybrid node containing mdast children - `Root`: Top-level node wrapping entire document - `MarkdownHandlerOptions`: Configuration for markdown parsing ### 4. Parser Updates - Integrates MarkdownHandler for parsing markdown content - Returns Root node instead of array - Spreads mdast nodes into children arrays - Maintains position tracking throughout ### 5. HTML Renderer Updates - Handles both slashdownTag and mdast nodes - Uses mdast-util-to-hast + hast-util-to-html for mdast rendering - Fixed attribute unpacking for boolean attributes ### 6. Test Updates - Added comprehensive hybrid-ast.test.ts with 9 new tests - Updated all existing tests for new AST structure - All 40 tests passing ✅ ## Migration Guide ### Before (v0.x): ```javascript { type: "Tag", tagName: "article", children: [ { type: "Markdown", content: "# Hello\n\nWorld" } ] } ``` ### After (v1.x): ```javascript { type: "root", children: [{ type: "slashdownTag", tagName: "article", children: [ { type: "heading", depth: 1, children: [{ type: "text", value: "Hello" }] }, { type: "paragraph", children: [{ type: "text", value: "World" }] } ] }] } ``` ## Benefits - ✅ Full unist/mdast compatibility - ✅ Use unist-util-visit for tree traversal - ✅ Apply remark plugins to markdown content - ✅ GFM support (tables, strikethrough, etc.) - ✅ Foundation for JSX/MDX support - ✅ Interoperable with rehype for HTML transforms ## Dependencies Added - mdast-util-from-markdown - mdast-util-to-markdown - mdast-util-to-hast - mdast-util-gfm - hast-util-to-html Version: 1.0.0-alpha --- bun.lockb | Bin 60407 -> 78883 bytes package.json | 7 ++ src/markdown-handler.ts | 97 ++++++++++++++++ src/parser.ts | 100 +++++++++++----- src/renderers/html.ts | 60 +++++----- src/types.d.ts | 85 ++++++++------ test/hybrid-ast.test.ts | 251 ++++++++++++++++++++++++++++++++++++++++ test/parser.test.ts | 62 +++++----- test/slashdown.test.ts | 4 +- test/syntax.test.ts | 33 ++++-- 10 files changed, 563 insertions(+), 136 deletions(-) create mode 100644 src/markdown-handler.ts create mode 100644 test/hybrid-ast.test.ts diff --git a/bun.lockb b/bun.lockb index b468ade8f5f207642053cc661414a8f2697fa26a..6ac0df34c217f76d38626f0c2ad9e632e9167cc1 100755 GIT binary patch delta 24194 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 delta 15336 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 VzBTec?Lyw1Xfs8&p~cHq{vSxU>-Ycw diff --git a/package.json b/package.json index ab20cbf..04a012e 100644 --- a/package.json +++ b/package.json @@ -13,12 +13,19 @@ "prepublishOnly": "npm run build" }, "devDependencies": { + "@types/hast": "^3.0.4", + "@types/mdast": "^4.0.4", "@vitest/coverage-v8": "^0.34.4", "typescript": "^5.0.2", "vite": "^4.4.5", "vitest": "^0.34.1" }, "dependencies": { + "hast-util-to-html": "^9.0.5", + "mdast-util-from-markdown": "^2.0.2", + "mdast-util-gfm": "3.0.0", + "mdast-util-to-hast": "^13.2.0", + "mdast-util-to-markdown": "^2.1.2", "micromark": "^4.0.0", "micromark-extension-gfm": "^3.0.0" } diff --git a/src/markdown-handler.ts b/src/markdown-handler.ts new file mode 100644 index 0000000..9badedb --- /dev/null +++ b/src/markdown-handler.ts @@ -0,0 +1,97 @@ +import { fromMarkdown } from 'mdast-util-from-markdown' +import { gfm } from 'micromark-extension-gfm' +import { gfmFromMarkdown } from 'mdast-util-gfm' +import type { Content as MdastContent } from 'mdast' +import type { SD } from './types' + +/** + * MarkdownHandler parses markdown strings into mdast nodes + * + * This allows SlashDown to have a hybrid AST where markdown content + * becomes proper mdast nodes instead of being stored as strings. + */ +export class MarkdownHandler { + private options: SD.MarkdownHandlerOptions + + constructor(options: SD.MarkdownHandlerOptions = {}) { + this.options = { + extensions: [gfm(), ...(options.extensions || [])], + mdastExtensions: [gfmFromMarkdown(), ...(options.mdastExtensions || [])] + } + } + + /** + * Parse markdown string to mdast nodes + * + * @param markdown - The markdown content to parse + * @param position - Optional position information from the token + * @returns Array of mdast content nodes + */ + parse(markdown: string, position?: SD.Position): MdastContent[] { + // Parse markdown to mdast tree + const tree = fromMarkdown(markdown, { + extensions: this.options.extensions, + mdastExtensions: this.options.mdastExtensions + }) + + // Attach position info if provided + if (position && tree.children.length > 0) { + // Set position on the first child to match the start of the markdown token + if (tree.children[0].position) { + tree.children[0].position.start = position.start + } + + // Set position on the last child to match the end of the markdown token + const lastChild = tree.children[tree.children.length - 1] + if (lastChild.position) { + lastChild.position.end = position.end + } + } + + // Return the children of the root node + // We don't want the root wrapper, just the content + return tree.children + } + + /** + * Parse inline text (from = syntax) to a text node + * + * @param text - The text content + * @param position - Optional position information + * @returns An mdast text node + */ + parseInlineText(text: string, position?: SD.Position): MdastContent { + return { + type: 'text', + value: text, + position + } + } + + /** + * Parse a code fence to an mdast code node + * + * @param content - The code fence content (with backticks and lang) + * @param position - Optional position information + * @returns An mdast code node + */ + parseCodeFence(content: string, position?: SD.Position): MdastContent { + // Extract language from ```lang + const lines = content.split('\n') + const firstLine = lines[0] + const langMatch = firstLine.match(/^```(\w+)?/) + const lang = langMatch?.[1] || null + + // Get the code content (everything after the first line and before the last ```) + const codeLines = lines.slice(1) + const code = codeLines.join('\n') + + return { + type: 'code', + lang, + meta: null, + value: code, + position + } + } +} diff --git a/src/parser.ts b/src/parser.ts index 2493e80..6b9caa9 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1,17 +1,27 @@ import type { SD } from "./types" +import type { Content as MdastContent } from 'mdast' +import { MarkdownHandler } from './markdown-handler' const INDENTATION_IMMUNE_TOKENS: Partial[] = ["Attribute", "Id", "Class", "Text"]; const isNonIndenting = ( tokenType: SD.TokenType ): boolean => INDENTATION_IMMUNE_TOKENS.includes( tokenType ) export class Parser { tokens: SD.Token[] - private tree: SD.Node[] + private root: SD.Root private cursor: number + private markdownHandler: MarkdownHandler - constructor( tokens: SD.Token[] = [] ) { + constructor( + tokens: SD.Token[] = [], + markdownOptions?: SD.MarkdownHandlerOptions + ) { this.tokens = tokens - this.tree = [] + this.root = { + type: 'root', + children: [] + } this.cursor = 0 + this.markdownHandler = new MarkdownHandler(markdownOptions) } private createPosition(startToken: SD.Token, endToken?: SD.Token): SD.Position { @@ -28,31 +38,45 @@ export class Parser { }; } - ast() { - if (this.tree.length) - return this.tree; - else { + ast(): SD.Ast { + if (this.root.children.length > 0) { + return this.root; + } else { return this.parse(); } } - parse( tokens: SD.Token[] = this.tokens ): any[] { + parse( tokens: SD.Token[] = this.tokens ): SD.Ast { // reset instance this.tokens = tokens; - this.tree = []; + this.root = { + type: 'root', + children: [] + }; + this.cursor = 0; + + // Collect all tokens for position tracking + const allTokens: SD.Token[] = [] // Top loop while (this.remaining()) { const token: SD.Token = this.consumeNext(); + allTokens.push(token) switch (token.type) { case "Tag": const tag = this.parseTag(token) - this.tree.push(tag); + this.root.children.push(tag); break; case "Markdown": - case "CodeFence": // CodeFences *are* markdown - this.tree.push(this.parseMarkdown(token)); + // Parse markdown into mdast nodes + const mdastNodes = this.parseMarkdown(token) + this.root.children.push(...mdastNodes); + break; + case "CodeFence": + // Parse code fence into mdast code node + const codeNode = this.parseCodeFence(token) + this.root.children.push(codeNode); break; // Top level items should only be Tags or Markdown @@ -62,7 +86,15 @@ export class Parser { } } - return this.tree; + // Set position on root node if we have tokens + if (allTokens.length > 0) { + this.root.position = this.createPosition( + allTokens[0], + allTokens[allTokens.length - 1] + ) + } + + return this.root; } private remaining(): boolean { @@ -79,15 +111,14 @@ export class Parser { return token; } - private parseTag(startTag: SD.Token): SD.TagNode { + private parseTag(startTag: SD.Token): SD.SlashDownTag { let tagName = startTag.content; // handle `/` shorthand - // TODO: Maybe move this to a rendering strategy or options object to set a "default" component tagName = tagName === "" ? "div" : tagName; - const tag: SD.TagNode = { - type: "Tag", + const tag: SD.SlashDownTag = { + type: "slashdownTag", tagName, children: [] }; @@ -104,8 +135,15 @@ export class Parser { switch (token.type) { case "Markdown": + // Parse markdown into mdast nodes and add as children + const mdastNodes = this.parseMarkdown(token) + tag.children.push(...mdastNodes); + break; + case "CodeFence": - tag.children.push(this.parseMarkdown(token)); + // Parse code fence into mdast code node + const codeNode = this.parseCodeFence(token) + tag.children.push(codeNode); break; case "Tag": @@ -138,11 +176,11 @@ export class Parser { break; case "Text": - const textNode: SD.TextNode = { - type: "Text", - content: token.content, - position: this.createPosition(token) - }; + // Parse inline text as mdast text node + const textNode = this.markdownHandler.parseInlineText( + token.content, + this.createPosition(token) + ) tag.children.push(textNode); break; } @@ -157,11 +195,13 @@ export class Parser { return tag; } - private parseMarkdown(token: SD.Token): SD.MarkdownNode { - return { - type: "Markdown", - content: token.content, - position: this.createPosition(token) - }; + private parseMarkdown(token: SD.Token): MdastContent[] { + const position = this.createPosition(token) + return this.markdownHandler.parse(token.content, position) + } + + private parseCodeFence(token: SD.Token): MdastContent { + const position = this.createPosition(token) + return this.markdownHandler.parseCodeFence(token.content, position) } -} \ No newline at end of file +} diff --git a/src/renderers/html.ts b/src/renderers/html.ts index 5369116..2ca47f5 100644 --- a/src/renderers/html.ts +++ b/src/renderers/html.ts @@ -1,47 +1,51 @@ import type { SD } from "../types"; -import {micromark} from 'micromark'; -import {gfm} from 'micromark-extension-gfm'; +import type { Content as MdastContent } from 'mdast' +import { toHast } from 'mdast-util-to-hast' +import { toHtml } from 'hast-util-to-html' export default class HTMLRenderer implements SD.Renderer { render(ast: SD.Ast): string { - return ast.map(this.renderNode).join(""); + return ast.children.map(this.renderNode).join(""); } - private renderNode = ( node: SD.Node ): string => { - switch (node.type) { - case "Tag": - return this.renderTag(node as SD.TagNode); - break; - case "Markdown": - return this.renderMarkdown(node as SD.MarkdownNode); - break; - case "Text": - return node.content; - break; - default: - throw new Error(`Unknown node type: ${node.type}`); + private renderNode = (node: SD.SlashDownTag | MdastContent): string => { + if (node.type === 'slashdownTag') { + return this.renderSlashDownTag(node); + } else { + // It's an mdast node - convert to hast then HTML + return this.renderMdastNode(node); } } - private renderMarkdown(node: SD.MarkdownNode): string { - return micromark( node.content, { - extensions: [gfm()], - }); - } - - private renderTag(node: SD.TagNode): string { - let attributes = this.unpackAttributes(node); + private renderSlashDownTag(node: SD.SlashDownTag): string { + const attributes = this.unpackAttributes(node); const children = node.children.map(this.renderNode).join(""); return `<${node.tagName}${attributes}>${children}`; } - private unpackAttributes(node: SD.TagNode): string { + private renderMdastNode(node: MdastContent): string { + // Convert mdast to hast (HTML AST) + const hast = toHast(node); + + // Convert hast to HTML string + if (!hast) return ''; + + return toHtml(hast); + } + + private unpackAttributes(node: SD.SlashDownTag): string { let attributes: string[] = [] if (node.ids) attributes.push(`id="${node.ids.join(" ")}"`); if (node.classes) attributes.push(`class="${node.classes.join(" ")}"`); - if (node.attributes) attributes = Object.entries(attributes) - .map(([key, value]) => `${key}="${value}"`); + if (node.attributes) { + attributes.push( + ...Object.entries(node.attributes).map(([key, value]) => { + if (value === true) return key; // Boolean attributes + return `${key}="${value}"`; + }) + ); + } return attributes.length ? " " + attributes.join(" ") : ""; } -} \ No newline at end of file +} diff --git a/src/types.d.ts b/src/types.d.ts index 3a70df6..f0de5dd 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,3 +1,6 @@ +import type { Node as UnistNode, Position, Point } from 'unist' +import type { Content as MdastContent, Root as MdastRoot } from 'mdast' + const TOKEN_TYPES = [ "Tag", "Attribute", @@ -7,7 +10,6 @@ const TOKEN_TYPES = [ "Markdown", "CodeFence" ] as const; -const NODE_TYPES = ["Tag", "Text", "Markdown"] as const; export declare namespace SD { // Tokens @@ -22,48 +24,63 @@ export declare namespace SD { endColumn?: number, } - // Unist-compatible position types - type Point = { - line: number, // 1-indexed line number - column: number, // 1-indexed column number - offset?: number, // 0-indexed character offset (optional) - } + // Re-export unist position types for convenience + export type { Point, Position } - type Position = { - start: Point, - end: Point, - } + // SlashDown-specific nodes - // Base Node type conforming to unist spec - type NodeType = typeof NODE_TYPES[number]; - type Node = { - type: NodeType, - position?: Position, // Optional position info (unist spec) - data?: any, // Optional ecosystem-specific data (unist spec) - [key: string]: any + /** + * SlashDown tag node (like
,