@dogsbay/serialize-core 0.2.0-beta.98
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/capability.d.ts +142 -0
- package/dist/capability.d.ts.map +1 -0
- package/dist/capability.js +189 -0
- package/dist/capability.js.map +1 -0
- package/dist/includes.d.ts +68 -0
- package/dist/includes.d.ts.map +1 -0
- package/dist/includes.js +94 -0
- package/dist/includes.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/inline.d.ts +141 -0
- package/dist/inline.d.ts.map +1 -0
- package/dist/inline.js +183 -0
- package/dist/inline.js.map +1 -0
- package/dist/plugins.d.ts +99 -0
- package/dist/plugins.d.ts.map +1 -0
- package/dist/plugins.js +119 -0
- package/dist/plugins.js.map +1 -0
- package/dist/reads.d.ts +165 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +268 -0
- package/dist/reads.js.map +1 -0
- package/dist/text.d.ts +55 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +191 -0
- package/dist/text.js.map +1 -0
- package/dist/unknown.d.ts +39 -0
- package/dist/unknown.d.ts.map +1 -0
- package/dist/unknown.js +34 -0
- package/dist/unknown.js.map +1 -0
- package/package.json +42 -0
package/dist/text.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format-agnostic text utilities.
|
|
3
|
+
*
|
|
4
|
+
* These are byte-identical (or strictly stronger) versions of helpers
|
|
5
|
+
* currently duplicated across serializers: `indent` exists three times
|
|
6
|
+
* (format-dogsbay-md, format-obsidian, format-astro's `indentStr`), and
|
|
7
|
+
* format-obsidian's `chooseFence` is a weaker `pickCodeFence` (hardcoded
|
|
8
|
+
* backtick, `match` instead of `matchAll`).
|
|
9
|
+
*
|
|
10
|
+
* Only genuinely universal helpers live here. Per-dialect escaping
|
|
11
|
+
* (CommonMark text escaping, Astro brace-neutralising, dogsbay-md attribute
|
|
12
|
+
* syntax) stays in its own package — those profiles are not interchangeable.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Choose a fence long enough to wrap `content` without being terminated early.
|
|
16
|
+
*
|
|
17
|
+
* Scans for the longest run of the fence character and returns one longer,
|
|
18
|
+
* with a minimum of three.
|
|
19
|
+
*/
|
|
20
|
+
export function pickCodeFence(content, fenceChar = "`") {
|
|
21
|
+
const re = fenceChar === "`" ? /`+/g : /~+/g;
|
|
22
|
+
let max = 2;
|
|
23
|
+
for (const match of content.matchAll(re)) {
|
|
24
|
+
if (match[0].length > max)
|
|
25
|
+
max = match[0].length;
|
|
26
|
+
}
|
|
27
|
+
return fenceChar.repeat(max + 1);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Choose a `:::` directive fence long enough to wrap `content`.
|
|
31
|
+
* Used by markdown dialects with container directives (Docusaurus
|
|
32
|
+
* admonitions, MyST, dogsbay-md).
|
|
33
|
+
*/
|
|
34
|
+
export function pickDirectiveFence(content) {
|
|
35
|
+
let max = 2;
|
|
36
|
+
for (const match of content.matchAll(/:{3,}/g)) {
|
|
37
|
+
if (match[0].length > max)
|
|
38
|
+
max = match[0].length;
|
|
39
|
+
}
|
|
40
|
+
return ":".repeat(max + 1);
|
|
41
|
+
}
|
|
42
|
+
/** Indent every non-empty line by `spaces`. Empty lines stay empty. */
|
|
43
|
+
export function indent(content, spaces) {
|
|
44
|
+
const prefix = " ".repeat(spaces);
|
|
45
|
+
return content
|
|
46
|
+
.split("\n")
|
|
47
|
+
.map((line) => (line ? `${prefix}${line}` : line))
|
|
48
|
+
.join("\n");
|
|
49
|
+
}
|
|
50
|
+
/** Prefix every line, using a trimmed prefix for empty lines (blockquotes). */
|
|
51
|
+
export function prefixLines(content, prefix) {
|
|
52
|
+
return content
|
|
53
|
+
.split("\n")
|
|
54
|
+
.map((line) => (line ? `${prefix}${line}` : prefix.trimEnd()))
|
|
55
|
+
.join("\n");
|
|
56
|
+
}
|
|
57
|
+
/** Collapse 3+ blank lines to 2 and strip trailing whitespace on each line. */
|
|
58
|
+
export function normalizeTrailingWhitespace(content) {
|
|
59
|
+
return content
|
|
60
|
+
.split("\n")
|
|
61
|
+
.map((line) => line.replace(/[ \t]+$/, ""))
|
|
62
|
+
.join("\n")
|
|
63
|
+
.replace(/\n{3,}/g, "\n\n");
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Strip HTML tags, keeping text content — the lossy fallback markdown targets
|
|
67
|
+
* use for HTML they cannot represent. Callers should record the degradation.
|
|
68
|
+
*/
|
|
69
|
+
export function stripHtml(html) {
|
|
70
|
+
return html
|
|
71
|
+
.replace(/<br\s*\/?>/gi, "\n")
|
|
72
|
+
.replace(/<\/p>\s*<p[^>]*>/gi, "\n\n")
|
|
73
|
+
// Comments and doctype are not tag-shaped (no letter after `<`), so the
|
|
74
|
+
// letter-anchored pattern below skips them. markdown-it really does hand
|
|
75
|
+
// importers `<!-- … -->` inside prose html, which then leaked as literal
|
|
76
|
+
// markup into plain-text contexts (step titles, table cells).
|
|
77
|
+
.replace(/<!--[\s\S]*?-->/g, "")
|
|
78
|
+
.replace(/<![^>]*>/g, "")
|
|
79
|
+
// An image is CONTENT, not markup: dropping the tag whole loses the alt
|
|
80
|
+
// text and every trace that a picture was there. Recovered as markdown
|
|
81
|
+
// image syntax before the generic tag sweep below.
|
|
82
|
+
//
|
|
83
|
+
// format-obsidian carried this rule locally and lost it when it adopted
|
|
84
|
+
// this function — measured: `See <img src="a.png" alt="Diagram of the
|
|
85
|
+
// flow">` became `See ` on a real mkdocs->obsidian conversion, because
|
|
86
|
+
// markdown-it hands importers raw `<img>` inside prose HTML routinely.
|
|
87
|
+
.replace(/<img\b(?:[^>"']|"[^"]*"|'[^']*')*>/gi, (tag) => {
|
|
88
|
+
const alt = /\balt\s*=\s*"([^"]*)"/i.exec(tag)?.[1]
|
|
89
|
+
?? /\balt\s*=\s*'([^']*)'/i.exec(tag)?.[1];
|
|
90
|
+
const src = /\bsrc\s*=\s*"([^"]*)"/i.exec(tag)?.[1]
|
|
91
|
+
?? /\bsrc\s*=\s*'([^']*)'/i.exec(tag)?.[1];
|
|
92
|
+
if (!alt && !src)
|
|
93
|
+
return "";
|
|
94
|
+
return src ? `` : `![${alt ?? ""}]`;
|
|
95
|
+
})
|
|
96
|
+
// Skip quoted attribute runs so a `>` inside an attribute doesn't end the tag early.
|
|
97
|
+
.replace(/<\/?[A-Za-z][^\s>]*(?:[^>"']|"[^"]*"|'[^']*')*>/g, "")
|
|
98
|
+
.replace(/&/g, "&")
|
|
99
|
+
.replace(/</g, "<")
|
|
100
|
+
.replace(/>/g, ">")
|
|
101
|
+
.replace(/"/g, '"')
|
|
102
|
+
.replace(/'/g, "'")
|
|
103
|
+
.trim();
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Convert common INLINE HTML back to markdown.
|
|
107
|
+
*
|
|
108
|
+
* Importers frequently hand serializers pre-rendered HTML for prose
|
|
109
|
+
* (`<code>x</code>`, `<strong>y</strong>`). Passing it through works in
|
|
110
|
+
* MDX-ish targets but produces source no human wants to maintain — and the
|
|
111
|
+
* point of a migration is clean, editable markdown.
|
|
112
|
+
*
|
|
113
|
+
* Deliberately conservative: only unambiguous inline tags, non-greedy, and
|
|
114
|
+
* block-level markup is left completely alone (a regex cannot restructure
|
|
115
|
+
* tables or lists safely). Anything not listed here survives as raw HTML.
|
|
116
|
+
*/
|
|
117
|
+
export function inlineHtmlToMarkdown(html) {
|
|
118
|
+
// Code spans are converted FIRST and then masked, so the emphasis/link rules
|
|
119
|
+
// below cannot rewrite markup that is meant to be shown literally
|
|
120
|
+
// (`<code><b>x</b></code>` must stay `<b>x</b>`, not become `**x**`).
|
|
121
|
+
const masked = [];
|
|
122
|
+
let out = html.replace(/<code>([\s\S]*?)<\/code>/gi, (_m, inner) => {
|
|
123
|
+
masked.push(codeSpanText(inner));
|
|
124
|
+
return `\u0000CODE${masked.length - 1}\u0000`;
|
|
125
|
+
});
|
|
126
|
+
out = out
|
|
127
|
+
.replace(/<(?:strong|b)>([\s\S]*?)<\/(?:strong|b)>/gi, "**$1**")
|
|
128
|
+
.replace(/<(?:em|i)>([\s\S]*?)<\/(?:em|i)>/gi, "*$1*")
|
|
129
|
+
.replace(/<(?:del|s|strike)>([\s\S]*?)<\/(?:del|s|strike)>/gi, "~~$1~~")
|
|
130
|
+
.replace(/<mark>([\s\S]*?)<\/mark>/gi, "==$1==")
|
|
131
|
+
.replace(
|
|
132
|
+
// `[^>]*` would stop at a `>` inside another attribute value
|
|
133
|
+
// (`<a href="x" title="a > b">`), so skip quoted runs explicitly.
|
|
134
|
+
/<a\s+href="([^"]*)"(?:[^>"']|"[^"]*"|'[^']*')*>([\s\S]*?)<\/a>/gi, (_m, href, text) => `[${text}](${href})`)
|
|
135
|
+
.replace(/<br\s*\/?>/gi, " \n");
|
|
136
|
+
return out.replace(/\u0000CODE(\d+)\u0000/g, (_m, i) => masked[Number(i)]);
|
|
137
|
+
}
|
|
138
|
+
/** CommonMark code span (see serialize-core `codeSpan`; duplicated here to keep
|
|
139
|
+
* text.ts free of an inline.ts import cycle). */
|
|
140
|
+
function codeSpanText(text) {
|
|
141
|
+
const longest = (text.match(/`+/g) ?? []).reduce((max, run) => Math.max(max, run.length), 0);
|
|
142
|
+
const fence = "`".repeat(longest + 1);
|
|
143
|
+
const needsPad = text.length === 0 ||
|
|
144
|
+
text.startsWith("`") || text.endsWith("`") ||
|
|
145
|
+
text.startsWith(" ") || text.endsWith(" ");
|
|
146
|
+
const pad = needsPad ? " " : "";
|
|
147
|
+
return `${fence}${pad}${text}${pad}${fence}`;
|
|
148
|
+
}
|
|
149
|
+
/** Serialize a value as YAML frontmatter scalar, quoting when required. */
|
|
150
|
+
export function yamlScalar(value) {
|
|
151
|
+
if (value === "")
|
|
152
|
+
return '""';
|
|
153
|
+
const needsQuote =
|
|
154
|
+
// structural / indicator characters
|
|
155
|
+
/[:#[\]{}&*!|>'"%@`,]/.test(value) ||
|
|
156
|
+
// leading indicators YAML reads as block syntax
|
|
157
|
+
/^[-?]/.test(value) ||
|
|
158
|
+
// surrounding whitespace, or any newline
|
|
159
|
+
/^\s|\s$/.test(value) ||
|
|
160
|
+
/[\n\r]/.test(value) ||
|
|
161
|
+
// values YAML 1.1 would coerce to a non-string: booleans, null, numbers
|
|
162
|
+
// (incl. hex/octal/binary/exponent), dates. A page titled "123" or "null"
|
|
163
|
+
// must stay a STRING in frontmatter.
|
|
164
|
+
/^(?:true|false|yes|no|on|off|null|~)$/i.test(value) ||
|
|
165
|
+
/^[+-]?(?:\d[\d_]*(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/.test(value) ||
|
|
166
|
+
/^0[bxo][0-9a-fA-F_]+$/i.test(value) ||
|
|
167
|
+
// YAML 1.1 float specials — `.inf` loads as Infinity, `.nan` as NaN.
|
|
168
|
+
/^[-+]?\.(?:inf|nan)$/i.test(value) ||
|
|
169
|
+
/^\d{4}-\d{2}-\d{2}/.test(value);
|
|
170
|
+
if (needsQuote) {
|
|
171
|
+
// Newlines MUST be escaped, not embedded: a literal `\n---\n` inside a
|
|
172
|
+
// quoted scalar terminates the frontmatter block early and the file no
|
|
173
|
+
// longer parses.
|
|
174
|
+
return `"${value
|
|
175
|
+
.replace(/\\/g, "\\\\")
|
|
176
|
+
.replace(/"/g, '\\"')
|
|
177
|
+
.replace(/\n/g, "\\n")
|
|
178
|
+
.replace(/\r/g, "\\r")}"`;
|
|
179
|
+
}
|
|
180
|
+
return value;
|
|
181
|
+
}
|
|
182
|
+
/** Build a YAML frontmatter block from ordered entries. Empty → "". */
|
|
183
|
+
export function frontmatterBlock(entries) {
|
|
184
|
+
const lines = entries
|
|
185
|
+
.filter((e) => e[1] !== undefined)
|
|
186
|
+
.map(([key, value]) => typeof value === "string" ? `${key}: ${yamlScalar(value)}` : `${key}: ${value}`);
|
|
187
|
+
if (lines.length === 0)
|
|
188
|
+
return "";
|
|
189
|
+
return `---\n${lines.join("\n")}\n---`;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=text.js.map
|
package/dist/text.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../src/text.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unknown / unsupported block-node fallback.
|
|
3
|
+
*
|
|
4
|
+
* Generalises `format-dogsbay-md`'s `renderUnknown`, with one deliberate
|
|
5
|
+
* change: **the loss is recorded.** The original's `skip` mode returns `""`
|
|
6
|
+
* and tells nobody, which is precisely the silent-loss failure this package
|
|
7
|
+
* exists to end.
|
|
8
|
+
*
|
|
9
|
+
* The three existing peer fallbacks (dogsbay-md's configurable one, obsidian's
|
|
10
|
+
* `stripHtml`-or-children, astro's children-or-empty) are all expressible
|
|
11
|
+
* here.
|
|
12
|
+
*/
|
|
13
|
+
import type { TreeNode } from "@dogsbay/types";
|
|
14
|
+
export type UnknownNodePolicy =
|
|
15
|
+
/** Emit `node.html`, else children, else a comment. Most content-preserving. */
|
|
16
|
+
"html"
|
|
17
|
+
/** Emit a visible marker comment only. */
|
|
18
|
+
| "comment"
|
|
19
|
+
/** Emit nothing. Loss is still recorded. */
|
|
20
|
+
| "skip";
|
|
21
|
+
export interface UnknownNodeOptions {
|
|
22
|
+
policy?: UnknownNodePolicy;
|
|
23
|
+
/** Render child nodes (needed by the "html" policy). */
|
|
24
|
+
renderChildren?: (children: TreeNode[]) => string;
|
|
25
|
+
/** How to write a comment in the target format. Default: HTML comment. */
|
|
26
|
+
comment?: (text: string) => string;
|
|
27
|
+
/** Loss recorder — wire to an `ExportLedger`. */
|
|
28
|
+
report?: (feature: string, detail?: string) => void;
|
|
29
|
+
/** Separator when falling back to children. */
|
|
30
|
+
join?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Render a node whose type the exporter has no mapping for.
|
|
34
|
+
*
|
|
35
|
+
* Always records the event before returning, so an exporter cannot lose
|
|
36
|
+
* content without it appearing in the ledger.
|
|
37
|
+
*/
|
|
38
|
+
export declare function renderUnknownNode(node: TreeNode, options?: UnknownNodeOptions): string;
|
|
39
|
+
//# sourceMappingURL=unknown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unknown.d.ts","sourceRoot":"","sources":["../src/unknown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,MAAM,iBAAiB;AAC3B,gFAAgF;AAC9E,MAAM;AACR,0CAA0C;GACxC,SAAS;AACX,4CAA4C;GAC1C,MAAM,CAAC;AAEX,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,wDAAwD;IACxD,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,MAAM,CAAC;IAClD,0EAA0E;IAC1E,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,iDAAiD;IACjD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,QAAQ,EACd,OAAO,GAAE,kBAAuB,GAC/B,MAAM,CAgCR"}
|
package/dist/unknown.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render a node whose type the exporter has no mapping for.
|
|
3
|
+
*
|
|
4
|
+
* Always records the event before returning, so an exporter cannot lose
|
|
5
|
+
* content without it appearing in the ledger.
|
|
6
|
+
*/
|
|
7
|
+
export function renderUnknownNode(node, options = {}) {
|
|
8
|
+
const policy = options.policy ?? "html";
|
|
9
|
+
const comment = options.comment ?? ((text) => `<!-- ${text} -->`);
|
|
10
|
+
const report = options.report ?? (() => { });
|
|
11
|
+
const join = options.join ?? "\n\n";
|
|
12
|
+
switch (policy) {
|
|
13
|
+
case "skip":
|
|
14
|
+
report(node.type, "unsupported node type — omitted from output");
|
|
15
|
+
return "";
|
|
16
|
+
case "comment":
|
|
17
|
+
report(node.type, "unsupported node type — replaced with a comment");
|
|
18
|
+
return comment(`unsupported: ${node.type}`);
|
|
19
|
+
case "html":
|
|
20
|
+
default: {
|
|
21
|
+
if (node.html) {
|
|
22
|
+
report(node.type, "unsupported node type — emitted as raw HTML");
|
|
23
|
+
return node.html;
|
|
24
|
+
}
|
|
25
|
+
if (node.children && node.children.length > 0 && options.renderChildren) {
|
|
26
|
+
report(node.type, "unsupported node type — wrapper dropped, children preserved");
|
|
27
|
+
return options.renderChildren(node.children);
|
|
28
|
+
}
|
|
29
|
+
report(node.type, "unsupported node type — no content to preserve");
|
|
30
|
+
return comment(`unsupported: ${node.type}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=unknown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unknown.js","sourceRoot":"","sources":["../src/unknown.ts"],"names":[],"mappings":"AAkCA;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAc,EACd,UAA8B,EAAE;IAEhC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC;IACxC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,QAAQ,IAAI,MAAM,CAAC,CAAC;IAC1E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC;IAEpC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,6CAA6C,CAAC,CAAC;YACjE,OAAO,EAAE,CAAC;QAEZ,KAAK,SAAS;YACZ,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,iDAAiD,CAAC,CAAC;YACrE,OAAO,OAAO,CAAC,gBAAgB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAE9C,KAAK,MAAM,CAAC;QACZ,OAAO,CAAC,CAAC,CAAC;YACR,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACd,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,6CAA6C,CAAC,CAAC;gBACjE,OAAO,IAAI,CAAC,IAAI,CAAC;YACnB,CAAC;YACD,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;gBACxE,MAAM,CACJ,IAAI,CAAC,IAAI,EACT,6DAA6D,CAC9D,CAAC;gBACF,OAAO,OAAO,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/C,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,gDAAgD,CAAC,CAAC;YACpE,OAAO,OAAO,CAAC,gBAAgB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dogsbay/serialize-core",
|
|
3
|
+
"version": "0.2.0-beta.98",
|
|
4
|
+
"description": "Shared serializer core — shape-tolerant TreeNode reads, a generic inline walker, fence/indent utilities, and the export capability ledger every format exporter builds on",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md"
|
|
17
|
+
],
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^25.9.5",
|
|
20
|
+
"typescript": "^5.9.3",
|
|
21
|
+
"vitest": "^4.1.10",
|
|
22
|
+
"@dogsbay/format-dogsbay-md": "0.2.0-beta.98"
|
|
23
|
+
},
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@dogsbay/types": "0.2.0-beta.98"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/dogsbay/dogsbay.git",
|
|
31
|
+
"directory": "packages/serialize-core"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/dogsbay/dogsbay/tree/main/packages/serialize-core",
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/dogsbay/dogsbay/issues"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsc",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"test:watch": "vitest"
|
|
41
|
+
}
|
|
42
|
+
}
|