@gentbajko/slopify 3.10.1 → 3.10.2
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/extension/slopify-studio-chrome.zip +0 -0
- package/dist/extension/slopify-studio-firefox.zip +0 -0
- package/dist/patch-notes/3.10.2.md +5 -0
- package/dist/patch-notes/index.json +6 -0
- package/dist/slices/rebuild/recipe-build.js +29 -0
- package/dist/slices/rebuild/recipe-edit.js +2 -1
- package/dist/slices/rebuild/recipe-save.js +1 -0
- package/dist/slices/rebuild/recipe-work.js +1 -0
- package/package.json +1 -1
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Slopify 3.10.2
|
|
2
|
+
|
|
3
|
+
Released 6 October 2026.
|
|
4
|
+
|
|
5
|
+
- **Writing the YouTube description again no longer remakes the video.** A video with chapter cards draws them from the description, so writing the description again (YouTube → Write again) used to render the whole video again. A finished video now keeps the description it was drawn from: only the description, tags, pinned comment and titles are written again. The video is still remade when something it shows changes (its images, narration, captions or edit settings), and then its chapter cards follow the current description.
|
|
@@ -20,7 +20,36 @@ function withLines(master, lines) {
|
|
|
20
20
|
? master
|
|
21
21
|
: { values: [...master.values, ...lines.values], keys: [...master.keys, ...lines.keys] };
|
|
22
22
|
}
|
|
23
|
+
// Every recipe of a version. A finished video whose only change is a description written again
|
|
24
|
+
// keeps the description its chapter cards were drawn from: the video is never remade for a new
|
|
25
|
+
// description, only when what it shows changes.
|
|
23
26
|
export function buildRecipes(context) {
|
|
27
|
+
const built = buildEach(context);
|
|
28
|
+
const video = built.find((value) => value.key === "export:video");
|
|
29
|
+
const rendered = new Set(context.manifest.pieces
|
|
30
|
+
.filter((one) => one.key === "export:video" && one.piece.state === "done")
|
|
31
|
+
.map((one) => one.fingerprint));
|
|
32
|
+
if (video === undefined || rendered.size === 0 || rendered.has(video.fingerprint))
|
|
33
|
+
return built;
|
|
34
|
+
if (!video.dependsOn.includes(descriptionKey))
|
|
35
|
+
return built;
|
|
36
|
+
const past = context.history ?? context.manifest;
|
|
37
|
+
const fingerprints = new Set(past.pieces.filter((one) => one.key === descriptionKey).map((one) => one.fingerprint));
|
|
38
|
+
const assets = new Set([
|
|
39
|
+
null,
|
|
40
|
+
...past.outputs.filter((one) => one.workKey === descriptionKey).map((one) => one.assetId),
|
|
41
|
+
...past.pieces.filter((one) => one.key === descriptionKey).map((one) => one.assetId),
|
|
42
|
+
]);
|
|
43
|
+
for (const described of fingerprints)
|
|
44
|
+
for (const asset of assets) {
|
|
45
|
+
const kept = buildEach({ ...context, pinnedChapters: [described, asset] }).find((value) => value.key === "export:video");
|
|
46
|
+
if (kept !== undefined && rendered.has(kept.fingerprint))
|
|
47
|
+
return built.map((value) => (value.key === "export:video" ? kept : value));
|
|
48
|
+
}
|
|
49
|
+
return built;
|
|
50
|
+
}
|
|
51
|
+
const descriptionKey = "youtube:description";
|
|
52
|
+
function buildEach(context) {
|
|
24
53
|
const text = textRecipes(context);
|
|
25
54
|
const audio = audioRecipes(context, text);
|
|
26
55
|
const exports = exportRecipes(context, audio);
|
|
@@ -49,7 +49,8 @@ export function editPlan(context, exports, youtube, images, cards = []) {
|
|
|
49
49
|
values.push(["timing", resourceIdentity(context, timing)]);
|
|
50
50
|
dependsOn.push(timing.key);
|
|
51
51
|
if (fromDescription && description !== undefined) {
|
|
52
|
-
|
|
52
|
+
// A finished video keeps the description it was drawn from (`recipe-build.ts`).
|
|
53
|
+
values.push(["chapters", context.pinnedChapters ?? resourceIdentity(context, description)]);
|
|
53
54
|
dependsOn.push(description.key);
|
|
54
55
|
}
|
|
55
56
|
else
|
|
@@ -83,6 +83,7 @@ export function planRevision(base, edit, prepared = { outputs: [], pieces: [] },
|
|
|
83
83
|
config: base.revision.config,
|
|
84
84
|
content: base.revision.content,
|
|
85
85
|
manifest,
|
|
86
|
+
history: { outputs: base.outputs, pieces: base.pieces },
|
|
86
87
|
resolved: {
|
|
87
88
|
articleMarkdown: base.articleMarkdown,
|
|
88
89
|
researchNotes: base.revision.config.provided.research ?? null,
|
|
@@ -30,6 +30,7 @@ export function planRevisionWork(revision, manifest, catalogue, availableAssetId
|
|
|
30
30
|
config: revision.config,
|
|
31
31
|
content: revision.content,
|
|
32
32
|
manifest: available,
|
|
33
|
+
history: manifest,
|
|
33
34
|
resolved: { ...resolved, articleMarkdown: usableArticle ? resolved.articleMarkdown : null },
|
|
34
35
|
};
|
|
35
36
|
const logical = buildRecipes(logicalContext);
|