deckjsx 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +165 -2
- package/dist/index.mjs +568 -22
- package/dist/jsx-Crlbye9V.mjs +290 -0
- package/dist/jsx-dev-runtime.d.mts +6 -2
- package/dist/jsx-dev-runtime.mjs +17 -2
- package/dist/{jsx-runtime-BWV9tOov.d.mts → jsx-runtime-ru5t8S3z.d.mts} +80 -24
- package/dist/jsx-runtime.d.mts +1 -1
- package/dist/jsx-runtime.mjs +3 -3
- package/package.json +1 -1
- package/dist/jsx-lqMAdW2X.mjs +0 -175
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as isContentNode, c as toLegacyJsxNode, d as Slide, f as Text, i as isAuthorNode, l as Image, m as isAuthorTreeNode, n as createElement, o as isSlideNode, p as View, s as isLegacyAuthorNode, t as Fragment, u as Shape } from "./jsx-Crlbye9V.mjs";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
4
4
|
import { dirname } from "node:path";
|
|
@@ -3863,24 +3863,15 @@ function compileGroupNode(node, parentFrame, idGenerator, placement, clipRect, c
|
|
|
3863
3863
|
}, childClipRect, context)
|
|
3864
3864
|
};
|
|
3865
3865
|
}
|
|
3866
|
-
function
|
|
3867
|
-
const { props } = node;
|
|
3868
|
-
const textLengthContext = getTextLengthContext(props, context);
|
|
3869
|
-
const resolved = frameFromProps(props, parentFrame, placement, textLengthContext);
|
|
3870
|
-
const strokes = resolveNodeStrokes(props, textLengthContext);
|
|
3871
|
-
const shadow = parseShadowShorthand(props.textShadow ?? props.boxShadow);
|
|
3866
|
+
function textStyleFromProps(props, textLengthContext) {
|
|
3872
3867
|
const list = resolveListStyle(props, textLengthContext);
|
|
3873
3868
|
const lineHeight = resolveLineHeight(props.lineHeight, textLengthContext);
|
|
3874
3869
|
const underlineStyle = resolveUnderlineStyle(props.textDecorationStyle);
|
|
3875
3870
|
const underlineColor = normalizeColor(props.textDecorationColor);
|
|
3876
3871
|
const textDirection = resolveTextDirection(props.writingMode);
|
|
3877
3872
|
const tabStops = resolveTabStops(props.tabStops, textLengthContext);
|
|
3878
|
-
const hyperlink = props.href ? {
|
|
3879
|
-
url: props.href,
|
|
3880
|
-
...props.tooltip ? { tooltip: props.tooltip } : {}
|
|
3881
|
-
} : void 0;
|
|
3882
3873
|
const fontSizePt = props.fontSize === void 0 ? void 0 : parsePointValue(props.fontSize, 0, textLengthContext);
|
|
3883
|
-
|
|
3874
|
+
return {
|
|
3884
3875
|
fontFamily: props.fontFamily,
|
|
3885
3876
|
fontSizePt,
|
|
3886
3877
|
fontWeight: props.fontWeight,
|
|
@@ -3908,6 +3899,48 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
|
|
|
3908
3899
|
...props.superscript ? { superscript: true } : {},
|
|
3909
3900
|
...props.subscript ? { subscript: true } : {}
|
|
3910
3901
|
};
|
|
3902
|
+
}
|
|
3903
|
+
function isEmptyRunStyle(style) {
|
|
3904
|
+
return Object.values(style).every((value) => value === void 0);
|
|
3905
|
+
}
|
|
3906
|
+
function flattenUnknownChildren(children) {
|
|
3907
|
+
return children.flatMap((child) => Array.isArray(child) ? flattenUnknownChildren(child) : [child]);
|
|
3908
|
+
}
|
|
3909
|
+
function extractRichTextRuns(children, textTransform, textLengthContext) {
|
|
3910
|
+
const runs = [];
|
|
3911
|
+
for (const child of flattenUnknownChildren(children)) {
|
|
3912
|
+
if (child === null || child === void 0 || child === false || child === true) continue;
|
|
3913
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
3914
|
+
runs.push({ text: extractText([child], textTransform) });
|
|
3915
|
+
continue;
|
|
3916
|
+
}
|
|
3917
|
+
if (typeof child === "object" && child !== null && "kind" in child) {
|
|
3918
|
+
const authorNode = child;
|
|
3919
|
+
if (authorNode.kind !== "text") throw new Error("Text nodes can only contain primitive text or inline text runs.");
|
|
3920
|
+
const props = normalizeTextProps(authorNode.props);
|
|
3921
|
+
const childLengthContext = getTextLengthContext(props, textLengthContext);
|
|
3922
|
+
const style = textStyleFromProps(props, childLengthContext);
|
|
3923
|
+
const text = extractRichTextRuns(authorNode.children, props.textTransform ?? textTransform, childLengthContext).map((run) => run.text).join("");
|
|
3924
|
+
runs.push({
|
|
3925
|
+
text,
|
|
3926
|
+
...!isEmptyRunStyle(style) ? { style } : {}
|
|
3927
|
+
});
|
|
3928
|
+
}
|
|
3929
|
+
}
|
|
3930
|
+
return runs;
|
|
3931
|
+
}
|
|
3932
|
+
function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, context) {
|
|
3933
|
+
const { props } = node;
|
|
3934
|
+
const textLengthContext = getTextLengthContext(props, context);
|
|
3935
|
+
const resolved = frameFromProps(props, parentFrame, placement, textLengthContext);
|
|
3936
|
+
const strokes = resolveNodeStrokes(props, textLengthContext);
|
|
3937
|
+
const shadow = parseShadowShorthand(props.textShadow ?? props.boxShadow);
|
|
3938
|
+
const hyperlink = props.href ? {
|
|
3939
|
+
url: props.href,
|
|
3940
|
+
...props.tooltip ? { tooltip: props.tooltip } : {}
|
|
3941
|
+
} : void 0;
|
|
3942
|
+
const style = textStyleFromProps(props, textLengthContext);
|
|
3943
|
+
const runs = extractRichTextRuns(node.source.children, props.textTransform, textLengthContext);
|
|
3911
3944
|
const visibleFrame = intersectClipRect({
|
|
3912
3945
|
xEmu: resolved.xEmu,
|
|
3913
3946
|
yEmu: resolved.yEmu,
|
|
@@ -3930,7 +3963,10 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
|
|
|
3930
3963
|
...props.visibility !== void 0 ? { visibility: props.visibility } : {},
|
|
3931
3964
|
flipH: resolved.flipH,
|
|
3932
3965
|
flipV: resolved.flipV,
|
|
3933
|
-
content: {
|
|
3966
|
+
content: {
|
|
3967
|
+
text: runs.map((run) => run.text).join(""),
|
|
3968
|
+
...runs.length > 1 || runs.some((run) => run.style) ? { runs } : {}
|
|
3969
|
+
},
|
|
3934
3970
|
style,
|
|
3935
3971
|
fill: backgroundFill.fill,
|
|
3936
3972
|
...backgroundFill.backgroundLayers ? { backgroundLayers: backgroundFill.backgroundLayers } : {},
|
|
@@ -4102,13 +4138,442 @@ function renderPresentation(options, slides) {
|
|
|
4102
4138
|
version: "0.1",
|
|
4103
4139
|
meta: options.meta,
|
|
4104
4140
|
size: slideSize,
|
|
4105
|
-
slides: slides.map((factory, slideIndex) =>
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4141
|
+
slides: slides.map((factory, slideIndex) => {
|
|
4142
|
+
return compileSlide(toLegacyJsxNode(factory({
|
|
4143
|
+
slideIndex,
|
|
4144
|
+
totalSlides: slides.length,
|
|
4145
|
+
context: {
|
|
4146
|
+
slideIndex,
|
|
4147
|
+
totalSlides: slides.length
|
|
4148
|
+
}
|
|
4149
|
+
})), {
|
|
4150
|
+
slideIndex,
|
|
4151
|
+
totalSlides: slides.length
|
|
4152
|
+
}, slideFrame, idGenerator, lengthContext);
|
|
4153
|
+
})
|
|
4154
|
+
};
|
|
4155
|
+
}
|
|
4156
|
+
//#endregion
|
|
4157
|
+
//#region src/diagnostics/format.ts
|
|
4158
|
+
function formatSpan(path) {
|
|
4159
|
+
return ` at ${path}`;
|
|
4160
|
+
}
|
|
4161
|
+
function formatDiagnostic(diagnostic) {
|
|
4162
|
+
const lines = [`${diagnostic.severity}[${diagnostic.code}]: ${diagnostic.title}`];
|
|
4163
|
+
if (diagnostic.message) lines.push(` ${diagnostic.message}`);
|
|
4164
|
+
for (const label of diagnostic.labels) {
|
|
4165
|
+
lines.push(formatSpan(label.path));
|
|
4166
|
+
lines.push(` = ${label.message}`);
|
|
4167
|
+
}
|
|
4168
|
+
for (const note of diagnostic.notes ?? []) lines.push(`note: ${note}`);
|
|
4169
|
+
for (const help of diagnostic.help ?? []) lines.push(`help: ${help}`);
|
|
4170
|
+
return lines.join("\n");
|
|
4171
|
+
}
|
|
4172
|
+
function formatDiagnostics(diagnostics) {
|
|
4173
|
+
return diagnostics.items.map((item) => formatDiagnostic(item)).join("\n\n");
|
|
4174
|
+
}
|
|
4175
|
+
//#endregion
|
|
4176
|
+
//#region src/diagnostics/errors.ts
|
|
4177
|
+
var DeckDiagnosticError = class extends Error {
|
|
4178
|
+
diagnostics;
|
|
4179
|
+
constructor(message, diagnostics) {
|
|
4180
|
+
super(message);
|
|
4181
|
+
this.name = "DeckDiagnosticError";
|
|
4182
|
+
this.diagnostics = diagnostics;
|
|
4183
|
+
}
|
|
4184
|
+
};
|
|
4185
|
+
var SemanticGraphDiagnosticError = class extends DeckDiagnosticError {
|
|
4186
|
+
constructor(diagnostics) {
|
|
4187
|
+
super(formatDiagnostics(diagnostics), diagnostics);
|
|
4188
|
+
this.name = "SemanticGraphDiagnosticError";
|
|
4189
|
+
}
|
|
4190
|
+
};
|
|
4191
|
+
//#endregion
|
|
4192
|
+
//#region src/diagnostics/index.ts
|
|
4193
|
+
function createDiagnostics(items = []) {
|
|
4194
|
+
return {
|
|
4195
|
+
items,
|
|
4196
|
+
hasErrors: items.some((item) => item.severity === "error"),
|
|
4197
|
+
hasWarnings: items.some((item) => item.severity === "warning")
|
|
4198
|
+
};
|
|
4199
|
+
}
|
|
4200
|
+
function diagnostic(input) {
|
|
4201
|
+
return input;
|
|
4202
|
+
}
|
|
4203
|
+
//#endregion
|
|
4204
|
+
//#region src/graph/identity.ts
|
|
4205
|
+
function slug(value) {
|
|
4206
|
+
return value.replace(/[^a-zA-Z0-9:_-]+/g, "_");
|
|
4207
|
+
}
|
|
4208
|
+
function graphNodeId(material) {
|
|
4209
|
+
return slug(material.join("/"));
|
|
4210
|
+
}
|
|
4211
|
+
function styleEntityId(material) {
|
|
4212
|
+
return slug(`style/${material.join("/")}`);
|
|
4213
|
+
}
|
|
4214
|
+
function assetEntityId(material) {
|
|
4215
|
+
return slug(`asset/${material.join("/")}`);
|
|
4216
|
+
}
|
|
4217
|
+
//#endregion
|
|
4218
|
+
//#region src/graph/roles.ts
|
|
4219
|
+
function semanticKindForTag(tag) {
|
|
4220
|
+
if (tag === "img") return "image";
|
|
4221
|
+
if (tag === "p" || tag.startsWith("h") || tag === "span") return tag === "span" ? "textRun" : "text";
|
|
4222
|
+
return "container";
|
|
4223
|
+
}
|
|
4224
|
+
function semanticKindForComponent(component) {
|
|
4225
|
+
switch (component) {
|
|
4226
|
+
case "Slide": return "slide";
|
|
4227
|
+
case "View": return "container";
|
|
4228
|
+
case "Text": return "text";
|
|
4229
|
+
case "Image": return "image";
|
|
4230
|
+
case "Shape": return "shape";
|
|
4231
|
+
}
|
|
4232
|
+
}
|
|
4233
|
+
function semanticRoleForTag(tag) {
|
|
4234
|
+
switch (tag) {
|
|
4235
|
+
case "article":
|
|
4236
|
+
case "aside":
|
|
4237
|
+
case "footer":
|
|
4238
|
+
case "header":
|
|
4239
|
+
case "main":
|
|
4240
|
+
case "nav":
|
|
4241
|
+
case "section": return {
|
|
4242
|
+
kind: "sectioning",
|
|
4243
|
+
tag
|
|
4244
|
+
};
|
|
4245
|
+
case "div": return { kind: "genericContainer" };
|
|
4246
|
+
case "figure": return { kind: "figure" };
|
|
4247
|
+
case "p": return { kind: "paragraph" };
|
|
4248
|
+
case "h1":
|
|
4249
|
+
case "h2":
|
|
4250
|
+
case "h3":
|
|
4251
|
+
case "h4":
|
|
4252
|
+
case "h5":
|
|
4253
|
+
case "h6": return {
|
|
4254
|
+
kind: "heading",
|
|
4255
|
+
level: Number(tag.slice(1))
|
|
4256
|
+
};
|
|
4257
|
+
case "img": return { kind: "image" };
|
|
4258
|
+
case "span": return;
|
|
4259
|
+
}
|
|
4260
|
+
}
|
|
4261
|
+
function semanticRoleForComponent(component) {
|
|
4262
|
+
switch (component) {
|
|
4263
|
+
case "Slide": return { kind: "slide" };
|
|
4264
|
+
case "Image": return { kind: "image" };
|
|
4265
|
+
case "Shape": return { kind: "shape" };
|
|
4266
|
+
case "Text":
|
|
4267
|
+
case "View": return;
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
//#endregion
|
|
4271
|
+
//#region src/graph/build.ts
|
|
4272
|
+
function keySegment(key, index) {
|
|
4273
|
+
return key === void 0 ? `index:${index}` : `key:${String(key)}`;
|
|
4274
|
+
}
|
|
4275
|
+
function sourceName(node) {
|
|
4276
|
+
return node.source.kind === "tag" ? node.source.tag : node.source.component;
|
|
4277
|
+
}
|
|
4278
|
+
function nodeSemanticKind(node) {
|
|
4279
|
+
return node.source.kind === "tag" ? semanticKindForTag(node.source.tag) : semanticKindForComponent(node.source.component);
|
|
4280
|
+
}
|
|
4281
|
+
function nodeRole(node) {
|
|
4282
|
+
return node.source.kind === "tag" ? semanticRoleForTag(node.source.tag) : semanticRoleForComponent(node.source.component);
|
|
4283
|
+
}
|
|
4284
|
+
function originFor(node, path) {
|
|
4285
|
+
return {
|
|
4286
|
+
kind: "authored",
|
|
4287
|
+
path,
|
|
4288
|
+
...node.sourceSpan ? { sourceSpan: node.sourceSpan } : {}
|
|
4289
|
+
};
|
|
4290
|
+
}
|
|
4291
|
+
function textOriginFor(node, path) {
|
|
4292
|
+
return {
|
|
4293
|
+
kind: "authored",
|
|
4294
|
+
path,
|
|
4295
|
+
...node.sourceSpan ? { sourceSpan: node.sourceSpan } : {}
|
|
4296
|
+
};
|
|
4297
|
+
}
|
|
4298
|
+
function propsWithoutStyle(props) {
|
|
4299
|
+
const { style: _style, children: _children, ...direct } = props;
|
|
4300
|
+
return Object.keys(direct).length === 0 ? void 0 : direct;
|
|
4301
|
+
}
|
|
4302
|
+
function styleRefFor(state, idMaterial, target, props) {
|
|
4303
|
+
const style = props.style;
|
|
4304
|
+
const direct = propsWithoutStyle(props);
|
|
4305
|
+
if (style === void 0 && direct === void 0) return;
|
|
4306
|
+
const id = styleEntityId(idMaterial);
|
|
4307
|
+
state.styles.set(id, {
|
|
4308
|
+
id,
|
|
4309
|
+
target,
|
|
4310
|
+
authored: {
|
|
4311
|
+
...style !== void 0 ? { style } : {},
|
|
4312
|
+
...direct !== void 0 ? { direct } : {}
|
|
4313
|
+
}
|
|
4314
|
+
});
|
|
4315
|
+
return id;
|
|
4316
|
+
}
|
|
4317
|
+
function addDiagnostic(state, item) {
|
|
4318
|
+
state.diagnostics.push(item);
|
|
4319
|
+
}
|
|
4320
|
+
function invalidStructure(path, title, message, help) {
|
|
4321
|
+
return diagnostic({
|
|
4322
|
+
severity: "error",
|
|
4323
|
+
code: "E_SEMANTIC_STRUCTURE",
|
|
4324
|
+
title,
|
|
4325
|
+
labels: [{
|
|
4326
|
+
path,
|
|
4327
|
+
message
|
|
4328
|
+
}],
|
|
4329
|
+
...message ? { message } : {},
|
|
4330
|
+
...help ? { help } : {}
|
|
4331
|
+
});
|
|
4332
|
+
}
|
|
4333
|
+
function assetForImage(state, idMaterial, props, path) {
|
|
4334
|
+
if (typeof props.src !== "string" && typeof props.data !== "string") {
|
|
4335
|
+
addDiagnostic(state, invalidStructure(path, "image source is missing", "Image nodes require either src or data.", ["Add a src path or data URL to the image."]));
|
|
4336
|
+
return;
|
|
4337
|
+
}
|
|
4338
|
+
const id = assetEntityId(idMaterial);
|
|
4339
|
+
const entity = {
|
|
4340
|
+
id,
|
|
4341
|
+
kind: "image",
|
|
4342
|
+
source: typeof props.src === "string" ? {
|
|
4343
|
+
kind: "path",
|
|
4344
|
+
path: props.src
|
|
4345
|
+
} : {
|
|
4346
|
+
kind: "data",
|
|
4347
|
+
data: props.data
|
|
4348
|
+
},
|
|
4349
|
+
metadata: typeof props.data === "string" && props.data.startsWith("data:") ? { mediaType: props.data.slice(5, props.data.indexOf(";")) || void 0 } : {},
|
|
4350
|
+
resolution: "unresolved"
|
|
4351
|
+
};
|
|
4352
|
+
state.assets.set(id, entity);
|
|
4353
|
+
return id;
|
|
4354
|
+
}
|
|
4355
|
+
function semanticBase(state, node, id, kind, path, material) {
|
|
4356
|
+
const styleRef = styleRefFor(state, material, kind, node.props);
|
|
4357
|
+
return {
|
|
4358
|
+
id,
|
|
4359
|
+
kind,
|
|
4360
|
+
origin: originFor(node, path),
|
|
4361
|
+
...node.source.kind === "tag" ? { authoredTag: node.source.tag } : {},
|
|
4362
|
+
...node.source.kind === "component" ? { authoredComponent: node.source.component } : {},
|
|
4363
|
+
...node.key !== void 0 ? { key: node.key } : {},
|
|
4364
|
+
...nodeRole(node) ? { role: nodeRole(node) } : {},
|
|
4365
|
+
...styleRef ? { styleRef } : {}
|
|
4366
|
+
};
|
|
4367
|
+
}
|
|
4368
|
+
function buildTextRunFromLeaf(state, leaf, context, index) {
|
|
4369
|
+
const text = typeof leaf.value === "string" ? leaf.value : String(leaf.value);
|
|
4370
|
+
if (text.trim().length === 0) return;
|
|
4371
|
+
const segment = `text:${index}`;
|
|
4372
|
+
const id = graphNodeId([...context.parentMaterial, segment]);
|
|
4373
|
+
const path = `${context.path} > text[${index}]`;
|
|
4374
|
+
state.nodes.set(id, {
|
|
4375
|
+
id,
|
|
4376
|
+
kind: "textRun",
|
|
4377
|
+
origin: textOriginFor(leaf, path),
|
|
4378
|
+
text
|
|
4379
|
+
});
|
|
4380
|
+
return {
|
|
4381
|
+
id,
|
|
4382
|
+
kind: "textRun"
|
|
4383
|
+
};
|
|
4384
|
+
}
|
|
4385
|
+
function buildImplicitTextNode(state, leaf, context, index) {
|
|
4386
|
+
const run = buildTextRunFromLeaf(state, leaf, {
|
|
4387
|
+
...context,
|
|
4388
|
+
parentMaterial: [...context.parentMaterial, `implicit-text:${index}`],
|
|
4389
|
+
path: `${context.path} > implicitText[${index}]`
|
|
4390
|
+
}, 0);
|
|
4391
|
+
if (!run) return;
|
|
4392
|
+
const id = graphNodeId([...context.parentMaterial, `implicit-text:${index}`]);
|
|
4393
|
+
state.nodes.set(id, {
|
|
4394
|
+
id,
|
|
4395
|
+
kind: "text",
|
|
4396
|
+
origin: {
|
|
4397
|
+
kind: "implicit",
|
|
4398
|
+
path: `${context.path} > implicitText[${index}]`,
|
|
4399
|
+
...leaf.sourceSpan ? { sourceSpan: leaf.sourceSpan } : {},
|
|
4400
|
+
reason: "primitive-text-in-container"
|
|
4401
|
+
},
|
|
4402
|
+
implicit: true,
|
|
4403
|
+
inlineChildren: [run.id]
|
|
4404
|
+
});
|
|
4405
|
+
return {
|
|
4406
|
+
id,
|
|
4407
|
+
kind: "text"
|
|
4408
|
+
};
|
|
4409
|
+
}
|
|
4410
|
+
function buildChildren(state, children, context) {
|
|
4411
|
+
const ids = [];
|
|
4412
|
+
children.forEach((child, index) => {
|
|
4413
|
+
if (child.kind === "fragment") {
|
|
4414
|
+
const segment = `fragment:${keySegment(child.key, index)}`;
|
|
4415
|
+
ids.push(...buildChildren(state, child.children, {
|
|
4416
|
+
...context,
|
|
4417
|
+
parentMaterial: [...context.parentMaterial, segment],
|
|
4418
|
+
path: `${context.path} > fragment[${keySegment(child.key, index)}]`
|
|
4419
|
+
}));
|
|
4420
|
+
return;
|
|
4421
|
+
}
|
|
4422
|
+
const built = buildNode(state, child, context, index);
|
|
4423
|
+
if (built) ids.push(built.id);
|
|
4424
|
+
});
|
|
4425
|
+
return ids;
|
|
4426
|
+
}
|
|
4427
|
+
function buildTextLikeNode(state, node, id, path, material) {
|
|
4428
|
+
const inlineChildren = [];
|
|
4429
|
+
node.children.forEach((child, index) => {
|
|
4430
|
+
if (child.kind === "text") {
|
|
4431
|
+
const run = buildTextRunFromLeaf(state, child, {
|
|
4432
|
+
parentId: id,
|
|
4433
|
+
parentMaterial: material,
|
|
4434
|
+
path,
|
|
4435
|
+
inline: true
|
|
4436
|
+
}, index);
|
|
4437
|
+
if (run) inlineChildren.push(run.id);
|
|
4438
|
+
return;
|
|
4439
|
+
}
|
|
4440
|
+
if (child.kind === "fragment") {
|
|
4441
|
+
inlineChildren.push(...buildChildren(state, child.children, {
|
|
4442
|
+
parentId: id,
|
|
4443
|
+
parentMaterial: [...material, `fragment:${keySegment(child.key, index)}`],
|
|
4444
|
+
path: `${path} > fragment[${keySegment(child.key, index)}]`,
|
|
4445
|
+
inline: true
|
|
4446
|
+
}));
|
|
4447
|
+
return;
|
|
4448
|
+
}
|
|
4449
|
+
if (child.source.kind === "tag" && child.source.tag === "span") {
|
|
4450
|
+
const built = buildNode(state, child, {
|
|
4451
|
+
parentId: id,
|
|
4452
|
+
parentMaterial: material,
|
|
4453
|
+
path,
|
|
4454
|
+
inline: true
|
|
4455
|
+
}, index);
|
|
4456
|
+
if (built) inlineChildren.push(built.id);
|
|
4457
|
+
return;
|
|
4458
|
+
}
|
|
4459
|
+
addDiagnostic(state, invalidStructure(`${path} > ${sourceName(child)}[${index}]`, "block content cannot appear inside text", "Text-like elements accept primitive text and inline spans only."));
|
|
4460
|
+
});
|
|
4461
|
+
state.nodes.set(id, {
|
|
4462
|
+
...semanticBase(state, node, id, "text", path, material),
|
|
4463
|
+
kind: "text",
|
|
4464
|
+
inlineChildren
|
|
4465
|
+
});
|
|
4466
|
+
return {
|
|
4467
|
+
id,
|
|
4468
|
+
kind: "text"
|
|
4469
|
+
};
|
|
4470
|
+
}
|
|
4471
|
+
function collectInlineText(state, children, path) {
|
|
4472
|
+
let text = "";
|
|
4473
|
+
children.forEach((child, index) => {
|
|
4474
|
+
if (child.kind === "text") {
|
|
4475
|
+
text += typeof child.value === "string" ? child.value : String(child.value);
|
|
4476
|
+
return;
|
|
4477
|
+
}
|
|
4478
|
+
if (child.kind === "fragment") {
|
|
4479
|
+
text += collectInlineText(state, child.children, `${path} > fragment[${keySegment(child.key, index)}]`);
|
|
4480
|
+
return;
|
|
4481
|
+
}
|
|
4482
|
+
if (child.source.kind === "tag" && child.source.tag === "span") {
|
|
4483
|
+
text += collectInlineText(state, child.children, `${path} > span[${keySegment(child.key, index)}]`);
|
|
4484
|
+
return;
|
|
4485
|
+
}
|
|
4486
|
+
addDiagnostic(state, invalidStructure(`${path} > ${sourceName(child)}[${index}]`, "block content cannot appear inside span", "span accepts primitive text or nested inline spans only."));
|
|
4487
|
+
});
|
|
4488
|
+
return text;
|
|
4489
|
+
}
|
|
4490
|
+
function buildNode(state, node, context, index) {
|
|
4491
|
+
if (node.kind === "fragment") return;
|
|
4492
|
+
if (node.kind === "text") return context.inline ? buildTextRunFromLeaf(state, node, context, index) : buildImplicitTextNode(state, node, context, index);
|
|
4493
|
+
const kind = nodeSemanticKind(node);
|
|
4494
|
+
const segment = `${sourceName(node)}:${keySegment(node.key, index)}`;
|
|
4495
|
+
const material = [...context.parentMaterial, segment];
|
|
4496
|
+
const id = graphNodeId(material);
|
|
4497
|
+
const path = `${context.path} > ${sourceName(node)}[${keySegment(node.key, index)}]`;
|
|
4498
|
+
if (kind === "textRun") {
|
|
4499
|
+
if (!context.inline) {
|
|
4500
|
+
addDiagnostic(state, invalidStructure(path, "span cannot appear here", "span must be inside a text-like element.", ["Wrap the span in <p>...</p> or move it inside an existing text element."]));
|
|
4501
|
+
return;
|
|
4502
|
+
}
|
|
4503
|
+
const text = collectInlineText(state, node.children, path);
|
|
4504
|
+
state.nodes.set(id, {
|
|
4505
|
+
...semanticBase(state, node, id, "textRun", path, material),
|
|
4506
|
+
kind: "textRun",
|
|
4507
|
+
text
|
|
4508
|
+
});
|
|
4509
|
+
return {
|
|
4510
|
+
id,
|
|
4511
|
+
kind: "textRun"
|
|
4512
|
+
};
|
|
4513
|
+
}
|
|
4514
|
+
if (kind === "text") return buildTextLikeNode(state, node, id, path, material);
|
|
4515
|
+
if (kind === "image") {
|
|
4516
|
+
if (node.children.length > 0) addDiagnostic(state, invalidStructure(path, "image cannot have children", "Image nodes are leaf nodes."));
|
|
4517
|
+
const assetRef = assetForImage(state, material, node.props, path);
|
|
4518
|
+
state.nodes.set(id, {
|
|
4519
|
+
...semanticBase(state, node, id, "image", path, material),
|
|
4520
|
+
kind: "image",
|
|
4521
|
+
...assetRef ? { assetRef } : {}
|
|
4522
|
+
});
|
|
4523
|
+
return {
|
|
4524
|
+
id,
|
|
4525
|
+
kind: "image"
|
|
4526
|
+
};
|
|
4527
|
+
}
|
|
4528
|
+
const childIds = buildChildren(state, node.children, {
|
|
4529
|
+
parentId: id,
|
|
4530
|
+
parentMaterial: material,
|
|
4531
|
+
path,
|
|
4532
|
+
inline: false
|
|
4533
|
+
});
|
|
4534
|
+
state.nodes.set(id, {
|
|
4535
|
+
...semanticBase(state, node, id, kind, path, material),
|
|
4536
|
+
kind,
|
|
4537
|
+
children: childIds
|
|
4538
|
+
});
|
|
4539
|
+
return {
|
|
4540
|
+
id,
|
|
4541
|
+
kind
|
|
4542
|
+
};
|
|
4543
|
+
}
|
|
4544
|
+
function buildSemanticAuthorGraph(roots) {
|
|
4545
|
+
const documentId = graphNodeId(["document", "root"]);
|
|
4546
|
+
const state = {
|
|
4547
|
+
nodes: /* @__PURE__ */ new Map(),
|
|
4548
|
+
styles: /* @__PURE__ */ new Map(),
|
|
4549
|
+
assets: /* @__PURE__ */ new Map(),
|
|
4550
|
+
diagnostics: []
|
|
4551
|
+
};
|
|
4552
|
+
const documentNode = {
|
|
4553
|
+
id: documentId,
|
|
4554
|
+
kind: "document",
|
|
4555
|
+
origin: {
|
|
4556
|
+
kind: "implicit",
|
|
4557
|
+
path: "document"
|
|
4558
|
+
},
|
|
4559
|
+
role: { kind: "document" },
|
|
4560
|
+
children: buildChildren(state, roots, {
|
|
4561
|
+
parentId: documentId,
|
|
4562
|
+
parentMaterial: ["document", "root"],
|
|
4563
|
+
path: "document",
|
|
4564
|
+
inline: false
|
|
4565
|
+
})
|
|
4566
|
+
};
|
|
4567
|
+
state.nodes.set(documentId, documentNode);
|
|
4568
|
+
const diagnostics = createDiagnostics(state.diagnostics);
|
|
4569
|
+
return {
|
|
4570
|
+
graph: {
|
|
4571
|
+
documentId,
|
|
4572
|
+
nodes: state.nodes,
|
|
4573
|
+
styles: state.styles,
|
|
4574
|
+
assets: state.assets
|
|
4575
|
+
},
|
|
4576
|
+
diagnostics
|
|
4112
4577
|
};
|
|
4113
4578
|
}
|
|
4114
4579
|
//#endregion
|
|
@@ -14974,6 +15439,24 @@ function toPptxTabStops(tabStops) {
|
|
|
14974
15439
|
...tabStop.alignment ? { alignment: tabStop.alignment } : {}
|
|
14975
15440
|
}));
|
|
14976
15441
|
}
|
|
15442
|
+
function toPptxTextRunOptions(style) {
|
|
15443
|
+
if (!style) return;
|
|
15444
|
+
const options = {
|
|
15445
|
+
fontFace: style.fontFamily,
|
|
15446
|
+
fontSize: style.fontSizePt,
|
|
15447
|
+
color: style.color,
|
|
15448
|
+
bold: style.fontWeight === "bold" || typeof style.fontWeight === "number" && style.fontWeight >= 600,
|
|
15449
|
+
italic: style.italic,
|
|
15450
|
+
underline: toPptxUnderline(style),
|
|
15451
|
+
strike: style.strike,
|
|
15452
|
+
charSpacing: style.charSpacing,
|
|
15453
|
+
superscript: style.superscript,
|
|
15454
|
+
subscript: style.subscript,
|
|
15455
|
+
breakLine: false
|
|
15456
|
+
};
|
|
15457
|
+
if (Object.values(options).every((value) => value === void 0 || value === false)) return;
|
|
15458
|
+
return options;
|
|
15459
|
+
}
|
|
14977
15460
|
function emitOutlineShape(slide, shapeName, frame, outline, radiusEmu, effectiveOpacity, rotation, flipH, flipV) {
|
|
14978
15461
|
if (!outline) return;
|
|
14979
15462
|
const insetEmu = pointsToEmu(outline.widthPt) / 2;
|
|
@@ -15048,7 +15531,14 @@ function emitText(slide, node, inheritedOpacity) {
|
|
|
15048
15531
|
emitOutlineShape(slide, node.radiusEmu && node.radiusEmu > 0 ? "roundRect" : "rect", node.frame, node.outline, node.radiusEmu, effectiveOpacity, node.rotation, node.flipH, node.flipV);
|
|
15049
15532
|
emitEdgeStrokes(slide, node.frame, node.edgeStrokes, effectiveOpacity, node.rotation, node.flipH, node.flipV);
|
|
15050
15533
|
emitBackgroundLayers(slide, node.frame, node.backgroundLayers, node.radiusEmu && node.radiusEmu > 0 ? "roundRect" : "rect", node.radiusEmu, effectiveOpacity, node.rotation, node.flipH, node.flipV);
|
|
15051
|
-
|
|
15534
|
+
const textContent = node.content.runs ? node.content.runs.map((run) => {
|
|
15535
|
+
const options = toPptxTextRunOptions(run.style);
|
|
15536
|
+
return {
|
|
15537
|
+
text: run.text,
|
|
15538
|
+
...options ? { options } : {}
|
|
15539
|
+
};
|
|
15540
|
+
}) : node.content.text;
|
|
15541
|
+
slide.addText(textContent, {
|
|
15052
15542
|
x: emuToInches(node.frame.xEmu),
|
|
15053
15543
|
y: emuToInches(node.frame.yEmu),
|
|
15054
15544
|
w: emuToInches(node.frame.widthEmu),
|
|
@@ -15212,6 +15702,33 @@ async function outputPresentation(presentation, config) {
|
|
|
15212
15702
|
}
|
|
15213
15703
|
//#endregion
|
|
15214
15704
|
//#region src/deck.ts
|
|
15705
|
+
function isSlideRoot(value) {
|
|
15706
|
+
return value.kind === "element" && value.source.kind === "component" && value.source.component === "Slide";
|
|
15707
|
+
}
|
|
15708
|
+
function describeInvalidRoot(value) {
|
|
15709
|
+
if (isLegacyAuthorNode(value)) return "Slide factory returned a legacy author node.";
|
|
15710
|
+
if (isAuthorTreeNode(value)) return "Slide factory returned an author tree node that is not a <Slide /> root.";
|
|
15711
|
+
if (value === null) return "Slide factory returned null.";
|
|
15712
|
+
return `Slide factory returned ${typeof value}.`;
|
|
15713
|
+
}
|
|
15714
|
+
function invalidRootSourceSpan(value) {
|
|
15715
|
+
return isAuthorTreeNode(value) ? value.sourceSpan : void 0;
|
|
15716
|
+
}
|
|
15717
|
+
function invalidRootDiagnostic(value, slideIndex) {
|
|
15718
|
+
const path = `document > slideFactory[${slideIndex}]`;
|
|
15719
|
+
return diagnostic({
|
|
15720
|
+
severity: "error",
|
|
15721
|
+
code: "E_COMPILE_ROOT",
|
|
15722
|
+
title: "slide factory must return a <Slide /> root",
|
|
15723
|
+
message: describeInvalidRoot(value),
|
|
15724
|
+
labels: [{
|
|
15725
|
+
path,
|
|
15726
|
+
message: "Expected a deckjsx Author Tree <Slide /> node.",
|
|
15727
|
+
...invalidRootSourceSpan(value) ? { sourceSpan: invalidRootSourceSpan(value) } : {}
|
|
15728
|
+
}],
|
|
15729
|
+
help: ["Return <Slide>...</Slide> from the slide factory passed to deck.add()."]
|
|
15730
|
+
});
|
|
15731
|
+
}
|
|
15215
15732
|
var Deck = class {
|
|
15216
15733
|
#options;
|
|
15217
15734
|
#slides = [];
|
|
@@ -15225,9 +15742,38 @@ var Deck = class {
|
|
|
15225
15742
|
render() {
|
|
15226
15743
|
return renderPresentation(this.#options, this.#slides);
|
|
15227
15744
|
}
|
|
15745
|
+
compile(config = {}) {
|
|
15746
|
+
const roots = [];
|
|
15747
|
+
const diagnostics = [];
|
|
15748
|
+
this.#slides.forEach((factory, slideIndex) => {
|
|
15749
|
+
const root = factory({
|
|
15750
|
+
slideIndex,
|
|
15751
|
+
totalSlides: this.#slides.length,
|
|
15752
|
+
context: {
|
|
15753
|
+
slideIndex,
|
|
15754
|
+
totalSlides: this.#slides.length
|
|
15755
|
+
}
|
|
15756
|
+
});
|
|
15757
|
+
if (!isAuthorTreeNode(root) || !isSlideRoot(root)) {
|
|
15758
|
+
diagnostics.push(invalidRootDiagnostic(root, slideIndex));
|
|
15759
|
+
return;
|
|
15760
|
+
}
|
|
15761
|
+
roots.push(root);
|
|
15762
|
+
});
|
|
15763
|
+
if (diagnostics.length > 0) {
|
|
15764
|
+
const result = { diagnostics: createDiagnostics(diagnostics) };
|
|
15765
|
+
if (config.mode === "inspect") return result;
|
|
15766
|
+
throw new SemanticGraphDiagnosticError(result.diagnostics);
|
|
15767
|
+
}
|
|
15768
|
+
const result = buildSemanticAuthorGraph(roots);
|
|
15769
|
+
if (config.mode === "inspect") return result;
|
|
15770
|
+
if (result.diagnostics.hasErrors) throw new SemanticGraphDiagnosticError(result.diagnostics);
|
|
15771
|
+
if (!result.graph) throw new SemanticGraphDiagnosticError(result.diagnostics);
|
|
15772
|
+
return result.graph;
|
|
15773
|
+
}
|
|
15228
15774
|
async output(config) {
|
|
15229
15775
|
await outputPresentation(this.render(), config);
|
|
15230
15776
|
}
|
|
15231
15777
|
};
|
|
15232
15778
|
//#endregion
|
|
15233
|
-
export { Deck, EMU_PER_INCH, Fragment, Image, POINTS_PER_INCH, Shape, Slide, Text, View, createElement, isAuthorNode, isContentNode, isSlideNode, pptxgenjsBackend };
|
|
15779
|
+
export { Deck, DeckDiagnosticError, EMU_PER_INCH, Fragment, Image, POINTS_PER_INCH, SemanticGraphDiagnosticError, Shape, Slide, Text, View, createElement, formatDiagnostic, formatDiagnostics, isAuthorNode, isContentNode, isSlideNode, pptxgenjsBackend };
|