diff --git a/package.json b/package.json index d07f8c97a051649ab53105a0d059855474e97792..f1ecf3fb032a6e695c25e3d0a626f96351ef3490 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,9 @@ "license": "ISC", "devDependencies": { "@types/markdown-it": "^14.1.2", + "@types/markdown-it-attrs": "^4.1.3", + "@types/markdown-it-emoji": "^3.0.1", + "@types/markdown-it-footnote": "^3.0.4", "@types/node": "^22.10.10", "bootstrap": "5.3.6", "commander": "^14.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c7e3aa04c1718f8643dd6aa24e35b06b8abd3fc..5c719d9b200269af97455d32271b783747ae0689 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,15 @@ importers: '@types/markdown-it': specifier: ^14.1.2 version: 14.1.2 + '@types/markdown-it-attrs': + specifier: ^4.1.3 + version: 4.1.3 + '@types/markdown-it-emoji': + specifier: ^3.0.1 + version: 3.0.1 + '@types/markdown-it-footnote': + specifier: ^3.0.4 + version: 3.0.4 '@types/node': specifier: ^22.10.10 version: 22.15.19 @@ -336,6 +345,15 @@ packages: '@types/linkify-it@5.0.0': resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + '@types/markdown-it-attrs@4.1.3': + resolution: {integrity: sha512-1JsseFdHD6rQHsPcy4W3xx/whxvZ09Z+CqPpnOtrGtpmkFW07N11q7oM383//LtoKv54yn+HGnk6r4ZHUTHJVg==} + + '@types/markdown-it-emoji@3.0.1': + resolution: {integrity: sha512-cz1j8R35XivBqq9mwnsrP2fsz2yicLhB8+PDtuVkKOExwEdsVBNI+ROL3sbhtR5occRZ66vT0QnwFZCqdjf3pA==} + + '@types/markdown-it-footnote@3.0.4': + resolution: {integrity: sha512-XJ6n+v+2u+2gmYLSHcxyoNT/YrgrKvHuDJQlykFjuxCQCr86P2/fx1V6/0lcKxv5cSIlCaJ6sUcNS3zDI7I+LA==} + '@types/markdown-it@14.1.2': resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} @@ -848,6 +866,18 @@ snapshots: '@types/linkify-it@5.0.0': {} + '@types/markdown-it-attrs@4.1.3': + dependencies: + '@types/markdown-it': 14.1.2 + + '@types/markdown-it-emoji@3.0.1': + dependencies: + '@types/markdown-it': 14.1.2 + + '@types/markdown-it-footnote@3.0.4': + dependencies: + '@types/markdown-it': 14.1.2 + '@types/markdown-it@14.1.2': dependencies: '@types/linkify-it': 5.0.0 diff --git a/src/index.ts b/src/index.ts index 1c5a900355f014befc9d7451d81317aa8b1479dd..0eda5766128c3860c27748409fbee536dff6ddd4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -217,7 +217,7 @@ async function generateAllTranscriptPages( } async function generateTranscriptPage( - transcript, + transcript: { meta: any; html: string; ast: any }, outputDir: string, options: CliOptions, ) { diff --git a/src/lib/parsing.test.ts b/src/lib/parsing.test.ts index f7cacd83336e46e600146f1f2a54dcc26a65975f..a57c34bb6c9c813033eb04412e5673d28a7f8a7f 100644 --- a/src/lib/parsing.test.ts +++ b/src/lib/parsing.test.ts @@ -1,24 +1,5 @@ -import { expect, describe, it, test } from "vitest"; +import { describe, it } from "vitest"; import { parse } from "./parsing"; -import { writeFileSync } from "fs"; - -const exampleMarkdown = ` ---- -start: "xx" ---- - -TEST_MARKDOWN_BEFORE - -[ - Der FSR beschließt, X - ]{.resolution .fin money-granted="150,00" yes=6 no=0 abstention=1 result=Angenommen} - -TEST_MARKDOWN_AFTER - ---- -end: "yy" ---- -`.trim(); const fullExampleMarkdown = ` --- @@ -290,6 +271,6 @@ end: "17:36" describe("Parsing", () => { it("parses", () => { - const { meta, html } = parse(fullExampleMarkdown); + parse(fullExampleMarkdown); }); }); diff --git a/src/lib/parsing.ts b/src/lib/parsing.ts index 384cfb37ce5051bf0a4396944dc04d9870a1c190..b323207058aad8274ea79719565689bcb2f98de3 100644 --- a/src/lib/parsing.ts +++ b/src/lib/parsing.ts @@ -94,7 +94,7 @@ export function parseOld( })); } -function _endBlock(ast, start, level, close) { +function _endBlock(ast: Token[], start: number, level: number, close: string) { let end = start; for (end++; end < ast.length; end++) { const token = ast[end]; @@ -197,7 +197,7 @@ export function parse(markdown: string): ParseResults { } // First off, check metadata: - const { warnings, errors } = getMetadataProblems(data); + const { errors } = getMetadataProblems(data); if (errors.length > 0) { throw errors.join("\n"); } @@ -376,11 +376,19 @@ function extractHeaderMeta(token: Token): Map<string, string> { return new Map(token.attrs); } -function _extractMainClass(token: Token) { - return [...token.type.matchAll(/^container_(\S+)_open$/g)]?.[0]?.[1]; +function _extractMainClass(token: Token): string | undefined { + return token.type.match(/^container_(\S+)_open$/g)?.[1]; } -function _extractBase(tokens: Token[], mainClass?: string) { +function _extractBase( + tokens: Token[], + mainClass?: string, +): { + spanAttributes: Map<string, string>; + classes: Set<string>; + html: string; + text: string; +} { if (tokens.length < 1) { throw TypeError( "Parsing this requires an inline span with at least one child", @@ -389,7 +397,7 @@ function _extractBase(tokens: Token[], mainClass?: string) { const duplicateAttrs = tokens[0].attrs - ?.map(([k, v]) => k) + ?.map(([k, _v]) => k) .filter((k, i, a) => a.indexOf(k) !== i) ?? []; if (duplicateAttrs.length > 0) { throw TypeError( @@ -428,8 +436,16 @@ function _extractBase(tokens: Token[], mainClass?: string) { function tryExtractCards( tokens: Token[], - sharedState, - mainClass, + sharedState: { + nextResoNumbers: { + B: number; + F: number; + P: number; + }; + resolutions: Resolution[]; + data: FinishedTranscriptMeta; + }, + mainClass?: string, ): Token | undefined { let rendered: undefined | string = undefined; @@ -453,10 +469,10 @@ function tryExtractCards( other.match(/(^\d+)/)![1], ); - if (otherTranscriptNumber > sharedState.data.number) + if (otherTranscriptNumber > sharedState.data.number!) return true; - if (otherTranscriptNumber < sharedState.data.number) + if (otherTranscriptNumber < sharedState.data.number!) return false; const otherResolutionNumber = parseInt( @@ -490,7 +506,7 @@ function tryExtractCards( res.content = rendered; return res; } else { - const { spanAttributes, classes, html } = base; + const { spanAttributes, classes } = base; _assertEmpty(spanAttributes, "unknown card"); if ( !["warning", "Meinungsbild", "GO-Antrag"].some((mainClass) => @@ -503,7 +519,15 @@ function tryExtractCards( } } -function tryExtractResolution(base, date): Resolution | null { +function tryExtractResolution( + base: { + spanAttributes: Map<string, string>; + classes: Set<string>; + html: string; + text: string; + }, + date: string, +): Resolution | null { const { spanAttributes, classes, html, text } = base; if (!classes.delete("resolution")) { @@ -673,7 +697,12 @@ function tryExtractResolution(base, date): Resolution | null { }; } -function tryExtractNewTodo(base): Todo | null { +function tryExtractNewTodo(base: { + spanAttributes: Map<string, string>; + classes: Set<string>; + html: string; + text: string; +}): Todo | null { const { spanAttributes, classes, html, text } = base; if (!classes.delete("todo")) { diff --git a/src/lib/rendering.ts b/src/lib/rendering.ts index 9e63f5963d04539536b49c7ab1e3b9d4b9d65027..1af282e3a0d53a8e832c04c8d8a3a96b2bbe971a 100644 --- a/src/lib/rendering.ts +++ b/src/lib/rendering.ts @@ -1,8 +1,9 @@ import { FinishedTranscriptMeta, Resolution, Todo } from "./parsing"; import { Attendance } from "./attendance"; +import Token from "markdown-it/lib/token.mjs"; export function renderContainerToAlert(context: String, title?: String) { - return function (tokens, idx) { + return function (tokens: Token[], idx: number) { return tokens[idx].nesting === 1 ? `<div class="alert ${context}" role="alert"">\n${ title === undefined @@ -188,19 +189,19 @@ export function renderTranscriptPageHtml( <div class="col"> <b>Anwesend:</b> <ul> - ${meta.present.map((p) => "<li>" + p + "</li>").join("\n")} + ${meta.present.map((p: string) => "<li>" + p + "</li>").join("\n")} </ul> </div> <div class="col"> <b>Abwesend:</b> <ul> - ${meta.absent.map((p) => "<li>" + p + "</li>").join("\n")} + ${meta.absent.map((p: string) => "<li>" + p + "</li>").join("\n")} </ul> </div> <div class="col"> <b>Gäste:</b> <ul> - ${meta.guests.map((p) => "<li>" + p + "</li>").join("\n")} + ${meta.guests.map((p: string) => "<li>" + p + "</li>").join("\n")} </ul> </div> </div> @@ -445,7 +446,7 @@ function generateResolutionRowHtml( ? `<a href="../protokolle/${transcriptFileName}/#${resolution.number}">${resolution.number}</a>` : `${resolution.number}`; - let votes; + let votes: string; if (resolution.votes === undefined) { votes = ""; } else if ( diff --git a/test/single_transcript/fsr-sitzung-700-2024-07-22.md b/test/single_transcript/fsr-sitzung-700-2024-07-22.md index ad97c38ac0c69a965bcf1941e73d076cda07b230..e3e3fde6ac5448f6c1180db1047029da8344a78b 100644 --- a/test/single_transcript/fsr-sitzung-700-2024-07-22.md +++ b/test/single_transcript/fsr-sitzung-700-2024-07-22.md @@ -138,12 +138,12 @@ Der FSR beschließt, 700.2B aufzuheben. ]{.resolution yes=15 no=4 abstention=0 result=Angenommen revokes=700.2B modifies=700.2B} [ -Der FSR versucht beschluss 700.4B aufzuheben auf -]{.resolution yes=0 no=19 abstention=0 result=Abgelehnt revokes=700.4B} +Der FSR versucht beschluss 700.3B aufzuheben auf +]{.resolution yes=0 no=19 abstention=0 result=Abgelehnt revokes=700.3B} [ -Der FSR hebt beschluss 700.4B auf -]{.resolution yes=19 no=0 abstention=0 result=Angenommen revokes=700.4B} +Der FSR hebt beschluss 700.3B auf +]{.resolution yes=19 no=0 abstention=0 result=Angenommen revokes=700.3B} # Sonstiges {start="12:39"} diff --git a/test/sitzungen b/test/sitzungen index 949e022026129c1d8718fab752c1ff02dbca3c2c..1f1dbdfdfee3044e7921c0e57334a43493f298fd 160000 --- a/test/sitzungen +++ b/test/sitzungen @@ -1 +1 @@ -Subproject commit 949e022026129c1d8718fab752c1ff02dbca3c2c +Subproject commit 1f1dbdfdfee3044e7921c0e57334a43493f298fd