@bendyline/squisq-formats 2.6.16 → 2.6.18
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/chunk-34KECNZO.js +15 -0
- package/dist/{chunk-SAMQZRJU.js → chunk-53CTG4YR.js} +5 -85
- package/dist/{chunk-EMAPNC32.js → chunk-76BFHBZD.js} +50 -3
- package/dist/chunk-C23JYVPG.js +89 -0
- package/dist/{chunk-TLDBJH7D.js → chunk-JY3T4KOP.js} +247 -20
- package/dist/{chunk-ZDRSDYXN.js → chunk-VJQZMIXU.js} +3 -14
- package/dist/{chunk-EQAHFGGX.js → chunk-YFSFEPBB.js} +160 -15
- package/dist/docx/index.js +1 -1
- package/dist/html/index.d.ts +14 -2
- package/dist/html/index.js +1 -1
- package/dist/{import-D8y5SV0T.d.ts → import-ipP4Ghp8.d.ts} +7 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +13 -10
- package/dist/outside-in/index.d.ts +7 -39
- package/dist/outside-in/index.js +8 -6
- package/dist/outside-in/layout.d.ts +58 -0
- package/dist/outside-in/layout.js +12 -0
- package/dist/pdf/index.js +2 -1
- package/dist/pptx/index.js +1 -1
- package/dist/registry/index.d.ts +3 -3
- package/dist/registry/index.js +1 -1
- package/dist/{types-Cubj9A8c.d.ts → types-CVv9eldp.d.ts} +1 -1
- package/dist/videoPoster-D7DTZC2L.js +104 -0
- package/package.json +7 -2
- /package/dist/{chunk-VE2ADQ5T.js → chunk-SZDCCL6O.js} +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// src/pdf/upng.ts
|
|
2
|
+
import UPNG from "@pdf-lib/upng";
|
|
3
|
+
function isUpngEncoder(value) {
|
|
4
|
+
return typeof value === "object" && value !== null && "encode" in value && typeof value.encode === "function";
|
|
5
|
+
}
|
|
6
|
+
function resolveUpngEncoder(value) {
|
|
7
|
+
if (isUpngEncoder(value)) return value;
|
|
8
|
+
if (typeof value !== "object" || value === null || !("default" in value)) return null;
|
|
9
|
+
return isUpngEncoder(value.default) ? value.default : null;
|
|
10
|
+
}
|
|
11
|
+
var upngEncoder = resolveUpngEncoder(UPNG);
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
upngEncoder
|
|
15
|
+
};
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
convert,
|
|
3
3
|
defaultRegistry
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SZDCCL6O.js";
|
|
5
5
|
import {
|
|
6
6
|
ConversionError
|
|
7
7
|
} from "./chunk-KXOZMWBS.js";
|
|
8
|
+
import {
|
|
9
|
+
OUTSIDE_IN_FORMAT_IDS,
|
|
10
|
+
resolveOutsideInLayout
|
|
11
|
+
} from "./chunk-C23JYVPG.js";
|
|
8
12
|
|
|
9
13
|
// src/outside-in/index.ts
|
|
10
14
|
import {
|
|
@@ -14,91 +18,11 @@ import {
|
|
|
14
18
|
stringifyMarkdown
|
|
15
19
|
} from "@bendyline/squisq/markdown";
|
|
16
20
|
import { MemoryContentContainer } from "@bendyline/squisq/storage";
|
|
17
|
-
var OUTSIDE_IN_FORMAT_IDS = ["html", "docx", "pdf", "pptx", "xlsx", "csv"];
|
|
18
21
|
var OUTSIDE_IN_FORMAT_SET = new Set(OUTSIDE_IN_FORMAT_IDS);
|
|
19
22
|
var OUTSIDE_IN_VERSION_KEY = "squisq-outside-in";
|
|
20
23
|
var OUTSIDE_IN_OUTPUT_KEY = "squisq-output";
|
|
21
24
|
var OUTSIDE_IN_FORMAT_KEY = "squisq-output-format";
|
|
22
25
|
var OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY = "squisq-updatefrommarkdown";
|
|
23
|
-
function normalizePath(path) {
|
|
24
|
-
const slash = path.replace(/\\/g, "/");
|
|
25
|
-
const leading = slash.startsWith("/") ? "/" : "";
|
|
26
|
-
const parts = slash.split("/").filter((part) => part !== "");
|
|
27
|
-
if (parts.some((part) => part === "." || part === "..")) {
|
|
28
|
-
throw new Error(`Outside-in paths must be canonical workspace paths: ${path}`);
|
|
29
|
-
}
|
|
30
|
-
return leading + parts.join("/");
|
|
31
|
-
}
|
|
32
|
-
function joinPath(parent, child) {
|
|
33
|
-
if (!parent || parent === "/") return parent === "/" ? `/${child}` : child;
|
|
34
|
-
return `${parent}/${child}`;
|
|
35
|
-
}
|
|
36
|
-
function dirname(path) {
|
|
37
|
-
const slash = path.lastIndexOf("/");
|
|
38
|
-
if (slash < 0) return "";
|
|
39
|
-
if (slash === 0) return "/";
|
|
40
|
-
return path.slice(0, slash);
|
|
41
|
-
}
|
|
42
|
-
function basename(path) {
|
|
43
|
-
return path.slice(path.lastIndexOf("/") + 1);
|
|
44
|
-
}
|
|
45
|
-
function slugStem(stem) {
|
|
46
|
-
const slug = stem.normalize("NFKD").replace(/\p{Mark}+/gu, "").toLocaleLowerCase("en-US").replace(/[^\p{Letter}\p{Number}]+/gu, "-").replace(/^-+|-+$/g, "");
|
|
47
|
-
return slug || "document";
|
|
48
|
-
}
|
|
49
|
-
function formatFromExtension(extension) {
|
|
50
|
-
const normalized = extension.toLowerCase();
|
|
51
|
-
if (normalized === "htm") return "html";
|
|
52
|
-
return OUTSIDE_IN_FORMAT_SET.has(normalized) ? normalized : null;
|
|
53
|
-
}
|
|
54
|
-
function resolveOutsideInLayout(targetPath) {
|
|
55
|
-
const normalized = normalizePath(targetPath);
|
|
56
|
-
const filename = basename(normalized);
|
|
57
|
-
const dot = filename.lastIndexOf(".");
|
|
58
|
-
if (dot <= 0 || dot === filename.length - 1) return null;
|
|
59
|
-
const format = formatFromExtension(filename.slice(dot + 1));
|
|
60
|
-
if (!format) return null;
|
|
61
|
-
const stem = filename.slice(0, dot);
|
|
62
|
-
const parentDirectory = dirname(normalized);
|
|
63
|
-
const companionName = `${stem}_files`;
|
|
64
|
-
const companionDirectory = joinPath(parentDirectory, companionName);
|
|
65
|
-
const markdownFilename = `${slugStem(stem)}.md`;
|
|
66
|
-
const backupDirectory = joinPath(companionDirectory, ".original");
|
|
67
|
-
const backupFilename = `original.${format}`;
|
|
68
|
-
return {
|
|
69
|
-
targetPath: normalized,
|
|
70
|
-
format,
|
|
71
|
-
parentDirectory,
|
|
72
|
-
stem,
|
|
73
|
-
companionName,
|
|
74
|
-
companionDirectory,
|
|
75
|
-
markdownFilename,
|
|
76
|
-
markdownPath: joinPath(companionDirectory, markdownFilename),
|
|
77
|
-
relativeTargetPath: `../${filename}`,
|
|
78
|
-
backupDirectory,
|
|
79
|
-
backupFilename,
|
|
80
|
-
backupPath: joinPath(backupDirectory, backupFilename)
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
function isOutsideInTargetPath(path) {
|
|
84
|
-
return resolveOutsideInLayout(path) !== null;
|
|
85
|
-
}
|
|
86
|
-
function chooseOutsideInMarkdownPath(layout, paths) {
|
|
87
|
-
const canonical = normalizePath(layout.markdownPath);
|
|
88
|
-
const normalized = paths.map(normalizePath);
|
|
89
|
-
const exact = normalized.find((path) => path === canonical);
|
|
90
|
-
if (exact) return exact;
|
|
91
|
-
const canonicalFolded = canonical.toLocaleLowerCase("en-US");
|
|
92
|
-
const folded = normalized.find((path) => path.toLocaleLowerCase("en-US") === canonicalFolded);
|
|
93
|
-
if (folded) return folded;
|
|
94
|
-
const prefix = `${normalizePath(layout.companionDirectory).replace(/\/$/, "")}/`;
|
|
95
|
-
const markdown = normalized.filter((path) => {
|
|
96
|
-
if (!path.toLocaleLowerCase("en-US").endsWith(".md")) return false;
|
|
97
|
-
if (!path.startsWith(prefix)) return false;
|
|
98
|
-
return !path.slice(prefix.length).includes("/");
|
|
99
|
-
});
|
|
100
|
-
return markdown.length === 1 ? markdown[0] : null;
|
|
101
|
-
}
|
|
102
26
|
function rawFrontmatter(source) {
|
|
103
27
|
const block = splitFrontmatterBlock(source).frontmatter;
|
|
104
28
|
if (!block) return null;
|
|
@@ -277,11 +201,7 @@ async function renderOutsideInDocument(source, options = {}) {
|
|
|
277
201
|
}
|
|
278
202
|
|
|
279
203
|
export {
|
|
280
|
-
OUTSIDE_IN_FORMAT_IDS,
|
|
281
204
|
OUTSIDE_IN_UPDATE_FROM_MARKDOWN_KEY,
|
|
282
|
-
resolveOutsideInLayout,
|
|
283
|
-
isOutsideInTargetPath,
|
|
284
|
-
chooseOutsideInMarkdownPath,
|
|
285
205
|
readOutsideInMetadata,
|
|
286
206
|
withOutsideInMetadata,
|
|
287
207
|
isOutsideInMarkdownEditingEnabled,
|
|
@@ -74,7 +74,7 @@ import {
|
|
|
74
74
|
resolveThemeForDoc
|
|
75
75
|
} from "@bendyline/squisq/doc";
|
|
76
76
|
import { splitIconMarkers } from "@bendyline/squisq/icon-marker";
|
|
77
|
-
import { readFrontmatterThemeId } from "@bendyline/squisq/markdown";
|
|
77
|
+
import { parseVideoEmbedUrl, readFrontmatterThemeId } from "@bendyline/squisq/markdown";
|
|
78
78
|
|
|
79
79
|
// src/pptx/styles.ts
|
|
80
80
|
var SLIDE_WIDTH = 12192e3;
|
|
@@ -202,6 +202,9 @@ async function docToPptx(doc, options = {}) {
|
|
|
202
202
|
if (slideBlocks.length === 0) {
|
|
203
203
|
slideBlocks.push({ id: "empty-slide", startTime: 0, duration: 0, audioSegment: 0, layers: [] });
|
|
204
204
|
}
|
|
205
|
+
const videoPosters = slideBlocks.some(
|
|
206
|
+
(block) => block.layers?.some((layer) => layer.type === "videoEmbed")
|
|
207
|
+
) ? await import("./videoPoster-D7DTZC2L.js") : null;
|
|
205
208
|
const slideXmls = [];
|
|
206
209
|
const slideContexts = [];
|
|
207
210
|
for (let index = 0; index < slideBlocks.length; index++) {
|
|
@@ -214,6 +217,7 @@ async function docToPptx(doc, options = {}) {
|
|
|
214
217
|
effectiveOptions.signal
|
|
215
218
|
);
|
|
216
219
|
ctx.diagramImages = effectiveOptions.diagramImages;
|
|
220
|
+
ctx.videoPosters = videoPosters;
|
|
217
221
|
slideXmls.push(buildLayerSlideXml(slideBlocks[index], ctx));
|
|
218
222
|
slideContexts.push(ctx);
|
|
219
223
|
}
|
|
@@ -315,6 +319,8 @@ var SlideContext = class {
|
|
|
315
319
|
*/
|
|
316
320
|
this.relIds = new RelIdAllocator();
|
|
317
321
|
this.relationships = [];
|
|
322
|
+
/** Poster helpers for hosted videos, loaded only when the deck has one. */
|
|
323
|
+
this.videoPosters = null;
|
|
318
324
|
this.embeddedImages = [];
|
|
319
325
|
this.nextShapeId = 4;
|
|
320
326
|
/** Font Awesome families referenced by semantic or materialized text runs. */
|
|
@@ -553,6 +559,44 @@ function convertLayerToShapes(layer, ctx, textBottom) {
|
|
|
553
559
|
)
|
|
554
560
|
];
|
|
555
561
|
}
|
|
562
|
+
case "videoEmbed": {
|
|
563
|
+
const embed = parseVideoEmbedUrl(layer.content.url);
|
|
564
|
+
const thumbnail = embed?.thumbnailUrl ? ctx.images?.get(embed.thumbnailUrl) : void 0;
|
|
565
|
+
const poster = embed && (thumbnail ?? ctx.videoPosters?.videoPosterPng(embed.aspectRatio < 1)?.data);
|
|
566
|
+
if (embed && poster) {
|
|
567
|
+
const label = layer.content.title || `${embed.providerName} video`;
|
|
568
|
+
const relId = ctx.addImage(
|
|
569
|
+
thumbnail ? embed.thumbnailUrl ?? "poster.jpg" : "video-poster.png",
|
|
570
|
+
poster,
|
|
571
|
+
label
|
|
572
|
+
);
|
|
573
|
+
const embedded = ctx.embeddedImages.find((candidate) => candidate.relId === relId);
|
|
574
|
+
const area = toEmuRect(resolveLayerRect(layer.position, 1920, 1080));
|
|
575
|
+
const width = Math.min(area.width, Math.round(area.height * embed.aspectRatio));
|
|
576
|
+
const height = Math.round(width / embed.aspectRatio);
|
|
577
|
+
return [
|
|
578
|
+
buildImageShape(
|
|
579
|
+
embedded,
|
|
580
|
+
ctx.allocShapeId(),
|
|
581
|
+
area.x + Math.round((area.width - width) / 2),
|
|
582
|
+
area.y + Math.round((area.height - height) / 2),
|
|
583
|
+
width,
|
|
584
|
+
height,
|
|
585
|
+
ctx.addHyperlink(embed.watchUrl)
|
|
586
|
+
)
|
|
587
|
+
];
|
|
588
|
+
}
|
|
589
|
+
return [
|
|
590
|
+
buildLayerTextShape(
|
|
591
|
+
textLayerForPlaceholder(
|
|
592
|
+
layer.position,
|
|
593
|
+
`[Video: ${layer.content.title || layer.content.url}]`,
|
|
594
|
+
ctx
|
|
595
|
+
),
|
|
596
|
+
ctx.allocShapeId()
|
|
597
|
+
)
|
|
598
|
+
];
|
|
599
|
+
}
|
|
556
600
|
case "mermaid": {
|
|
557
601
|
const picture = ctx.diagramImages?.get(layer.content.source.trim());
|
|
558
602
|
if (picture && picture.width > 0 && picture.height > 0) {
|
|
@@ -1113,8 +1157,11 @@ function buildBodyShapeCustom(bodyContent, top, height, style) {
|
|
|
1113
1157
|
const defRPr = style.hasTheme ? `<a:defRPr><a:solidFill><a:srgbClr val="${style.text}"/></a:solidFill><a:latin typeface="${escapeXml(style.bodyFont)}"/></a:defRPr>` : "";
|
|
1114
1158
|
return `<p:sp><p:nvSpPr><p:cNvPr id="3" name="Content"/><p:cNvSpPr><a:spLocks noGrp="1"/></p:cNvSpPr><p:nvPr><p:ph idx="1"/></p:nvPr></p:nvSpPr><p:spPr><a:xfrm><a:off x="${BODY_LEFT}" y="${top}"/><a:ext cx="${BODY_WIDTH}" cy="${height}"/></a:xfrm></p:spPr><p:txBody><a:bodyPr/><a:lstStyle><a:lvl1pPr>${defRPr}</a:lvl1pPr></a:lstStyle>` + bodyContent + `</p:txBody></p:sp>`;
|
|
1115
1159
|
}
|
|
1116
|
-
function buildImageShape(img, shapeId, left, top, maxWidth, maxHeight) {
|
|
1117
|
-
|
|
1160
|
+
function buildImageShape(img, shapeId, left, top, maxWidth, maxHeight, hyperlinkRelId) {
|
|
1161
|
+
const name = escapeXml(img.alt || "Picture");
|
|
1162
|
+
const descr = img.alt ? ` descr="${escapeXml(img.alt)}"` : "";
|
|
1163
|
+
const link = hyperlinkRelId ? `<a:hlinkClick r:id="${hyperlinkRelId}"/>` : "";
|
|
1164
|
+
return `<p:pic><p:nvPicPr>` + (link ? `<p:cNvPr id="${shapeId}" name="${name}"${descr}>${link}</p:cNvPr>` : `<p:cNvPr id="${shapeId}" name="${name}"${descr}/>`) + `<p:cNvPicPr><a:picLocks noChangeAspect="1"/></p:cNvPicPr><p:nvPr/></p:nvPicPr><p:blipFill><a:blip r:embed="${img.relId}"/><a:stretch><a:fillRect/></a:stretch></p:blipFill><p:spPr><a:xfrm><a:off x="${left}" y="${top}"/><a:ext cx="${maxWidth}" cy="${maxHeight}"/></a:xfrm><a:prstGeom prst="rect"><a:avLst/></a:prstGeom></p:spPr></p:pic>`;
|
|
1118
1165
|
}
|
|
1119
1166
|
function convertBodyBlocks(nodes, ctx) {
|
|
1120
1167
|
const parts = [];
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// src/outside-in/layout.ts
|
|
2
|
+
var OUTSIDE_IN_FORMAT_IDS = ["html", "docx", "pdf", "pptx", "xlsx", "csv"];
|
|
3
|
+
var OUTSIDE_IN_FORMAT_SET = new Set(OUTSIDE_IN_FORMAT_IDS);
|
|
4
|
+
function normalizePath(path) {
|
|
5
|
+
const slash = path.replace(/\\/g, "/");
|
|
6
|
+
const leading = slash.startsWith("/") ? "/" : "";
|
|
7
|
+
const parts = slash.split("/").filter((part) => part !== "");
|
|
8
|
+
if (parts.some((part) => part === "." || part === "..")) {
|
|
9
|
+
throw new Error(`Outside-in paths must be canonical workspace paths: ${path}`);
|
|
10
|
+
}
|
|
11
|
+
return leading + parts.join("/");
|
|
12
|
+
}
|
|
13
|
+
function joinPath(parent, child) {
|
|
14
|
+
if (!parent || parent === "/") return parent === "/" ? `/${child}` : child;
|
|
15
|
+
return `${parent}/${child}`;
|
|
16
|
+
}
|
|
17
|
+
function dirname(path) {
|
|
18
|
+
const slash = path.lastIndexOf("/");
|
|
19
|
+
if (slash < 0) return "";
|
|
20
|
+
if (slash === 0) return "/";
|
|
21
|
+
return path.slice(0, slash);
|
|
22
|
+
}
|
|
23
|
+
function basename(path) {
|
|
24
|
+
return path.slice(path.lastIndexOf("/") + 1);
|
|
25
|
+
}
|
|
26
|
+
function slugStem(stem) {
|
|
27
|
+
const slug = stem.normalize("NFKD").replace(/\p{Mark}+/gu, "").toLocaleLowerCase("en-US").replace(/[^\p{Letter}\p{Number}]+/gu, "-").replace(/^-+|-+$/g, "");
|
|
28
|
+
return slug || "document";
|
|
29
|
+
}
|
|
30
|
+
function formatFromExtension(extension) {
|
|
31
|
+
const normalized = extension.toLowerCase();
|
|
32
|
+
if (normalized === "htm") return "html";
|
|
33
|
+
return OUTSIDE_IN_FORMAT_SET.has(normalized) ? normalized : null;
|
|
34
|
+
}
|
|
35
|
+
function resolveOutsideInLayout(targetPath) {
|
|
36
|
+
const normalized = normalizePath(targetPath);
|
|
37
|
+
const filename = basename(normalized);
|
|
38
|
+
const dot = filename.lastIndexOf(".");
|
|
39
|
+
if (dot <= 0 || dot === filename.length - 1) return null;
|
|
40
|
+
const format = formatFromExtension(filename.slice(dot + 1));
|
|
41
|
+
if (!format) return null;
|
|
42
|
+
const stem = filename.slice(0, dot);
|
|
43
|
+
const parentDirectory = dirname(normalized);
|
|
44
|
+
const companionName = `${stem}_files`;
|
|
45
|
+
const companionDirectory = joinPath(parentDirectory, companionName);
|
|
46
|
+
const markdownFilename = `${slugStem(stem)}.md`;
|
|
47
|
+
const backupDirectory = joinPath(companionDirectory, ".original");
|
|
48
|
+
const backupFilename = `original.${format}`;
|
|
49
|
+
return {
|
|
50
|
+
targetPath: normalized,
|
|
51
|
+
format,
|
|
52
|
+
parentDirectory,
|
|
53
|
+
stem,
|
|
54
|
+
companionName,
|
|
55
|
+
companionDirectory,
|
|
56
|
+
markdownFilename,
|
|
57
|
+
markdownPath: joinPath(companionDirectory, markdownFilename),
|
|
58
|
+
relativeTargetPath: `../${filename}`,
|
|
59
|
+
backupDirectory,
|
|
60
|
+
backupFilename,
|
|
61
|
+
backupPath: joinPath(backupDirectory, backupFilename)
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function isOutsideInTargetPath(path) {
|
|
65
|
+
return resolveOutsideInLayout(path) !== null;
|
|
66
|
+
}
|
|
67
|
+
function chooseOutsideInMarkdownPath(layout, paths) {
|
|
68
|
+
const canonical = normalizePath(layout.markdownPath);
|
|
69
|
+
const normalized = paths.map(normalizePath);
|
|
70
|
+
const exact = normalized.find((path) => path === canonical);
|
|
71
|
+
if (exact) return exact;
|
|
72
|
+
const canonicalFolded = canonical.toLocaleLowerCase("en-US");
|
|
73
|
+
const folded = normalized.find((path) => path.toLocaleLowerCase("en-US") === canonicalFolded);
|
|
74
|
+
if (folded) return folded;
|
|
75
|
+
const prefix = `${normalizePath(layout.companionDirectory).replace(/\/$/, "")}/`;
|
|
76
|
+
const markdown = normalized.filter((path) => {
|
|
77
|
+
if (!path.toLocaleLowerCase("en-US").endsWith(".md")) return false;
|
|
78
|
+
if (!path.startsWith(prefix)) return false;
|
|
79
|
+
return !path.slice(prefix.length).includes("/");
|
|
80
|
+
});
|
|
81
|
+
return markdown.length === 1 ? markdown[0] : null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export {
|
|
85
|
+
OUTSIDE_IN_FORMAT_IDS,
|
|
86
|
+
resolveOutsideInLayout,
|
|
87
|
+
isOutsideInTargetPath,
|
|
88
|
+
chooseOutsideInMarkdownPath
|
|
89
|
+
};
|