@shadow-garden/bapbong-model 0.4.0 → 0.6.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
@@ -43,7 +43,8 @@ function pastedParagraphAttrs(el, heading) {
43
43
  return {
44
44
  heading,
45
45
  align: m ? m[1].toLowerCase() : null,
46
- borders: dataJson(el, "data-borders")
46
+ borders: dataJson(el, "data-borders"),
47
+ carry: dataJson(el, "data-carry")
47
48
  };
48
49
  }
49
50
  function pastedImageAttrs(el) {
@@ -80,7 +81,8 @@ function pastedCellAttrs(el) {
80
81
  background: bg ? bg[1].trim() : null,
81
82
  vAlign: e.getAttribute("data-valign"),
82
83
  borders: dataJson(el, "data-borders"),
83
- padding: dataJson(el, "data-padding")
84
+ padding: dataJson(el, "data-padding"),
85
+ carry: dataJson(el, "data-carry")
84
86
  };
85
87
  }
86
88
  var schema = new import_prosemirror_model.Schema({
@@ -94,6 +96,10 @@ var schema = new import_prosemirror_model.Schema({
94
96
  // SectionConfig[] (contracts) — per-section column flow, delimited by
95
97
  // w:sectPr breaks. null/absent → one implicit single-column section.
96
98
  sections: { default: null },
99
+ // PageConfig (contracts) — page size + margins in CSS px, from the
100
+ // body w:sectPr. Edited via setDocAttribute (page-setup commands) so
101
+ // orientation/paper-size changes undo cleanly. null → A4 default.
102
+ page: { default: null },
97
103
  // CommentNode[] (contracts) — comment threads keyed to `comment` marks.
98
104
  // Edited via setDocAttribute so add/reply/resolve/delete undo cleanly.
99
105
  comments: { default: null }
@@ -132,7 +138,13 @@ var schema = new import_prosemirror_model.Schema({
132
138
  pageBreakBefore: { default: false },
133
139
  // w:pBdr — { top?, bottom?, left?, right? } of BorderSide, or null.
134
140
  // Importer-set; painted as a box around the paragraph's lines.
135
- borders: { default: null }
141
+ borders: { default: null },
142
+ // Carry-through fidelity (docx round-trip): OOXML paragraph
143
+ // properties the model does NOT represent, preserved verbatim so a
144
+ // customer's save never drops them. { pPr?: string, markRPr?: string }
145
+ // — raw XML fragments (pPr extras / the paragraph-mark w:rPr), or
146
+ // null. Importer-set; the exporter splices them back into w:pPr.
147
+ carry: { default: null }
136
148
  },
137
149
  // HTML paste path: recover heading level from h1–h6 and alignment from
138
150
  // inline style. Other attrs (list/indent/tabs/spacing) stay importer-only
@@ -152,6 +164,8 @@ var schema = new import_prosemirror_model.Schema({
152
164
  if (attrs.styleId) dom["data-style"] = attrs.styleId;
153
165
  if (node.attrs["borders"])
154
166
  dom["data-borders"] = JSON.stringify(node.attrs["borders"]);
167
+ if (node.attrs["carry"])
168
+ dom["data-carry"] = JSON.stringify(node.attrs["carry"]);
155
169
  return [tag, dom, 0];
156
170
  }
157
171
  },
@@ -233,7 +247,12 @@ var schema = new import_prosemirror_model.Schema({
233
247
  // insideV }, or null — OOXML tables are borderless unless declared.
234
248
  borders: { default: null },
235
249
  // w:tblPr/w:jc — 'center' | 'right' table alignment, or null (left).
236
- align: { default: null }
250
+ align: { default: null },
251
+ // Carry-through fidelity: unmodelled w:tblPr children (tblStyle,
252
+ // tblLayout, tblLook, tblInd, floating tblpPr, …) as one raw XML
253
+ // string ({ tblPr: string }), or null. Importer-set; the exporter
254
+ // splices it back so a save never drops them.
255
+ carry: { default: null }
237
256
  },
238
257
  // Complex attrs round-trip as data-* JSON — ProseMirror's clipboard is
239
258
  // a toDOM → parseDOM pass, so without this an internal copy/paste
@@ -244,7 +263,8 @@ var schema = new import_prosemirror_model.Schema({
244
263
  getAttrs: (el) => ({
245
264
  borders: dataJson(el, "data-borders"),
246
265
  cellPadding: dataJson(el, "data-cell-padding"),
247
- align: el.getAttribute("data-align")
266
+ align: el.getAttribute("data-align"),
267
+ carry: dataJson(el, "data-carry")
248
268
  })
249
269
  }
250
270
  ],
@@ -255,6 +275,7 @@ var schema = new import_prosemirror_model.Schema({
255
275
  if (a["cellPadding"])
256
276
  dom["data-cell-padding"] = JSON.stringify(a["cellPadding"]);
257
277
  if (a["align"]) dom["data-align"] = String(a["align"]);
278
+ if (a["carry"]) dom["data-carry"] = JSON.stringify(a["carry"]);
258
279
  return ["table", dom, ["tbody", 0]];
259
280
  }
260
281
  },
@@ -267,7 +288,10 @@ var schema = new import_prosemirror_model.Schema({
267
288
  // (Word's default) means the paginator may split the row mid-content.
268
289
  cantSplit: { default: false },
269
290
  // w:trHeight — { value: px, exact: boolean } or null (auto).
270
- height: { default: null }
291
+ height: { default: null },
292
+ // Carry-through fidelity: unmodelled w:trPr children ({ trPr: string
293
+ // } — gridBefore/wBefore, cnfStyle, …), or null. Importer-set.
294
+ carry: { default: null }
271
295
  },
272
296
  parseDOM: [
273
297
  {
@@ -275,7 +299,8 @@ var schema = new import_prosemirror_model.Schema({
275
299
  getAttrs: (el) => ({
276
300
  header: el.getAttribute("data-header") === "true",
277
301
  cantSplit: el.getAttribute("data-cant-split") === "true",
278
- height: dataJson(el, "data-height")
302
+ height: dataJson(el, "data-height"),
303
+ carry: dataJson(el, "data-carry")
279
304
  })
280
305
  }
281
306
  ],
@@ -285,6 +310,8 @@ var schema = new import_prosemirror_model.Schema({
285
310
  if (node.attrs["cantSplit"]) dom["data-cant-split"] = "true";
286
311
  if (node.attrs["height"])
287
312
  dom["data-height"] = JSON.stringify(node.attrs["height"]);
313
+ if (node.attrs["carry"])
314
+ dom["data-carry"] = JSON.stringify(node.attrs["carry"]);
288
315
  return ["tr", dom, 0];
289
316
  }
290
317
  },
@@ -302,8 +329,11 @@ var schema = new import_prosemirror_model.Schema({
302
329
  // w:vAlign — 'center' | 'bottom' (top default)
303
330
  borders: { default: null },
304
331
  // w:tcBorders per-side visibility override
305
- padding: { default: null }
332
+ padding: { default: null },
306
333
  // w:tcMar per-side margin override (px)
334
+ // Carry-through fidelity: unmodelled w:tcPr children ({ tcPr: string
335
+ // } — textDirection, noWrap, tcFitText, …), or null. Importer-set.
336
+ carry: { default: null }
307
337
  },
308
338
  parseDOM: [
309
339
  { tag: "td", getAttrs: pastedCellAttrs },
@@ -325,6 +355,8 @@ var schema = new import_prosemirror_model.Schema({
325
355
  attrs["data-borders"] = JSON.stringify(node.attrs["borders"]);
326
356
  if (node.attrs["padding"])
327
357
  attrs["data-padding"] = JSON.stringify(node.attrs["padding"]);
358
+ if (node.attrs["carry"])
359
+ attrs["data-carry"] = JSON.stringify(node.attrs["carry"]);
328
360
  return ["td", attrs, 0];
329
361
  }
330
362
  }
@@ -471,6 +503,28 @@ var schema = new import_prosemirror_model.Schema({
471
503
  0
472
504
  ];
473
505
  }
506
+ },
507
+ // Carry-through fidelity (docx round-trip): run properties the model does
508
+ // NOT represent (w:rtl, w:kern, w:szCs, …), preserved verbatim as one raw
509
+ // XML fragment so saving a customer's file never drops them. Invisible —
510
+ // no rendering; the docx exporter splices `xml` back into the run's rPr.
511
+ // Typing inside/at the edge of a carried run extends the mark (inclusive
512
+ // default), which is the faithful behavior for properties like w:rtl.
513
+ carryRPr: {
514
+ attrs: { xml: {} },
515
+ toDOM(mark) {
516
+ return ["span", { "data-carry-rpr": String(mark.attrs["xml"]) }, 0];
517
+ },
518
+ parseDOM: [
519
+ {
520
+ tag: "span[data-carry-rpr]",
521
+ getAttrs: (el) => ({
522
+ xml: el.getAttribute(
523
+ "data-carry-rpr"
524
+ ) ?? ""
525
+ })
526
+ }
527
+ ]
474
528
  }
475
529
  // The `comment` mark (w:commentRangeStart/End) is contributed by the comment
476
530
  // plugin (@shadow-garden/bapbong-comments) via the editor's schema
package/dist/index.js CHANGED
@@ -15,7 +15,8 @@ function pastedParagraphAttrs(el, heading) {
15
15
  return {
16
16
  heading,
17
17
  align: m ? m[1].toLowerCase() : null,
18
- borders: dataJson(el, "data-borders")
18
+ borders: dataJson(el, "data-borders"),
19
+ carry: dataJson(el, "data-carry")
19
20
  };
20
21
  }
21
22
  function pastedImageAttrs(el) {
@@ -52,7 +53,8 @@ function pastedCellAttrs(el) {
52
53
  background: bg ? bg[1].trim() : null,
53
54
  vAlign: e.getAttribute("data-valign"),
54
55
  borders: dataJson(el, "data-borders"),
55
- padding: dataJson(el, "data-padding")
56
+ padding: dataJson(el, "data-padding"),
57
+ carry: dataJson(el, "data-carry")
56
58
  };
57
59
  }
58
60
  var schema = new Schema({
@@ -66,6 +68,10 @@ var schema = new Schema({
66
68
  // SectionConfig[] (contracts) — per-section column flow, delimited by
67
69
  // w:sectPr breaks. null/absent → one implicit single-column section.
68
70
  sections: { default: null },
71
+ // PageConfig (contracts) — page size + margins in CSS px, from the
72
+ // body w:sectPr. Edited via setDocAttribute (page-setup commands) so
73
+ // orientation/paper-size changes undo cleanly. null → A4 default.
74
+ page: { default: null },
69
75
  // CommentNode[] (contracts) — comment threads keyed to `comment` marks.
70
76
  // Edited via setDocAttribute so add/reply/resolve/delete undo cleanly.
71
77
  comments: { default: null }
@@ -104,7 +110,13 @@ var schema = new Schema({
104
110
  pageBreakBefore: { default: false },
105
111
  // w:pBdr — { top?, bottom?, left?, right? } of BorderSide, or null.
106
112
  // Importer-set; painted as a box around the paragraph's lines.
107
- borders: { default: null }
113
+ borders: { default: null },
114
+ // Carry-through fidelity (docx round-trip): OOXML paragraph
115
+ // properties the model does NOT represent, preserved verbatim so a
116
+ // customer's save never drops them. { pPr?: string, markRPr?: string }
117
+ // — raw XML fragments (pPr extras / the paragraph-mark w:rPr), or
118
+ // null. Importer-set; the exporter splices them back into w:pPr.
119
+ carry: { default: null }
108
120
  },
109
121
  // HTML paste path: recover heading level from h1–h6 and alignment from
110
122
  // inline style. Other attrs (list/indent/tabs/spacing) stay importer-only
@@ -124,6 +136,8 @@ var schema = new Schema({
124
136
  if (attrs.styleId) dom["data-style"] = attrs.styleId;
125
137
  if (node.attrs["borders"])
126
138
  dom["data-borders"] = JSON.stringify(node.attrs["borders"]);
139
+ if (node.attrs["carry"])
140
+ dom["data-carry"] = JSON.stringify(node.attrs["carry"]);
127
141
  return [tag, dom, 0];
128
142
  }
129
143
  },
@@ -205,7 +219,12 @@ var schema = new Schema({
205
219
  // insideV }, or null — OOXML tables are borderless unless declared.
206
220
  borders: { default: null },
207
221
  // w:tblPr/w:jc — 'center' | 'right' table alignment, or null (left).
208
- align: { default: null }
222
+ align: { default: null },
223
+ // Carry-through fidelity: unmodelled w:tblPr children (tblStyle,
224
+ // tblLayout, tblLook, tblInd, floating tblpPr, …) as one raw XML
225
+ // string ({ tblPr: string }), or null. Importer-set; the exporter
226
+ // splices it back so a save never drops them.
227
+ carry: { default: null }
209
228
  },
210
229
  // Complex attrs round-trip as data-* JSON — ProseMirror's clipboard is
211
230
  // a toDOM → parseDOM pass, so without this an internal copy/paste
@@ -216,7 +235,8 @@ var schema = new Schema({
216
235
  getAttrs: (el) => ({
217
236
  borders: dataJson(el, "data-borders"),
218
237
  cellPadding: dataJson(el, "data-cell-padding"),
219
- align: el.getAttribute("data-align")
238
+ align: el.getAttribute("data-align"),
239
+ carry: dataJson(el, "data-carry")
220
240
  })
221
241
  }
222
242
  ],
@@ -227,6 +247,7 @@ var schema = new Schema({
227
247
  if (a["cellPadding"])
228
248
  dom["data-cell-padding"] = JSON.stringify(a["cellPadding"]);
229
249
  if (a["align"]) dom["data-align"] = String(a["align"]);
250
+ if (a["carry"]) dom["data-carry"] = JSON.stringify(a["carry"]);
230
251
  return ["table", dom, ["tbody", 0]];
231
252
  }
232
253
  },
@@ -239,7 +260,10 @@ var schema = new Schema({
239
260
  // (Word's default) means the paginator may split the row mid-content.
240
261
  cantSplit: { default: false },
241
262
  // w:trHeight — { value: px, exact: boolean } or null (auto).
242
- height: { default: null }
263
+ height: { default: null },
264
+ // Carry-through fidelity: unmodelled w:trPr children ({ trPr: string
265
+ // } — gridBefore/wBefore, cnfStyle, …), or null. Importer-set.
266
+ carry: { default: null }
243
267
  },
244
268
  parseDOM: [
245
269
  {
@@ -247,7 +271,8 @@ var schema = new Schema({
247
271
  getAttrs: (el) => ({
248
272
  header: el.getAttribute("data-header") === "true",
249
273
  cantSplit: el.getAttribute("data-cant-split") === "true",
250
- height: dataJson(el, "data-height")
274
+ height: dataJson(el, "data-height"),
275
+ carry: dataJson(el, "data-carry")
251
276
  })
252
277
  }
253
278
  ],
@@ -257,6 +282,8 @@ var schema = new Schema({
257
282
  if (node.attrs["cantSplit"]) dom["data-cant-split"] = "true";
258
283
  if (node.attrs["height"])
259
284
  dom["data-height"] = JSON.stringify(node.attrs["height"]);
285
+ if (node.attrs["carry"])
286
+ dom["data-carry"] = JSON.stringify(node.attrs["carry"]);
260
287
  return ["tr", dom, 0];
261
288
  }
262
289
  },
@@ -274,8 +301,11 @@ var schema = new Schema({
274
301
  // w:vAlign — 'center' | 'bottom' (top default)
275
302
  borders: { default: null },
276
303
  // w:tcBorders per-side visibility override
277
- padding: { default: null }
304
+ padding: { default: null },
278
305
  // w:tcMar per-side margin override (px)
306
+ // Carry-through fidelity: unmodelled w:tcPr children ({ tcPr: string
307
+ // } — textDirection, noWrap, tcFitText, …), or null. Importer-set.
308
+ carry: { default: null }
279
309
  },
280
310
  parseDOM: [
281
311
  { tag: "td", getAttrs: pastedCellAttrs },
@@ -297,6 +327,8 @@ var schema = new Schema({
297
327
  attrs["data-borders"] = JSON.stringify(node.attrs["borders"]);
298
328
  if (node.attrs["padding"])
299
329
  attrs["data-padding"] = JSON.stringify(node.attrs["padding"]);
330
+ if (node.attrs["carry"])
331
+ attrs["data-carry"] = JSON.stringify(node.attrs["carry"]);
300
332
  return ["td", attrs, 0];
301
333
  }
302
334
  }
@@ -443,6 +475,28 @@ var schema = new Schema({
443
475
  0
444
476
  ];
445
477
  }
478
+ },
479
+ // Carry-through fidelity (docx round-trip): run properties the model does
480
+ // NOT represent (w:rtl, w:kern, w:szCs, …), preserved verbatim as one raw
481
+ // XML fragment so saving a customer's file never drops them. Invisible —
482
+ // no rendering; the docx exporter splices `xml` back into the run's rPr.
483
+ // Typing inside/at the edge of a carried run extends the mark (inclusive
484
+ // default), which is the faithful behavior for properties like w:rtl.
485
+ carryRPr: {
486
+ attrs: { xml: {} },
487
+ toDOM(mark) {
488
+ return ["span", { "data-carry-rpr": String(mark.attrs["xml"]) }, 0];
489
+ },
490
+ parseDOM: [
491
+ {
492
+ tag: "span[data-carry-rpr]",
493
+ getAttrs: (el) => ({
494
+ xml: el.getAttribute(
495
+ "data-carry-rpr"
496
+ ) ?? ""
497
+ })
498
+ }
499
+ ]
446
500
  }
447
501
  // The `comment` mark (w:commentRangeStart/End) is contributed by the comment
448
502
  // plugin (@shadow-garden/bapbong-comments) via the editor's schema
@@ -8,7 +8,7 @@ import { Schema } from 'prosemirror-model';
8
8
  * extend THIS schema so the importer, layout engine, and (canvas) painter all
9
9
  * agree on one document model.
10
10
  */
11
- export declare const schema: Schema<"doc" | "paragraph" | "text" | "hard_break" | "image" | "page_field" | "table" | "table_row" | "table_cell", "strong" | "em" | "underline" | "strike" | "textColor" | "fontSize" | "vertAlign" | "highlight" | "fontFamily" | "link" | "footnote">;
11
+ export declare const schema: Schema<"doc" | "paragraph" | "text" | "hard_break" | "image" | "page_field" | "table" | "table_row" | "table_cell", "strong" | "em" | "underline" | "strike" | "textColor" | "fontSize" | "vertAlign" | "highlight" | "fontFamily" | "link" | "footnote" | "carryRPr">;
12
12
  /** Concrete schema type, handy for typing Node/Mark across packages. */
13
13
  export type BapbongSchema = typeof schema;
14
14
  /**
@@ -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;AAgF3C;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,2PA6YjB,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;AAkF3C;;;;;;;;GAQG;AACH,eAAO,MAAM,MAAM,wQAscjB,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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shadow-garden/bapbong-model",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "bapbong — ProseMirror document model / schema",
5
5
  "license": "MIT",
6
6
  "repository": {