allyhub 0.5.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/commands/render.js +1 -1
- package/dist/commands/sheet.js +7 -7
- package/dist/commands/slides.js +1 -1
- package/dist/node_modules/@allyhub-next/audio/package.json +1 -1
- package/dist/node_modules/@allyhub-next/browser/package.json +1 -1
- package/dist/node_modules/@allyhub-next/build/package.json +1 -1
- package/dist/node_modules/@allyhub-next/chart/package.json +1 -1
- package/dist/node_modules/@allyhub-next/check/package.json +1 -1
- package/dist/node_modules/@allyhub-next/cloud/package.json +1 -1
- package/dist/node_modules/@allyhub-next/components/package.json +1 -1
- package/dist/node_modules/@allyhub-next/dev-server/dist/exports.js +1 -1
- package/dist/node_modules/@allyhub-next/dev-server/package.json +1 -1
- package/dist/node_modules/@allyhub-next/doc/package.json +1 -1
- package/dist/node_modules/@allyhub-next/export/dist/export.d.ts +2 -2
- package/dist/node_modules/@allyhub-next/export/dist/export.js +4 -4
- package/dist/node_modules/@allyhub-next/export/dist/names.d.ts +1 -1
- package/dist/node_modules/@allyhub-next/export/package.json +1 -1
- package/dist/node_modules/@allyhub-next/formats/dist/data/sheet.d.ts +179 -0
- package/dist/node_modules/@allyhub-next/formats/dist/data/sheet.js +1 -1
- package/dist/node_modules/@allyhub-next/formats/dist/data/slides.d.ts +303 -11
- package/dist/node_modules/@allyhub-next/formats/dist/data/slides.js +1 -1
- package/dist/node_modules/@allyhub-next/formats/dist/index.d.ts +1 -0
- package/dist/node_modules/@allyhub-next/formats/dist/index.js +1 -1
- package/dist/node_modules/@allyhub-next/formats/dist/items.js +1 -1
- package/dist/node_modules/@allyhub-next/formats/dist/schemas.d.ts +135 -3
- package/dist/node_modules/@allyhub-next/formats/dist/zip.d.ts +17 -0
- package/dist/node_modules/@allyhub-next/formats/dist/zip.js +2 -0
- package/dist/node_modules/@allyhub-next/formats/package.json +1 -1
- package/dist/node_modules/@allyhub-next/measure/package.json +1 -1
- package/dist/node_modules/@allyhub-next/media/package.json +1 -1
- package/dist/node_modules/@allyhub-next/model/package.json +1 -1
- package/dist/node_modules/@allyhub-next/project/package.json +1 -1
- package/dist/node_modules/@allyhub-next/protocol/dist/editor.d.ts +10 -0
- package/dist/node_modules/@allyhub-next/protocol/dist/editor.js +1 -1
- package/dist/node_modules/@allyhub-next/protocol/dist/notes.d.ts +2 -0
- package/dist/node_modules/@allyhub-next/protocol/dist/notes.js +1 -1
- package/dist/node_modules/@allyhub-next/protocol/package.json +1 -1
- package/dist/node_modules/@allyhub-next/registry/package.json +1 -1
- package/dist/node_modules/@allyhub-next/render/dist/exports.d.ts +2 -11
- package/dist/node_modules/@allyhub-next/render/dist/exports.js +2 -2
- package/dist/node_modules/@allyhub-next/render/dist/page.d.ts +1 -9
- package/dist/node_modules/@allyhub-next/render/package.json +1 -1
- package/dist/node_modules/@allyhub-next/runtime/package.json +1 -1
- package/dist/node_modules/@allyhub-next/runtimes/package.json +1 -1
- package/dist/node_modules/@allyhub-next/scaffold/package.json +1 -1
- package/dist/node_modules/@allyhub-next/scenery/package.json +1 -1
- package/dist/node_modules/@allyhub-next/scenery-host/package.json +1 -1
- package/dist/node_modules/@allyhub-next/sheet/dist/api/capabilities.js +1 -1
- package/dist/node_modules/@allyhub-next/sheet/dist/api/index.d.ts +1 -0
- package/dist/node_modules/@allyhub-next/sheet/dist/api/index.js +1 -1
- package/dist/node_modules/@allyhub-next/sheet/dist/api/page.d.ts +83 -0
- package/dist/node_modules/@allyhub-next/sheet/dist/api/page.js +2 -0
- package/dist/node_modules/@allyhub-next/sheet/dist/api/workbook.d.ts +40 -1
- package/dist/node_modules/@allyhub-next/sheet/dist/api/workbook.js +1 -1
- package/dist/node_modules/@allyhub-next/sheet/dist/check.js +1 -1
- package/dist/node_modules/@allyhub-next/sheet/dist/structure.js +1 -1
- package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/charts.d.ts +2 -0
- package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/charts.js +1 -1
- package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/import.d.ts +3 -0
- package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/import.js +1 -1
- package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/read.d.ts +2 -1
- package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/read.js +1 -1
- package/dist/node_modules/@allyhub-next/sheet/dist/xlsx/write.js +1 -1
- package/dist/node_modules/@allyhub-next/sheet/package.json +1 -1
- package/dist/node_modules/@allyhub-next/site/package.json +1 -1
- package/dist/node_modules/@allyhub-next/slides-core/dist/api.d.ts +64 -7
- package/dist/node_modules/@allyhub-next/slides-core/dist/api.js +2 -2
- package/dist/node_modules/@allyhub-next/slides-core/dist/capabilities.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-core/dist/chart-api.d.ts +23 -0
- package/dist/node_modules/@allyhub-next/slides-core/dist/chart-api.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-core/dist/chart-file.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-core/dist/enums.d.ts +20 -0
- package/dist/node_modules/@allyhub-next/slides-core/dist/enums.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-core/dist/index.d.ts +1 -0
- package/dist/node_modules/@allyhub-next/slides-core/dist/index.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-core/dist/model.d.ts +37 -1
- package/dist/node_modules/@allyhub-next/slides-core/dist/office.d.ts +10 -0
- package/dist/node_modules/@allyhub-next/slides-core/dist/office.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-core/dist/preset.d.ts +5 -0
- package/dist/node_modules/@allyhub-next/slides-core/dist/preset.js +2 -0
- package/dist/node_modules/@allyhub-next/slides-core/dist/resolve.d.ts +7 -2
- package/dist/node_modules/@allyhub-next/slides-core/dist/resolve.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-core/package.json +1 -1
- package/dist/node_modules/@allyhub-next/slides-pptx/dist/charts.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-pptx/dist/import.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-pptx/dist/read.d.ts +2 -1
- package/dist/node_modules/@allyhub-next/slides-pptx/dist/read.js +2 -2
- package/dist/node_modules/@allyhub-next/slides-pptx/dist/shapes.d.ts +6 -1
- package/dist/node_modules/@allyhub-next/slides-pptx/dist/shapes.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-pptx/dist/text.d.ts +11 -0
- package/dist/node_modules/@allyhub-next/slides-pptx/dist/text.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-pptx/dist/write.js +2 -2
- package/dist/node_modules/@allyhub-next/slides-pptx/dist/xml.d.ts +10 -4
- package/dist/node_modules/@allyhub-next/slides-pptx/dist/xml.js +2 -2
- package/dist/node_modules/@allyhub-next/slides-pptx/package.json +1 -1
- package/dist/node_modules/@allyhub-next/slides-runtime/dist/draw.d.ts +3 -0
- package/dist/node_modules/@allyhub-next/slides-runtime/dist/draw.js +2 -2
- package/dist/node_modules/@allyhub-next/slides-runtime/dist/edit.js +1 -1
- package/dist/node_modules/@allyhub-next/slides-runtime/package.json +1 -1
- package/dist/node_modules/@allyhub-next/stage/dist/graphics.js +1 -1
- package/dist/node_modules/@allyhub-next/stage/package.json +1 -1
- package/dist/node_modules/@allyhub-next/stage-page/dist/page.js +19 -19
- package/dist/node_modules/@allyhub-next/stage-page/package.json +1 -1
- package/dist/node_modules/@allyhub-next/video-core/package.json +1 -1
- package/editor-web/assets/dist-BW2s9FMO.js +4 -0
- package/editor-web/assets/{dist-CuW84oPe.js → dist-C-6JmebI.js} +22 -22
- package/editor-web/assets/dist-CCYMLMKN.js +6 -0
- package/editor-web/assets/dist-CHzurjMx.js +33 -0
- package/editor-web/assets/{dist-Yi3sy7Ea.js → dist-DF7H1dxw.js} +1 -1
- package/editor-web/assets/dist-Da5AUSKX.js +2 -0
- package/editor-web/assets/index-CovQYWvD.js +69 -0
- package/editor-web/assets/minus-BrvjaJyO.js +1 -0
- package/editor-web/assets/react-DV5fPdiH.js +101 -0
- package/editor-web/assets/{textarea-CvxipnGW.js → textarea-B0vCGdZI.js} +2 -2
- package/editor-web/assets/{trash-2-Bq1Dt8XG.js → trash-2-B0dvc1cZ.js} +1 -1
- package/editor-web/assets/{undo-2-Djhvu4xt.js → undo-2-A1EPubPO.js} +1 -1
- package/editor-web/index.html +2 -2
- package/package.json +2 -2
- package/editor-web/assets/dist-Cg2PdedY.js +0 -6
- package/editor-web/assets/dist-CxAS_vp7.js +0 -2
- package/editor-web/assets/dist-DCVaj9i1.js +0 -4
- package/editor-web/assets/dist-DGVUuVPB.js +0 -33
- package/editor-web/assets/index-pwRfZ2Jv.js +0 -69
- package/editor-web/assets/minus-BizJdinJ.js +0 -1
- package/editor-web/assets/react-D54s6gwK.js +0 -101
package/dist/commands/render.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
-
import{join as
|
|
2
|
+
import{join as y,resolve as x}from"node:path";import{z as t}from"zod";import{formatConsole as w,formatProblem as v}from"../text/index.js";import{exportProject as k}from"@allyhub-next/export";import{SHARE_ENCODE as n}from"@allyhub-next/render";import{consoleJson as p}from"@allyhub-next/project";import{OUT_DIR as $}from"@allyhub-next/formats";import{EXIT as c}from"@allyhub-next/protocol";import{defineCommand as P}from"../command.js";import{parameters as O}from"../parameters.js";import{projectRoot as S}from"../project.js";import{combosOf as j,commandError as B}from"../version.js";import{dir as A,indexing as D}from"../fields.js";const N={codec:t.enum(["h264","h265"]).default("h264").describe("The mp4's video codec; h265 is smaller"),crf:t.number().int().min(0).max(63).optional().describe(`Quality, lower is better: default ${String(n.crf)} for an mp4, ready to share (a platform profile's format its own), 30 for a webm`),maxBitrate:t.number().int().min(0).max(5e5).optional().describe(`An mp4's most video bitrate, kbit/s, 0 for none: default ${String(n.maxKbps)} at 1080p ${String(n.fps)} fps, scaled by the frame's pixels and the frames a second (16000 at 1080p 60, 32000 at 4K 30), so the file is ready to share; a platform profile's format its own`),audioBitrate:t.number().int().min(32).max(512).optional().describe("The sound's bitrate, kbit/s: default 192 (AAC in an mp4), 160 (Opus in a webm); a mov keeps PCM"),steps:t.boolean().default(!1).describe("A deck's pdf, png and pptx: a page, a file or a slide per step of each page, not only its last"),pptx:t.enum(["native","picture"]).default("native").describe("A deck's pptx: native, PowerPoint's own model, editable there (the deck's masters, layouts, placeholders, shapes, text, pictures, videos and notes, a component as its picture); or picture, each slide a picture of the page")},T=(o,i)=>`${String(o)} ${i}${o===1?"":"s"}`;export const render=P({name:"render",summary:"The files: a video, its frames, subtitles, cover and mastered mix; a batch's table of ads; a deck's PDF, PPTX and PNGs; a doc's PDF and Markdown; a sheet's Excel workbook with live formulas, PDF, PNG, CSV, Markdown and JSON; a 3D model's GLB",input:t.strictObject({items:t.array(t.string()).optional().describe("Only these items: an id, a path into one, or a folder of items; default every one"),combo:t.array(t.string()).optional().describe("Only the combos matching name=value pairs joined with commas (lang=zh-cn,hook=b), or a combo's id (c03)"),type:t.array(t.string()).optional().describe("File types: mp4, mov, webm, gif, png, srt, vtt (cues cut as the piece's captions layer cuts them, else by default), cover, wav (the mix, mastered as the render masters it: 48 kHz, 16 bits, the film's length), pdf, pptx; csv for a piece with slots, its table of ads (<piece>/ads.csv: a row per ad with its combo, picks, length, file, name and generated media); a doc's pdf, docx, png, md; a sheet's xlsx (every sheet, formulas live with their values cached), pdf, png, csv, md, json; a 3D model's glb. Default mp4 for a video, pdf for a deck and a doc, xlsx for a sheet, glb for a model; a type an item does not have is skipped"),out:t.string().optional().describe("The folder the files go in; default .allyhub/out"),name:t.string().optional().describe("Name a video's or deck's files <name>.<ext> in its folder of the output, with what tells its versions apart before the extension when there are several (<name>.zh-cn.mp4, <name>.c03.mp4); default <output>.<combo>.<ext>"),params:O(N),dir:A}),positional:["items"],output:t.looseObject({out:t.string(),files:t.array(t.looseObject({name:t.string(),path:t.string(),type:t.string()})),failed:t.array(t.looseObject({name:t.string(),code:t.string()}))}),examples:["allyhub render","allyhub render launch/film --type mp4,srt","allyhub render launch/film --type wav","allyhub render ads/tidyform --type csv","allyhub render launch/plan --type pdf,md","allyhub render finance/budget --type xlsx,pdf","allyhub render launch/deck --type pptx --param pptx=picture","allyhub render --combo lang=zh-cn --param crf=16","allyhub render launch/film --name launch-film --param max-bitrate=0"]},async(o,i)=>{const d=await S(i.cwd,o.dir),f=x(i.cwd,o.out??y(d,$)),r=o.params,h={codec:r.codec,...r.crf===void 0?{}:{crf:r.crf},...r.maxBitrate===void 0?{}:{maxBitrate:r.maxBitrate},...r.audioBitrate===void 0?{}:{audioBitrate:r.audioBitrate}};let l=0,a;try{a=await k({root:d,out:f,...o.items===void 0?{}:{items:o.items},combos:j(o),...o.type===void 0?{}:{types:o.type},...o.name===void 0?{}:{name:o.name},encode:h,...r.steps?{steps:!0}:{},...r.pptx==="native"?{}:{pptx:r.pptx},index:D(i.env),log:e=>{i.progress(e)},onProgress:e=>{const s=Math.floor(e*10);s<=l||s>=10||(l=s,i.progress(`${String(s*10)}%`))},signal:i.signal})}catch(e){throw B(e)}const u=e=>e?` (${e.integrated.toFixed(1)} LUFS, true peak ${e.truePeak===void 0?"–":e.truePeak.toFixed(1)} dBTP)`:"",b=a.problems.filter(e=>e.level==="error"),m=a.files.flatMap(e=>e.files.length>1?e.files.map(s=>` ${s}`):[` ${e.path}${u(e.loudness)}`]),g=[`${T(m.length,"file")} in ${a.out}:`,...m,...a.failed.length>0?["Not made:",...a.failed.map(e=>` ${e.name}: ${e.message}${e.hint?` ${e.hint}`:""}`)]:[],...a.unindexed.map(e=>`Not indexed, drawn the fallback way: ${e.file} (${e.error})`),...new Set(a.files.flatMap(e=>(e.fontsLeft??[]).map(s=>`Not in the file: ${s.font} (${s.why}); PowerPoint shows another font where it is not installed.`))),...b.map(v),...w(p(a.console))];return{value:{out:a.out,files:a.files.map(e=>({...e})),failed:a.failed.map(e=>({...e})),problems:a.problems,...a.unindexed.length>0?{unindexed:a.unindexed}:{},...p(a.console)},text:g.join(`
|
|
3
3
|
`),exit:a.failed.length>0?c.failed:c.ok}});
|
package/dist/commands/sheet.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
-
import{mkdir as ie,readFile as
|
|
3
|
-
`)}});const
|
|
4
|
-
`)}});function
|
|
5
|
-
`)}}const
|
|
6
|
-
`)}}),sheetCapabilities=E({name:"sheet capabilities",summary:"What @allyhub/sdk/sheets holds of openpyxl's (its classes), how it differs and what it adds, and the worksheet functions, as JSON",input:
|
|
7
|
-
`)}});const
|
|
8
|
-
`)}}let w;try{w=
|
|
2
|
+
import{mkdir as ie,readFile as H,stat as X,writeFile as ce}from"node:fs/promises";import{basename as k,dirname as N,extname as A,join as S,relative as B,resolve as D}from"node:path";import{z as d}from"zod";import{readSheetSource as he,sheetRoot as de,workbookFiles as fe}from"@allyhub-next/build";import{ITEM_KINDS as me,ZIP_LIMITS as ue}from"@allyhub-next/formats";import{EXIT as $}from"@allyhub-next/protocol";import{CellError as we,DIFF_DEFAULTS as pe,FormulaCell as O,Matrix as be,PROFILE_TOP as $e,SharedFormula as ge,cellName as M,checkWorkbook as q,dataValue as _,diffWorkbooks as ye,importRows as xe,profileTable as ve,rangeName as G,readAddress as ke,readArea as Se,scenarioNames as K,shownValue as j}from"@allyhub-next/sheet";import{CAPABILITIES as Y}from"@allyhub-next/sheet/api";import{COMPARE_TOLERANCE as je,importXlsx as Z}from"@allyhub-next/sheet/xlsx";import{CommandError as g,defineCommand as E}from"../command.js";import{projectRoot as T}from"../project.js";import{dir as C}from"../fields.js";const x=me.sheet.entries[0];export const CALC_ROWS=50,TRACE_CELLS=50;export async function findSheet(e,o,s){const t=D(o,s);for(const n of[k(t)===x?t:S(t,x),S(e,s,x),S(e,"content",s,x)])if((await X(n).catch(()=>{}))?.isFile())return n}export const sheetFolderName=(e,o)=>B(e,N(o)).replace(/^content\//u,"");export async function sheetAt(e,o,s){const t=await findSheet(e,o,s);if(t!==void 0)return t;throw new g("not-found",`There is no sheet ${s}.`,{exit:$.notFound,hint:"Name it by its folder (research/leads, a folder under content/ with or without content/) or its sheet.yaml."})}export async function sourceOfSheet(e,o){const s=de(e,N(o)),t=await he(s.root,s.dir);return{...s,source:t,files:fe(s.root,t)}}export async function openSheet(e,o,s,t){const n=await sheetAt(e,o,s),{source:a,files:r}=await sourceOfSheet(e,n),{workbook:c,calc:i,problems:l}=q(r,{scenario:t});if(!c||!i)throw new g("bad-file",`${B(e,n)} cannot be read: ${l.map(m=>`${m.line===void 0?"":`line ${String(m.line)}: `}${m.message}`).join("; ")}`,{exit:$.usage,hint:"allyhub check lists what is wrong."});return{file:B(e,n),workbook:c,calc:i,problems:l.length+a.problems.length}}function Ee(e,o){const s=K(e);if(!s.includes(o))throw new g("not-found",`There is no scenario ${o}.`,{exit:$.notFound,hint:s.length>0?`It has ${s.join(", ")}.`:"sheet.yaml's scenarios holds none."})}const u=e=>e.toLocaleString("en-US"),I=e=>e.toLocaleString("en-US",{maximumFractionDigits:4}),P=e=>e>0?["",`The workbook has ${String(e)} problem${e===1?"":"s"}: allyhub check lists them.`]:[];function Oe(e,o){const s=[`${u(e.empty)} empty`,`${u(e.distinct)} distinct`];e.errors>0&&s.push(`${u(e.errors)} errors`),e.min!==void 0&&e.max!==void 0&&s.push(`${I(e.min)} to ${I(e.max)}`),e.sum!==void 0&&s.push(`sum ${I(e.sum)}`),e.mean!==void 0&&s.push(`mean ${I(e.mean)}`),e.shortest!==void 0&&e.longest!==void 0&&s.push(`${String(e.shortest)} to ${String(e.longest)} characters`);const t=[`${e.name.padEnd(o)} ${s.join(", ")}`];return e.formula!==void 0&&t.push(`${"".padEnd(o)} ${e.formula}`),e.top.some(n=>n.count>1)&&t.push(`${"".padEnd(o)} most: ${e.top.map(n=>`${JSON.stringify(n.value.length>40?`${n.value.slice(0,39)}…`:n.value)} ${u(n.count)}`).join(", ")}`),t}export const sheet=E({name:"sheet",summary:"Each table of a sheet measured: its columns' counts, empty, distinct, ranges and frequent values",input:d.strictObject({sheet:d.string().describe("The sheet, by its folder or its sheet.yaml"),dir:C}),positional:["sheet"],output:d.looseObject({}),examples:["allyhub sheet research/leads"]},async(e,o)=>{const s=await T(o.cwd,e.dir),{file:t,workbook:n,calc:a,problems:r}=await openSheet(s,o.cwd,e.sheet),c=n.tables.map(l=>({name:l.name,rows:l.rows,columns:ve(a,l)})),i=c.flatMap(l=>{const m=Math.min(24,Math.max(4,...l.columns.map(w=>w.name.length)));return["",`${l.name}: ${u(l.rows)} rows, ${String(l.columns.length)} columns; each column's ${String($e)} most frequent values`,...l.columns.flatMap(w=>Oe(w,m))]});return{value:{file:t,tables:c,problems:r},text:[`${t}: ${String(n.sheets.length)} sheet${n.sheets.length===1?"":"s"}, ${String(c.length)} table${c.length===1?"":"s"}`,...i,...P(r)].join(`
|
|
3
|
+
`)}});const Q=e=>{const o=e.sheets[0];if(!o)throw new g("bad-file","The workbook has no sheets.",{exit:$.usage});return o};function ee(e,o){const s=o.lastIndexOf("!");if(s<0)return{sheet:Q(e),address:o};const t=o.slice(0,s).replace(/^'|'$/gu,"").replaceAll("''","'"),n=e.sheet(t);if(!n)throw new g("not-found",`There is no sheet ${t}.`,{exit:$.notFound,hint:`It has ${e.sheets.map(a=>a.name).join(", ")}.`});return{sheet:n,address:o.slice(s+1)}}function R(e,o,s,t){const n=[];for(let a=o.top;a<=o.bottom;a++){const r=[];for(let c=o.left;c<=o.right;c++){const i=t.value(e,a,c),l=e.lookAt(a,c).format,m=e.at(a,c);r.push({address:M({row:a,col:c}),value:_(i,l),shown:j(i,l),...m instanceof O?{formula:m.text}:{}})}n.push(r)}return{sheet:e.name,what:s,area:G(o),rows:n}}function Te(e,o,s){const t=a=>({address:"",value:_(a,void 0),shown:j(a)});if(!(s instanceof be))return{sheet:e.name,what:o,rows:[[t(s)]]};const n=[];for(let a=0;a<s.rows;a++){const r=[];for(let c=0;c<s.cols;c++)r.push(t(s.at(a,c)));n.push(r)}return{sheet:e.name,what:o,rows:n}}function te(e,o){const{wb:s}=e;if(o===void 0)return s.sheets.flatMap(l=>{const m=l.used;return m?[R(l,m,l.name,e)]:[]});const t=s.table(o);if(t)return[R(t.sheet,t.area,o,e)];const n=s.name(o);if(n){const l=new ge(n.formula?.text??`=${o}`,0,0,{file:""}),m=Q(s);return[Te(m,o,e.evaluate(l,m))]}const a=s.sheet(o);if(a){const l=a.used;return[l?R(a,l,o,e):{sheet:a.name,what:o,rows:[]}]}const{sheet:r,address:c}=ee(s,o),i=Se(c);if(!i)throw new g("not-found",`${o} is not a sheet, a table, a name or a range of this workbook.`,{exit:$.notFound,hint:[`Sheets: ${s.sheets.map(l=>l.name).join(", ")}.`,s.tables.length>0?`Tables: ${s.tables.map(l=>l.name).join(", ")}.`:"",s.names.size>0?`Names: ${[...s.names.values()].map(l=>l.name).join(", ")}.`:"","A range is Summary!B3:D3, or B3 on the first sheet."].filter(Boolean).join(" ")});return[R(r,i,o,e)]}function U(e){const o=[];for(const s of e)s.forEach((t,n)=>{o[n]=Math.max(o[n]??0,t.length)});return e.map(s=>s.map((t,n)=>n===s.length-1?t:t.padEnd(o[n]??0)).join(" ").trimEnd())}function Ce(e,o){const s=e.area===void 0?e.what:`${e.sheet}!${e.area}`,t=e.rows.slice(0,o),n=e.area!==void 0,a=t.map(c=>[...n?[/\d+$/u.exec(c[0]?.address??"")?.[0]??""]:[],...c.map(i=>i.shown)]),r=(e.rows[0]??[]).map(c=>c.address.replace(/\d+$/u,""));return[s,...U(n?[["",...r],...a]:a),...e.rows.length>t.length?[`… ${u(e.rows.length-t.length)} more rows (--all)`]:[]]}export const sheetCalc=E({name:"sheet calc",summary:"What a sheet computes, without opening anything: a sheet, a range, a table, a name, or every sheet, as an aligned table",input:d.strictObject({sheet:d.string().describe("The sheet, by its folder or its sheet.yaml"),what:d.string().optional().describe("A sheet (its used range), a range (Summary!B3:D3, or B3 on the first sheet), a table or a name; default every sheet"),all:d.boolean().default(!1).describe(`Every row, not the first ${String(CALC_ROWS)}`),scenario:d.string().optional().describe("Compute it with this scenario's inputs (sheet.yaml's scenarios); nothing is written"),scenarios:d.boolean().default(!1).describe("Compare the base case and every scenario: what is names, cells or ranges, apart by commas, a row each; default the names no scenario sets"),dir:C}),positional:["sheet","what"],output:d.looseObject({}),examples:["allyhub sheet calc finance/budget","allyhub sheet calc finance/budget Summary","allyhub sheet calc finance/budget orders","allyhub sheet calc finance/budget 'Summary!B3:M3' --json","allyhub sheet calc finance/budget revenue --scenario high","allyhub sheet calc finance/budget 'revenue,Summary!B4' --scenarios"]},async(e,o)=>{const s=await T(o.cwd,e.dir);if(e.scenarios)return Ae(s,o.cwd,e.sheet,e.what);const{file:t,calc:n,problems:a,workbook:r}=await openSheet(s,o.cwd,e.sheet,e.scenario);e.scenario!==void 0&&Ee(r,e.scenario);const c=te(n,e.what),i=e.all?1/0:CALC_ROWS;return{value:{file:t,grids:c,problems:a},text:[...c.flatMap((l,m)=>[...m>0?[""]:[],...Ce(l,i)]),...P(a)].join(`
|
|
4
|
+
`)}});function Fe(e,o){return te(e,o.trim()).flatMap(s=>s.rows.flat().map(t=>({...t,address:t.address===""?o.trim():`${s.sheet}!${t.address}`})))}async function Ae(e,o,s,t){const n=await openSheet(e,o,s),a=K(n.workbook);if(a.length===0)throw new g("not-found",`${n.file} has no scenarios.`,{exit:$.notFound,hint:"sheet.yaml's scenarios: { high: { growth: 0.2 } } names some."});const r=new Set(a.flatMap(h=>Object.keys(n.workbook.file.scenarios?.[h]??{}).map(b=>b.toLowerCase()))),c=t?.split(",")??[...n.workbook.names.values()].map(h=>h.name).filter(h=>!r.has(h.toLowerCase()));if(c.length===0)throw new g("bad-input","Say what to compare: names, cells or ranges, apart by commas.",{exit:$.usage});const i=["Base case",...a],l=[n,...await Promise.all(a.map(h=>openSheet(e,o,s,h)))],w=c.map(h=>l.map(b=>Fe(b.calc,h))).flatMap(h=>(h[0]??[]).map((b,p)=>({output:b.address,values:Object.fromEntries(i.map((v,y)=>[v,h[y]?.[p]?.value??null])),shown:Object.fromEntries(i.map((v,y)=>[v,h[y]?.[p]?.shown??""]))})));return{value:{file:n.file,scenarios:i,outputs:w},text:[...U([["",...i],...w.map(h=>[h.output,...i.map(b=>h.shown[b]??"")])]),...P(n.problems)].join(`
|
|
5
|
+
`)}}const Me=(e,o)=>`${e.sheet===o?"":`${e.sheet.name}!`}${G({top:e.top,left:e.left,bottom:Math.min(e.bottom,Math.max(e.top,e.sheet.lastRow)),right:e.right})}`;export const sheetTrace=E({name:"sheet trace",summary:"What a cell depends on and what depends on it: its formula, where it is written, the places it reads and the cells that read it",input:d.strictObject({sheet:d.string().describe("The sheet, by its folder or its sheet.yaml"),cell:d.string().describe("The cell: Summary!B5, or B5 on the first sheet"),all:d.boolean().default(!1).describe(`Every cell that reads it, not the first ${String(TRACE_CELLS)}`),dir:C}),positional:["sheet","cell"],output:d.looseObject({}),examples:["allyhub sheet trace finance/budget 'Summary!B1'"]},async(e,o)=>{const s=await T(o.cwd,e.dir),{file:t,workbook:n,calc:a}=await openSheet(s,o.cwd,e.sheet),{sheet:r,address:c}=ee(n,e.cell),i=ke(c);if(!i)throw new g("bad-input",`${e.cell} is not a cell.`,{exit:$.usage});const{row:l,col:m}=i,w=a.value(r,l,m),h=r.lookAt(l,m).format,b=r.at(l,m),p=n.sourceOf(r,l,m),v=b instanceof O?a.precedents(b).map(f=>{const le=f.single?j(a.value(f.sheet,f.top,f.left),f.sheet.lookAt(f.top,f.left).format):`${u(f.cols)} × ${u(Math.max(0,Math.min(f.bottom,f.sheet.lastRow)-f.top+1))}`,V=f.single?f.sheet.at(f.top,f.left):void 0,J=V instanceof O?V.text:void 0;return{address:Me(f,r),shown:le,...J===void 0?{}:{formula:J}}}):[],y=a.readers(r,l,m),L=e.all?y:y.slice(0,TRACE_CELLS),W=L.map(f=>({address:`${f.sheet===r?"":`${f.sheet.name}!`}${M(f)}`,shown:j(f.value,f.sheet.lookAt(f.row,f.col).format),formula:f.text})),z=f=>[` ${f.address}`,f.shown,f.formula].filter(Boolean).join(" "),F=p===void 0?void 0:p.line===void 0?p.file:`${p.file}:${String(p.line)}`;return{value:{file:t,cell:`${r.name}!${M(i)}`,value:_(w,h),shown:j(w,h),...w instanceof we?{error:w.code}:{},...b instanceof O?{formula:b.text}:{},...F===void 0?{}:{written:F},reads:v,readBy:W,readers:y.length},text:[`${r.name}!${M(i)} ${j(w,h)}`,...b instanceof O?[` ${b.text}`]:[],...F===void 0?[]:[` written in ${F}`],...v.length>0?["reads:",...v.map(z)]:[],...y.length>0?[`read by ${u(y.length)}:`,...W.map(z),...y.length>L.length?[` … ${u(y.length-L.length)} more (--all)`]:[]]:["read by nothing"]].join(`
|
|
6
|
+
`)}}),sheetCapabilities=E({name:"sheet capabilities",summary:"What @allyhub/sdk/sheets holds of openpyxl's (its classes), how it differs and what it adds, and the worksheet functions, as JSON",input:d.strictObject({}),output:d.looseObject({}),examples:["allyhub sheet capabilities"]},()=>Promise.resolve({value:{...Y},text:JSON.stringify(Y,null,2)}));const se=new Set([".xlsx",".xlsm",".xltx",".xltm"]);export const DIFF_ROWS=50;const oe={value:"Value changed, formula the same",formula:"Formula changed, value the same",both:"Formula and value changed",added:"Added",removed:"Removed"},Ie=e=>{const o=(e.now??e.was)?.cell??"",s=e.table===void 0?o:`${e.table}[${e.key??o}]`,t=e.column===void 0?"":` ${e.column}`;return`${e.sheet}!${s}${t}`},Re=e=>{const o=e.was?.formula??"",s=e.now?.formula??"";return[Ie(e),e.was?.shown??"","→",e.now?.shown??"",e.kind==="value"?s:e.kind==="formula"||e.kind==="both"?`${o} → ${s}`:s===""?o:s]};function Le(e,o){const s=[];for(const t of e.sheets)s.push(`Sheet ${t.name} ${t.added?"added":"removed"}`);for(const t of e.tables){const n=[t.rowsAdded.length>0?`rows added: ${t.rowsAdded.slice(0,20).join(", ")}`:"",t.rowsRemoved.length>0?`rows removed: ${t.rowsRemoved.slice(0,20).join(", ")}`:"",t.columnsAdded.length>0?`columns added: ${t.columnsAdded.join(", ")}`:"",t.columnsRemoved.length>0?`columns removed: ${t.columnsRemoved.join(", ")}`:""].filter(Boolean);s.push(`Table ${t.name}, rows lined up by ${t.by==="key"?t.key??"its key":"their place"}${n.length>0?`: ${n.join("; ")}`:""}`)}for(const t of e.names)s.push(`Name ${t.name}: ${t.was??"(none)"} → ${t.now??"(none)"}`);for(const t of e.charts)s.push(`Charts of ${t} changed`);for(const t of Object.keys(oe)){const n=e.cells.filter(r=>r.kind===t);if(n.length===0)continue;const a=o?n:n.slice(0,DIFF_ROWS);s.push("",`${oe[t]}: ${u(n.length)}`,...U(a.map(Re)).map(r=>` ${r}`),...n.length>a.length?[` … ${u(n.length-a.length)} more (--all)`]:[])}return s}async function ne(e,o,s){const t=D(o,s);if(se.has(A(t).toLowerCase())){const r=await H(t).catch(()=>{throw new g("not-found",`There is no file ${t}.`,{exit:$.notFound})}),c=Z(new Uint8Array(r),{name:k(t,A(t))}),{calc:i}=q({text:c.files.get(x)??"",read:l=>c.files.get(l)});if(!i)throw new g("bad-file",`${s} cannot be read.`,{exit:$.usage});return{calc:i,file:s}}const{calc:n,file:a}=await openSheet(e,o,s);return{calc:n,file:a}}export const sheetDiff=E({name:"sheet diff",summary:"Two versions of a workbook compared, by value and by formula: two folders, or a folder and an .xlsx. Cells whose formula changed and value did not are apart from those whose value changed; rows of a table line up by its key, else by their place",input:d.strictObject({was:d.string().describe("The version before: a sheet's folder or an .xlsx"),now:d.string().describe("The version after: a sheet's folder or an .xlsx"),tolerance:d.number().min(0).default(pe.tolerance).describe("How far apart two numbers may be, as a share of the larger, and be the same"),all:d.boolean().default(!1).describe(`Every cell, not the first ${String(DIFF_ROWS)} of each kind`),dir:C}),positional:["was","now"],output:d.looseObject({}),examples:["allyhub sheet diff finance/budget finance/budget-v2","allyhub sheet diff finance/budget ~/Downloads/budget.xlsx --json"]},async(e,o)=>{const s=await T(o.cwd,e.dir),t=await ne(s,o.cwd,e.was),n=await ne(s,o.cwd,e.now),a=ye(t.calc,n.calc,{tolerance:e.tolerance}),{counts:r}=a,c=a.cells.length;return{value:{was:t.file,now:n.file,...a},text:[`${t.file} → ${n.file}: ${u(c)} cell${c===1?"":"s"} differ (${u(r.value)} value, ${u(r.formula)} formula, ${u(r.both)} both, ${u(r.added)} added, ${u(r.removed)} removed)`,...Le(a,e.all)].join(`
|
|
7
|
+
`)}});const Ne=d.string().transform(e=>e.replace(/^\/+|\/+$/gu,"")).refine(e=>e!==""&&!e.split("/").some(o=>o===""||o==="."||o===".."),{message:"a folder from the project's root, such as research/leads"});export const IMPORT_DIFFERENCES=50;const ae=e=>e===null?"empty":typeof e=="string"?JSON.stringify(e):String(e);function Be(e,o){const{formulas:s,same:t,uncached:n,moving:a,differences:r}=e,c=[`${u(t)} of ${u(s)} formulas compute what the file holds`,...a>0?[`${u(a)} read the clock or a random number, not compared`]:[],...n>0?[`${u(n)} have no value in the file`]:[]],i=o?r:r.slice(0,IMPORT_DIFFERENCES);return[`Computed here against the file: ${c.join("; ")}.`,...r.length>0?[`${u(r.length)} differ${r.length===1?"s":""}:`,...i.map(l=>` ${l.sheet}!${l.cell} ${l.formula} file ${ae(l.file)} here ${ae(l.engine)}`),...r.length>i.length?[` … ${u(r.length-i.length)} more (--all)`]:[]]:[]]}async function re(e,o){for(const[s,t]of o){const n=S(e,s);await ie(N(n),{recursive:!0}),await ce(n,t,{flag:"wx"})}}export const sheetImport=E({name:"sheet import",summary:"Makes a sheet of an Excel, CSV or TSV file: its sheets, tables, formulas, names and looks as sheet.yaml and CSV files, said what could not be carried over, each formula computed here and compared with the value the file holds; never over a place that is taken",input:d.strictObject({file:d.string().describe("The file to make a sheet of: .xlsx, .xlsm, .csv or .tsv"),to:Ne.optional().describe("The sheet's folder, from the project's root (default the file's name)"),maxUnzipped:d.number().positive().default(ue.bytes/1024/1024).describe("MB the file may unzip to, a file past it refused"),tolerance:d.number().min(0).default(je).describe("How far apart a computed number and the file's may be, as a share of the larger, and count as the same; 0 lists every difference"),all:d.boolean().default(!1).describe(`Every difference, not the first ${String(IMPORT_DIFFERENCES)}`),dir:C}),positional:["file"],output:d.looseObject({}),examples:["allyhub sheet import ~/Downloads/forecast.xlsx --to finance/forecast","allyhub sheet import ~/Downloads/leads.csv --to research/leads"]},async(e,o)=>{const s=await T(o.cwd,e.dir),t=D(o.cwd,e.file),n=A(t).toLowerCase(),a=se.has(n);if(n===".xls"||n===".xlsb")throw new g("bad-file",`${k(t)} is Excel's binary format.`,{exit:$.usage,hint:"Save it as .xlsx, then import that."});if(!a&&n!==".csv"&&n!==".tsv")throw new g("bad-file",`${k(t)} is not an .xlsx, .xlsm, .csv or .tsv file.`,{exit:$.usage});const r=await H(t).catch(()=>{throw new g("not-found",`There is no file ${t}.`,{exit:$.notFound})}),c=k(t,A(t)),i=e.to??c;if(await X(S(s,i)).catch(()=>{}))throw new g("place-taken",`${i} is already there.`,{exit:$.conflict,hint:"Name another place with --to."});const l=S(s,i),m=e.to===void 0?c:k(e.to);if(a){let h;try{h=Z(new Uint8Array(r),{name:m,tolerance:e.tolerance,zip:{bytes:e.maxUnzipped*1024*1024}})}catch(p){throw new g("bad-file",`${k(t)} cannot be read: ${p.message}`,{exit:$.usage})}await re(l,h.files);const b=[...h.files.keys()];return{value:{place:i,files:b.map(p=>`${i}/${p}`),sheets:h.sheets,tables:h.tables,lost:h.lost,problems:h.problems,compared:h.compared},text:[`Made ${i}/: ${b.join(", ")}`,...h.lost.length>0?["Not carried over:",...h.lost.map(p=>` ${p}`)]:["Nothing was left out."],...Be(h.compared,e.all),...h.problems.length>0?["Problems:",...h.problems.map(p=>` ${p.file}${p.line===void 0?"":`:${String(p.line)}`}: ${p.message}`)]:[],`allyhub sheet calc ${i}, then allyhub frames ${i}, to see it.`].join(`
|
|
8
|
+
`)}}let w;try{w=xe(m,r.toString("utf8"),n===".tsv"?" ":",")}catch(h){throw new g("bad-file",h.message,{exit:$.usage})}return await re(l,new Map([[x,w.text],[w.path,w.csv]])),{value:{place:i,files:[`${i}/${x}`,`${i}/${w.path}`],rows:w.rows,lost:[]},text:`Made ${i}/${x} and ${i}/${w.path}: ${u(w.rows)} row${w.rows===1?"":"s"}`}});
|
package/dist/commands/slides.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
-
import{mkdir as y,readFile as
|
|
2
|
+
import{mkdir as y,readFile as g,stat as x,writeFile as k}from"node:fs/promises";import{basename as p,dirname as $,join as f,resolve as v}from"node:path";import{z as t}from"zod";import{ZIP_LIMITS as j}from"@allyhub-next/formats";import{EXIT as l}from"@allyhub-next/protocol";import{CAPABILITIES as h}from"@allyhub-next/slides-core";import{importDeck as I,nameOf as P,readPptx as z}from"@allyhub-next/slides-pptx";import{CommandError as n,defineCommand as u}from"../command.js";import{dir as O}from"../fields.js";import{projectRoot as T}from"../project.js";export const slidesCapabilities=u({name:"slides capabilities",summary:"What a deck's API holds of python-pptx's (its classes and enums), how it differs and what it adds, as JSON",input:t.strictObject({}),output:t.looseObject({}),examples:["allyhub slides capabilities"]},()=>Promise.resolve({value:{...h},text:JSON.stringify(h,null,2)}));const S=t.string().transform(e=>e.replace(/^\/+|\/+$/gu,"")).refine(e=>e!==""&&!e.split("/").some(a=>a===""||a==="."||a===".."),{message:"a folder from the project's root, such as launch/deck"});export const slidesImport=u({name:"slides import",summary:"Makes a deck of a PowerPoint file: its masters and layouts as slides.ts, its slides as slides.yaml, its words and notes as the script, its pictures and videos in media/; says what it could not hold; never over a place that is taken",input:t.strictObject({file:t.string().describe("The .pptx to make a deck of"),to:S.optional().describe("The deck's folder, from the project's root (default the file's name)"),maxUnzipped:t.number().positive().default(j.bytes/1024/1024).describe("MB the file may unzip to, a file past it refused"),lang:t.string().regex(/^[a-z]{2,3}(-[a-z0-9]+)*$/u).default("en").describe("The language of its words: the script is script.<lang>.yaml"),dir:O}),positional:["file"],output:t.looseObject({}),examples:["allyhub slides import ~/Downloads/q3-review.pptx --to reviews/q3","allyhub slides import 培训.pptx --to training --lang zh-cn"]},async(e,a)=>{const c=await T(a.cwd,e.dir),r=v(a.cwd,e.file),w=await g(r).catch(()=>{throw new n("not-found",`There is no file ${r}.`,{exit:l.notFound})}),s=e.to??P(p(r).replace(/\.pptx$/iu,""),new Set,"deck");if(await x(f(c,s)).catch(()=>{}))throw new n("place-taken",`${s} is already there.`,{exit:l.conflict,hint:"Name another place with --to."});let o;try{o=I(z(new Uint8Array(w),{bytes:e.maxUnzipped*1024*1024}),{lang:e.lang,source:p(r)})}catch(i){throw new n("bad-file",`${r} is not a PowerPoint file this can read: ${i.message}`,{exit:l.usage})}for(const[i,b]of o.files){const m=f(c,s,i);await y($(m),{recursive:!0}),await k(m,b,{flag:"wx"})}const d=[...o.files.keys()];return{value:{place:s,files:d.map(i=>`${s}/${i}`),lost:o.lost},text:[`Made ${s}/: ${d.join(", ")}`,...o.lost.length>0?["Not carried over:",...o.lost.map(i=>` ${i}`)]:[],`allyhub check, then allyhub frames ${s}, to see it.`].join(`
|
|
3
3
|
`)}});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
-
import{randomBytes as n}from"node:crypto";import{join as h}from"node:path";import{exportProject as l}from"@allyhub-next/export";import{OUT_DIR as c}from"@allyhub-next/formats";import{parseCombo as
|
|
2
|
+
import{randomBytes as n}from"node:crypto";import{join as h}from"node:path";import{exportProject as l}from"@allyhub-next/export";import{OUT_DIR as c}from"@allyhub-next/formats";import{parseCombo as p}from"@allyhub-next/project";import{projectPathOf as d}from"./paths.js";function u(i){const t=i?.pptx;return{...i?.steps===!0?{steps:!0}:{},...t==="picture"?{pptx:t}:{}}}export class Exports{root;changed;jobs=[];aborts=new Map;queue=Promise.resolve();constructor(t,s){this.root=t,this.changed=s}list(){return this.jobs.map(t=>({...t}))}start(t,s,r,o){const e={id:`x${n(4).toString("hex")}`,item:t,versions:s,types:r,...o?{options:o}:{},state:"queued",progress:0,files:[]};this.jobs.push(e);const a=new AbortController;return this.aborts.set(e.id,a),this.changed({...e}),this.queue=this.queue.then(()=>this.run(e,a.signal)),{...e}}cancel(t){const s=this.jobs.find(r=>r.id===t);return!s||s.state==="done"||s.state==="failed"?!1:(this.aborts.get(t)?.abort(),this.set(s,{state:"cancelled"}),!0)}idle(){return this.queue}async close(){for(const t of this.aborts.values())t.abort();await this.queue}set(t,s){Object.assign(t,s),this.changed({...t})}async run(t,s){if(t.state!=="cancelled"){this.set(t,{state:"running"});try{const r=await l({root:this.root,items:[t.item],...t.versions.length?{combos:t.versions.map(e=>p(e))}:{},...t.types.length?{types:t.types}:{},...u(t.options),out:h(this.root,c),signal:s,onProgress:e=>{s.aborted||this.set(t,{progress:Math.max(t.progress,Math.min(1,e))})}}),o=r.files.flatMap(e=>e.files).map(e=>d(this.root,e)).filter(e=>e!==void 0);s.aborted?this.set(t,{state:"cancelled",files:o}):r.failed.length>0&&o.length===0?this.set(t,{state:"failed",error:r.failed.map(e=>e.message).join(" ")}):this.set(t,{state:"done",progress:1,files:o,...r.failed.length>0?{error:[...new Map(r.failed.map(e=>[e.code,e.message])).values()].join(" ")}:{}})}catch(r){this.set(t,{state:s.aborted?"cancelled":"failed",...s.aborted?{}:{error:r instanceof Error?r.message:String(r)}})}finally{this.aborts.delete(t.id)}}}}
|
|
@@ -12,8 +12,8 @@ export interface VersionExportOptions {
|
|
|
12
12
|
partCache?: false;
|
|
13
13
|
/** A deck's pdf, png and pptx: a page, a file or a slide per step, not only each page's last. */
|
|
14
14
|
steps?: boolean;
|
|
15
|
-
/** A deck's pptx: PowerPoint's own model (the default), each slide a picture
|
|
16
|
-
pptx?: "native" | "picture"
|
|
15
|
+
/** A deck's pptx: PowerPoint's own model (the default), or each slide a picture. */
|
|
16
|
+
pptx?: "native" | "picture";
|
|
17
17
|
/** 0–1. */
|
|
18
18
|
onProgress?: (p: number) => void;
|
|
19
19
|
/** Aborting it stops the export: what runs stops, and no part of a file stays. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*! AllyHub. Copyright (c) 2026 AllyHub, Inc. All rights reserved. Use is subject to LICENSE.md. */
|
|
2
|
-
import{renderDeckPptx as xe}from"./deck-pptx.js";import{readFileSync as be}from"node:fs";import{mkdir as D,readFile as $e,stat as ne,writeFile as R}from"node:fs/promises";import{cpus as ke}from"node:os";import{basename as G,dirname as se,isAbsolute as ye,join as w,posix as oe,relative as ie,sep as Pe}from"node:path";import{parseDoc as Se,markdownOf as je}from"@allyhub-next/doc";import{createPackages as Oe}from"@allyhub-next/runtimes";import{codeOf as Ce,fontsDigest as Ee,readSheetSource as Me,workbookFiles as Ne}from"@allyhub-next/build";import{RenderError as ve,VIDEO_TYPES as Fe,renderCaptions as Te,renderCover as Ae,renderPdf as Ie,renderPng as Le,renderPptx as _e,renderVideo as De,mixSound as Re,requireEncoder as We,requireFfmpeg as Ve}from"@allyhub-next/render";import{docFontsCss as Ye,printPage as ze,renderDoc as Ge,renderWord as He}from"@allyhub-next/render/doc";import{checkWorkbook as Ue,csvOf as qe,jsonOf as Je,markdownOf as re,seededRandom as Be,sheetHtml as Ke}from"@allyhub-next/sheet";import{writeXlsx as Xe}from"@allyhub-next/sheet/xlsx";import{CACHE_DIR as Qe}from"@allyhub-next/formats";import{buildModule as Ze}from"@allyhub-next/model/build";import{graphicsPage as et,stageIdentity as tt}from"@allyhub-next/stage";import{DEFAULT_TYPES as nt,FILE_TYPES as ae,comboKey as H,exportProblem as st,pieceIs as U,pieceNamed as ce}from"@allyhub-next/video-core";import{runCheck as ot}from"@allyhub-next/check";import{batchCsv as it,batchRows as rt}from"./batch.js";import{batchName as at,checkName as ct,exportName as le,exportNames as lt}from"./names.js";import{ConsolePool as dt,mergeConsole as ft,dedupe as de,indexNeeds as pt,makeIndex as mt,CheckSession as ut,OpenedVersion as ht,ProjectError as I,versionLabel as fe}from"@allyhub-next/project";const pe=e=>Fe.includes(e);async function gt(e){const o=Oe(),c=()=>e?.("Getting docx, once, to write Word documents…"),[t,p]=await Promise.all([o.load("docx",{onFetch:c}),o.load("docx",{module:"fflate",onFetch:c})]);return{docx:t,zip:p}}export async function exportVersion(e,o,c,t={}){await D(se(c),{recursive:!0});const p={page:e.graphics(),target:e.target,look:e.look,media:e.media,out:c,...t.steps===!0?{steps:!0}:{},...t.pptx&&t.pptx!=="native"?{pptx:t.pptx}:{}};if(o==="pptx"&&e.piece.kind==="slides"&&(t.pptx??"native")==="native"){const d=await xe(e,c);if(d)return t.onProgress?.(1),d}if(o==="wav"){const d=await Re({timeline:e.timeline,sound:await e.sound(),out:c});return t.onProgress?.(1),{files:[c],duration:Math.round(e.timeline.duration*e.timeline.fps)/e.timeline.fps,...d.loudness?{loudness:d.loudness}:{},master:{...d}}}if(pe(o)&&(o!=="png"||e.piece.kind==="video")){const d=e.prepared,i=await Ee(d.root,d.files,d.fonts),a=await De({target:e.target,look:e.look,media:e.media,pages:[e.graphics()],openPage:async()=>{const m=await e.session.open(e.piece,e.target,"render");return et(m.stage,{gpu:e.session.gpu})},...o==="gif"?{}:{sound:await e.sound()},out:c,type:o,...t.encode?{encode:t.encode}:{},...t.workers===void 0?{}:{workers:t.workers},...t.onProgress?{onProgress:t.onProgress}:{},code:await Ce(d,e.piece,tt(i)),...t.partCache===!1?{partCache:!1}:{},...t.signal?{signal:t.signal}:{}});return{files:a.files??[a.out],duration:a.duration,parts:a.parts,...a.junctions?{junctions:a.junctions}:{},...a.loudness?{loudness:a.loudness}:{},...a.master?{master:{...a.master}}:{},timings:a.timings}}const u=o==="srt"||o==="vtt"?await Te({...p,type:o,...t.captions?{captions:t.captions}:{}}):o==="pdf"?await Ie(p):o==="pptx"?await _e(p):o==="png"?await Le(p):await Ae(p);return t.onProgress?.(1),{files:u.files??[u.out]}}export const exportsAtOnce=e=>Math.max(1,Math.min(e,Math.floor(ke().length/4))),DOC_TYPES=["pdf","docx","png","md"],SHEET_TYPES=["xlsx","pdf","png","csv","md","json"],MODEL_TYPES=["glb"];const q=(e,o)=>`${String(e)} ${o}${e===1?"":"s"}`,J=(e,o)=>U({id:e,path:e},o)||U({id:e,path:e},`content/${o}`);function wt(e){if(e===void 0)return;const o=new Set([...Object.keys(ae),...DOC_TYPES,...SHEET_TYPES,...MODEL_TYPES]);for(const c of e)if(!o.has(c))throw new I("bad-type",`Cannot render ${c}.`,"usage",`Types: ${[...o].join(", ")}.`);return[...e]}export async function exportProject(e){const o=wt(e.types);e.name!==void 0&&ct(e.name);const c=e.items??[],t=c.length>0,p=f=>c.some(P=>J(f,P)),u=[],d=[],i=[],a=()=>ut.open({root:e.root,...e.gpu===void 0?{}:{gpu:e.gpu},...e.consoleLimit===void 0?{}:{consoleLimit:e.consoleLimit}});let m=await a();try{const f=m.prepared,P=f.docs.filter(n=>!t||p(n.place)),b=f.sheets.filter(n=>!t||p(n.place)),L=f.items.filter(n=>n.kind==="model"&&(!t||p(n.dir))),x=c.filter(n=>!f.items.some(s=>s.kind==="model"&&U({id:s.dir,path:s.dir},n))&&!f.docs.some(s=>J(s.place,n))&&!f.sheets.some(s=>J(s.place,n)));for(const n of x)if(!f.pieces.some(s=>ce({id:s.id,path:s.place},n)))throw new I("no-item",`No item ${n}.`,"not-found",`Items: ${[...f.pieces.map(s=>s.id),...f.docs.map(s=>s.place),...f.sheets.map(s=>s.place),...f.items.filter(s=>s.kind==="model").map(s=>s.dir)].join(", ")||"none"}.`);const T=t&&x.length===0,_=o?.filter(n=>n in ae),$=T?[]:f.pieces.filter(n=>x.length===0||x.some(s=>ce({id:n.id,path:n.place},s))),S=o?.includes("csv")===!0?$.filter(n=>n.matrix!==void 0):[];if(o?.includes("csv")===!0&&x.length>0&&S.length===0)throw new I("bad-type",`${x.join(", ")} has no slots (matrix.slots), so there is no table of ads to write as csv.`,"usage","csv is a batch's table of ads, or a sheet's rows.");let g=[...f.problems];const N=new dt(m.consoleLimit),W=new Set([...f.docs.map(n=>n.file),...f.sheets.flatMap(n=>n.files)]),ue=n=>n.where?.file!==void 0&&W.has(n.where.file),B=n=>n.filter(s=>s.level==="error"&&!ue(s)).length;if(!T&&(_?.length!==0||S.length>0)&&(f.pieces.length>0||B(f.problems)>0)){e.log?.("Checking…");const n=()=>bt(m,e.root,x,e.combos);let s=await n();const A=e.index===!1?[]:pt(s.results);if(A.length>0){const r=await mt(f.root,A,$t(e.log),e.signal);i.push(...r.failed.map(l=>({file:l.need.file,error:l.error}))),r.done.length>0&&(await m.close(),m=await a(),s=await n())}g=s.problems,N.addReport(s.console);const F=B(s.problems);if(F>0)throw new I("check-failed",`The check found ${q(F,"must-fix problem")}, so nothing is rendered.`,"failed","allyhub check lists them; fix them, then render.");for(const r of S){const l=performance.now(),j=at(r.id),C=rt(r,s.plans,m.prepared.media,xt(e.root,e.out),e.name);await D(se(w(e.out,j)),{recursive:!0}),await R(w(e.out,j),it(C));const E=s.targets.filter(k=>k.piece===r.id).length;C.length<E&&e.log?.(`${j}: ${q(E-C.length,"ad")} not listed, which did not load (allyhub check says why).`),u.push(await M(e.out,j,r.id,"csv",l))}const O=[],V=new Set;for(const r of s.targets){const l=m.prepared.pieces.find(h=>h.id===r.piece);if(!l)continue;if(!t&&l.options.deliverable===!1){V.add(r.piece);continue}const j=l.kind,C=s.results.find(h=>h.piece===r.piece&&H(h.combo)===r.key&&h.format===r.format),E=s.plans.find(h=>h.piece===r.piece&&H(h.combo)===r.key&&h.format===r.format),k=C?.timeline?(C.timeline.audio.speech?.length??0)>0:E?.parts.some(h=>h.speech!==void 0)??!1,v={piece:r.piece,output:r.output,combo:r.combo,format:r.format,...r.id===void 0?{}:{id:r.id}};for(const h of _??nt[j]){const y=st({kind:j,speech:k},h);if(!(y?.code==="bad_type"&&!t)){if(y&&y.code!=="no_speech")throw new I("bad-type",`${fe(v)}: ${y.message}`,"usage",y.hint);O.push({target:v,type:h,...y?{refused:{name:le(v,h,e),piece:v.piece,type:h,code:"no-speech",message:`${fe(v)}: ${y.message}`,...y.hint?{hint:y.hint}:{}}}:{}})}}}if(V.size>0&&e.log?.(`Not rendered, shown only inside another video (deliverable: false): ${[...V].join(", ")}. Name one to render it.`),O.some(r=>pe(r.type)||r.type==="wav")){await Ve();for(const r of new Set(O.map(l=>l.type)))await We(r,e.encode?.codec)}const Q=lt(O,e.name,e);O.forEach((r,l)=>{r.refused&&(r.refused.name=Q[l]??r.refused.name)});const Z=[],Y=new Array(O.length).fill(0),z=(r,l)=>{Y[r]=Math.max(Y[r]??0,l),e.onProgress?.(Y.reduce((j,C)=>j+C,0)/O.length)};let ee=0,he=0;const ge=async()=>{for(let r=ee++;r<O.length;r=ee++){e.signal?.throwIfAborted();const l=O[r];if(!l)continue;const j=Q[r]??le(l.target,l.type,e);if(l.refused){d.push(l.refused),z(r,1);continue}const C=performance.now(),E=await ht.open({root:e.root,session:m,item:l.target.piece,combos:[l.target.combo],purpose:"render"});try{const k=await exportVersion(E,l.type,w(e.out,j),{...e,onProgress:y=>{z(r,y)}}),v=(await Promise.all(k.files.map(y=>ne(y)))).reduce((y,we)=>y+we.size,0),h=Math.round((performance.now()-C)/10)/100;u.push({...k,name:me(ie(e.out,k.files[0]??"")),path:k.files[0]??w(e.out,j),piece:l.target.piece,type:l.type,combo:l.target.combo,key:H(l.target.combo),format:l.target.format,bytes:v,seconds:h}),e.log?.(`[${String(++he)}/${String(O.length)}] ${j} (${h.toFixed(1)} s)`)}catch(k){if(e.signal?.aborted||!(k instanceof ve))throw k;d.push({name:j,piece:l.target.piece,type:l.type,code:k.code,message:k.message,...k.hint?{hint:k.hint}:{}})}finally{Z.push(...await E.problems()),N.add(l.target,await E.console()),await E.close(),z(r,1)}}};O.length>0&&e.log?.(`Rendering ${q(O.length,"file")}…`);const te=(await Promise.allSettled(Array.from({length:exportsAtOnce(O.length)},ge))).find(r=>r.status==="rejected");if(te)throw te.reason;g=de([...g,...Z])}const K=n=>f.problems.find(s=>s.level==="error"&&s.where?.file!==void 0&&n.includes(s.where.file));for(const n of[...P,...b]){const s=K("files"in n?n.files:[n.file]);s&&d.push({name:n.place,piece:n.place,type:"files"in n?"xlsx":"pdf",code:"check-failed",message:`${s.where?.file??n.place}: ${s.message}`,hint:"Fix it, then render again."})}e.signal?.throwIfAborted();const X=n=>n.filter(s=>K("files"in s?s.files:[s.file])===void 0);if(u.push(...await kt(e.root,X(P),o,e.out,e.log),...await yt(e.root,X(b),o,e.out,e.log)),o===void 0||o.includes("glb"))for(const n of L){e.log?.(`Building ${n.entry}…`);const s=performance.now(),A=`${n.dir}/${G(n.dir)}.glb`;try{await Ze(w(e.root,n.entry),{root:e.root,out:w(e.out,A),cache:w(e.root,Qe,"model"),log:()=>{}}),u.push(await M(e.out,A,n.dir,"glb",s))}catch(F){d.push({name:n.dir,piece:n.dir,type:"glb",code:"model-failed",message:`${n.entry}: ${F instanceof Error?F.message:String(F)}`,hint:"Fix it, then render again."})}}return{out:e.out,files:u,failed:d,problems:g,console:N.report(),unindexed:i}}finally{await m.close()}}const me=e=>e.split(Pe).join("/");function xt(e,o){const c=ie(e,o);return c===""?".":c.startsWith("..")||ye(c)?o:me(c)}async function bt(e,o,c,t){const p=[];for(const a of c.length>0?c:[void 0])p.push(await ot({dir:o,session:e,facts:!1,...a===void 0?{}:{piece:a},...t?{combos:[...t]}:{}}));const u=new Set,d=p.flatMap(a=>a.targets).filter(a=>{const m=`${a.piece}\0${a.key}\0${a.format}`;return u.has(m)?!1:(u.add(m),!0)}),i=de(p.flatMap(a=>a.problems));return{targets:d,results:p.flatMap(a=>a.results),plans:p.flatMap(a=>a.plans),problems:i,errors:i.filter(a=>a.level==="error").length,console:ft(e.consoleLimit,...p.map(a=>a.console))}}function $t(e){let o="";return c=>{const t=c.status==="failed"?`Could not index ${c.file}: ${c.message}`:c.message;c.status==="running"&&c.share!==void 0||t!==o&&(o=t,e?.(t))}}async function M(e,o,c,t,p){const u=w(e,o);return{files:[u],name:o,path:u,piece:c,type:t,bytes:(await ne(u)).size,seconds:Math.round((performance.now()-p)/10)/100}}async function kt(e,o,c,t,p){const u=(c??["pdf"]).filter(i=>DOC_TYPES.includes(i)),d=[];for(const i of o){if(u.length===0)break;p?.(`Rendering ${i.file}…`);const a=performance.now(),m=G(i.place);if(u.includes("md")){const b=await $e(w(e,i.file),"utf8");await D(w(t,i.place),{recursive:!0}),await R(w(t,i.place,`${m}.md`),je(Se(b).blocks)),d.push(await M(t,`${i.place}/${m}.md`,i.place,"md",a))}if(u.includes("docx")){const b=`${i.place}/${m}.docx`;await He({root:e,doc:{file:i.file,dir:i.dir,path:i.place,title:i.title},out:w(t,b),...await gt(p)}),d.push(await M(t,b,i.place,"docx",a))}const f=u.filter(b=>b==="pdf"||b==="png");if(f.length===0)continue;const P=await Ge({root:e,doc:{file:i.file,dir:i.dir,path:i.place,title:i.title},out:w(t,i.place),name:m,types:f});for(const b of P)d.push(await M(t,`${i.place}/${b}`,i.place,b.endsWith(".png")?"png":"pdf",a))}return d}export const PNG_ROWS=700,PNG_COLUMNS=200;async function yt(e,o,c,t,p){const u=(c??["xlsx"]).filter(i=>SHEET_TYPES.includes(i)),d=[];for(const i of o){if(u.length===0)break;p?.(`Writing ${i.file}…`);const a=performance.now(),m=await Me(e,i.dir);if(m.failed){p?.(`${i.file}: its sheet.ts does not run. allyhub check says why.`);continue}const{workbook:f,calc:P}=Ue(Ne(e,m),{random:Be([m.text,...m.csv.values(),m.generated?JSON.stringify(m.generated):""].join(`
|
|
3
|
-
`))});if(!f||!P)continue;const
|
|
2
|
+
import{renderDeckPptx as be}from"./deck-pptx.js";import{readFileSync as xe}from"node:fs";import{mkdir as D,readFile as $e,stat as ne,writeFile as R}from"node:fs/promises";import{cpus as ke}from"node:os";import{basename as G,dirname as se,isAbsolute as ye,join as w,posix as oe,relative as ie,sep as Pe}from"node:path";import{parseDoc as Se,markdownOf as je}from"@allyhub-next/doc";import{createPackages as Oe}from"@allyhub-next/runtimes";import{codeOf as Ce,fontsDigest as Ee,readSheetSource as Me,workbookFiles as Ne}from"@allyhub-next/build";import{RenderError as Fe,VIDEO_TYPES as ve,renderCaptions as Te,renderCover as Ae,renderPdf as Ie,renderPng as Le,renderPptx as _e,renderVideo as De,mixSound as Re,requireEncoder as We,requireFfmpeg as Ve}from"@allyhub-next/render";import{docFontsCss as Ye,printPage as ze,renderDoc as Ge,renderWord as He}from"@allyhub-next/render/doc";import{checkWorkbook as Ue,csvOf as qe,jsonOf as Je,markdownOf as re,seededRandom as Be,sheetHtml as Ke}from"@allyhub-next/sheet";import{writeXlsx as Xe}from"@allyhub-next/sheet/xlsx";import{CACHE_DIR as Qe}from"@allyhub-next/formats";import{buildModule as Ze}from"@allyhub-next/model/build";import{graphicsPage as et,stageIdentity as tt}from"@allyhub-next/stage";import{DEFAULT_TYPES as nt,FILE_TYPES as ae,comboKey as H,exportProblem as st,pieceIs as U,pieceNamed as ce}from"@allyhub-next/video-core";import{runCheck as ot}from"@allyhub-next/check";import{batchCsv as it,batchRows as rt}from"./batch.js";import{batchName as at,checkName as ct,exportName as le,exportNames as lt}from"./names.js";import{ConsolePool as dt,mergeConsole as ft,dedupe as de,indexNeeds as pt,makeIndex as mt,CheckSession as ut,OpenedVersion as ht,ProjectError as I,versionLabel as fe}from"@allyhub-next/project";const pe=e=>ve.includes(e);async function gt(e){const o=Oe(),c=()=>e?.("Getting docx, once, to write Word documents…"),[n,p]=await Promise.all([o.load("docx",{onFetch:c}),o.load("docx",{module:"fflate",onFetch:c})]);return{docx:n,zip:p}}export async function exportVersion(e,o,c,n={}){await D(se(c),{recursive:!0});const p={page:e.graphics(),target:e.target,look:e.look,media:e.media,out:c,...n.steps===!0?{steps:!0}:{}};if(o==="pptx"&&e.piece.kind==="slides"&&(n.pptx??"native")==="native"){const d=await be(e,c);if(d)return n.onProgress?.(1),d}if(o==="wav"){const d=await Re({timeline:e.timeline,sound:await e.sound(),out:c});return n.onProgress?.(1),{files:[c],duration:Math.round(e.timeline.duration*e.timeline.fps)/e.timeline.fps,...d.loudness?{loudness:d.loudness}:{},master:{...d}}}if(pe(o)&&(o!=="png"||e.piece.kind==="video")){const d=e.prepared,i=await Ee(d.root,d.files,d.fonts),a=await De({target:e.target,look:e.look,media:e.media,pages:[e.graphics()],openPage:async()=>{const m=await e.session.open(e.piece,e.target,"render");return et(m.stage,{gpu:e.session.gpu})},...o==="gif"?{}:{sound:await e.sound()},out:c,type:o,...n.encode?{encode:n.encode}:{},...n.workers===void 0?{}:{workers:n.workers},...n.onProgress?{onProgress:n.onProgress}:{},code:await Ce(d,e.piece,tt(i)),...n.partCache===!1?{partCache:!1}:{},...n.signal?{signal:n.signal}:{}});return{files:a.files??[a.out],duration:a.duration,parts:a.parts,...a.junctions?{junctions:a.junctions}:{},...a.loudness?{loudness:a.loudness}:{},...a.master?{master:{...a.master}}:{},timings:a.timings}}const u=o==="srt"||o==="vtt"?await Te({...p,type:o,...n.captions?{captions:n.captions}:{}}):o==="pdf"?await Ie(p):o==="pptx"?await _e(p):o==="png"?await Le(p):await Ae(p);return n.onProgress?.(1),{files:u.files??[u.out]}}export const exportsAtOnce=e=>Math.max(1,Math.min(e,Math.floor(ke().length/4))),DOC_TYPES=["pdf","docx","png","md"],SHEET_TYPES=["xlsx","pdf","png","csv","md","json"],MODEL_TYPES=["glb"];const q=(e,o)=>`${String(e)} ${o}${e===1?"":"s"}`,J=(e,o)=>U({id:e,path:e},o)||U({id:e,path:e},`content/${o}`);function wt(e){if(e===void 0)return;const o=new Set([...Object.keys(ae),...DOC_TYPES,...SHEET_TYPES,...MODEL_TYPES]);for(const c of e)if(!o.has(c))throw new I("bad-type",`Cannot render ${c}.`,"usage",`Types: ${[...o].join(", ")}.`);return[...e]}export async function exportProject(e){const o=wt(e.types);e.name!==void 0&&ct(e.name);const c=e.items??[],n=c.length>0,p=f=>c.some(P=>J(f,P)),u=[],d=[],i=[],a=()=>ut.open({root:e.root,...e.gpu===void 0?{}:{gpu:e.gpu},...e.consoleLimit===void 0?{}:{consoleLimit:e.consoleLimit}});let m=await a();try{const f=m.prepared,P=f.docs.filter(t=>!n||p(t.place)),x=f.sheets.filter(t=>!n||p(t.place)),L=f.items.filter(t=>t.kind==="model"&&(!n||p(t.dir))),b=c.filter(t=>!f.items.some(s=>s.kind==="model"&&U({id:s.dir,path:s.dir},t))&&!f.docs.some(s=>J(s.place,t))&&!f.sheets.some(s=>J(s.place,t)));for(const t of b)if(!f.pieces.some(s=>ce({id:s.id,path:s.place},t)))throw new I("no-item",`No item ${t}.`,"not-found",`Items: ${[...f.pieces.map(s=>s.id),...f.docs.map(s=>s.place),...f.sheets.map(s=>s.place),...f.items.filter(s=>s.kind==="model").map(s=>s.dir)].join(", ")||"none"}.`);const T=n&&b.length===0,_=o?.filter(t=>t in ae),$=T?[]:f.pieces.filter(t=>b.length===0||b.some(s=>ce({id:t.id,path:t.place},s))),S=o?.includes("csv")===!0?$.filter(t=>t.matrix!==void 0):[];if(o?.includes("csv")===!0&&b.length>0&&S.length===0)throw new I("bad-type",`${b.join(", ")} has no slots (matrix.slots), so there is no table of ads to write as csv.`,"usage","csv is a batch's table of ads, or a sheet's rows.");let g=[...f.problems];const N=new dt(m.consoleLimit),W=new Set([...f.docs.map(t=>t.file),...f.sheets.flatMap(t=>t.files)]),ue=t=>t.where?.file!==void 0&&W.has(t.where.file),B=t=>t.filter(s=>s.level==="error"&&!ue(s)).length;if(!T&&(_?.length!==0||S.length>0)&&(f.pieces.length>0||B(f.problems)>0)){e.log?.("Checking…");const t=()=>xt(m,e.root,b,e.combos);let s=await t();const A=e.index===!1?[]:pt(s.results);if(A.length>0){const r=await mt(f.root,A,$t(e.log),e.signal);i.push(...r.failed.map(l=>({file:l.need.file,error:l.error}))),r.done.length>0&&(await m.close(),m=await a(),s=await t())}g=s.problems,N.addReport(s.console);const v=B(s.problems);if(v>0)throw new I("check-failed",`The check found ${q(v,"must-fix problem")}, so nothing is rendered.`,"failed","allyhub check lists them; fix them, then render.");for(const r of S){const l=performance.now(),j=at(r.id),C=rt(r,s.plans,m.prepared.media,bt(e.root,e.out),e.name);await D(se(w(e.out,j)),{recursive:!0}),await R(w(e.out,j),it(C));const E=s.targets.filter(k=>k.piece===r.id).length;C.length<E&&e.log?.(`${j}: ${q(E-C.length,"ad")} not listed, which did not load (allyhub check says why).`),u.push(await M(e.out,j,r.id,"csv",l))}const O=[],V=new Set;for(const r of s.targets){const l=m.prepared.pieces.find(h=>h.id===r.piece);if(!l)continue;if(!n&&l.options.deliverable===!1){V.add(r.piece);continue}const j=l.kind,C=s.results.find(h=>h.piece===r.piece&&H(h.combo)===r.key&&h.format===r.format),E=s.plans.find(h=>h.piece===r.piece&&H(h.combo)===r.key&&h.format===r.format),k=C?.timeline?(C.timeline.audio.speech?.length??0)>0:E?.parts.some(h=>h.speech!==void 0)??!1,F={piece:r.piece,output:r.output,combo:r.combo,format:r.format,...r.id===void 0?{}:{id:r.id}};for(const h of _??nt[j]){const y=st({kind:j,speech:k},h);if(!(y?.code==="bad_type"&&!n)){if(y&&y.code!=="no_speech")throw new I("bad-type",`${fe(F)}: ${y.message}`,"usage",y.hint);O.push({target:F,type:h,...y?{refused:{name:le(F,h,e),piece:F.piece,type:h,code:"no-speech",message:`${fe(F)}: ${y.message}`,...y.hint?{hint:y.hint}:{}}}:{}})}}}if(V.size>0&&e.log?.(`Not rendered, shown only inside another video (deliverable: false): ${[...V].join(", ")}. Name one to render it.`),O.some(r=>pe(r.type)||r.type==="wav")){await Ve();for(const r of new Set(O.map(l=>l.type)))await We(r,e.encode?.codec)}const Q=lt(O,e.name,e);O.forEach((r,l)=>{r.refused&&(r.refused.name=Q[l]??r.refused.name)});const Z=[],Y=new Array(O.length).fill(0),z=(r,l)=>{Y[r]=Math.max(Y[r]??0,l),e.onProgress?.(Y.reduce((j,C)=>j+C,0)/O.length)};let ee=0,he=0;const ge=async()=>{for(let r=ee++;r<O.length;r=ee++){e.signal?.throwIfAborted();const l=O[r];if(!l)continue;const j=Q[r]??le(l.target,l.type,e);if(l.refused){d.push(l.refused),z(r,1);continue}const C=performance.now(),E=await ht.open({root:e.root,session:m,item:l.target.piece,combos:[l.target.combo],purpose:"render"});try{const k=await exportVersion(E,l.type,w(e.out,j),{...e,onProgress:y=>{z(r,y)}}),F=(await Promise.all(k.files.map(y=>ne(y)))).reduce((y,we)=>y+we.size,0),h=Math.round((performance.now()-C)/10)/100;u.push({...k,name:me(ie(e.out,k.files[0]??"")),path:k.files[0]??w(e.out,j),piece:l.target.piece,type:l.type,combo:l.target.combo,key:H(l.target.combo),format:l.target.format,bytes:F,seconds:h}),e.log?.(`[${String(++he)}/${String(O.length)}] ${j} (${h.toFixed(1)} s)`)}catch(k){if(e.signal?.aborted||!(k instanceof Fe))throw k;d.push({name:j,piece:l.target.piece,type:l.type,code:k.code,message:k.message,...k.hint?{hint:k.hint}:{}})}finally{Z.push(...await E.problems()),N.add(l.target,await E.console()),await E.close(),z(r,1)}}};O.length>0&&e.log?.(`Rendering ${q(O.length,"file")}…`);const te=(await Promise.allSettled(Array.from({length:exportsAtOnce(O.length)},ge))).find(r=>r.status==="rejected");if(te)throw te.reason;g=de([...g,...Z])}const K=t=>f.problems.find(s=>s.level==="error"&&s.where?.file!==void 0&&t.includes(s.where.file));for(const t of[...P,...x]){const s=K("files"in t?t.files:[t.file]);s&&d.push({name:t.place,piece:t.place,type:"files"in t?"xlsx":"pdf",code:"check-failed",message:`${s.where?.file??t.place}: ${s.message}`,hint:"Fix it, then render again."})}e.signal?.throwIfAborted();const X=t=>t.filter(s=>K("files"in s?s.files:[s.file])===void 0);if(u.push(...await kt(e.root,X(P),o,e.out,e.log),...await yt(e.root,X(x),o,e.out,e.log)),o===void 0||o.includes("glb"))for(const t of L){e.log?.(`Building ${t.entry}…`);const s=performance.now(),A=`${t.dir}/${G(t.dir)}.glb`;try{await Ze(w(e.root,t.entry),{root:e.root,out:w(e.out,A),cache:w(e.root,Qe,"model"),log:()=>{}}),u.push(await M(e.out,A,t.dir,"glb",s))}catch(v){d.push({name:t.dir,piece:t.dir,type:"glb",code:"model-failed",message:`${t.entry}: ${v instanceof Error?v.message:String(v)}`,hint:"Fix it, then render again."})}}return{out:e.out,files:u,failed:d,problems:g,console:N.report(),unindexed:i}}finally{await m.close()}}const me=e=>e.split(Pe).join("/");function bt(e,o){const c=ie(e,o);return c===""?".":c.startsWith("..")||ye(c)?o:me(c)}async function xt(e,o,c,n){const p=[];for(const a of c.length>0?c:[void 0])p.push(await ot({dir:o,session:e,facts:!1,...a===void 0?{}:{piece:a},...n?{combos:[...n]}:{}}));const u=new Set,d=p.flatMap(a=>a.targets).filter(a=>{const m=`${a.piece}\0${a.key}\0${a.format}`;return u.has(m)?!1:(u.add(m),!0)}),i=de(p.flatMap(a=>a.problems));return{targets:d,results:p.flatMap(a=>a.results),plans:p.flatMap(a=>a.plans),problems:i,errors:i.filter(a=>a.level==="error").length,console:ft(e.consoleLimit,...p.map(a=>a.console))}}function $t(e){let o="";return c=>{const n=c.status==="failed"?`Could not index ${c.file}: ${c.message}`:c.message;c.status==="running"&&c.share!==void 0||n!==o&&(o=n,e?.(n))}}async function M(e,o,c,n,p){const u=w(e,o);return{files:[u],name:o,path:u,piece:c,type:n,bytes:(await ne(u)).size,seconds:Math.round((performance.now()-p)/10)/100}}async function kt(e,o,c,n,p){const u=(c??["pdf"]).filter(i=>DOC_TYPES.includes(i)),d=[];for(const i of o){if(u.length===0)break;p?.(`Rendering ${i.file}…`);const a=performance.now(),m=G(i.place);if(u.includes("md")){const x=await $e(w(e,i.file),"utf8");await D(w(n,i.place),{recursive:!0}),await R(w(n,i.place,`${m}.md`),je(Se(x).blocks)),d.push(await M(n,`${i.place}/${m}.md`,i.place,"md",a))}if(u.includes("docx")){const x=`${i.place}/${m}.docx`;await He({root:e,doc:{file:i.file,dir:i.dir,path:i.place,title:i.title},out:w(n,x),...await gt(p)}),d.push(await M(n,x,i.place,"docx",a))}const f=u.filter(x=>x==="pdf"||x==="png");if(f.length===0)continue;const P=await Ge({root:e,doc:{file:i.file,dir:i.dir,path:i.place,title:i.title},out:w(n,i.place),name:m,types:f});for(const x of P)d.push(await M(n,`${i.place}/${x}`,i.place,x.endsWith(".png")?"png":"pdf",a))}return d}export const PNG_ROWS=700,PNG_COLUMNS=200;async function yt(e,o,c,n,p){const u=(c??["xlsx"]).filter(i=>SHEET_TYPES.includes(i)),d=[];for(const i of o){if(u.length===0)break;p?.(`Writing ${i.file}…`);const a=performance.now(),m=await Me(e,i.dir);if(m.failed){p?.(`${i.file}: its sheet.ts does not run. allyhub check says why.`);continue}const{workbook:f,calc:P}=Ue(Ne(e,m),{random:Be([m.text,...m.csv.values(),m.generated?JSON.stringify(m.generated):""].join(`
|
|
3
|
+
`))});if(!f||!P)continue;const x=$=>{const S=oe.normalize(oe.join(i.dir,$));try{return S.startsWith("..")?void 0:new Uint8Array(xe(w(e,S)))}catch{return}};await D(w(n,i.place),{recursive:!0});const L=G(i.place),b=`${i.place}/${L}`,T=f.sheets.length>1,_=async $=>{const S=Ke(P,{css:await Ye(),font:"Commissioner Variable",file:x,...$==="png"?{rows:PNG_ROWS,columns:PNG_COLUMNS,headings:!1}:{}});for(const g of S.cut)p?.(`${b}.png: ${g}`);await ze({html:S.html,out:w(n,i.place),name:L,types:[$]}),d.push(await M(n,`${b}.${$}`,i.place,$,a))};for(const $ of u){if($==="pdf"||$==="png"){await _($);continue}if($==="xlsx"){const{bytes:g,left:N}=Xe(P,{file:x});await R(w(n,`${b}.xlsx`),g);for(const W of N)p?.(`${b}.xlsx does not hold ${W}.`);d.push(await M(n,`${b}.xlsx`,i.place,"xlsx",a));continue}const S=[];if($==="csv")for(const g of f.sheets)S.push([T?`${b}-${g.name.replace(/\W+/gu,"-")}.csv`:`${b}.csv`,qe(P,g)]);else $==="md"?S.push([`${b}.md`,f.sheets.map(g=>T?`## ${g.name}
|
|
4
4
|
|
|
5
5
|
${re(P,g)}`:re(P,g)).join(`
|
|
6
|
-
`)]):S.push([`${
|
|
7
|
-
`]);for(const[g,N]of S)await R(w(
|
|
6
|
+
`)]):S.push([`${b}.json`,`${JSON.stringify(Je(P),null,2)}
|
|
7
|
+
`]);for(const[g,N]of S)await R(w(n,g),N),d.push(await M(n,g,i.place,$,a))}}return d}
|
|
@@ -3,7 +3,7 @@ import { type FileType } from "@allyhub-next/video-core";
|
|
|
3
3
|
/** How a deck's file was made, which its name says: another way never overwrites it. */
|
|
4
4
|
export interface ExportManner {
|
|
5
5
|
steps?: boolean;
|
|
6
|
-
pptx?: "native" | "picture"
|
|
6
|
+
pptx?: "native" | "picture";
|
|
7
7
|
}
|
|
8
8
|
/**
|
|
9
9
|
* Where a version's file goes in the output folder, by the name of the
|