@taloswork/ose-shared 0.1.2 → 0.1.3

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.
Files changed (138) hide show
  1. package/package.json +3 -3
  2. package/skills/document/SKILL.md +29 -33
  3. package/skills/document/assets/fonts/Archivo-Regular.woff2 +0 -0
  4. package/skills/document/assets/fonts/Archivo-SemiBold.woff2 +0 -0
  5. package/skills/document/assets/fonts/BigShouldersDisplay-Bold.woff2 +0 -0
  6. package/skills/document/assets/fonts/BodoniModa-SemiBold.woff2 +0 -0
  7. package/skills/document/assets/fonts/CormorantGaramond-SemiBold.woff2 +0 -0
  8. package/skills/document/assets/fonts/Fraunces-SemiBold.woff2 +0 -0
  9. package/skills/document/assets/fonts/GochiHand-Regular.woff2 +0 -0
  10. package/skills/document/assets/fonts/IBMPlexSans-Regular.woff2 +0 -0
  11. package/skills/document/assets/fonts/IBMPlexSans-SemiBold.woff2 +0 -0
  12. package/skills/document/assets/fonts/Inter-Regular.woff2 +0 -0
  13. package/skills/document/assets/fonts/Jost-Regular.woff2 +0 -0
  14. package/skills/document/assets/fonts/Jost-SemiBold.woff2 +0 -0
  15. package/skills/document/assets/fonts/Karla-Regular.woff2 +0 -0
  16. package/skills/document/assets/fonts/Lora-Regular.woff2 +0 -0
  17. package/skills/document/assets/fonts/Manrope-Bold.woff2 +0 -0
  18. package/skills/document/assets/fonts/Manrope-Regular.woff2 +0 -0
  19. package/skills/document/assets/fonts/Marcellus-Regular.woff2 +0 -0
  20. package/skills/document/assets/fonts/PublicSans-Regular.woff2 +0 -0
  21. package/skills/document/assets/fonts/Sora-Regular.woff2 +0 -0
  22. package/skills/document/assets/fonts/Sora-SemiBold.woff2 +0 -0
  23. package/skills/document/assets/fonts/fonts.json +218 -0
  24. package/skills/document/bin/deck-build.cjs +273 -5
  25. package/skills/document/bin/doc-gen.cjs +108 -23
  26. package/skills/document/bin/html2pptx.cjs +280 -49
  27. package/skills/document/catalog.json +25 -0
  28. package/skills/document/deck-design.md +191 -0
  29. package/skills/document/layouts/README.md +32 -0
  30. package/skills/document/layouts/banner-columns.tpl +9 -9
  31. package/skills/document/layouts/bento.tpl +3 -3
  32. package/skills/document/layouts/big-stat.tpl +3 -3
  33. package/skills/document/layouts/blocks-2x2.tpl +12 -12
  34. package/skills/document/layouts/brand-values.tpl +5 -5
  35. package/skills/document/layouts/cards-3.tpl +3 -3
  36. package/skills/document/layouts/cards-grid.tpl +3 -3
  37. package/skills/document/layouts/chart-full.tpl +3 -3
  38. package/skills/document/layouts/chart-kpi.tpl +3 -3
  39. package/skills/document/layouts/color-palette.tpl +5 -5
  40. package/skills/document/layouts/comparison.tpl +3 -3
  41. package/skills/document/layouts/concept-hub.tpl +3 -3
  42. package/skills/document/layouts/cover-centered.tpl +1 -1
  43. package/skills/document/layouts/cover-image.tpl +1 -1
  44. package/skills/document/layouts/cover-minimal.tpl +3 -3
  45. package/skills/document/layouts/cover-statement.tpl +3 -3
  46. package/skills/document/layouts/cover.tpl +1 -1
  47. package/skills/document/layouts/data-table.tpl +3 -3
  48. package/skills/document/layouts/dos-donts.tpl +14 -14
  49. package/skills/document/layouts/editorial-panel.tpl +11 -11
  50. package/skills/document/layouts/ending-contact.tpl +1 -1
  51. package/skills/document/layouts/ending.tpl +1 -1
  52. package/skills/document/layouts/funnel.tpl +3 -3
  53. package/skills/document/layouts/gantt.tpl +3 -3
  54. package/skills/document/layouts/hero.tpl +3 -3
  55. package/skills/document/layouts/icon-row.tpl +3 -3
  56. package/skills/document/layouts/image-full.tpl +5 -5
  57. package/skills/document/layouts/image-grid.tpl +3 -3
  58. package/skills/document/layouts/image-left.tpl +3 -3
  59. package/skills/document/layouts/list.tpl +3 -3
  60. package/skills/document/layouts/logo-guidelines.tpl +8 -8
  61. package/skills/document/layouts/map-distribution.tpl +3 -3
  62. package/skills/document/layouts/map-quad.tpl +6 -6
  63. package/skills/document/layouts/matrix-2x2.tpl +3 -3
  64. package/skills/document/layouts/numbered-brief.tpl +12 -12
  65. package/skills/document/layouts/org-tree.tpl +3 -3
  66. package/skills/document/layouts/problem-solution-banner.tpl +7 -7
  67. package/skills/document/layouts/problem-solution.tpl +3 -3
  68. package/skills/document/layouts/pyramid.tpl +3 -3
  69. package/skills/document/layouts/quote.tpl +1 -1
  70. package/skills/document/layouts/radar.tpl +3 -3
  71. package/skills/document/layouts/ring-progress.tpl +3 -3
  72. package/skills/document/layouts/section-fullbleed.tpl +3 -3
  73. package/skills/document/layouts/section-image.tpl +1 -1
  74. package/skills/document/layouts/section-stat.tpl +1 -1
  75. package/skills/document/layouts/section.tpl +1 -1
  76. package/skills/document/layouts/slots.json +1 -1
  77. package/skills/document/layouts/split-two-col.tpl +3 -3
  78. package/skills/document/layouts/stats-chart.tpl +3 -3
  79. package/skills/document/layouts/steps-serpentine.tpl +11 -11
  80. package/skills/document/layouts/steps-vertical.tpl +3 -3
  81. package/skills/document/layouts/steps.tpl +3 -3
  82. package/skills/document/layouts/team-row.tpl +4 -4
  83. package/skills/document/layouts/three-kpi.tpl +3 -3
  84. package/skills/document/layouts/timeline.tpl +3 -3
  85. package/skills/document/layouts/title-meta.tpl +5 -5
  86. package/skills/document/layouts/title.tpl +2 -2
  87. package/skills/document/layouts/toc-agenda.tpl +3 -3
  88. package/skills/document/layouts/toc-editorial.tpl +15 -0
  89. package/skills/document/layouts/toc-panel.tpl +4 -4
  90. package/skills/document/layouts/toc.tpl +3 -3
  91. package/skills/document/layouts/transition.tpl +1 -1
  92. package/skills/document/layouts/two-kpi.tpl +3 -3
  93. package/skills/document/layouts/type-specimen.tpl +10 -10
  94. package/skills/document/layouts/versus.tpl +3 -3
  95. package/skills/document/motion/README.md +11 -0
  96. package/skills/document/packs/README.md +9 -0
  97. package/skills/document/styles/README.md +36 -15
  98. package/skills/document/styles/_contract-defaults.css +55 -0
  99. package/skills/document/styles/_samples/_groups/biz-premium.webp +0 -0
  100. package/skills/document/styles/_samples/_groups/creative.webp +0 -0
  101. package/skills/document/styles/_samples/_groups/editorial.webp +0 -0
  102. package/skills/document/styles/_samples/_groups/minimal.webp +0 -0
  103. package/skills/document/styles/_samples/_groups/natural.webp +0 -0
  104. package/skills/document/styles/_samples/_groups/tech-future.webp +0 -0
  105. package/skills/document/styles/_samples/anthropic.webp +0 -0
  106. package/skills/document/styles/_samples/apple.webp +0 -0
  107. package/skills/document/styles/_samples/black-gold.webp +0 -0
  108. package/skills/document/styles/_samples/branding.webp +0 -0
  109. package/skills/document/styles/_samples/cinereel.webp +0 -0
  110. package/skills/document/styles/_samples/cool.webp +0 -0
  111. package/skills/document/styles/_samples/hand-drawn.webp +0 -0
  112. package/skills/document/styles/_samples/ivory-gold.webp +0 -0
  113. package/skills/document/styles/_samples/magazine-ink.webp +0 -0
  114. package/skills/document/styles/_samples/mckinsey.webp +0 -0
  115. package/skills/document/styles/_samples/mono.webp +0 -0
  116. package/skills/document/styles/_samples/olive-gold.webp +0 -0
  117. package/skills/document/styles/_samples/swiss-grid.webp +0 -0
  118. package/skills/document/styles/anthropic/backdrop.html +4 -0
  119. package/skills/document/styles/anthropic/skin.css +15 -8
  120. package/skills/document/styles/apple/backdrop.html +4 -1
  121. package/skills/document/styles/apple/skin.css +5 -2
  122. package/skills/document/styles/black-gold/backdrop.html +3 -0
  123. package/skills/document/styles/black-gold/skin.css +15 -8
  124. package/skills/document/styles/branding/backdrop.html +4 -0
  125. package/skills/document/styles/branding/skin.css +14 -7
  126. package/skills/document/styles/cinereel/skin.css +28 -10
  127. package/skills/document/styles/cool/backdrop.html +3 -0
  128. package/skills/document/styles/cool/skin.css +5 -2
  129. package/skills/document/styles/hand-drawn/skin.css +14 -6
  130. package/skills/document/styles/ivory-gold/skin.css +19 -6
  131. package/skills/document/styles/magazine-ink/skin.css +6 -1
  132. package/skills/document/styles/mckinsey/backdrop.html +5 -0
  133. package/skills/document/styles/mckinsey/skin.css +5 -2
  134. package/skills/document/styles/mono/backdrop.html +6 -0
  135. package/skills/document/styles/mono/skin.css +5 -2
  136. package/skills/document/styles/olive-gold/backdrop.html +5 -0
  137. package/skills/document/styles/olive-gold/skin.css +15 -8
  138. package/skills/document/styles/swiss-grid/skin.css +6 -1
