@plurnk/plurnk-mimetypes-application-ipynb 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PossumTech Laboratories, LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # @plurnk/plurnk-mimetypes-application-ipynb
2
+
3
+ `application/x-ipynb+json` (Jupyter notebook) mimetype handler for the [plurnk](https://github.com/plurnk) ecosystem. Hand-rolled, no parser dependency.
4
+
5
+ ## install
6
+
7
+ ```
8
+ npm i @plurnk/plurnk-mimetypes-application-ipynb
9
+ ```
10
+
11
+ ## what it does
12
+
13
+ A `.ipynb` *is* JSON, but the JSON is the noise — a model reading a notebook wants the narrative and code as a reader sees them, not `{"cell_type":"code","source":[...]}`. So the load-bearing channel here is the **content channel** (SPEC §18):
14
+
15
+ - `content(content)` — the notebook projected to clean **reading markdown**: markdown cells verbatim, code cells fenced in the kernel language, text/stream/`text/plain`/error-traceback outputs folded in, images and other binary payloads dropped. This is also the **embed-source**, so a notebook's embedding reflects what it *says*, not its JSON envelope.
16
+ - `extractRaw(content)` — symbols that index into that same projection: markdown headings become `heading` symbols (outline-nesting by level, like text-markdown), each code cell becomes a `module` symbol spanning its fenced block (named `In[n]` by execution count). An outline of a notebook reads as its sections with their code cells nested underneath.
17
+ - `deepJson(content)` — the parsed notebook verbatim, so jsonpath/xpath reach `$.cells[*].cell_type`, `$.metadata.kernelspec.language`, etc.
18
+ - `extent` — the projection's line count. `validate` — strict JSON parse (a malformed notebook is a validation failure; every other channel degrades to empty rather than throwing).
19
+
20
+ References are deferred: a notebook's imports/calls are kernel-language code, and classifying them would mean embedding a per-kernel parser — out of scope for v1.
21
+
22
+ ## license
23
+
24
+ MIT.
@@ -0,0 +1,41 @@
1
+ import { BaseHandler } from "@plurnk/plurnk-mimetypes";
2
+ import type { HandlerContent, MimeSymbol } from "@plurnk/plurnk-mimetypes";
3
+ export default class Ipynb extends BaseHandler {
4
+ extractRaw(content: HandlerContent): MimeSymbol[];
5
+ content(content: HandlerContent): string | undefined;
6
+ deepJson(content: HandlerContent): unknown;
7
+ extent(content: HandlerContent): number;
8
+ validate(content: HandlerContent): void;
9
+ protected toText(content: HandlerContent): string;
10
+ }
11
+ interface NbOutput {
12
+ output_type?: string;
13
+ text?: string | string[];
14
+ data?: Record<string, unknown>;
15
+ traceback?: string[];
16
+ }
17
+ interface NbCell {
18
+ cell_type?: string;
19
+ source?: string | string[];
20
+ outputs?: NbOutput[];
21
+ execution_count?: number | null;
22
+ }
23
+ export interface Notebook {
24
+ cells?: NbCell[];
25
+ metadata?: {
26
+ kernelspec?: {
27
+ language?: string;
28
+ };
29
+ language_info?: {
30
+ name?: string;
31
+ };
32
+ };
33
+ nbformat?: number;
34
+ }
35
+ export interface Projection {
36
+ markdown: string;
37
+ symbols: MimeSymbol[];
38
+ }
39
+ export declare function project(nb: Notebook): Projection;
40
+ export {};
41
+ //# sourceMappingURL=Ipynb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Ipynb.d.ts","sourceRoot":"","sources":["../src/Ipynb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAsB3E,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,WAAW;IACjC,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,UAAU,EAAE;IAKjD,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,SAAS;IAOpD,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO;IAI1C,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM;IAOvC,QAAQ,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;cAK7B,MAAM,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM;CAI7D;AAED,UAAU,QAAQ;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,UAAU,MAAM;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,QAAQ;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE;QACP,UAAU,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACnC,aAAa,CAAC,EAAE;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KACrC,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,UAAU,EAAE,CAAC;CACzB;AAkBD,wBAAgB,OAAO,CAAC,EAAE,EAAE,QAAQ,GAAG,UAAU,CA6DhD"}
package/dist/Ipynb.js ADDED
@@ -0,0 +1,187 @@
1
+ import { BaseHandler } from "@plurnk/plurnk-mimetypes";
2
+ // application/x-ipynb+json (Jupyter notebook) handler — Tier 4, no parser dep.
3
+ //
4
+ // A .ipynb IS json, but the json IS the noise: a model that wants to read a
5
+ // notebook does not want `{"cell_type":"code","source":["import x\n",...]}`,
6
+ // it wants the narrative + code the way a reader sees it. So the load-bearing
7
+ // channel here is `content` (SPEC §18): the notebook projected to clean reading
8
+ // markdown — markdown cells verbatim, code cells fenced in the kernel language,
9
+ // text/stream/error outputs folded in, images dropped. That projection is also
10
+ // the embed-source, so a notebook's embedding reflects what it SAYS, not its
11
+ // json envelope.
12
+ //
13
+ // symbols index into that SAME projection (not the raw json): markdown headings
14
+ // become `heading` symbols (outline-nesting by level, like text-markdown), each
15
+ // code cell becomes a `module` symbol spanning its fenced block. So an outline
16
+ // of a notebook reads as its sections with their code cells nested underneath.
17
+ //
18
+ // deepJson is the parsed notebook verbatim — jsonpath/xpath reach `$.cells[*]`,
19
+ // `$.metadata.kernelspec.language`, etc. References are deferred (a notebook's
20
+ // imports/calls are kernel-language code; parsing them would mean embedding a
21
+ // per-kernel parser — out of scope for v1).
22
+ export default class Ipynb extends BaseHandler {
23
+ extractRaw(content) {
24
+ const nb = safeParse(content);
25
+ return nb ? project(nb).symbols : [];
26
+ }
27
+ content(content) {
28
+ const nb = safeParse(content);
29
+ if (!nb)
30
+ return undefined;
31
+ const md = project(nb).markdown;
32
+ return md.length > 0 ? md : undefined;
33
+ }
34
+ deepJson(content) {
35
+ return safeParse(content);
36
+ }
37
+ extent(content) {
38
+ const nb = safeParse(content);
39
+ return nb ? countLines(project(nb).markdown) : 0;
40
+ }
41
+ // Strict: a malformed notebook IS a validation failure (unlike the other
42
+ // channels, which degrade to empty per the family's error policy).
43
+ validate(content) {
44
+ JSON.parse(toStr(content));
45
+ }
46
+ // regex/glob and embeddings run against the readable projection, not json.
47
+ toText(content) {
48
+ const nb = safeParse(content);
49
+ return nb ? project(nb).markdown : toStr(content);
50
+ }
51
+ }
52
+ // Parse to a notebook object, or null on anything that isn't one — the
53
+ // degrade-not-throw policy every channel but validate() follows.
54
+ function safeParse(content) {
55
+ let value;
56
+ try {
57
+ value = JSON.parse(toStr(content));
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ return typeof value === "object" && value !== null ? value : null;
63
+ }
64
+ // Project a notebook to reading markdown + the symbols that index into it.
65
+ // One pass builds the markdown line buffer and records each code cell's span
66
+ // and each markdown heading's position; heading end-lines (for outline
67
+ // nesting) are resolved in a second pass over the collected headings.
68
+ export function project(nb) {
69
+ const lang = nb.metadata?.kernelspec?.language ?? nb.metadata?.language_info?.name ?? "";
70
+ const cells = Array.isArray(nb.cells) ? nb.cells : [];
71
+ const lines = [];
72
+ const headings = [];
73
+ const codeSyms = [];
74
+ let codeIndex = 0;
75
+ for (const cell of cells) {
76
+ // Trim a single trailing newline: nbformat source usually carries one
77
+ // per cell, which would otherwise render as a blank line inside the
78
+ // fence / after the cell.
79
+ const src = joinSource(cell.source).replace(/\n$/, "");
80
+ if (cell.cell_type === "markdown") {
81
+ for (const l of src.split("\n")) {
82
+ lines.push(l);
83
+ const m = /^(#{1,6})\s+(.+?)\s*#*\s*$/.exec(l);
84
+ if (m)
85
+ headings.push({ line: lines.length, level: m[1].length, name: m[2].trim() });
86
+ }
87
+ }
88
+ else if (cell.cell_type === "code") {
89
+ codeIndex += 1;
90
+ const start = lines.length + 1;
91
+ lines.push("```" + lang);
92
+ for (const l of src.split("\n"))
93
+ lines.push(l);
94
+ lines.push("```");
95
+ const outputs = renderOutputs(cell.outputs);
96
+ if (outputs.length > 0) {
97
+ lines.push("");
98
+ lines.push("_Output:_");
99
+ lines.push("```");
100
+ for (const l of outputs)
101
+ lines.push(l);
102
+ lines.push("```");
103
+ }
104
+ const ec = typeof cell.execution_count === "number" ? cell.execution_count : null;
105
+ codeSyms.push({
106
+ name: ec !== null ? `In[${ec}]` : `code cell ${codeIndex}`,
107
+ kind: "module",
108
+ line: start,
109
+ endLine: lines.length,
110
+ });
111
+ }
112
+ else if (cell.cell_type === "raw") {
113
+ for (const l of src.split("\n"))
114
+ lines.push(l);
115
+ }
116
+ lines.push("");
117
+ }
118
+ const docEnd = lines.length;
119
+ const headingSyms = headings.map((h, i) => {
120
+ // A heading's section runs until the next heading of equal-or-shallower
121
+ // level (text-markdown's outline rule), so deeper headings and the code
122
+ // cells in between nest under it via line-range containment.
123
+ let endLine = docEnd;
124
+ for (let j = i + 1; j < headings.length; j += 1) {
125
+ if (headings[j].level <= h.level) {
126
+ endLine = headings[j].line - 1;
127
+ break;
128
+ }
129
+ }
130
+ return { name: h.name, kind: "heading", level: h.level, line: h.line, endLine };
131
+ });
132
+ const symbols = [...headingSyms, ...codeSyms]
133
+ .sort((a, b) => a.line - b.line || b.endLine - a.endLine);
134
+ return { markdown: lines.join("\n"), symbols };
135
+ }
136
+ // Fold a code cell's outputs into readable text: stream + text/plain results +
137
+ // error tracebacks (ANSI stripped). Images / html / json payloads are dropped —
138
+ // the content channel is reading text, not a render.
139
+ function renderOutputs(outputs) {
140
+ if (!Array.isArray(outputs))
141
+ return [];
142
+ const out = [];
143
+ for (const o of outputs) {
144
+ if (o.output_type === "stream" && o.text !== undefined) {
145
+ pushText(out, joinSource(o.text));
146
+ }
147
+ else if ((o.output_type === "execute_result" || o.output_type === "display_data") && o.data) {
148
+ const plain = o.data["text/plain"];
149
+ if (plain !== undefined)
150
+ pushText(out, joinSource(plain));
151
+ }
152
+ else if (o.output_type === "error" && Array.isArray(o.traceback)) {
153
+ for (const frame of o.traceback)
154
+ pushText(out, stripAnsi(frame));
155
+ }
156
+ }
157
+ return out;
158
+ }
159
+ function pushText(out, text) {
160
+ for (const l of text.replace(/\n$/, "").split("\n"))
161
+ out.push(l);
162
+ }
163
+ function stripAnsi(text) {
164
+ return text.replace(/\u001b\[[0-9;]*m/g, "");
165
+ }
166
+ // nbformat stores source/text as either a string or an array of line-strings
167
+ // (each typically carrying its own trailing newline). join("") reconstructs.
168
+ function joinSource(source) {
169
+ if (Array.isArray(source))
170
+ return source.join("");
171
+ return typeof source === "string" ? source : "";
172
+ }
173
+ function toStr(content) {
174
+ return typeof content === "string" ? content : new TextDecoder("utf-8").decode(content);
175
+ }
176
+ // Editor-convention line count, mirroring the framework's default extent.
177
+ function countLines(text) {
178
+ if (text.length === 0)
179
+ return 0;
180
+ let newlines = 0;
181
+ for (let i = 0; i < text.length; i += 1) {
182
+ if (text.charCodeAt(i) === 0x0a)
183
+ newlines += 1;
184
+ }
185
+ return text.charCodeAt(text.length - 1) === 0x0a ? newlines : newlines + 1;
186
+ }
187
+ //# sourceMappingURL=Ipynb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Ipynb.js","sourceRoot":"","sources":["../src/Ipynb.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { default as Ipynb } from "./Ipynb.ts";
2
+ export { default } from "./Ipynb.ts";
3
+ export { project } from "./Ipynb.ts";
4
+ export type { Notebook, Projection } from "./Ipynb.ts";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { default as Ipynb } from "./Ipynb.js";
2
+ export { default } from "./Ipynb.js";
3
+ export { project } from "./Ipynb.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@plurnk/plurnk-mimetypes-application-ipynb",
3
+ "version": "0.1.0",
4
+ "description": "application/x-ipynb+json (Jupyter notebook) mimetype handler for plurnk-service. Cells as symbols; notebook projected to clean reading markdown via the content channel. Hand-rolled, no parser dependency.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "engines": {
11
+ "node": ">=25"
12
+ },
13
+ "plurnk": {
14
+ "kind": "mimetype",
15
+ "handlers": [
16
+ {
17
+ "name": "application/x-ipynb+json",
18
+ "glyph": "📓",
19
+ "extensions": [
20
+ ".ipynb"
21
+ ]
22
+ }
23
+ ]
24
+ },
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "default": "./dist/index.js"
29
+ },
30
+ "./package.json": "./package.json"
31
+ },
32
+ "files": [
33
+ "dist/**/*",
34
+ "README.md"
35
+ ],
36
+ "scripts": {
37
+ "test:lint": "tsc --noEmit",
38
+ "test:unit": "node --test src/**/*.test.ts",
39
+ "test": "npm run test:lint && npm run test:unit",
40
+ "build:dist": "tsc -p tsconfig.build.json",
41
+ "build": "npm run build:dist",
42
+ "prepare": "npm run build"
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^25.8.0",
46
+ "typescript": "^6.0.3",
47
+ "@plurnk/plurnk-mimetypes": "^0.15.0"
48
+ },
49
+ "peerDependencies": {
50
+ "@plurnk/plurnk-mimetypes": "^0.15.0"
51
+ }
52
+ }