@inshapardaz/likhari-converters 0.1.18-dev.152 → 0.1.18-dev.154

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.
@@ -1 +1 @@
1
- {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/html/parse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAiCjD,kEAAkE;AAClE,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIlD;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKvD;AAiVD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,qBAAqB,CAMvF"}
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/html/parse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAiCjD,kEAAkE;AAClE,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIlD;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKvD;AAsWD,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,qBAAqB,CAMvF"}
@@ -251,28 +251,43 @@ function convertLayout(container) {
251
251
  const templateColumns = container.style.gridTemplateColumns || `repeat(${Math.max(items.length, 2)}, 1fr)`;
252
252
  return elementBase('layout-container', items.length > 0 ? items : [elementBase('layout-item', [paragraph()])], { templateColumns });
253
253
  }
254
- const POETRY_LAYOUTS = new Set(['single', 'two-column']);
254
+ const POETRY_LAYOUTS = new Set(['single', 'two-column', 'alternating']);
255
255
  const POETRY_ALIGNS = new Set(['justify', 'left', 'right', 'start']);
256
+ function convertPoetryCouplet(el) {
257
+ const centered = el.getAttribute('data-likhari-poetry-couplet-centered') === 'true';
258
+ const children = flowBlocks(el);
259
+ return elementBase('poetry-couplet', children.length > 0 ? children : [paragraph(), paragraph()], { centered });
260
+ }
256
261
  function convertPoetry(el) {
257
262
  const rawLayout = el.getAttribute('data-likhari-poetry-layout') ?? 'single';
258
263
  const layout = POETRY_LAYOUTS.has(rawLayout) ? rawLayout : 'single';
259
264
  const rawAlign = el.getAttribute('data-likhari-poetry-align') ?? 'justify';
260
265
  const align = POETRY_ALIGNS.has(rawAlign) ? rawAlign : 'justify';
266
+ // Couplets may mix wrapper types within one block — a two-column layout
267
+ // row (data-likhari-layout-container) and a centered single couplet
268
+ // (data-likhari-poetry-couplet) can sit side by side — grab all of them,
269
+ // not just the first, or every couplet past the first silently disappears.
270
+ const couplets = Array.from(el.children)
271
+ .map((c) => {
272
+ if (c.hasAttribute('data-likhari-layout-container'))
273
+ return convertLayout(c);
274
+ if (c.hasAttribute('data-likhari-poetry-couplet'))
275
+ return convertPoetryCouplet(c);
276
+ return null;
277
+ })
278
+ .filter((n) => n !== null);
279
+ if (couplets.length > 0)
280
+ return elementBase('poetry-block', couplets, { layout, align });
281
+ // Fallback: legacy markup with no explicit couplet wrappers at all.
261
282
  if (layout === 'two-column') {
262
- // One LayoutContainerNode row per couplet — grab all of them, not just
263
- // the first, or every couplet past the first silently disappears.
264
- const containerEls = Array.from(el.children).filter((c) => c.hasAttribute('data-likhari-layout-container'));
265
- const containers = containerEls.length > 0
266
- ? containerEls.map((c) => convertLayout(c))
267
- : [
268
- elementBase('layout-container', [elementBase('layout-item', [paragraph()]), elementBase('layout-item', [paragraph()])], {
269
- templateColumns: 'repeat(2, 1fr)',
270
- }),
271
- ];
272
- return elementBase('poetry-couplet', containers, { layout, align });
283
+ return elementBase('poetry-block', [
284
+ elementBase('layout-container', [elementBase('layout-item', [paragraph()]), elementBase('layout-item', [paragraph()])], {
285
+ templateColumns: 'repeat(2, 1fr)',
286
+ }),
287
+ ], { layout, align });
273
288
  }
274
289
  const children = flowBlocks(el);
275
- return elementBase('poetry-couplet', children.length > 0 ? children : [paragraph(), paragraph()], { layout, align });
290
+ return elementBase('poetry-block', [elementBase('poetry-couplet', children.length > 0 ? children : [paragraph(), paragraph()], { centered: false })], { layout, align });
276
291
  }
277
292
  function convertFootnoteList(el) {
278
293
  const items = [];
@@ -1 +1 @@
1
- {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/html/serialize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAEkG,KAAK,KAAK,EAClH,MAAM,sBAAsB,CAAC;AAE9B,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAuID,wBAAgB,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,gBAAgB,GAAG,MAAM,CA+CtE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAI1F"}
1
+ {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/html/serialize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAEkG,KAAK,KAAK,EAClH,MAAM,sBAAsB,CAAC;AAE9B,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEhD;AA8ID,wBAAgB,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAiDtE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAI1F"}
@@ -116,11 +116,17 @@ function layoutToHtml(node, ctx) {
116
116
  return `<div data-likhari-layout-container style="display: grid; grid-template-columns: ${escapeAttr(templateColumns)}">${columns}</div>`;
117
117
  }
118
118
  function poetryToHtml(node, ctx) {
119
- const layout = node.layout === 'two-column' ? 'two-column' : 'single';
119
+ const layout = node.layout === 'two-column' || node.layout === 'alternating' ? node.layout : 'single';
120
120
  const align = typeof node.align === 'string' ? node.align : 'justify';
121
121
  const inner = (node.children ?? []).map((child) => nodeToHtml(child, ctx)).join('');
122
122
  return `<div data-likhari-poetry-layout="${layout}" data-likhari-poetry-align="${align}" style="text-align: ${escapeAttr(align)}">${inner}</div>`;
123
123
  }
124
+ function poetryCoupletToHtml(node, ctx) {
125
+ const centered = node.centered === true;
126
+ const inner = (node.children ?? []).map((child) => nodeToHtml(child, ctx)).join('');
127
+ const centeredAttr = centered ? ' data-likhari-poetry-couplet-centered="true"' : '';
128
+ return `<div data-likhari-poetry-couplet${centeredAttr}>${inner}</div>`;
129
+ }
124
130
  function imageToHtml(node, ctx) {
125
131
  const rawSrc = String(node.src ?? '');
126
132
  const src = ctx?.resolveImageUrl ? ctx.resolveImageUrl(rawSrc) : rawSrc;
@@ -173,8 +179,10 @@ export function nodeToHtml(node, ctx) {
173
179
  return footnoteReferenceToHtml(node);
174
180
  case 'footnote-list':
175
181
  return footnoteListToHtml(node, ctx);
176
- case 'poetry-couplet':
182
+ case 'poetry-block':
177
183
  return poetryToHtml(node, ctx);
184
+ case 'poetry-couplet':
185
+ return poetryCoupletToHtml(node, ctx);
178
186
  default:
179
187
  // Unknown node (e.g. a future feature): keep its content, drop the wrapper.
180
188
  return inlineChildren(node, ctx);
@@ -1 +1 @@
1
- {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/markdown/parse.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAwTjD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,qBAAqB,CAO3F"}
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/markdown/parse.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAkUjD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,qBAAqB,CAO3F"}
@@ -239,10 +239,21 @@ function blocks(nodes, extra = {}) {
239
239
  }
240
240
  else if (node.name === 'poetry') {
241
241
  const attrs = node.attributes ?? {};
242
- const layout = attrs.layout === 'two-column' ? 'two-column' : 'single';
242
+ const layout = attrs.layout === 'two-column' || attrs.layout === 'alternating' ? attrs.layout : 'single';
243
243
  const align = ALIGNMENTS.has(attrs.align ?? '') ? attrs.align : 'justify';
244
+ let children = blocks(node.children ?? []);
245
+ // Legacy markup (no explicit couplet/column wrappers): treat the
246
+ // flat content as a single couplet, same as the import fallback.
247
+ const hasWrappers = children.some((c) => c.type === 'poetry-couplet' || c.type === 'layout-container');
248
+ if (!hasWrappers) {
249
+ children = [elementBase('poetry-couplet', children.length > 0 ? children : [paragraph(), paragraph()], { centered: false })];
250
+ }
251
+ out.push(elementBase('poetry-block', children, { layout, align }));
252
+ }
253
+ else if (node.name === 'couplet') {
254
+ const centered = (node.attributes ?? {}).centered === 'true';
244
255
  const children = blocks(node.children ?? []);
245
- out.push(elementBase('poetry-couplet', children.length > 0 ? children : [paragraph(), paragraph()], { layout, align }));
256
+ out.push(elementBase('poetry-couplet', children.length > 0 ? children : [paragraph(), paragraph()], { centered }));
246
257
  }
247
258
  else {
248
259
  // Unknown containers (including a stray "column" outside "columns")
@@ -1 +1 @@
1
- {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/markdown/serialize.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAKjD,OAAO,EAAa,KAAK,KAAK,EAAe,MAAM,SAAS,CAAC;AAyC7D,2GAA2G;AAC3G,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAUjD;AAqHD,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,CAMhE;AAoID,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAI9F"}
1
+ {"version":3,"file":"serialize.d.ts","sourceRoot":"","sources":["../../src/markdown/serialize.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAKjD,OAAO,EAAa,KAAK,KAAK,EAAe,MAAM,SAAS,CAAC;AAyC7D,2GAA2G;AAC3G,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAUjD;AAqHD,wFAAwF;AACxF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,CAMhE;AA4ID,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,qBAAqB,EAAE,GAAG,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAI9F"}
@@ -247,11 +247,16 @@ function layoutToMd(node, ctx) {
247
247
  return directive('containerDirective', 'columns', { count: String(items.length) }, columns);
248
248
  }
249
249
  function poetryToMd(node, ctx) {
250
- const layout = node.layout === 'two-column' ? 'two-column' : 'single';
250
+ const layout = node.layout === 'two-column' || node.layout === 'alternating' ? node.layout : 'single';
251
251
  const align = typeof node.align === 'string' ? node.align : 'justify';
252
252
  const inner = (node.children ?? []).flatMap((child) => blockToMd(child, ctx));
253
253
  return directive('containerDirective', 'poetry', { layout, align }, inner);
254
254
  }
255
+ function poetryCoupletToMd(node, ctx) {
256
+ const inner = (node.children ?? []).flatMap((child) => blockToMd(child, ctx));
257
+ const attrs = node.centered === true ? { centered: 'true' } : {};
258
+ return directive('containerDirective', 'couplet', attrs, inner);
259
+ }
255
260
  function tableToMd(node, ctx) {
256
261
  const rows = (node.children ?? []).map((row) => ({
257
262
  type: 'tableRow',
@@ -295,8 +300,10 @@ function blockToMd(node, ctx) {
295
300
  return [tableToMd(node, ctx)];
296
301
  case 'layout-container':
297
302
  return [layoutToMd(node, ctx)];
298
- case 'poetry-couplet':
303
+ case 'poetry-block':
299
304
  return [poetryToMd(node, ctx)];
305
+ case 'poetry-couplet':
306
+ return [poetryCoupletToMd(node, ctx)];
300
307
  case 'footnote-list':
301
308
  return (node.children ?? []).map((item) => ({
302
309
  type: 'footnoteDefinition',
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plain-text/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AA4FhD,eAAO,MAAM,kBAAkB,EAAE,eAsDhC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plain-text/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAgGhD,eAAO,MAAM,kBAAkB,EAAE,eAsDhC,CAAC"}
@@ -28,15 +28,19 @@ function nodeToText(node, order, listItemIndex = 0) {
28
28
  return `[${order.get(id) ?? '?'}]`;
29
29
  }
30
30
  // Linearized per the fidelity matrix ("Poetry layout variants ⚠️ linearized"):
31
- // one misra per line, regardless of single/two-column layout and however
32
- // many couplets the block holds — in two-column layout each couplet is
33
- // its own layout-container row, so each contributes its two item lines
34
- // in turn rather than only the block's first couplet being read.
35
- if (node.type === 'poetry-couplet') {
31
+ // one misra per line, regardless of single/two-column/alternating layout
32
+ // and however many couplets the block holds, mixed wrapper types included
33
+ // (a two-column couplet is its own layout-container row; a single or
34
+ // centered couplet is its own poetry-couplet wrapper) — so each couplet
35
+ // contributes its two misra lines in turn rather than only the block's
36
+ // first couplet being read.
37
+ if (node.type === 'poetry-block' || node.type === 'poetry-couplet') {
36
38
  const children = withChildren.children ?? [];
37
39
  const lines = children.flatMap((child) => child.type === 'layout-container'
38
40
  ? (child.children ?? []).map((item) => nodeToText(item, order))
39
- : [nodeToText(child, order)]);
41
+ : child.type === 'poetry-couplet'
42
+ ? (child.children ?? []).map((item) => nodeToText(item, order))
43
+ : [nodeToText(child, order)]);
40
44
  return lines.join('\n');
41
45
  }
42
46
  if (node.type === 'list' && withChildren.children) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inshapardaz/likhari-converters",
3
- "version": "0.1.18-dev.152",
3
+ "version": "0.1.18-dev.154",
4
4
  "description": "Format transformers (Markdown/HTML/plain-text/Lexical JSON) against the canonical Lexical EditorState, isolated from UI.",
5
5
  "license": "MIT",
6
6
  "repository": {