@kadal/prettier-plugin 0.0.0-stage → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/split.js ADDED
@@ -0,0 +1,151 @@
1
+ //#region src/split.ts
2
+ /**
3
+ * ─────────────────────────────────────────────────────────────────────────────
4
+ * CUTTING A DECK INTO PIECES, the engine's way
5
+ * ─────────────────────────────────────────────────────────────────────────────
6
+ *
7
+ * The same reading of the text as `@kadal/deck`'s compiler (packages/deck/src/compiler/split.ts,
8
+ * `cut`), kept here so the plugin installs without the engine: a `---` line starts a slide, a
9
+ * `----` line starts one beneath the last, the block after a separator is that slide's YAML when
10
+ * it reads as YAML and a `---` closes it, a bare ```yaml fence as the first thing in a body is
11
+ * "block frontmatter", and the fenced YAML at the top of the file is the headmatter. Fenced code
12
+ * is never cut. split.test.ts checks this file against the engine's on the showcase and on the
13
+ * tricky fixtures, piece for piece.
14
+ *
15
+ * Unlike the engine's, a piece here keeps the lines as written — the separator, the fences, the
16
+ * blank lines — because a formatter rebuilds the text from them.
17
+ * ─────────────────────────────────────────────────────────────────────────────
18
+ */
19
+ const HORIZONTAL = /^---\s*$/;
20
+ const VERTICAL = /^----+\s*$/;
21
+ const FRONTMATTER_LINE = /^\s*[A-Za-z_][\w.-]*\s*:(\s|$)/;
22
+ /** True when every non-empty line could be a YAML mapping line or a continuation (split.ts). */
23
+ function looksLikeYaml(lines) {
24
+ let any = false;
25
+ for (const line of lines) {
26
+ if (!line.trim()) continue;
27
+ if (/^\s+/.test(line) || /^\s*-\s/.test(line) || /^\s*#/.test(line)) continue;
28
+ if (!FRONTMATTER_LINE.test(line)) return false;
29
+ any = true;
30
+ }
31
+ return any;
32
+ }
33
+ /**
34
+ * Cut the text at separators (the engine's `cut`, line for line). The head piece is always first,
35
+ * possibly empty.
36
+ */
37
+ function cutDeck(text) {
38
+ const lines = text.split(/\r?\n/);
39
+ const pieces = [];
40
+ const blockAt = (from) => {
41
+ let k = from;
42
+ while (k < lines.length && !lines[k].trim()) k++;
43
+ const open = /^\s*(`{3,}|~{3,})ya?ml\s*$/.exec(lines[k] ?? "");
44
+ if (!open) return null;
45
+ const mark = open[1];
46
+ for (let c = k + 1; c < lines.length; c++) {
47
+ const close = /^\s*(`{3,}|~{3,})\s*$/.exec(lines[c]);
48
+ if (close && close[1][0] === mark[0] && close[1].length >= mark.length) return {
49
+ yaml: lines.slice(k + 1, c).join("\n"),
50
+ open: k,
51
+ close: c
52
+ };
53
+ }
54
+ return null;
55
+ };
56
+ const frontmatterAt = (from) => {
57
+ let close = -1;
58
+ for (let k = from; k < lines.length; k++) {
59
+ const l = lines[k];
60
+ if (HORIZONTAL.test(l)) {
61
+ close = k;
62
+ break;
63
+ }
64
+ if (VERTICAL.test(l)) return null;
65
+ }
66
+ if (close === -1) return null;
67
+ const block = lines.slice(from, close);
68
+ if (!looksLikeYaml(block)) return null;
69
+ return {
70
+ yaml: block.join("\n"),
71
+ next: close + 1
72
+ };
73
+ };
74
+ let i = 0;
75
+ let firstContent = 0;
76
+ while (firstContent < lines.length && !lines[firstContent].trim()) firstContent++;
77
+ const head = {
78
+ separator: null,
79
+ vertical: false,
80
+ frontmatter: null,
81
+ body: [],
82
+ line: 0
83
+ };
84
+ if (firstContent < lines.length && HORIZONTAL.test(lines[firstContent])) {
85
+ const fm = frontmatterAt(firstContent + 1);
86
+ if (fm) {
87
+ head.frontmatter = {
88
+ kind: "fence",
89
+ yaml: fm.yaml,
90
+ open: "---",
91
+ close: "---"
92
+ };
93
+ i = fm.next;
94
+ }
95
+ }
96
+ pieces.push(head);
97
+ let inFence = false;
98
+ let fence = "";
99
+ for (; i < lines.length; i++) {
100
+ const line = lines[i];
101
+ const fenceMatch = /^\s*(`{3,}|~{3,})/.exec(line);
102
+ if (fenceMatch) {
103
+ const mark = fenceMatch[1];
104
+ if (!inFence) {
105
+ inFence = true;
106
+ fence = mark;
107
+ } else if (mark[0] === fence[0] && mark.length >= fence.length) inFence = false;
108
+ }
109
+ if (!inFence && (HORIZONTAL.test(line) || VERTICAL.test(line))) {
110
+ const vertical = VERTICAL.test(line);
111
+ const fm = frontmatterAt(i + 1);
112
+ const block = fm ? null : blockAt(i + 1);
113
+ const piece = {
114
+ separator: line,
115
+ vertical,
116
+ frontmatter: null,
117
+ body: [],
118
+ line: i
119
+ };
120
+ if (fm) {
121
+ piece.frontmatter = {
122
+ kind: "fence",
123
+ yaml: fm.yaml,
124
+ open: "---",
125
+ close: "---"
126
+ };
127
+ i = fm.next - 1;
128
+ } else if (block) {
129
+ piece.frontmatter = {
130
+ kind: "block",
131
+ yaml: block.yaml,
132
+ open: lines[block.open],
133
+ close: lines[block.close]
134
+ };
135
+ i = block.close;
136
+ }
137
+ pieces.push(piece);
138
+ continue;
139
+ }
140
+ pieces[pieces.length - 1].body.push(line);
141
+ }
142
+ return pieces;
143
+ }
144
+ /** Whether a piece becomes a slide in the engine (split.ts: an empty head is not; an empty
145
+ * later piece is one only when it carries frontmatter). */
146
+ function isSlide(piece, index, frontmatterKeys) {
147
+ if (!!piece.body.join("\n").trim()) return true;
148
+ return index > 0 && frontmatterKeys > 0;
149
+ }
150
+ //#endregion
151
+ export { HORIZONTAL, VERTICAL, cutDeck, isSlide, looksLikeYaml };
package/package.json CHANGED
@@ -1,6 +1,75 @@
1
1
  {
2
2
  "name": "@kadal/prettier-plugin",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.4.0",
4
+ "description": "Prettier for Kadal Deck decks (deck.mdx): separators and frontmatter normalised, YAML formatted with its comments, and every slide's Markdown formatted, with code, notes, magic-move and ::slot:: sugar left exactly as written.",
5
+ "keywords": [
6
+ "prettier",
7
+ "prettier-plugin",
8
+ "kadal-deck",
9
+ "presentation",
10
+ "slides",
11
+ "mdx"
12
+ ],
13
+ "homepage": "https://deck.kadal.cc/docs/",
14
+ "funding": {
15
+ "type": "github",
16
+ "url": "https://github.com/sponsors/pmithunish"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/kadalcc/deck.git",
21
+ "directory": "packages/prettier-plugin"
22
+ },
23
+ "bugs": {
24
+ "url": "https://github.com/kadalcc/deck/issues"
25
+ },
26
+ "license": "AGPL-3.0-or-later",
27
+ "author": "Mithunish Prabhakaran <pmithunish@gmail.com>",
28
+ "type": "module",
29
+ "sideEffects": false,
30
+ "files": [
31
+ "dist",
32
+ "README.md",
33
+ "LICENSE"
34
+ ],
35
+ "main": "./dist/index.js",
36
+ "types": "./dist/index.d.ts",
37
+ "exports": {
38
+ ".": {
39
+ "types": "./dist/index.d.ts",
40
+ "import": "./dist/index.js",
41
+ "default": "./dist/index.js"
42
+ },
43
+ "./package.json": "./package.json"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public",
47
+ "provenance": true
48
+ },
49
+ "engines": {
50
+ "node": ">=20.19"
51
+ },
52
+ "scripts": {
53
+ "build": "tsdown",
54
+ "typecheck": "tsc --noEmit",
55
+ "lint": "oxlint src",
56
+ "test": "bun test",
57
+ "prepack": "tsdown"
58
+ },
59
+ "dependencies": {
60
+ "remark-gfm": "^4.0.1",
61
+ "remark-math": "^6.0.0",
62
+ "remark-mdx": "^3.1.1",
63
+ "remark-parse": "^11.0.0",
64
+ "unified": "^11.0.5",
65
+ "yaml": "^2.8.0"
66
+ },
67
+ "devDependencies": {
68
+ "@types/node": "^25.9.3",
69
+ "prettier": "^3.9.10",
70
+ "typescript": "^6.0.3"
71
+ },
72
+ "peerDependencies": {
73
+ "prettier": "^3.0.0"
74
+ }
75
+ }