@@ -9790,9 +9790,9 @@ var require_load = __commonJS({
9790
9790
  var require_lib3 = __commonJS({
9791
9791
  "node_modules/jszip/lib/index.js"(exports2, module2) {
9792
9792
  "use strict";
9793
- function JSZip4() {
9794
- if (!(this instanceof JSZip4)) {
9795
- return new JSZip4();
9793
+ function JSZip5() {
9794
+ if (!(this instanceof JSZip5)) {
9795
+ return new JSZip5();
9796
9796
  }
9797
9797
  if (arguments.length) {
9798
9798
  throw new Error("The constructor with parameters has been removed in JSZip 3.0, please check the upgrade guide.");
@@ -9801,7 +9801,7 @@ var require_lib3 = __commonJS({
9801
9801
  this.comment = null;
9802
9802
  this.root = "";
9803
9803
  this.clone = function() {
9804
- var newObj = new JSZip4();
9804
+ var newObj = new JSZip5();
9805
9805
  for (var i in this) {
9806
9806
  if (typeof this[i] !== "function") {
9807
9807
  newObj[i] = this[i];
@@ -9810,16 +9810,16 @@ var require_lib3 = __commonJS({
9810
9810
  return newObj;
9811
9811
  };
9812
9812
  }
9813
- JSZip4.prototype = require_object();
9814
- JSZip4.prototype.loadAsync = require_load();
9815
- JSZip4.support = require_support();
9816
- JSZip4.defaults = require_defaults();
9817
- JSZip4.version = "3.10.1";
9818
- JSZip4.loadAsync = function(content, options) {
9819
- return new JSZip4().loadAsync(content, options);
9813
+ JSZip5.prototype = require_object();
9814
+ JSZip5.prototype.loadAsync = require_load();
9815
+ JSZip5.support = require_support();
9816
+ JSZip5.defaults = require_defaults();
9817
+ JSZip5.version = "3.10.1";
9818
+ JSZip5.loadAsync = function(content, options) {
9819
+ return new JSZip5().loadAsync(content, options);
9820
9820
  };
9821
- JSZip4.external = require_external();
9822
- module2.exports = JSZip4;
9821
+ JSZip5.external = require_external();
9822
+ module2.exports = JSZip5;
9823
9823
  }
9824
9824
  });
9825
9825
 
@@ -16738,7 +16738,7 @@ var require_browser_buffer_encode = __commonJS({
16738
16738
  var require_zip_stream = __commonJS({
16739
16739
  "node_modules/exceljs/lib/utils/zip-stream.js"(exports2, module2) {
16740
16740
  var events = require("events");
16741
- var JSZip4 = require_lib3();
16741
+ var JSZip5 = require_lib3();
16742
16742
  var StreamBuf = require_stream_buf();
16743
16743
  var { stringToBuffer } = require_browser_buffer_encode();
16744
16744
  var ZipWriter = class extends events.EventEmitter {
@@ -16751,7 +16751,7 @@ var require_zip_stream = __commonJS({
16751
16751
  },
16752
16752
  options
16753
16753
  );
16754
- this.zip = new JSZip4();
16754
+ this.zip = new JSZip5();
16755
16755
  this.stream = new StreamBuf();
16756
16756
  }
16757
16757
  append(data, options) {
@@ -28431,7 +28431,7 @@ var require_theme1 = __commonJS({
28431
28431
  var require_xlsx = __commonJS({
28432
28432
  "node_modules/exceljs/lib/xlsx/xlsx.js"(exports2, module2) {
28433
28433
  var fs = require("fs");
28434
- var JSZip4 = require_lib3();
28434
+ var JSZip5 = require_lib3();
28435
28435
  var { PassThrough } = require_readable2();
28436
28436
  var ZipStream = require_zip_stream();
28437
28437
  var StreamBuf = require_stream_buf();
@@ -28670,7 +28670,7 @@ var require_xlsx = __commonJS({
28670
28670
  tables: {},
28671
28671
  vmlDrawings: {}
28672
28672
  };
28673
- const zip = await JSZip4.loadAsync(buffer);
28673
+ const zip = await JSZip5.loadAsync(buffer);
28674
28674
  for (const entry of Object.values(zip.files)) {
28675
28675
  if (!entry.dir) {
28676
28676
  let entryName = entry.name;
@@ -72933,11 +72933,11 @@ var require_excel = __commonJS({
72933
72933
  var require_pptxgen_cjs = __commonJS({
72934
72934
  "node_modules/pptxgenjs/dist/pptxgen.cjs.js"(exports2, module2) {
72935
72935
  "use strict";
72936
- var JSZip4 = require_lib3();
72936
+ var JSZip5 = require_lib3();
72937
72937
  function _interopDefaultLegacy(e) {
72938
72938
  return e && typeof e === "object" && "default" in e ? e : { "default": e };
72939
72939
  }
72940
- var JSZip__default = /* @__PURE__ */ _interopDefaultLegacy(JSZip4);
72940
+ var JSZip__default = /* @__PURE__ */ _interopDefaultLegacy(JSZip5);
72941
72941
  var __assign2 = function() {
72942
72942
  __assign2 = Object.assign || function __assign3(t) {
72943
72943
  for (var s, i = 1, n = arguments.length; i < n; i++) {
@@ -132887,7 +132887,7 @@ var import_node_fs = require("node:fs");
132887
132887
  var import_node_path = require("node:path");
132888
132888
 
132889
132889
  // packages/core/dist/document/html-pptx.js
132890
- var import_jszip3 = __toESM(require_lib3(), 1);
132890
+ var import_jszip4 = __toESM(require_lib3(), 1);
132891
132891
 
132892
132892
  // packages/core/dist/document/pptx-anim.js
132893
132893
  var import_jszip = __toESM(require_lib3(), 1);
@@ -132928,11 +132928,15 @@ function buildSlideTiming(steps, spidOf) {
132928
132928
  return "";
132929
132929
  let id = 100;
132930
132930
  const next = () => id++;
132931
+ const beatOpened = /* @__PURE__ */ new Set();
132931
132932
  const stepPars = resolved.map(({ s, spid }, i) => {
132932
132933
  const { id: pid, sub } = presetOf(s.effect);
132933
132934
  const dur = Math.max(1, Math.round(s.durMs ?? 500));
132934
- const delay = Math.max(0, Math.round(s.delayMs ?? (i === 0 ? 0 : 200)));
132935
- const node = i === 0 ? "clickEffect" : s.start === "with" ? "withEffect" : "afterEffect";
132935
+ const ridesAlong = s.group !== void 0 && beatOpened.has(s.group);
132936
+ if (s.group !== void 0)
132937
+ beatOpened.add(s.group);
132938
+ const delay = ridesAlong ? 0 : Math.max(0, Math.round(s.delayMs ?? (i === 0 ? 0 : 200)));
132939
+ const node = ridesAlong ? "withEffect" : i === 0 ? "clickEffect" : s.start === "with" ? "withEffect" : "afterEffect";
132936
132940
  const effectCtnId = next();
132937
132941
  const beh = behaviorsOf(s.effect, next, spid, dur);
132938
132942
  return `<p:par><p:cTn id="${effectCtnId}" presetID="${pid}" presetClass="entr" presetSubtype="${sub}" fill="hold" grpId="0" nodeType="${node}"><p:stCondLst><p:cond delay="${delay}"/></p:stCondLst><p:childTnLst>${beh}</p:childTnLst></p:cTn></p:par>`;
@@ -132966,6 +132970,84 @@ async function injectAnimations(buf, perSlide) {
132966
132970
  return await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
132967
132971
  }
132968
132972
 
132973
+ // packages/core/dist/document/pptx-transition.js
132974
+ var import_jszip2 = __toESM(require_lib3(), 1);
132975
+ var MC_NS = "http://schemas.openxmlformats.org/markup-compatibility/2006";
132976
+ var P14_NS = "http://schemas.microsoft.com/office/powerpoint/2010/main";
132977
+ var P159_NS = "http://schemas.microsoft.com/office/powerpoint/2015/09/main";
132978
+ var STANDARD = {
132979
+ cut: { tag: "cut", dirs: null },
132980
+ fade: { tag: "fade", dirs: null },
132981
+ dissolve: { tag: "dissolve", dirs: null },
132982
+ wedge: { tag: "wedge", dirs: null },
132983
+ wipe: { tag: "wipe", dirs: ["l", "r", "u", "d"], defaultDir: "l" },
132984
+ push: { tag: "push", dirs: ["l", "r", "u", "d"], defaultDir: "l" },
132985
+ cover: { tag: "cover", dirs: ["l", "r", "u", "d"], defaultDir: "l" },
132986
+ zoom: { tag: "zoom", dirs: ["in", "out"], defaultDir: "in" },
132987
+ split: { tag: "split", dirs: ["in", "out"], dirAttr: "dir", defaultDir: "in" }
132988
+ };
132989
+ var MORPH = "morph";
132990
+ var TRANSITION_EFFECTS = [...Object.keys(STANDARD), MORPH];
132991
+ function speedOf(durMs) {
132992
+ if (durMs === void 0)
132993
+ return "med";
132994
+ if (durMs >= 1e3)
132995
+ return "slow";
132996
+ if (durMs >= 500)
132997
+ return "med";
132998
+ return "fast";
132999
+ }
133000
+ function effectElement(effect, dir) {
133001
+ const def = STANDARD[effect];
133002
+ if (!def)
133003
+ return "<p:fade/>";
133004
+ if (!def.dirs)
133005
+ return `<p:${def.tag}/>`;
133006
+ const chosen = dir && def.dirs.includes(dir) ? dir : def.defaultDir;
133007
+ return `<p:${def.tag} ${def.dirAttr ?? "dir"}="${chosen}"/>`;
133008
+ }
133009
+ function buildTransition(spec) {
133010
+ const effect = (spec.effect || "").trim();
133011
+ if (!effect || effect === "none")
133012
+ return "";
133013
+ const spd = speedOf(spec.durMs);
133014
+ const dur = spec.durMs !== void 0 ? Math.max(1, Math.round(spec.durMs)) : void 0;
133015
+ const isMorph = effect === MORPH;
133016
+ const plain = `<p:transition spd="${spd}">${effectElement(isMorph ? "fade" : effect, spec.dir)}</p:transition>`;
133017
+ if (!isMorph && dur === void 0)
133018
+ return plain;
133019
+ const choiceNs = isMorph ? ` xmlns:p14="${P14_NS}" xmlns:p159="${P159_NS}" Requires="p159"` : ` xmlns:p14="${P14_NS}" Requires="p14"`;
133020
+ const inner = isMorph ? `<p159:morph option="byObject"/>` : effectElement(effect, spec.dir);
133021
+ const durAttr = dur !== void 0 ? ` p14:dur="${dur}"` : "";
133022
+ return `<mc:AlternateContent xmlns:mc="${MC_NS}"><mc:Choice${choiceNs}><p:transition spd="${spd}"${durAttr}>${inner}</p:transition></mc:Choice><mc:Fallback>${plain}</mc:Fallback></mc:AlternateContent>`;
133023
+ }
133024
+ async function injectTransitions(buf, perSlide) {
133025
+ if (!perSlide.some((t) => t && t.effect && t.effect !== "none"))
133026
+ return buf;
133027
+ const zip = await import_jszip2.default.loadAsync(buf);
133028
+ const slidePaths = Object.keys(zip.files).filter((p) => /^ppt\/slides\/slide\d+\.xml$/.test(p)).sort((a, b) => parseInt(a.match(/(\d+)/)[1], 10) - parseInt(b.match(/(\d+)/)[1], 10));
133029
+ for (let i = 0; i < slidePaths.length; i++) {
133030
+ const spec = perSlide[i];
133031
+ if (!spec)
133032
+ continue;
133033
+ const xml0 = await zip.file(slidePaths[i]).async("string");
133034
+ if (xml0.includes("<p:transition") || xml0.includes("mc:AlternateContent"))
133035
+ continue;
133036
+ const frag = buildTransition(spec);
133037
+ if (!frag)
133038
+ continue;
133039
+ let xml;
133040
+ if (xml0.includes("</p:clrMapOvr>"))
133041
+ xml = xml0.replace("</p:clrMapOvr>", `</p:clrMapOvr>${frag}`);
133042
+ else if (xml0.includes("</p:cSld>"))
133043
+ xml = xml0.replace("</p:cSld>", `</p:cSld>${frag}`);
133044
+ else
133045
+ continue;
133046
+ zip.file(slidePaths[i], xml);
133047
+ }
133048
+ return await zip.generateAsync({ type: "nodebuffer", compression: "DEFLATE" });
133049
+ }
133050
+
132969
133051
  // node_modules/docx/dist/index.mjs
132970
133052
  var __create2 = Object.create;
132971
133053
  var __defProp2 = Object.defineProperty;
@@ -146661,7 +146743,7 @@ var findPatchKeys = (text) => {
146661
146743
 
146662
146744
  // packages/core/dist/document/doc-gen.js
146663
146745
  var import_exceljs = __toESM(require_excel(), 1);
146664
- var import_jszip2 = __toESM(require_lib3(), 1);
146746
+ var import_jszip3 = __toESM(require_lib3(), 1);
146665
146747
  var import_pptxgenjs = __toESM(require_pptxgen_cjs(), 1);
146666
146748
  var import_pdf_lib = __toESM(require_cjs(), 1);
146667
146749
  var import_fontkit = __toESM(require_fontkit_umd(), 1);
@@ -147060,7 +147142,7 @@ async function finalizePptx(bytes) {
147060
147142
  return stripDanglingOverrides(await normalizeChartParts(bytes));
147061
147143
  }
147062
147144
  async function normalizeChartParts(bytes) {
147063
- const zip = await import_jszip2.default.loadAsync(Buffer.from(bytes));
147145
+ const zip = await import_jszip3.default.loadAsync(Buffer.from(bytes));
147064
147146
  const pres = zip.file("ppt/presentation.xml");
147065
147147
  if (pres) {
147066
147148
  let xml = await pres.async("string");
@@ -147113,7 +147195,7 @@ async function normalizeChartParts(bytes) {
147113
147195
  return new Uint8Array(out);
147114
147196
  }
147115
147197
  async function stripDanglingOverrides(bytes) {
147116
- const zip = await import_jszip2.default.loadAsync(Buffer.from(bytes));
147198
+ const zip = await import_jszip3.default.loadAsync(Buffer.from(bytes));
147117
147199
  const ctFile = zip.file("[Content_Types].xml");
147118
147200
  if (!ctFile)
147119
147201
  return bytes;
@@ -147274,7 +147356,7 @@ function gradFillXml(g) {
147274
147356
  return `<a:gradFill rotWithShape="1"><a:gsLst>${gs}</a:gsLst><a:lin ang="${Math.round(deg * 6e4)}" scaled="1"/></a:gradFill>`;
147275
147357
  }
147276
147358
  async function injectGradients(buf, grads) {
147277
- const zip = await import_jszip3.default.loadAsync(buf);
147359
+ const zip = await import_jszip4.default.loadAsync(buf);
147278
147360
  for (const path of Object.keys(zip.files).filter((p) => /^ppt\/slides\/slide\d+\.xml$/.test(p))) {
147279
147361
  let xml = await zip.file(path).async("string");
147280
147362
  let changed = false;
@@ -147342,6 +147424,7 @@ async function convertLayoutToPptx(snapshot) {
147342
147424
  pptx.layout = "TALOS_HTML_WIDE";
147343
147425
  const gradients = [];
147344
147426
  const perSlideAnims = [];
147427
+ const perSlideTransitions = [];
147345
147428
  for (const [slideNo, slideSpec] of snapshot.slides.entries()) {
147346
147429
  const slide = pptx.addSlide();
147347
147430
  const bg = cssColorToHex(slideSpec.background);
@@ -147549,10 +147632,12 @@ async function convertLayoutToPptx(snapshot) {
147549
147632
  if (slideSpec.speakerNotes)
147550
147633
  slide.addNotes(String(slideSpec.speakerNotes));
147551
147634
  perSlideAnims.push(slideAnims);
147635
+ perSlideTransitions.push(slideSpec.transition);
147552
147636
  }
147553
147637
  let buf = await pptx.write("nodebuffer");
147554
147638
  if (gradients.length)
147555
147639
  buf = await injectGradients(buf, gradients);
147640
+ buf = await injectTransitions(buf, perSlideTransitions);
147556
147641
  buf = await injectAnimations(buf, perSlideAnims);
147557
147642
  return { bytes: await finalizePptx(new Uint8Array(buf)), warnings };
147558
147643
  }
@@ -147585,15 +147670,20 @@ var LAYOUT_WALKER_JS = `
147585
147670
  // Entrance-animation intent: an element (or, for text, its nearest ancestor)
147586
147671
  // carrying data-anim="<effect>" [+ -seq/-start/-delay/-dur]. Emitted as {anim}
147587
147672
  // on the element snapshot; turned into a native <p:timing> step post-write.
147673
+ // Every element resolving to the same host gets that host's group id, so the
147674
+ // builder can collapse them into one beat instead of one step per text run.
147675
+ const animHosts = [];
147588
147676
  const animOf = (elm) => {
147589
147677
  if (!elm || !elm.getAttribute) return undefined;
147590
147678
  const host = elm.getAttribute("data-anim") ? elm : (elm.closest ? elm.closest("[data-anim]") : null);
147591
147679
  if (!host) return undefined;
147592
147680
  const effect = (host.getAttribute("data-anim") || "").trim();
147593
147681
  if (!effect) return undefined;
147682
+ let group = animHosts.indexOf(host);
147683
+ if (group < 0) { group = animHosts.length; animHosts.push(host); }
147594
147684
  const num = (a) => { const v = parseFloat(host.getAttribute(a)); return Number.isFinite(v) ? v : undefined; };
147595
147685
  const start = host.getAttribute("data-anim-start");
147596
- const o = { effect: effect };
147686
+ const o = { effect: effect, group: group };
147597
147687
  const seq = num("data-anim-seq"); if (seq !== undefined) o.seq = seq;
147598
147688
  if (start === "with" || start === "onclick" || start === "after") o.start = start;
147599
147689
  const d = num("data-anim-delay"); if (d !== undefined) o.delayMs = d;
@@ -147716,7 +147806,17 @@ var LAYOUT_WALKER_JS = `
147716
147806
  // data-notes attribute \u2192 pptx notesSlide (Stage B addNotes).
147717
147807
  const notesEl = sec.querySelector(".talos-notes");
147718
147808
  const speakerNotes = (((notesEl && notesEl.textContent) || sec.getAttribute("data-notes") || "").trim()) || undefined;
147719
- return { background: color(getComputedStyle(sec).backgroundColor) ?? "#ffffff", elements, ...(speakerNotes ? { speakerNotes } : {}) };
147809
+ // Slide transition: how the deck moves INTO this slide \u2192 native <p:transition>.
147810
+ const trEffect = (sec.getAttribute("data-transition") || "").trim();
147811
+ let transition;
147812
+ if (trEffect) {
147813
+ transition = { effect: trEffect };
147814
+ const trDur = parseFloat(sec.getAttribute("data-transition-dur"));
147815
+ if (Number.isFinite(trDur)) transition.durMs = trDur;
147816
+ const trDir = (sec.getAttribute("data-transition-dir") || "").trim();
147817
+ if (trDir) transition.dir = trDir;
147818
+ }
147819
+ return { background: color(getComputedStyle(sec).backgroundColor) ?? "#ffffff", elements, ...(speakerNotes ? { speakerNotes } : {}), ...(transition ? { transition } : {}) };
147720
147820
  });
147721
147821
  return { width: 1280, height: 720, slides, notes };
147722
147822
  })()
@@ -147844,6 +147944,90 @@ async function inlineHtmlImages(html, resolve) {
147844
147944
  return { html: out, inlined, skipped };
147845
147945
  }
147846
147946
 
147947
+ // packages/core/dist/document/deck-catalog.js
147948
+ var KINDS = ["skin", "pack"];
147949
+ var MODES = ["light", "dark"];
147950
+ var ID_RE = /^[a-z0-9][a-z0-9-]*$/;
147951
+ function isStr(v) {
147952
+ return typeof v === "string" && v.length > 0;
147953
+ }
147954
+ function isStrArr(v) {
147955
+ return Array.isArray(v) && v.every((x) => typeof x === "string");
147956
+ }
147957
+ function parseCatalog(raw) {
147958
+ const errors = [];
147959
+ const o = raw;
147960
+ if (!o || typeof o !== "object")
147961
+ return { catalog: null, errors: ["catalog is not an object"] };
147962
+ const groups = [];
147963
+ const rawGroups = Array.isArray(o.groups) ? o.groups : [];
147964
+ if (!Array.isArray(o.groups))
147965
+ errors.push("catalog.groups must be an array");
147966
+ rawGroups.forEach((g, i) => {
147967
+ const at = `group[${i}]`;
147968
+ if (!isStr(g?.id) || !ID_RE.test(g.id))
147969
+ errors.push(`${at}: bad id`);
147970
+ if (!isStr(g?.name_cn))
147971
+ errors.push(`${at}: missing name_cn`);
147972
+ if (!isStr(g?.sample))
147973
+ errors.push(`${at}: missing sample`);
147974
+ if (!isStrArr(g?.scenarios))
147975
+ errors.push(`${at}: scenarios must be a string array`);
147976
+ if (isStr(g?.id) && isStr(g?.name_cn) && isStr(g?.sample) && isStrArr(g?.scenarios)) {
147977
+ groups.push({ id: g.id, name_cn: g.name_cn, sample: g.sample, scenarios: g.scenarios });
147978
+ }
147979
+ });
147980
+ const entries = [];
147981
+ const rawEntries = Array.isArray(o.entries) ? o.entries : [];
147982
+ if (!Array.isArray(o.entries))
147983
+ errors.push("catalog.entries must be an array");
147984
+ rawEntries.forEach((e, i) => {
147985
+ const at = `entry[${i}]${isStr(e?.id) ? ` (${e.id})` : ""}`;
147986
+ const before = errors.length;
147987
+ if (!isStr(e?.id) || !ID_RE.test(e.id))
147988
+ errors.push(`${at}: bad id`);
147989
+ if (!isStr(e?.kind) || !KINDS.includes(e.kind))
147990
+ errors.push(`${at}: kind must be "skin" or "pack"`);
147991
+ if (!isStr(e?.group))
147992
+ errors.push(`${at}: missing group`);
147993
+ if (!isStr(e?.name_cn))
147994
+ errors.push(`${at}: missing name_cn`);
147995
+ if (!isStr(e?.oneliner))
147996
+ errors.push(`${at}: missing oneliner`);
147997
+ if (!isStrArr(e?.scenarios))
147998
+ errors.push(`${at}: scenarios must be a string array`);
147999
+ if (!isStr(e?.mode) || !MODES.includes(e.mode))
148000
+ errors.push(`${at}: mode must be "light" or "dark"`);
148001
+ if (!isStr(e?.sample))
148002
+ errors.push(`${at}: missing sample`);
148003
+ if (e?.motion !== void 0 && !isStr(e.motion))
148004
+ errors.push(`${at}: motion must be a string when present`);
148005
+ if (errors.length === before) {
148006
+ entries.push({
148007
+ id: e.id,
148008
+ kind: e.kind,
148009
+ group: e.group,
148010
+ name_cn: e.name_cn,
148011
+ oneliner: e.oneliner,
148012
+ scenarios: e.scenarios,
148013
+ mode: e.mode,
148014
+ sample: e.sample,
148015
+ ...e.motion !== void 0 ? { motion: e.motion } : {}
148016
+ });
148017
+ }
148018
+ });
148019
+ return { catalog: errors.length ? null : { groups, entries }, errors };
148020
+ }
148021
+ function resolveEntry(catalog, id) {
148022
+ return catalog.entries.find((e) => e.id === id) ?? null;
148023
+ }
148024
+ function assetDirOf(entry) {
148025
+ return entry.kind === "skin" ? `styles/${entry.id}` : `packs/${entry.id}`;
148026
+ }
148027
+ function cssFileOf(entry) {
148028
+ return entry.kind === "skin" ? "skin.css" : "pack.css";
148029
+ }
148030
+
147847
148031
  // apps/admin/data/skills.lib/document/bin-src/html2pptx.mjs
147848
148032
  function imageResolver(baseDir) {
147849
148033
  return async (src) => {
@@ -147869,27 +148053,52 @@ async function tailwindCss() {
147869
148053
  _tailwindCss = (0, import_node_fs.existsSync)(file) ? await (0, import_promises.readFile)(file, "utf8").catch(() => "") : "";
147870
148054
  return _tailwindCss;
147871
148055
  }
147872
- var CJK_RE2 = /[⺀-⿿ -〿぀-ヿ㐀-䶿一-鿿豈-﫿＀-￯]/;
147873
- var CJK_UNICODE_RANGE = "U+2E80-2EFF,U+3000-303F,U+3040-30FF,U+3200-4DBF,U+4E00-9FFF,U+F900-FAFF,U+FE30-FE4F,U+FF00-FFEF";
147874
- var CJK_SANS_FAMILIES = ["PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans SC", "Noto Sans CJK SC", "Source Han Sans SC", "WenQuanYi Zen Hei"];
147875
- var CJK_SERIF_FAMILIES = ["Songti SC", "STSong", "SimSun", "Noto Serif SC", "Noto Serif CJK SC", "Source Han Serif SC"];
148056
+ var CJK_RE2 = /[\u2E80-\u2FFF\u3000-\u303F\u3040-\u30FF\u3400-\u4DBF\u4E00-\u9FFF\uF900-\uFAFF\uFF00-\uFFEF]/;
148057
+ var _fontManifest;
148058
+ async function fontManifest() {
148059
+ if (_fontManifest !== void 0) return _fontManifest;
148060
+ const dir = process.env.TALOS_CJK_FONT_DIR || (0, import_node_path.join)((0, import_node_path.dirname)(process.argv[1]), "..", "assets", "fonts");
148061
+ const file = (0, import_node_path.join)(dir, "fonts.json");
148062
+ try {
148063
+ _fontManifest = { dir, ...JSON.parse(await (0, import_promises.readFile)(file, "utf8")) };
148064
+ } catch {
148065
+ _fontManifest = { dir, cjk: [], latin: [], cjkUnicodeRange: "" };
148066
+ }
148067
+ return _fontManifest;
148068
+ }
148069
+ async function faceCss(entries, range) {
148070
+ const { dir } = await fontManifest();
148071
+ const rules = [];
148072
+ for (const entry of entries ?? []) {
148073
+ const path = (0, import_node_path.join)(dir, entry.file);
148074
+ if (!(0, import_node_fs.existsSync)(path)) continue;
148075
+ const b64 = (await (0, import_promises.readFile)(path).catch(() => null))?.toString("base64");
148076
+ if (!b64) continue;
148077
+ for (const family of entry.families ?? []) {
148078
+ rules.push(
148079
+ `@font-face{font-family:'${family}';src:local('${family}'),url(data:font/woff2;base64,${b64}) format('woff2');${entry.weight ? `font-weight:${entry.weight};` : ""}${range ? `unicode-range:${range};` : ""}font-display:swap}`
148080
+ );
148081
+ }
148082
+ }
148083
+ return rules.join("");
148084
+ }
147876
148085
  var _cjkFontCss;
147877
148086
  async function cjkFontFaceCss() {
147878
- if (_cjkFontCss !== void 0) return _cjkFontCss;
147879
- const dir = process.env.TALOS_CJK_FONT_DIR || (0, import_node_path.join)((0, import_node_path.dirname)(process.argv[1]), "..", "assets", "fonts");
147880
- const enc = async (f) => {
147881
- const p = (0, import_node_path.join)(dir, f);
147882
- return (0, import_node_fs.existsSync)(p) ? (await (0, import_promises.readFile)(p).catch(() => null))?.toString("base64") : null;
147883
- };
147884
- const [sans, serif] = await Promise.all([enc("NotoSansSC.woff2"), enc("NotoSerifSC.woff2")]);
147885
- const face = (family, b64) => b64 ? `@font-face{font-family:'${family}';src:local('${family}'),url(data:font/woff2;base64,${b64}) format('woff2');unicode-range:${CJK_UNICODE_RANGE};font-display:swap}` : "";
147886
- const rules = [
147887
- ...CJK_SANS_FAMILIES.map((f) => face(f, sans)),
147888
- ...CJK_SERIF_FAMILIES.map((f) => face(f, serif))
147889
- ].filter(Boolean);
147890
- _cjkFontCss = rules.join("");
148087
+ if (_cjkFontCss === void 0) {
148088
+ const m = await fontManifest();
148089
+ _cjkFontCss = await faceCss(m.cjk, m.cjkUnicodeRange);
148090
+ }
147891
148091
  return _cjkFontCss;
147892
148092
  }
148093
+ var _latinFontCss;
148094
+ async function latinFontFaceCss(doc) {
148095
+ if (_latinFontCss === void 0) {
148096
+ const m = await fontManifest();
148097
+ const wanted = (m.latin ?? []).filter((e) => (e.families ?? []).some((f) => doc.includes(f)));
148098
+ _latinFontCss = await faceCss(wanted, void 0);
148099
+ }
148100
+ return _latinFontCss;
148101
+ }
147893
148102
  async function withHeadlessPage(html, fn) {
147894
148103
  const headless = (process.env.TALOS_HTML2PPTX_HEADLESS ?? "").trim().toLowerCase();
147895
148104
  if (headless === "off" || headless === "none" || headless === "0" || headless === "false") return null;
@@ -148004,7 +148213,7 @@ async function main() {
148004
148213
  process.stdout.write(JSON.stringify({ ok: true, out, engine: "layout-json", slides: snapshot2.slides?.length ?? 0, ...notesDocPath ? { notesDoc: notesDocPath } : {}, warnings: warnings2 }, null, 1) + "\n");
148005
148214
  return;
148006
148215
  }
148007
- if (!/section\s+class="slide"|class="slide"/.test(raw)) {
148216
+ if (!/<section[^>]*\bclass="[^"]*(?<![\w-])slide(?![\w-])/.test(raw)) {
148008
148217
  die('the HTML must contain one <section class="slide"> per slide (1280\xD7720 canvas) \u2014 see deck-design.md', 65);
148009
148218
  }
148010
148219
  const colorWarnings = [...lintHardcodedColors(raw), ...lintRepeatedLayouts(raw)];
@@ -148028,13 +148237,33 @@ async function main() {
148028
148237
  let skinCss = "", backdropHtml = "", skinAccent = "", skinAxis = "", skinChart1 = "";
148029
148238
  if (styleArg) {
148030
148239
  const skillDir = (0, import_node_path.dirname)((0, import_node_path.dirname)(process.argv[1] || ""));
148031
- const styleDir = (0, import_node_fs.existsSync)((0, import_node_path.join)(styleArg, "skin.css")) ? styleArg : (0, import_node_path.join)(skillDir, "styles", styleArg);
148032
- const skinPath = (0, import_node_path.join)(styleDir, "skin.css");
148240
+ let styleDir, cssName = "skin.css";
148241
+ if ((0, import_node_fs.existsSync)((0, import_node_path.join)(styleArg, "skin.css"))) {
148242
+ styleDir = styleArg;
148243
+ } else if ((0, import_node_fs.existsSync)((0, import_node_path.join)(styleArg, "pack.css"))) {
148244
+ styleDir = styleArg;
148245
+ cssName = "pack.css";
148246
+ } else {
148247
+ let entry = null;
148248
+ const catalogPath = (0, import_node_path.join)(skillDir, "catalog.json");
148249
+ if ((0, import_node_fs.existsSync)(catalogPath)) {
148250
+ try {
148251
+ const { catalog } = parseCatalog(JSON.parse((0, import_node_fs.readFileSync)(catalogPath, "utf8")));
148252
+ if (catalog) entry = resolveEntry(catalog, styleArg);
148253
+ } catch {
148254
+ }
148255
+ }
148256
+ styleDir = entry ? (0, import_node_path.join)(skillDir, assetDirOf(entry)) : (0, import_node_path.join)(skillDir, "styles", styleArg);
148257
+ if (entry) cssName = cssFileOf(entry);
148258
+ }
148259
+ const skinPath = (0, import_node_path.join)(styleDir, cssName);
148033
148260
  try {
148034
148261
  skinCss = await (0, import_promises.readFile)(skinPath, "utf8");
148035
148262
  } catch (e) {
148036
148263
  die(`cannot read style ${skinPath}: ${e.message}`, 66);
148037
148264
  }
148265
+ const defaultsPath = (0, import_node_path.join)(skillDir, "styles", "_contract-defaults.css");
148266
+ if ((0, import_node_fs.existsSync)(defaultsPath)) skinCss = await (0, import_promises.readFile)(defaultsPath, "utf8") + "\n" + skinCss;
148038
148267
  const sharedBackdropsDir = (0, import_node_path.join)(skillDir, "styles", "_backdrops");
148039
148268
  const NO_AUTO_BACKDROP_VARIETY = /* @__PURE__ */ new Set(["mckinsey", "mono", "cinereel"]);
148040
148269
  let bdPath;
@@ -148089,7 +148318,9 @@ async function main() {
148089
148318
  }
148090
148319
  const tw = await tailwindCss();
148091
148320
  const cjk = !hasService && CJK_RE2.test(rawInlined) ? await cjkFontFaceCss() : "";
148092
- const html = injectHead(rawInlined, `${cjk ? `<style>${cjk}</style>` : ""}${tw ? `<style>${tw}</style>` : ""}<style>${themeCss}${SKELETON_CSS}${skinCss}</style>`);
148321
+ const latin = await latinFontFaceCss(rawInlined + skinCss);
148322
+ const fontCss = cjk + latin;
148323
+ const html = injectHead(rawInlined, `${fontCss ? `<style>${fontCss}</style>` : ""}${tw ? `<style>${tw}</style>` : ""}<style>${themeCss}${SKELETON_CSS}${skinCss}</style>`);
148093
148324
  if (rasterize) {
148094
148325
  let images;
148095
148326
  if (hasService) ({ images } = await callService("/shot", html).catch((e) => die(e.message, 1)));
@@ -0,0 +1,25 @@
1
+ {
2
+ "groups": [
3
+ { "id": "tech-future", "name_cn": "科技未来", "sample": "styles/_samples/_groups/tech-future.webp", "scenarios": ["科技", "发布会", "产品", "pitch"] },
4
+ { "id": "biz-premium", "name_cn": "商务高端", "sample": "styles/_samples/_groups/biz-premium.webp", "scenarios": ["金融", "年报", "路演", "招商", "董事会"] },
5
+ { "id": "minimal", "name_cn": "极简设计", "sample": "styles/_samples/_groups/minimal.webp", "scenarios": ["极简", "设计", "作品集"] },
6
+ { "id": "editorial", "name_cn": "编辑人文", "sample": "styles/_samples/_groups/editorial.webp", "scenarios": ["人文", "行业观察", "杂志感", "研究分享"] },
7
+ { "id": "creative", "name_cn": "创意手作", "sample": "styles/_samples/_groups/creative.webp", "scenarios": ["创意", "教学", "工作坊", "头脑风暴"] },
8
+ { "id": "natural", "name_cn": "自然温和", "sample": "styles/_samples/_groups/natural.webp", "scenarios": ["品牌手册", "可持续", "美妆", "零售"] }
9
+ ],
10
+ "entries": [
11
+ { "id": "cool", "kind": "skin", "group": "tech-future", "name_cn": "酷炫深色", "oneliner": "深蓝辉光 · 科技发布", "scenarios": ["科技", "发布", "pitch", "主题演讲"], "mode": "dark", "sample": "styles/_samples/cool.webp" },
12
+ { "id": "swiss-grid", "kind": "skin", "group": "tech-future", "name_cn": "瑞士国际", "oneliner": "克莱因蓝白 · 瑞士国际", "scenarios": ["科技产品", "数据汇报", "设计", "年度总结"], "mode": "light", "sample": "styles/_samples/swiss-grid.webp" },
13
+ { "id": "black-gold", "kind": "skin", "group": "biz-premium", "name_cn": "黑金", "oneliner": "纯黑金辉 · 高端商务", "scenarios": ["金融", "年报", "路演", "奢侈品"], "mode": "dark", "sample": "styles/_samples/black-gold.webp" },
14
+ { "id": "olive-gold", "kind": "skin", "group": "biz-premium", "name_cn": "橄榄金", "oneliner": "橄榄亮金 · 高端招商", "scenarios": ["高端", "证书", "招商", "品牌"], "mode": "dark", "sample": "styles/_samples/olive-gold.webp" },
15
+ { "id": "mckinsey", "kind": "skin", "group": "biz-premium", "name_cn": "白底咨询", "oneliner": "白底藏青 · 咨询评审", "scenarios": ["咨询", "战略汇报", "评审", "董事会"], "mode": "light", "sample": "styles/_samples/mckinsey.webp" },
16
+ { "id": "apple", "kind": "skin", "group": "minimal", "name_cn": "纯黑极简", "oneliner": "纯黑极简 · 产品发布", "scenarios": ["产品发布", "主题演讲", "极简演示"], "mode": "dark", "sample": "styles/_samples/apple.webp" },
17
+ { "id": "mono", "kind": "skin", "group": "minimal", "name_cn": "纯白黑灰", "oneliner": "纯白黑灰 · 极简设计", "scenarios": ["极简", "高端", "设计", "单色报告"], "mode": "light", "sample": "styles/_samples/mono.webp" },
18
+ { "id": "ivory-gold", "kind": "skin", "group": "minimal", "name_cn": "奶油青铜", "oneliner": "奶油青铜 · 奢华极简", "scenarios": ["奢华极简", "品牌手册", "路演", "高端零售"], "mode": "light", "sample": "styles/_samples/ivory-gold.webp" },
19
+ { "id": "magazine-ink", "kind": "skin", "group": "editorial", "name_cn": "杂志墨", "oneliner": "瓷白靛蓝 · 杂志人文", "scenarios": ["人文分享", "行业观察", "商业发布"], "mode": "light", "sample": "styles/_samples/magazine-ink.webp" },
20
+ { "id": "anthropic", "kind": "skin", "group": "editorial", "name_cn": "奶油珊瑚", "oneliner": "奶油珊瑚 · AI 研究", "scenarios": ["AI", "产品", "研究分享", "人文品牌"], "mode": "light", "sample": "styles/_samples/anthropic.webp" },
21
+ { "id": "hand-drawn", "kind": "skin", "group": "creative", "name_cn": "纸感手绘", "oneliner": "纸感手绘 · 创意教学", "scenarios": ["创意", "头脑风暴", "教学", "工作坊"], "mode": "light", "sample": "styles/_samples/hand-drawn.webp" },
22
+ { "id": "cinereel", "kind": "skin", "group": "creative", "name_cn": "黑白胶片", "oneliner": "黑白胶片 · 影视创意", "scenarios": ["影视", "创意作品集", "音乐", "传媒"], "mode": "dark", "sample": "styles/_samples/cinereel.webp" },
23
+ { "id": "branding", "kind": "skin", "group": "natural", "name_cn": "暖米绿意", "oneliner": "暖米绿意 · 品牌手册", "scenarios": ["品牌手册", "可持续", "美妆", "零售", "极简"], "mode": "light", "sample": "styles/_samples/branding.webp" }
24
+ ]
25
+ }