mdmeld 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 +21 -0
- package/README.md +100 -0
- package/dist/chunk-UF532LMZ.js +426 -0
- package/dist/chunk-UF532LMZ.js.map +1 -0
- package/dist/chunk-UJZ43GZC.js +128 -0
- package/dist/chunk-UJZ43GZC.js.map +1 -0
- package/dist/cli/index.js +90 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/index.cjs +609 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +71 -0
- package/dist/core/index.d.ts +71 -0
- package/dist/core/index.js +570 -0
- package/dist/core/index.js.map +1 -0
- package/dist/finalize-NGDCBCTD.js +84 -0
- package/dist/finalize-NGDCBCTD.js.map +1 -0
- package/dist/pack-ODWNG5OH.js +84 -0
- package/dist/pack-ODWNG5OH.js.map +1 -0
- package/dist/release/SHA256SUMS +1 -0
- package/dist/release/SHA256SUMS.asc +16 -0
- package/dist/release/SHA256SUMS.minisig +4 -0
- package/dist/release/SHA512SUMS +1 -0
- package/dist/release/SHA512SUMS.asc +16 -0
- package/dist/release/SHA512SUMS.minisig +4 -0
- package/dist/release/mdmeld-0.1.0.tgz +0 -0
- package/dist/release/mdmeld-minisign.pub +2 -0
- package/dist/release/mdmeld-release-signing-key.asc +64 -0
- package/dist/release/release-notes-v0.1.0.md +29 -0
- package/dist/unpack-2BBZMGLH.js +25 -0
- package/dist/unpack-2BBZMGLH.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
HASH_PLACEHOLDER,
|
|
4
|
+
computeHash,
|
|
5
|
+
computeHashBytes,
|
|
6
|
+
decodeBase64,
|
|
7
|
+
dump,
|
|
8
|
+
load
|
|
9
|
+
} from "./chunk-UJZ43GZC.js";
|
|
10
|
+
|
|
11
|
+
// src/cli/commands/finalize.ts
|
|
12
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
13
|
+
import { resolve } from "path";
|
|
14
|
+
var TEXT_ENCODER = new TextEncoder();
|
|
15
|
+
async function runFinalize(args) {
|
|
16
|
+
const filePath = resolve(args.file);
|
|
17
|
+
const content = readFileSync(filePath, "utf-8");
|
|
18
|
+
let input = content;
|
|
19
|
+
let headerComment = "";
|
|
20
|
+
if (input.startsWith("<!--")) {
|
|
21
|
+
const commentEnd = input.indexOf("-->");
|
|
22
|
+
if (commentEnd !== -1) {
|
|
23
|
+
headerComment = input.slice(0, commentEnd + 3);
|
|
24
|
+
input = input.slice(commentEnd + 3).trimStart();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (!input.startsWith("---")) {
|
|
28
|
+
console.error("Invalid archive: missing YAML frontmatter");
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const secondDelim = input.indexOf("\n---", 3);
|
|
32
|
+
if (secondDelim === -1) {
|
|
33
|
+
console.error("Invalid archive: missing closing --- delimiter");
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
const yamlStr = input.slice(4, secondDelim);
|
|
37
|
+
const afterFrontmatter = input.slice(secondDelim + 4);
|
|
38
|
+
const contentSection = afterFrontmatter.replace(/^\n+/, "");
|
|
39
|
+
const manifest = load(yamlStr);
|
|
40
|
+
const algorithm = manifest.mdmeld.hash_algorithm ?? "xxh64";
|
|
41
|
+
let changed = false;
|
|
42
|
+
const fence = "`".repeat(manifest.mdmeld.backtick_count);
|
|
43
|
+
const pattern = new RegExp(
|
|
44
|
+
`### (.+?)\\s*\\n\\s*${fence}([^\\n]*)\\n([\\s\\S]*?)\\n?${fence}(?=\\s|$)`,
|
|
45
|
+
"g"
|
|
46
|
+
);
|
|
47
|
+
for (const match of contentSection.matchAll(pattern)) {
|
|
48
|
+
const path = match[1].trim();
|
|
49
|
+
const lang = match[2].trim();
|
|
50
|
+
const rawContent = match[3];
|
|
51
|
+
const entry = manifest.mdmeld.files.find((f) => f.path === path);
|
|
52
|
+
if (entry && entry.hash === HASH_PLACEHOLDER) {
|
|
53
|
+
const isEncoded = lang === "base64" || entry.encoding === "base64";
|
|
54
|
+
const bytes = isEncoded ? decodeBase64(rawContent) : TEXT_ENCODER.encode(rawContent);
|
|
55
|
+
entry.hash = await computeHashBytes(bytes, algorithm);
|
|
56
|
+
changed = true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (manifest.integrity.content_hash === HASH_PLACEHOLDER) {
|
|
60
|
+
manifest.integrity.content_hash = await computeHash(afterFrontmatter, algorithm);
|
|
61
|
+
changed = true;
|
|
62
|
+
}
|
|
63
|
+
if (manifest.integrity.manifest_hash === HASH_PLACEHOLDER) {
|
|
64
|
+
const manifestYaml = dump({ mdmeld: manifest.mdmeld });
|
|
65
|
+
manifest.integrity.manifest_hash = await computeHash(manifestYaml, algorithm);
|
|
66
|
+
changed = true;
|
|
67
|
+
}
|
|
68
|
+
if (!changed) {
|
|
69
|
+
console.log("No HASH_PLACEHOLDER values found \u2014 archive already finalized");
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const outputYaml = dump(manifest);
|
|
73
|
+
const prefix = headerComment ? `${headerComment}
|
|
74
|
+
` : "";
|
|
75
|
+
const output = `${prefix}---
|
|
76
|
+
${outputYaml}---
|
|
77
|
+
${afterFrontmatter}`;
|
|
78
|
+
writeFileSync(filePath, output, "utf-8");
|
|
79
|
+
console.log(`Finalized hashes in ${filePath}`);
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
runFinalize
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=finalize-NGDCBCTD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/finalize.ts"],"sourcesContent":["import { readFileSync, writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { decodeBase64 } from \"../../core/base64.js\";\nimport { HASH_PLACEHOLDER } from \"../../core/constants.js\";\nimport { computeHash, computeHashBytes } from \"../../core/hash.js\";\nimport type { HashAlgorithm, Manifest } from \"../../core/types.js\";\nimport * as yaml from \"../../core/yaml.js\";\n\nconst TEXT_ENCODER = new TextEncoder();\n\nexport interface FinalizeArgs {\n\tfile: string;\n}\n\n/**\n * Finalize an archive by computing real hashes for HASH_PLACEHOLDER values.\n * Useful for archives generated by AI assistants that can't compute hashes.\n */\nexport async function runFinalize(args: FinalizeArgs): Promise<void> {\n\tconst filePath = resolve(args.file);\n\tconst content = readFileSync(filePath, \"utf-8\");\n\n\t// Parse the archive\n\tlet input = content;\n\tlet headerComment = \"\";\n\n\tif (input.startsWith(\"<!--\")) {\n\t\tconst commentEnd = input.indexOf(\"-->\");\n\t\tif (commentEnd !== -1) {\n\t\t\theaderComment = input.slice(0, commentEnd + 3);\n\t\t\tinput = input.slice(commentEnd + 3).trimStart();\n\t\t}\n\t}\n\n\tif (!input.startsWith(\"---\")) {\n\t\tconsole.error(\"Invalid archive: missing YAML frontmatter\");\n\t\tprocess.exit(1);\n\t}\n\n\tconst secondDelim = input.indexOf(\"\\n---\", 3);\n\tif (secondDelim === -1) {\n\t\tconsole.error(\"Invalid archive: missing closing --- delimiter\");\n\t\tprocess.exit(1);\n\t}\n\n\tconst yamlStr = input.slice(4, secondDelim);\n\tconst afterFrontmatter = input.slice(secondDelim + 4);\n\tconst contentSection = afterFrontmatter.replace(/^\\n+/, \"\");\n\n\tconst manifest = yaml.load(yamlStr) as Manifest;\n\tconst algorithm: HashAlgorithm = manifest.mdmeld.hash_algorithm ?? \"xxh64\";\n\n\tlet changed = false;\n\n\t// Compute file hashes\n\tconst fence = \"`\".repeat(manifest.mdmeld.backtick_count);\n\tconst pattern = new RegExp(\n\t\t`### (.+?)\\\\s*\\\\n\\\\s*${fence}([^\\\\n]*)\\\\n([\\\\s\\\\S]*?)\\\\n?${fence}(?=\\\\s|$)`,\n\t\t\"g\",\n\t);\n\n\tfor (const match of contentSection.matchAll(pattern)) {\n\t\tconst path = match[1]!.trim();\n\t\tconst lang = match[2]!.trim();\n\t\tconst rawContent = match[3]!;\n\n\t\tconst entry = manifest.mdmeld.files.find((f) => f.path === path);\n\t\tif (entry && entry.hash === HASH_PLACEHOLDER) {\n\t\t\t// File hash is computed on original bytes (per spec)\n\t\t\tconst isEncoded = lang === \"base64\" || entry.encoding === \"base64\";\n\t\t\tconst bytes = isEncoded ? decodeBase64(rawContent) : TEXT_ENCODER.encode(rawContent);\n\t\t\tentry.hash = await computeHashBytes(bytes, algorithm);\n\t\t\tchanged = true;\n\t\t}\n\t}\n\n\t// Compute content hash (on raw content after closing ---, per spec)\n\tif (manifest.integrity.content_hash === HASH_PLACEHOLDER) {\n\t\tmanifest.integrity.content_hash = await computeHash(afterFrontmatter, algorithm);\n\t\tchanged = true;\n\t}\n\n\t// Compute manifest hash (must be last, after all other manifest changes)\n\tif (manifest.integrity.manifest_hash === HASH_PLACEHOLDER) {\n\t\t// Manifest hash includes the `mdmeld:` key line per spec\n\t\tconst manifestYaml = yaml.dump({ mdmeld: manifest.mdmeld });\n\t\tmanifest.integrity.manifest_hash = await computeHash(manifestYaml, algorithm);\n\t\tchanged = true;\n\t}\n\n\tif (!changed) {\n\t\tconsole.log(\"No HASH_PLACEHOLDER values found — archive already finalized\");\n\t\treturn;\n\t}\n\n\t// Re-serialize\n\tconst outputYaml = yaml.dump(manifest);\n\tconst prefix = headerComment ? `${headerComment}\\n` : \"\";\n\tconst output = `${prefix}---\\n${outputYaml}---\\n${afterFrontmatter}`;\n\n\twriteFileSync(filePath, output, \"utf-8\");\n\tconsole.log(`Finalized hashes in ${filePath}`);\n}\n"],"mappings":";;;;;;;;;;;AAAA,SAAS,cAAc,qBAAqB;AAC5C,SAAS,eAAe;AAOxB,IAAM,eAAe,IAAI,YAAY;AAUrC,eAAsB,YAAY,MAAmC;AACpE,QAAM,WAAW,QAAQ,KAAK,IAAI;AAClC,QAAM,UAAU,aAAa,UAAU,OAAO;AAG9C,MAAI,QAAQ;AACZ,MAAI,gBAAgB;AAEpB,MAAI,MAAM,WAAW,MAAM,GAAG;AAC7B,UAAM,aAAa,MAAM,QAAQ,KAAK;AACtC,QAAI,eAAe,IAAI;AACtB,sBAAgB,MAAM,MAAM,GAAG,aAAa,CAAC;AAC7C,cAAQ,MAAM,MAAM,aAAa,CAAC,EAAE,UAAU;AAAA,IAC/C;AAAA,EACD;AAEA,MAAI,CAAC,MAAM,WAAW,KAAK,GAAG;AAC7B,YAAQ,MAAM,2CAA2C;AACzD,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,cAAc,MAAM,QAAQ,SAAS,CAAC;AAC5C,MAAI,gBAAgB,IAAI;AACvB,YAAQ,MAAM,gDAAgD;AAC9D,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,UAAU,MAAM,MAAM,GAAG,WAAW;AAC1C,QAAM,mBAAmB,MAAM,MAAM,cAAc,CAAC;AACpD,QAAM,iBAAiB,iBAAiB,QAAQ,QAAQ,EAAE;AAE1D,QAAM,WAAgB,KAAK,OAAO;AAClC,QAAM,YAA2B,SAAS,OAAO,kBAAkB;AAEnE,MAAI,UAAU;AAGd,QAAM,QAAQ,IAAI,OAAO,SAAS,OAAO,cAAc;AACvD,QAAM,UAAU,IAAI;AAAA,IACnB,uBAAuB,KAAK,+BAA+B,KAAK;AAAA,IAChE;AAAA,EACD;AAEA,aAAW,SAAS,eAAe,SAAS,OAAO,GAAG;AACrD,UAAM,OAAO,MAAM,CAAC,EAAG,KAAK;AAC5B,UAAM,OAAO,MAAM,CAAC,EAAG,KAAK;AAC5B,UAAM,aAAa,MAAM,CAAC;AAE1B,UAAM,QAAQ,SAAS,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAC/D,QAAI,SAAS,MAAM,SAAS,kBAAkB;AAE7C,YAAM,YAAY,SAAS,YAAY,MAAM,aAAa;AAC1D,YAAM,QAAQ,YAAY,aAAa,UAAU,IAAI,aAAa,OAAO,UAAU;AACnF,YAAM,OAAO,MAAM,iBAAiB,OAAO,SAAS;AACpD,gBAAU;AAAA,IACX;AAAA,EACD;AAGA,MAAI,SAAS,UAAU,iBAAiB,kBAAkB;AACzD,aAAS,UAAU,eAAe,MAAM,YAAY,kBAAkB,SAAS;AAC/E,cAAU;AAAA,EACX;AAGA,MAAI,SAAS,UAAU,kBAAkB,kBAAkB;AAE1D,UAAM,eAAoB,KAAK,EAAE,QAAQ,SAAS,OAAO,CAAC;AAC1D,aAAS,UAAU,gBAAgB,MAAM,YAAY,cAAc,SAAS;AAC5E,cAAU;AAAA,EACX;AAEA,MAAI,CAAC,SAAS;AACb,YAAQ,IAAI,mEAA8D;AAC1E;AAAA,EACD;AAGA,QAAM,aAAkB,KAAK,QAAQ;AACrC,QAAM,SAAS,gBAAgB,GAAG,aAAa;AAAA,IAAO;AACtD,QAAM,SAAS,GAAG,MAAM;AAAA,EAAQ,UAAU;AAAA,EAAQ,gBAAgB;AAElE,gBAAc,UAAU,QAAQ,OAAO;AACvC,UAAQ,IAAI,uBAAuB,QAAQ,EAAE;AAC9C;","names":[]}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
pack
|
|
4
|
+
} from "./chunk-UF532LMZ.js";
|
|
5
|
+
import "./chunk-UJZ43GZC.js";
|
|
6
|
+
|
|
7
|
+
// src/cli/commands/pack.ts
|
|
8
|
+
import { writeFileSync } from "fs";
|
|
9
|
+
import { resolve } from "path";
|
|
10
|
+
|
|
11
|
+
// src/cli/fs-adapter.ts
|
|
12
|
+
import { readdirSync, readFileSync as readFileSync2 } from "fs";
|
|
13
|
+
import { join as join2, relative } from "path";
|
|
14
|
+
|
|
15
|
+
// src/cli/ignore.ts
|
|
16
|
+
import { existsSync, readFileSync } from "fs";
|
|
17
|
+
import { join } from "path";
|
|
18
|
+
import ignore from "ignore";
|
|
19
|
+
function createIgnoreFilter(dir) {
|
|
20
|
+
const ig = ignore();
|
|
21
|
+
ig.add([".git", "node_modules", ".DS_Store", ".gitignore", ".mdmeldignore"]);
|
|
22
|
+
const gitignorePath = join(dir, ".gitignore");
|
|
23
|
+
if (existsSync(gitignorePath)) {
|
|
24
|
+
const content = readFileSync(gitignorePath, "utf-8");
|
|
25
|
+
ig.add(content);
|
|
26
|
+
}
|
|
27
|
+
const mdmeldignorePath = join(dir, ".mdmeldignore");
|
|
28
|
+
if (existsSync(mdmeldignorePath)) {
|
|
29
|
+
const content = readFileSync(mdmeldignorePath, "utf-8");
|
|
30
|
+
ig.add(content);
|
|
31
|
+
}
|
|
32
|
+
return (path) => ig.ignores(path);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/cli/fs-adapter.ts
|
|
36
|
+
function walkDirectory(dir) {
|
|
37
|
+
const isIgnored = createIgnoreFilter(dir);
|
|
38
|
+
const files = [];
|
|
39
|
+
function walk(currentDir) {
|
|
40
|
+
const entries = readdirSync(currentDir, { withFileTypes: true });
|
|
41
|
+
for (const entry of entries) {
|
|
42
|
+
const fullPath = join2(currentDir, entry.name);
|
|
43
|
+
const relPath = relative(dir, fullPath);
|
|
44
|
+
const posixPath = relPath.split("\\").join("/");
|
|
45
|
+
if (isIgnored(posixPath)) continue;
|
|
46
|
+
if (entry.isDirectory()) {
|
|
47
|
+
walk(fullPath);
|
|
48
|
+
} else if (entry.isFile()) {
|
|
49
|
+
const content = readFileSync2(fullPath);
|
|
50
|
+
files.push({
|
|
51
|
+
path: posixPath,
|
|
52
|
+
content: new Uint8Array(content)
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
walk(dir);
|
|
58
|
+
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
59
|
+
return files;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// src/cli/commands/pack.ts
|
|
63
|
+
async function runPack(args) {
|
|
64
|
+
const dir = resolve(args.dir);
|
|
65
|
+
const files = walkDirectory(dir);
|
|
66
|
+
if (files.length === 0) {
|
|
67
|
+
console.error("No files found in directory (check .gitignore/.mdmeldignore)");
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
const archive = await pack(files, {
|
|
71
|
+
hashAlgorithm: args.hash ?? "xxh64"
|
|
72
|
+
});
|
|
73
|
+
if (args.output) {
|
|
74
|
+
const outPath = resolve(args.output);
|
|
75
|
+
writeFileSync(outPath, archive, "utf-8");
|
|
76
|
+
console.log(`Packed ${files.length} files \u2192 ${outPath}`);
|
|
77
|
+
} else {
|
|
78
|
+
process.stdout.write(archive);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
runPack
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=pack-ODWNG5OH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/pack.ts","../src/cli/fs-adapter.ts","../src/cli/ignore.ts"],"sourcesContent":["import { writeFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { pack } from \"../../core/index.js\";\nimport type { HashAlgorithm } from \"../../core/types.js\";\nimport { walkDirectory } from \"../fs-adapter.js\";\n\nexport interface PackArgs {\n\tdir: string;\n\toutput?: string;\n\thash?: HashAlgorithm;\n}\n\nexport async function runPack(args: PackArgs): Promise<void> {\n\tconst dir = resolve(args.dir);\n\tconst files = walkDirectory(dir);\n\n\tif (files.length === 0) {\n\t\tconsole.error(\"No files found in directory (check .gitignore/.mdmeldignore)\");\n\t\tprocess.exit(1);\n\t}\n\n\tconst archive = await pack(files, {\n\t\thashAlgorithm: args.hash ?? \"xxh64\",\n\t});\n\n\tif (args.output) {\n\t\tconst outPath = resolve(args.output);\n\t\twriteFileSync(outPath, archive, \"utf-8\");\n\t\tconsole.log(`Packed ${files.length} files → ${outPath}`);\n\t} else {\n\t\tprocess.stdout.write(archive);\n\t}\n}\n","import { readdirSync, readFileSync } from \"node:fs\";\nimport { join, relative } from \"node:path\";\nimport type { VirtualFile } from \"../core/types.js\";\nimport { createIgnoreFilter } from \"./ignore.js\";\n\n/**\n * Walk a directory and return all files as VirtualFile[].\n * Respects .gitignore and .mdmeldignore patterns.\n */\nexport function walkDirectory(dir: string): VirtualFile[] {\n\tconst isIgnored = createIgnoreFilter(dir);\n\tconst files: VirtualFile[] = [];\n\n\tfunction walk(currentDir: string) {\n\t\tconst entries = readdirSync(currentDir, { withFileTypes: true });\n\n\t\tfor (const entry of entries) {\n\t\t\tconst fullPath = join(currentDir, entry.name);\n\t\t\tconst relPath = relative(dir, fullPath);\n\t\t\t// Convert to POSIX path for ignore matching and storage\n\t\t\tconst posixPath = relPath.split(\"\\\\\").join(\"/\");\n\n\t\t\tif (isIgnored(posixPath)) continue;\n\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\twalk(fullPath);\n\t\t\t} else if (entry.isFile()) {\n\t\t\t\tconst content = readFileSync(fullPath);\n\t\t\t\tfiles.push({\n\t\t\t\t\tpath: posixPath,\n\t\t\t\t\tcontent: new Uint8Array(content),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\twalk(dir);\n\n\t// Sort by path for deterministic output\n\tfiles.sort((a, b) => a.path.localeCompare(b.path));\n\treturn files;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport ignore from \"ignore\";\n\n/**\n * Create an ignore filter from .gitignore and .mdmeldignore files in a directory.\n * Returns a function that tests whether a relative path should be ignored.\n */\nexport function createIgnoreFilter(dir: string): (path: string) => boolean {\n\tconst ig = ignore();\n\n\t// Always ignore these\n\tig.add([\".git\", \"node_modules\", \".DS_Store\", \".gitignore\", \".mdmeldignore\"]);\n\n\t// Load .gitignore\n\tconst gitignorePath = join(dir, \".gitignore\");\n\tif (existsSync(gitignorePath)) {\n\t\tconst content = readFileSync(gitignorePath, \"utf-8\");\n\t\tig.add(content);\n\t}\n\n\t// Load .mdmeldignore (takes precedence)\n\tconst mdmeldignorePath = join(dir, \".mdmeldignore\");\n\tif (existsSync(mdmeldignorePath)) {\n\t\tconst content = readFileSync(mdmeldignorePath, \"utf-8\");\n\t\tig.add(content);\n\t}\n\n\treturn (path: string) => ig.ignores(path);\n}\n"],"mappings":";;;;;;;AAAA,SAAS,qBAAqB;AAC9B,SAAS,eAAe;;;ACDxB,SAAS,aAAa,gBAAAA,qBAAoB;AAC1C,SAAS,QAAAC,OAAM,gBAAgB;;;ACD/B,SAAS,YAAY,oBAAoB;AACzC,SAAS,YAAY;AACrB,OAAO,YAAY;AAMZ,SAAS,mBAAmB,KAAwC;AAC1E,QAAM,KAAK,OAAO;AAGlB,KAAG,IAAI,CAAC,QAAQ,gBAAgB,aAAa,cAAc,eAAe,CAAC;AAG3E,QAAM,gBAAgB,KAAK,KAAK,YAAY;AAC5C,MAAI,WAAW,aAAa,GAAG;AAC9B,UAAM,UAAU,aAAa,eAAe,OAAO;AACnD,OAAG,IAAI,OAAO;AAAA,EACf;AAGA,QAAM,mBAAmB,KAAK,KAAK,eAAe;AAClD,MAAI,WAAW,gBAAgB,GAAG;AACjC,UAAM,UAAU,aAAa,kBAAkB,OAAO;AACtD,OAAG,IAAI,OAAO;AAAA,EACf;AAEA,SAAO,CAAC,SAAiB,GAAG,QAAQ,IAAI;AACzC;;;ADpBO,SAAS,cAAc,KAA4B;AACzD,QAAM,YAAY,mBAAmB,GAAG;AACxC,QAAM,QAAuB,CAAC;AAE9B,WAAS,KAAK,YAAoB;AACjC,UAAM,UAAU,YAAY,YAAY,EAAE,eAAe,KAAK,CAAC;AAE/D,eAAW,SAAS,SAAS;AAC5B,YAAM,WAAWC,MAAK,YAAY,MAAM,IAAI;AAC5C,YAAM,UAAU,SAAS,KAAK,QAAQ;AAEtC,YAAM,YAAY,QAAQ,MAAM,IAAI,EAAE,KAAK,GAAG;AAE9C,UAAI,UAAU,SAAS,EAAG;AAE1B,UAAI,MAAM,YAAY,GAAG;AACxB,aAAK,QAAQ;AAAA,MACd,WAAW,MAAM,OAAO,GAAG;AAC1B,cAAM,UAAUC,cAAa,QAAQ;AACrC,cAAM,KAAK;AAAA,UACV,MAAM;AAAA,UACN,SAAS,IAAI,WAAW,OAAO;AAAA,QAChC,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAEA,OAAK,GAAG;AAGR,QAAM,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AACjD,SAAO;AACR;;;AD7BA,eAAsB,QAAQ,MAA+B;AAC5D,QAAM,MAAM,QAAQ,KAAK,GAAG;AAC5B,QAAM,QAAQ,cAAc,GAAG;AAE/B,MAAI,MAAM,WAAW,GAAG;AACvB,YAAQ,MAAM,8DAA8D;AAC5E,YAAQ,KAAK,CAAC;AAAA,EACf;AAEA,QAAM,UAAU,MAAM,KAAK,OAAO;AAAA,IACjC,eAAe,KAAK,QAAQ;AAAA,EAC7B,CAAC;AAED,MAAI,KAAK,QAAQ;AAChB,UAAM,UAAU,QAAQ,KAAK,MAAM;AACnC,kBAAc,SAAS,SAAS,OAAO;AACvC,YAAQ,IAAI,UAAU,MAAM,MAAM,iBAAY,OAAO,EAAE;AAAA,EACxD,OAAO;AACN,YAAQ,OAAO,MAAM,OAAO;AAAA,EAC7B;AACD;","names":["readFileSync","join","join","readFileSync"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
542ae87d7c324732ef458a5aa942d76098c33dc225bad4af4a282b6ef0f16e92 mdmeld-0.1.0.tgz
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
-----BEGIN PGP SIGNATURE-----
|
|
2
|
+
|
|
3
|
+
iQIzBAABCAAdFiEEHt2kvOVJotrCIL73L5+J92c+z38FAmmklt4ACgkQL5+J92c+
|
|
4
|
+
z3+4Lw//bAH/lTMN6lkmkN4kLmYuJ9wo5frRlG+nVLWxr0j5hsIscZUGT/NUemRI
|
|
5
|
+
xs81PVNbiPNFJdq7ZBwebFl1QPY6lYWPOh5dDA1WgzUARgaZalx0A51gJvUVISTR
|
|
6
|
+
zMbGm1EhJiNsyiLchBNr2UQNbdcrsuTqK4pPeGqS6wHTLHaXqqogzYkGE9BV29+z
|
|
7
|
+
RLerPyZvh7XNeXOb+Ca8AC3p1Mzx5i6BwtY1OMJTQFF8ClNywouKgf9ezyhF8VRB
|
|
8
|
+
mWHWIMLIHlDkqKlf+cbd5CqoDv0mw410AH6mufwc2fWcsGTkcnRe+DAh93iiT8kD
|
|
9
|
+
CwHsbHY4NPqtOGH+z7w/1R+N8sB+d5I4PHrMWSl3g4A6oH/HY4+YQhMLllH2HdTQ
|
|
10
|
+
b+StFDZYjNQoJXI5FXxL/f0njBtJnJs2yUEj8Rs31rGcI+ZCligibTJpWR/b9b+B
|
|
11
|
+
tmS4x0o1+9xZsWaj6oWmfVA9lfR69lweX0e9tfQZ2YCCaDRsrIuJaxznlIcoavOi
|
|
12
|
+
sCZEHYZDLkWdEAN1f9GK8QCOAaqifhXd+UmzFKkFMtDeQMsLvKb1thZj6X07BpfZ
|
|
13
|
+
fVSzLYW90nf9EKSex1DZCI8/Y+4i21B4PSZeVUGtTFU4c3LJq8KynbfJZ2aUHvNr
|
|
14
|
+
Wj8KeBr0bCLzu3/EsUAKbo6DpT5jW4aT33Wk8AYzURkoEyMVc/o=
|
|
15
|
+
=mUbK
|
|
16
|
+
-----END PGP SIGNATURE-----
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
untrusted comment: signature from minisign secret key
|
|
2
|
+
RUTAoUJ007VE3uOIJmESKUHLMe80f66r4JtcMtc+bFuYMq4Tl4vgnV8GnyuAL2ccy2QtruQwE88O3yQrOoiO6mby2ZIL14aGOQk=
|
|
3
|
+
trusted comment: mdmeld v0.1.0 2026-03-01T19:43:15Z
|
|
4
|
+
haxxNEUIGMMMQa34C0Gtt2Z80oyniGkqPcSOkBinB6Tu7XR5HQX2GP2FcTpMUp00cxyGsW5EjzAs1Y2nKm2IDA==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0a037cde6d3ee5973f47a88894948eab9e1da105212f3dbcff461750550029f8c44fa12641e01dea36cad495d9731dac193f723bada398f89e608366a6ef4183 mdmeld-0.1.0.tgz
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
-----BEGIN PGP SIGNATURE-----
|
|
2
|
+
|
|
3
|
+
iQIzBAABCAAdFiEEHt2kvOVJotrCIL73L5+J92c+z38FAmmkluIACgkQL5+J92c+
|
|
4
|
+
z38UzhAA1mS3XY46CHJ22g4HS8oUH9vMJaZU8SE2bc6NO0avygfDtHAjpVefXsUw
|
|
5
|
+
/OmRnBmo7S4yG9niePGPHATtYaUjhWeDbcs3W7zvkSuz35uLtqxa9XQmcl5Ekcyg
|
|
6
|
+
1Ti49l0m0EN3Q0JtF8I6Dqv0ZEkeN4BZxgyJBWdjR7nN+KrYOK0zv8EGz5byO4jP
|
|
7
|
+
6wWpjDa6HzXl2KnmWgWLW4nBBR1+eqT36WFcjdvfxehPPCnKpbRo7lUINudt/xPf
|
|
8
|
+
hGQfkVzeVKULkjxnZxUEK6Yvs+HM6/cDarrUb4xwnZ9tPQdpivWwxT/3wOWKD9QT
|
|
9
|
+
AkGWnazub6399iMr9hjbqaVDFiqHYtZ5pldJ43BwpweSe//Xhtw552HuFRLWPraC
|
|
10
|
+
n+nEi91dXp/iQ5+kwpItfPIpeiVviP8tBa2uP85Jg81JFqiScPn74Txy5kOl0VBb
|
|
11
|
+
rF2ZOJMfiMmEh+o3SQNuSEZEA1d1mRHBPXv4RPWPQGAE4NPcxx7h/IkoJwvbyARB
|
|
12
|
+
JsKo9Vj16DfeES6EXgFN0o4JlNK1odNrDBpsozpQfIjSfjGFBWIcH4B6mzkf7i9Z
|
|
13
|
+
IIG/rQSAg74l2Wxpn9gzl1RwA37pO+dEDPyaYEYVLQ9FU1olTz4JOkkFIzcPdzzU
|
|
14
|
+
9tyBgnV6tD5dH+eiVnspoi03jnawuND1GvT5cMTsJZ9nBF2X9Xs=
|
|
15
|
+
=pgM/
|
|
16
|
+
-----END PGP SIGNATURE-----
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
untrusted comment: signature from minisign secret key
|
|
2
|
+
RUTAoUJ007VE3iYGRj5A7OsDwuEsL9FaIR++xdAbMGDp32tSvWaG7ZzBLx6M8qmRko1SSLrxDXtBjkwOBfQov/F6QG14XXC16gc=
|
|
3
|
+
trusted comment: mdmeld v0.1.0 2026-03-01T19:43:23Z
|
|
4
|
+
Bi2V0sxiiqXDQ3nbTg04qqmQoqbSugXUvsAQ71RKa4FyoEVVFZArf70khPVulpDnsaB77hCmLEASoSeQ0QlGBQ==
|
|
Binary file
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
2
|
+
|
|
3
|
+
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
|
|
63
|
+
=Ghyf
|
|
64
|
+
-----END PGP PUBLIC KEY BLOCK-----
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
First publishable release of mdmeld — a single npm package providing a programmatic API, CLI, and static web tool for packing directory trees into markdown archives designed for AI assistant consumption.
|
|
4
|
+
|
|
5
|
+
## Highlights
|
|
6
|
+
|
|
7
|
+
### Core library
|
|
8
|
+
|
|
9
|
+
Browser-safe, zero Node.js dependencies. Three functions: `pack()`, `unpack()`, `check()`. Dual exports (ESM + CJS) with TypeScript declarations. Works identically in Node.js and the browser.
|
|
10
|
+
|
|
11
|
+
### CLI
|
|
12
|
+
|
|
13
|
+
Three commands: `pack` (directory to archive), `unpack` (archive to directory), `finalize` (compute hashes for AI-generated archives). Supports `.gitignore` and `.mdmeldignore` patterns.
|
|
14
|
+
|
|
15
|
+
### Web tool
|
|
16
|
+
|
|
17
|
+
Static single-page app with drag-and-drop folder upload, copy-to-clipboard, and download. Dark terminal-aesthetic theme. Built with Vite (61KB JS, 4KB CSS).
|
|
18
|
+
|
|
19
|
+
### Archive format v1.0
|
|
20
|
+
|
|
21
|
+
Human-readable markdown with YAML frontmatter. Position metadata enables AI assistants to navigate directly to specific files. Integrity hashes (xxh64 or sha256) for verification. Backtick fence width auto-resolution (4-8).
|
|
22
|
+
|
|
23
|
+
## Breaking changes
|
|
24
|
+
|
|
25
|
+
None. Initial release.
|
|
26
|
+
|
|
27
|
+
## Migration
|
|
28
|
+
|
|
29
|
+
N/A — initial release.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
unpack
|
|
4
|
+
} from "./chunk-UF532LMZ.js";
|
|
5
|
+
import "./chunk-UJZ43GZC.js";
|
|
6
|
+
|
|
7
|
+
// src/cli/commands/unpack.ts
|
|
8
|
+
import { mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
9
|
+
import { dirname, join, resolve } from "path";
|
|
10
|
+
async function runUnpack(args) {
|
|
11
|
+
const filePath = resolve(args.file);
|
|
12
|
+
const content = readFileSync(filePath, "utf-8");
|
|
13
|
+
const outputDir = resolve(args.output ?? ".");
|
|
14
|
+
const result = await unpack(content);
|
|
15
|
+
for (const file of result.files) {
|
|
16
|
+
const outPath = join(outputDir, file.path);
|
|
17
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
18
|
+
writeFileSync(outPath, file.content);
|
|
19
|
+
}
|
|
20
|
+
console.log(`Unpacked ${result.files.length} files \u2192 ${outputDir}`);
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
runUnpack
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=unpack-2BBZMGLH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/commands/unpack.ts"],"sourcesContent":["import { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { unpack } from \"../../core/index.js\";\n\nexport interface UnpackArgs {\n\tfile: string;\n\toutput?: string;\n}\n\nexport async function runUnpack(args: UnpackArgs): Promise<void> {\n\tconst filePath = resolve(args.file);\n\tconst content = readFileSync(filePath, \"utf-8\");\n\tconst outputDir = resolve(args.output ?? \".\");\n\n\tconst result = await unpack(content);\n\n\tfor (const file of result.files) {\n\t\tconst outPath = join(outputDir, file.path);\n\t\tmkdirSync(dirname(outPath), { recursive: true });\n\t\twriteFileSync(outPath, file.content);\n\t}\n\n\tconsole.log(`Unpacked ${result.files.length} files → ${outputDir}`);\n}\n"],"mappings":";;;;;;;AAAA,SAAS,WAAW,cAAc,qBAAqB;AACvD,SAAS,SAAS,MAAM,eAAe;AAQvC,eAAsB,UAAU,MAAiC;AAChE,QAAM,WAAW,QAAQ,KAAK,IAAI;AAClC,QAAM,UAAU,aAAa,UAAU,OAAO;AAC9C,QAAM,YAAY,QAAQ,KAAK,UAAU,GAAG;AAE5C,QAAM,SAAS,MAAM,OAAO,OAAO;AAEnC,aAAW,QAAQ,OAAO,OAAO;AAChC,UAAM,UAAU,KAAK,WAAW,KAAK,IAAI;AACzC,cAAU,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AAC/C,kBAAc,SAAS,KAAK,OAAO;AAAA,EACpC;AAEA,UAAQ,IAAI,YAAY,OAAO,MAAM,MAAM,iBAAY,SAAS,EAAE;AACnE;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mdmeld",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Pack directory trees into a single markdown file for sharing with AI assistants",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/3leaps/mdmeld.git"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"mdmeld",
|
|
13
|
+
"markdown",
|
|
14
|
+
"archive",
|
|
15
|
+
"pack",
|
|
16
|
+
"ai",
|
|
17
|
+
"collaboration"
|
|
18
|
+
],
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
22
|
+
"bin": {
|
|
23
|
+
"mdmeld": "./dist/cli/index.js"
|
|
24
|
+
},
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/core/index.d.ts",
|
|
28
|
+
"import": "./dist/core/index.js",
|
|
29
|
+
"require": "./dist/core/index.cjs"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"main": "./dist/core/index.cjs",
|
|
33
|
+
"module": "./dist/core/index.js",
|
|
34
|
+
"types": "./dist/core/index.d.ts",
|
|
35
|
+
"files": [
|
|
36
|
+
"dist/",
|
|
37
|
+
"LICENSE",
|
|
38
|
+
"README.md"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsup",
|
|
42
|
+
"dev": "vite web",
|
|
43
|
+
"build:web": "vite build web",
|
|
44
|
+
"test": "vitest run",
|
|
45
|
+
"test:watch": "vitest",
|
|
46
|
+
"lint": "biome check src/ test/",
|
|
47
|
+
"lint:fix": "biome check --write src/ test/",
|
|
48
|
+
"check-types": "tsc --noEmit",
|
|
49
|
+
"check-all": "npm run check-types && npm run lint && npm run test"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"ignore": "^7.0.4",
|
|
53
|
+
"js-yaml": "^4.1.0",
|
|
54
|
+
"xxhash-wasm": "^1.1.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@biomejs/biome": "^2.2.5",
|
|
58
|
+
"@types/js-yaml": "^4.0.9",
|
|
59
|
+
"@types/node": "^22.0.0",
|
|
60
|
+
"tsup": "^8.3.0",
|
|
61
|
+
"typescript": "^5.7.2",
|
|
62
|
+
"vite": "^6.0.0",
|
|
63
|
+
"vitest": "^4.0.18"
|
|
64
|
+
}
|
|
65
|
+
}
|