@shadow-garden/bapbong-model 0.2.1 → 0.3.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/index.cjs CHANGED
@@ -28,10 +28,23 @@ module.exports = __toCommonJS(index_exports);
28
28
 
29
29
  // packages/model/src/lib/model.ts
30
30
  var import_prosemirror_model = require("prosemirror-model");
31
+ function dataJson(el, name) {
32
+ const raw = el.getAttribute(name);
33
+ if (!raw) return null;
34
+ try {
35
+ return JSON.parse(raw);
36
+ } catch {
37
+ return null;
38
+ }
39
+ }
31
40
  function pastedParagraphAttrs(el, heading) {
32
41
  const style = el.getAttribute("style") ?? "";
33
42
  const m = /(?:^|;)\s*text-align\s*:\s*(center|right|justify)/i.exec(style);
34
- return { heading, align: m ? m[1].toLowerCase() : null };
43
+ return {
44
+ heading,
45
+ align: m ? m[1].toLowerCase() : null,
46
+ borders: dataJson(el, "data-borders")
47
+ };
35
48
  }
36
49
  function pastedImageAttrs(el) {
37
50
  const e = el;
@@ -52,6 +65,24 @@ function pastedLinkAttrs(el) {
52
65
  const href = (el.getAttribute("href") ?? "").trim();
53
66
  return /^(https?:|mailto:|#)/i.test(href) ? { href } : false;
54
67
  }
68
+ function pastedCellAttrs(el) {
69
+ const e = el;
70
+ const span = (name) => {
71
+ const n = parseInt(e.getAttribute(name) ?? "1", 10);
72
+ return Number.isFinite(n) && n > 0 ? n : 1;
73
+ };
74
+ const style = e.getAttribute("style") ?? "";
75
+ const bg = /(?:^|;)\s*background-color\s*:\s*([^;]+)/i.exec(style);
76
+ return {
77
+ colspan: span("colspan"),
78
+ rowspan: span("rowspan"),
79
+ colwidth: dataJson(el, "data-colwidth"),
80
+ background: bg ? bg[1].trim() : null,
81
+ vAlign: e.getAttribute("data-valign"),
82
+ borders: dataJson(el, "data-borders"),
83
+ padding: dataJson(el, "data-padding")
84
+ };
85
+ }
55
86
  var schema = new import_prosemirror_model.Schema({
56
87
  nodes: {
57
88
  doc: {
@@ -119,6 +150,8 @@ var schema = new import_prosemirror_model.Schema({
119
150
  const tag = attrs.heading ? `h${attrs.heading}` : "p";
120
151
  const dom = style ? { style } : {};
121
152
  if (attrs.styleId) dom["data-style"] = attrs.styleId;
153
+ if (node.attrs["borders"])
154
+ dom["data-borders"] = JSON.stringify(node.attrs["borders"]);
122
155
  return [tag, dom, 0];
123
156
  }
124
157
  },
@@ -201,12 +234,28 @@ var schema = new import_prosemirror_model.Schema({
201
234
  // w:tblPr/w:jc — 'center' | 'right' table alignment, or null (left).
202
235
  align: { default: null }
203
236
  },
204
- parseDOM: [{ tag: "table" }],
205
- toDOM: (node) => [
206
- "table",
207
- node.attrs["borders"] ? { "data-borders": "1" } : {},
208
- ["tbody", 0]
209
- ]
237
+ // Complex attrs round-trip as data-* JSON — ProseMirror's clipboard is
238
+ // a toDOM parseDOM pass, so without this an internal copy/paste
239
+ // dropped borders / cell padding / alignment.
240
+ parseDOM: [
241
+ {
242
+ tag: "table",
243
+ getAttrs: (el) => ({
244
+ borders: dataJson(el, "data-borders"),
245
+ cellPadding: dataJson(el, "data-cell-padding"),
246
+ align: el.getAttribute("data-align")
247
+ })
248
+ }
249
+ ],
250
+ toDOM: (node) => {
251
+ const a = node.attrs;
252
+ const dom = {};
253
+ if (a["borders"]) dom["data-borders"] = JSON.stringify(a["borders"]);
254
+ if (a["cellPadding"])
255
+ dom["data-cell-padding"] = JSON.stringify(a["cellPadding"]);
256
+ if (a["align"]) dom["data-align"] = String(a["align"]);
257
+ return ["table", dom, ["tbody", 0]];
258
+ }
210
259
  },
211
260
  table_row: {
212
261
  content: "table_cell+",
@@ -219,10 +268,24 @@ var schema = new import_prosemirror_model.Schema({
219
268
  // w:trHeight — { value: px, exact: boolean } or null (auto).
220
269
  height: { default: null }
221
270
  },
222
- // No getAttrs (same rationale as paragraph): the importer sets attrs
223
- // directly; revisit when HTML paste lands.
224
- parseDOM: [{ tag: "tr" }],
225
- toDOM: (node) => node.attrs["header"] ? ["tr", { "data-header": "true" }, 0] : ["tr", 0]
271
+ parseDOM: [
272
+ {
273
+ tag: "tr",
274
+ getAttrs: (el) => ({
275
+ header: el.getAttribute("data-header") === "true",
276
+ cantSplit: el.getAttribute("data-cant-split") === "true",
277
+ height: dataJson(el, "data-height")
278
+ })
279
+ }
280
+ ],
281
+ toDOM: (node) => {
282
+ const dom = {};
283
+ if (node.attrs["header"]) dom["data-header"] = "true";
284
+ if (node.attrs["cantSplit"]) dom["data-cant-split"] = "true";
285
+ if (node.attrs["height"])
286
+ dom["data-height"] = JSON.stringify(node.attrs["height"]);
287
+ return ["tr", dom, 0];
288
+ }
226
289
  },
227
290
  table_cell: {
228
291
  content: "block+",
@@ -241,7 +304,10 @@ var schema = new import_prosemirror_model.Schema({
241
304
  padding: { default: null }
242
305
  // w:tcMar per-side margin override (px)
243
306
  },
244
- parseDOM: [{ tag: "td" }, { tag: "th" }],
307
+ parseDOM: [
308
+ { tag: "td", getAttrs: pastedCellAttrs },
309
+ { tag: "th", getAttrs: pastedCellAttrs }
310
+ ],
245
311
  toDOM(node) {
246
312
  const attrs = {};
247
313
  if (node.attrs["colspan"] !== 1)
@@ -250,6 +316,14 @@ var schema = new import_prosemirror_model.Schema({
250
316
  attrs["rowspan"] = String(node.attrs["rowspan"]);
251
317
  if (node.attrs["background"])
252
318
  attrs["style"] = `background-color: ${node.attrs["background"]}`;
319
+ if (node.attrs["colwidth"])
320
+ attrs["data-colwidth"] = JSON.stringify(node.attrs["colwidth"]);
321
+ if (node.attrs["vAlign"])
322
+ attrs["data-valign"] = String(node.attrs["vAlign"]);
323
+ if (node.attrs["borders"])
324
+ attrs["data-borders"] = JSON.stringify(node.attrs["borders"]);
325
+ if (node.attrs["padding"])
326
+ attrs["data-padding"] = JSON.stringify(node.attrs["padding"]);
253
327
  return ["td", attrs, 0];
254
328
  }
255
329
  }
@@ -513,6 +587,8 @@ function formatCounter(n, fmt) {
513
587
  return toRoman(n).toLowerCase();
514
588
  case "upperRoman":
515
589
  return toRoman(n);
590
+ case "decimalZero":
591
+ return String(n).padStart(2, "0");
516
592
  default:
517
593
  return String(n);
518
594
  }
package/dist/index.js CHANGED
@@ -1,9 +1,22 @@
1
1
  // packages/model/src/lib/model.ts
2
2
  import { Schema } from "prosemirror-model";
3
+ function dataJson(el, name) {
4
+ const raw = el.getAttribute(name);
5
+ if (!raw) return null;
6
+ try {
7
+ return JSON.parse(raw);
8
+ } catch {
9
+ return null;
10
+ }
11
+ }
3
12
  function pastedParagraphAttrs(el, heading) {
4
13
  const style = el.getAttribute("style") ?? "";
5
14
  const m = /(?:^|;)\s*text-align\s*:\s*(center|right|justify)/i.exec(style);
6
- return { heading, align: m ? m[1].toLowerCase() : null };
15
+ return {
16
+ heading,
17
+ align: m ? m[1].toLowerCase() : null,
18
+ borders: dataJson(el, "data-borders")
19
+ };
7
20
  }
8
21
  function pastedImageAttrs(el) {
9
22
  const e = el;
@@ -24,6 +37,24 @@ function pastedLinkAttrs(el) {
24
37
  const href = (el.getAttribute("href") ?? "").trim();
25
38
  return /^(https?:|mailto:|#)/i.test(href) ? { href } : false;
26
39
  }
40
+ function pastedCellAttrs(el) {
41
+ const e = el;
42
+ const span = (name) => {
43
+ const n = parseInt(e.getAttribute(name) ?? "1", 10);
44
+ return Number.isFinite(n) && n > 0 ? n : 1;
45
+ };
46
+ const style = e.getAttribute("style") ?? "";
47
+ const bg = /(?:^|;)\s*background-color\s*:\s*([^;]+)/i.exec(style);
48
+ return {
49
+ colspan: span("colspan"),
50
+ rowspan: span("rowspan"),
51
+ colwidth: dataJson(el, "data-colwidth"),
52
+ background: bg ? bg[1].trim() : null,
53
+ vAlign: e.getAttribute("data-valign"),
54
+ borders: dataJson(el, "data-borders"),
55
+ padding: dataJson(el, "data-padding")
56
+ };
57
+ }
27
58
  var schema = new Schema({
28
59
  nodes: {
29
60
  doc: {
@@ -91,6 +122,8 @@ var schema = new Schema({
91
122
  const tag = attrs.heading ? `h${attrs.heading}` : "p";
92
123
  const dom = style ? { style } : {};
93
124
  if (attrs.styleId) dom["data-style"] = attrs.styleId;
125
+ if (node.attrs["borders"])
126
+ dom["data-borders"] = JSON.stringify(node.attrs["borders"]);
94
127
  return [tag, dom, 0];
95
128
  }
96
129
  },
@@ -173,12 +206,28 @@ var schema = new Schema({
173
206
  // w:tblPr/w:jc — 'center' | 'right' table alignment, or null (left).
174
207
  align: { default: null }
175
208
  },
176
- parseDOM: [{ tag: "table" }],
177
- toDOM: (node) => [
178
- "table",
179
- node.attrs["borders"] ? { "data-borders": "1" } : {},
180
- ["tbody", 0]
181
- ]
209
+ // Complex attrs round-trip as data-* JSON — ProseMirror's clipboard is
210
+ // a toDOM parseDOM pass, so without this an internal copy/paste
211
+ // dropped borders / cell padding / alignment.
212
+ parseDOM: [
213
+ {
214
+ tag: "table",
215
+ getAttrs: (el) => ({
216
+ borders: dataJson(el, "data-borders"),
217
+ cellPadding: dataJson(el, "data-cell-padding"),
218
+ align: el.getAttribute("data-align")
219
+ })
220
+ }
221
+ ],
222
+ toDOM: (node) => {
223
+ const a = node.attrs;
224
+ const dom = {};
225
+ if (a["borders"]) dom["data-borders"] = JSON.stringify(a["borders"]);
226
+ if (a["cellPadding"])
227
+ dom["data-cell-padding"] = JSON.stringify(a["cellPadding"]);
228
+ if (a["align"]) dom["data-align"] = String(a["align"]);
229
+ return ["table", dom, ["tbody", 0]];
230
+ }
182
231
  },
183
232
  table_row: {
184
233
  content: "table_cell+",
@@ -191,10 +240,24 @@ var schema = new Schema({
191
240
  // w:trHeight — { value: px, exact: boolean } or null (auto).
192
241
  height: { default: null }
193
242
  },
194
- // No getAttrs (same rationale as paragraph): the importer sets attrs
195
- // directly; revisit when HTML paste lands.
196
- parseDOM: [{ tag: "tr" }],
197
- toDOM: (node) => node.attrs["header"] ? ["tr", { "data-header": "true" }, 0] : ["tr", 0]
243
+ parseDOM: [
244
+ {
245
+ tag: "tr",
246
+ getAttrs: (el) => ({
247
+ header: el.getAttribute("data-header") === "true",
248
+ cantSplit: el.getAttribute("data-cant-split") === "true",
249
+ height: dataJson(el, "data-height")
250
+ })
251
+ }
252
+ ],
253
+ toDOM: (node) => {
254
+ const dom = {};
255
+ if (node.attrs["header"]) dom["data-header"] = "true";
256
+ if (node.attrs["cantSplit"]) dom["data-cant-split"] = "true";
257
+ if (node.attrs["height"])
258
+ dom["data-height"] = JSON.stringify(node.attrs["height"]);
259
+ return ["tr", dom, 0];
260
+ }
198
261
  },
199
262
  table_cell: {
200
263
  content: "block+",
@@ -213,7 +276,10 @@ var schema = new Schema({
213
276
  padding: { default: null }
214
277
  // w:tcMar per-side margin override (px)
215
278
  },
216
- parseDOM: [{ tag: "td" }, { tag: "th" }],
279
+ parseDOM: [
280
+ { tag: "td", getAttrs: pastedCellAttrs },
281
+ { tag: "th", getAttrs: pastedCellAttrs }
282
+ ],
217
283
  toDOM(node) {
218
284
  const attrs = {};
219
285
  if (node.attrs["colspan"] !== 1)
@@ -222,6 +288,14 @@ var schema = new Schema({
222
288
  attrs["rowspan"] = String(node.attrs["rowspan"]);
223
289
  if (node.attrs["background"])
224
290
  attrs["style"] = `background-color: ${node.attrs["background"]}`;
291
+ if (node.attrs["colwidth"])
292
+ attrs["data-colwidth"] = JSON.stringify(node.attrs["colwidth"]);
293
+ if (node.attrs["vAlign"])
294
+ attrs["data-valign"] = String(node.attrs["vAlign"]);
295
+ if (node.attrs["borders"])
296
+ attrs["data-borders"] = JSON.stringify(node.attrs["borders"]);
297
+ if (node.attrs["padding"])
298
+ attrs["data-padding"] = JSON.stringify(node.attrs["padding"]);
225
299
  return ["td", attrs, 0];
226
300
  }
227
301
  }
@@ -485,6 +559,8 @@ function formatCounter(n, fmt) {
485
559
  return toRoman(n).toLowerCase();
486
560
  case "upperRoman":
487
561
  return toRoman(n);
562
+ case "decimalZero":
563
+ return String(n).padStart(2, "0");
488
564
  default:
489
565
  return String(n);
490
566
  }
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/lib/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AA0C3C;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,2PAkWjB,CAAC;AAEH,wEAAwE;AACxE,MAAM,MAAM,aAAa,GAAG,OAAO,MAAM,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,aAAa,yDA0CxB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC;AAEjD,qDAAqD;AACrD,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAE5D;+EAC+E;AAC/E,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,2EAA2E;AAC3E,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACzC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAAC;CACvC;AA0BD;;;4EAG4E;AAC5E,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/lib/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAgF3C;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,2PA4YjB,CAAC;AAEH,wEAAwE;AACxE,MAAM,MAAM,aAAa,GAAG,OAAO,MAAM,CAAC;AAE1C;;;;;GAKG;AACH,eAAO,MAAM,aAAa,yDA0CxB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC;AAEjD,qDAAqD;AACrD,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAE5D;+EAC+E;AAC/E,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,2EAA2E;AAC3E,MAAM,WAAW,OAAO;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACzC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAAC;CACvC;AA0BD;;;4EAG4E;AAC5E,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"numbering.d.ts","sourceRoot":"","sources":["../../src/lib/numbering.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;+EAC+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,CAAC,KAAK,EAAE,MAAM,GAAG;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;KAC3C,CAAC;CACH;AAED,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5C;AA8CD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,GAAG,gBAAgB,CA2B/F"}
1
+ {"version":3,"file":"numbering.d.ts","sourceRoot":"","sources":["../../src/lib/numbering.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,8EAA8E;AAC9E,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;+EAC+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,CAAC,KAAK,EAAE,MAAM,GAAG;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;KAC3C,CAAC;CACH;AAED,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5C;AA2DD,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,GACrC,gBAAgB,CA2BlB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shadow-garden/bapbong-model",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "bapbong — ProseMirror document model / schema",
5
5
  "license": "MIT",
6
6
  "repository": {