Skip to content

Commit 54e3ee4

Browse files
Use content stable value for code id
1 parent 510dc2c commit 54e3ee4

28 files changed

+73
-72
lines changed

src/hash.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {createHash} from "node:crypto";
22

33
export function computeHash(source: string): string {
4-
return createHash("sha256").update(source).digest("base64");
4+
return createHash("sha256").update(source).digest("hex");
55
}

src/javascript.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {Sourcemap} from "./sourcemap.js";
1313

1414
export interface FileReference {
1515
name: string;
16-
mimeType: string;
16+
mimeType: string | null;
1717
}
1818

1919
export interface ImportReference {
@@ -31,7 +31,7 @@ export interface Transpile {
3131
}
3232

3333
export interface TranspileOptions {
34-
id: number;
34+
id: string;
3535
root: string;
3636
}
3737

@@ -53,7 +53,7 @@ export function transpileJavaScript(input: string, {id, root, ...options}: Trans
5353
rewriteImports(output, node);
5454
rewriteFetches(output, node);
5555
return {
56-
id: `${id}`,
56+
id,
5757
...(inputs.length ? {inputs} : null),
5858
...(options.inline ? {inline: true} : null),
5959
...(node.declarations?.length ? {outputs: node.declarations.map(({name}) => name)} : null),

src/markdown.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import mime from "mime";
1212
import {join} from "path";
1313
import {canReadSync} from "./files.js";
1414
import {transpileJavaScript, type FileReference, type ImportReference, type Transpile} from "./javascript.js";
15+
import {computeHash} from "./hash.js";
1516

1617
export interface HtmlPiece {
1718
type: "html";
@@ -42,8 +43,6 @@ interface RenderPiece {
4243
}
4344

4445
interface ParseContext {
45-
id: number;
46-
js: string;
4746
pieces: RenderPiece[];
4847
files: {name: string; mimeType: string | null}[];
4948
imports: ImportReference[];
@@ -69,14 +68,24 @@ function makeHtmlRenderer(root: string, baseRenderer: RenderRule): RenderRule {
6968
};
7069
}
7170

71+
function uniqueCodeId(context: ParseContext, content: string): string {
72+
const hash = String(computeHash(content));
73+
let id = hash;
74+
let count = 1;
75+
while (context.pieces.some((piece) => piece.code.some((code) => code.id === id))) {
76+
id = `${hash}-${count++}`;
77+
}
78+
return id;
79+
}
80+
7281
function makeFenceRenderer(root: string, baseRenderer: RenderRule): RenderRule {
7382
return (tokens, idx, options, context: ParseContext, self) => {
7483
const token = tokens[idx];
7584
const [language, option] = token.info.split(" ");
7685
let result = "";
7786
let count = 0;
7887
if (language === "js" && option !== "no-run") {
79-
const id = ++context.id;
88+
const id = uniqueCodeId(context, token.content);
8089
const transpile = transpileJavaScript(token.content, {
8190
id,
8291
root,
@@ -163,12 +172,12 @@ function transformPlaceholderBlock(token) {
163172
const output: any[] = [];
164173
let i = 0;
165174
parsePlaceholder(input, (j, k) => {
166-
output.push({...token, content: input.slice(i, j)});
167-
output.push({type: "placeholder", content: input.slice(j + 2, k - 1)});
175+
output.push({...token, level: i > 0 ? token.level + 1 : token.level, content: input.slice(i, j)});
176+
output.push({type: "placeholder", level: token.level + 1, content: input.slice(j + 2, k - 1)});
168177
i = k;
169178
});
170179
if (i === 0) return [token];
171-
else if (i < input.length) output.push({...token, content: input.slice(i)});
180+
else if (i < input.length) output.push({...token, content: input.slice(i), nesting: -1});
172181
return output;
173182
}
174183

@@ -229,7 +238,7 @@ const transformPlaceholderCore: RuleCore = (state) => {
229238

230239
function makePlaceholderRenderer(root: string): RenderRule {
231240
return (tokens, idx, options, context: ParseContext) => {
232-
const id = ++context.id;
241+
const id = uniqueCodeId(context, tokens[idx].content);
233242
const token = tokens[idx];
234243
const transpile = transpileJavaScript(token.content, {
235244
id,
@@ -335,7 +344,7 @@ export function parseMarkdown(source: string, root: string): ParseResult {
335344
md.renderer.rules.fence = makeFenceRenderer(root, md.renderer.rules.fence!);
336345
md.renderer.rules.softbreak = makeSoftbreakRenderer(md.renderer.rules.softbreak!);
337346
md.renderer.render = renderIntoPieces(md.renderer);
338-
const context: ParseContext = {id: 0, js: "", files: [], imports: [], pieces: [], startLine: 0, currentLine: 0};
347+
const context: ParseContext = {files: [], imports: [], pieces: [], startLine: 0, currentLine: 0};
339348
const tokens = md.parse(parts.content, context);
340349
const html = md.renderer.render(tokens, md.options, context);
341350
return {

src/render.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,7 @@ ${JSON.stringify(
7474
7575
import {${preview ? "open, " : ""}define} from "/_observablehq/client.js";
7676
77-
${preview ? `open({hash: ${JSON.stringify(hash)}});\n` : ""}${parseResult.cells
78-
.map((cell) => renderDefineCell(cell))
79-
.join("")}
77+
${preview ? `open({hash: ${JSON.stringify(hash)}});\n` : ""}${parseResult.cells.map(renderDefineCell).join("")}
8078
</script>${
8179
parseResult.data
8280
? `

test/hash-test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import assert from "node:assert";
33

44
describe("computeHash(content)", () => {
55
it("returns the expected result", () => {
6-
assert.deepStrictEqual(computeHash(""), "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=");
7-
assert.deepStrictEqual(computeHash("hello"), "LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=");
6+
assert.deepStrictEqual(computeHash(""), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
7+
assert.deepStrictEqual(computeHash("hello"), "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824");
88
});
99
});

test/javascript-test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ describe("transpileJavaScript(input)", () => {
1818
const outfile = resolve("./test/output", `${basename(outname, ".js")}.js`);
1919
const diffile = resolve("./test/output", `${basename(outname, ".js")}-changed.js`);
2020
const actual = renderDefineCell(
21-
await transpileJavaScript(await readFile(path, "utf8"), {id: 0, root: "test/input"})
21+
await transpileJavaScript(await readFile(path, "utf8"), {id: "0", root: "test/input"})
2222
);
2323
let expected;
2424

test/output/block-expression.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<div><span id="cell-1"></span></div>
1+
<div><span id="cell-6212702c7a0d68f00b8b23b5aecfca631a96c20d2cad78cd874611ac87cdbce1"></span></div>

test/output/block-expression.json

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,15 @@
88
"type": "html",
99
"id": "",
1010
"cellIds": [
11-
"1"
11+
"6212702c7a0d68f00b8b23b5aecfca631a96c20d2cad78cd874611ac87cdbce1"
1212
],
13-
"html": "<div><span id=\"cell-1\"></span>"
14-
},
15-
{
16-
"type": "html",
17-
"id": "",
18-
"cellIds": [],
19-
"html": "</div>\n"
13+
"html": "<div><span id=\"cell-6212702c7a0d68f00b8b23b5aecfca631a96c20d2cad78cd874611ac87cdbce1\"></span></div>\n"
2014
}
2115
],
2216
"cells": [
2317
{
2418
"type": "cell",
25-
"id": "1",
19+
"id": "6212702c7a0d68f00b8b23b5aecfca631a96c20d2cad78cd874611ac87cdbce1",
2620
"inputs": [
2721
"display"
2822
],

test/output/dollar-expression.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<p>$<span id="cell-1"></span></p>
1+
<p>$<span id="cell-6212702c7a0d68f00b8b23b5aecfca631a96c20d2cad78cd874611ac87cdbce1"></span></p>

test/output/dollar-expression.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
"type": "html",
99
"id": "",
1010
"cellIds": [
11-
"1"
11+
"6212702c7a0d68f00b8b23b5aecfca631a96c20d2cad78cd874611ac87cdbce1"
1212
],
13-
"html": "<p>$<span id=\"cell-1\"></span></p>\n"
13+
"html": "<p>$<span id=\"cell-6212702c7a0d68f00b8b23b5aecfca631a96c20d2cad78cd874611ac87cdbce1\"></span></p>\n"
1414
}
1515
],
1616
"cells": [
1717
{
1818
"type": "cell",
19-
"id": "1",
19+
"id": "6212702c7a0d68f00b8b23b5aecfca631a96c20d2cad78cd874611ac87cdbce1",
2020
"inputs": [
2121
"display"
2222
],

0 commit comments

Comments
 (0)