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