@getguru/import-engine 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docx-import-cli.js +243 -11
- package/package.json +1 -1
package/docx-import-cli.js
CHANGED
|
@@ -98755,6 +98755,34 @@ var importType = typeArgIndex !== -1 ? process.argv[typeArgIndex + 1] : "";
|
|
|
98755
98755
|
var dom = new import_jsdom.JSDOM("", {
|
|
98756
98756
|
url: `http://localhost:8000/docx-import/index.html?type=${importType}&embed=`
|
|
98757
98757
|
});
|
|
98758
|
+
var UNUSED_INPUT_EVENTS = /* @__PURE__ */ new Set([
|
|
98759
|
+
"focus",
|
|
98760
|
+
"focusin",
|
|
98761
|
+
"keydown",
|
|
98762
|
+
"keyup",
|
|
98763
|
+
"mouseover",
|
|
98764
|
+
"mousedown",
|
|
98765
|
+
"mouseup",
|
|
98766
|
+
"click",
|
|
98767
|
+
"mouseout"
|
|
98768
|
+
]);
|
|
98769
|
+
var addWindowListener = dom.window.addEventListener;
|
|
98770
|
+
dom.window.addEventListener = function(type2, ...rest2) {
|
|
98771
|
+
if (UNUSED_INPUT_EVENTS.has(type2)) {
|
|
98772
|
+
return void 0;
|
|
98773
|
+
}
|
|
98774
|
+
return addWindowListener.call(this, type2, ...rest2);
|
|
98775
|
+
};
|
|
98776
|
+
var windowProperties = require("jsdom/lib/jsdom/living/window-properties.js");
|
|
98777
|
+
for (const hook of ["elementAttached", "elementDetached", "elementAttributeModified"]) {
|
|
98778
|
+
const track = windowProperties[hook];
|
|
98779
|
+
windowProperties[hook] = function(element, ...rest2) {
|
|
98780
|
+
if (!element._ownerDocument._defaultView) {
|
|
98781
|
+
return void 0;
|
|
98782
|
+
}
|
|
98783
|
+
return track.call(this, element, ...rest2);
|
|
98784
|
+
};
|
|
98785
|
+
}
|
|
98758
98786
|
var ALLOWED_GLOBALS = [
|
|
98759
98787
|
"window",
|
|
98760
98788
|
"document",
|
|
@@ -102636,6 +102664,52 @@ function markLinkRecorded(doc, link2) {
|
|
|
102636
102664
|
function isLinkRecorded(doc, link2) {
|
|
102637
102665
|
return !!doc.recordedLinks && doc.recordedLinks.has(link2);
|
|
102638
102666
|
}
|
|
102667
|
+
var RECORDED_LINK_ATTRIBUTE = "data-guru-import-recorded-link";
|
|
102668
|
+
function serializeDoctype(doctype) {
|
|
102669
|
+
if (!doctype) {
|
|
102670
|
+
return "";
|
|
102671
|
+
}
|
|
102672
|
+
const quote = (id) => id.includes('"') ? `'${id}'` : `"${id}"`;
|
|
102673
|
+
if (doctype.publicId) {
|
|
102674
|
+
return `<!DOCTYPE ${doctype.name} PUBLIC ${quote(doctype.publicId)}${doctype.systemId ? " " + quote(doctype.systemId) : ""}>`;
|
|
102675
|
+
}
|
|
102676
|
+
if (doctype.systemId) {
|
|
102677
|
+
return `<!DOCTYPE ${doctype.name} SYSTEM ${quote(doctype.systemId)}>`;
|
|
102678
|
+
}
|
|
102679
|
+
return `<!DOCTYPE ${doctype.name}>`;
|
|
102680
|
+
}
|
|
102681
|
+
function serializeDocTree(div, doc) {
|
|
102682
|
+
for (const element of div.querySelectorAll("pre, textarea, listing")) {
|
|
102683
|
+
const first2 = element.firstChild;
|
|
102684
|
+
if (first2 && first2.nodeType === 3 && first2.data.startsWith("\n")) {
|
|
102685
|
+
first2.data = "\n" + first2.data;
|
|
102686
|
+
}
|
|
102687
|
+
}
|
|
102688
|
+
if (doc.recordedLinks) {
|
|
102689
|
+
for (const element of div.querySelectorAll("*")) {
|
|
102690
|
+
if (doc.recordedLinks.has(element)) {
|
|
102691
|
+
element.setAttribute(RECORDED_LINK_ATTRIBUTE, "");
|
|
102692
|
+
}
|
|
102693
|
+
}
|
|
102694
|
+
}
|
|
102695
|
+
return flattenString(serializeDoctype(div.ownerDocument.doctype) + div.outerHTML);
|
|
102696
|
+
}
|
|
102697
|
+
function flattenString(string) {
|
|
102698
|
+
string.charCodeAt(0);
|
|
102699
|
+
return string;
|
|
102700
|
+
}
|
|
102701
|
+
function parseDocTree(source, doc) {
|
|
102702
|
+
const div = new DOMParser().parseFromString(source, "text/html").documentElement;
|
|
102703
|
+
const hadRecordedLinks = !!doc.recordedLinks;
|
|
102704
|
+
delete doc.recordedLinks;
|
|
102705
|
+
if (hadRecordedLinks) {
|
|
102706
|
+
for (const element of div.querySelectorAll(`[${RECORDED_LINK_ATTRIBUTE}]`)) {
|
|
102707
|
+
element.removeAttribute(RECORDED_LINK_ATTRIBUTE);
|
|
102708
|
+
markLinkRecorded(doc, element);
|
|
102709
|
+
}
|
|
102710
|
+
}
|
|
102711
|
+
return div;
|
|
102712
|
+
}
|
|
102639
102713
|
function safeDecode(string) {
|
|
102640
102714
|
try {
|
|
102641
102715
|
return decodeURIComponent(string);
|
|
@@ -111340,11 +111414,17 @@ function buildSlabPostSlugIndex(allDocs, zip) {
|
|
|
111340
111414
|
}
|
|
111341
111415
|
return index;
|
|
111342
111416
|
}
|
|
111417
|
+
function getSlabPostSlugIndex(zip, allDocs) {
|
|
111418
|
+
if (!zip.slabPostSlugIndex) {
|
|
111419
|
+
zip.slabPostSlugIndex = buildSlabPostSlugIndex(allDocs, zip);
|
|
111420
|
+
}
|
|
111421
|
+
return zip.slabPostSlugIndex;
|
|
111422
|
+
}
|
|
111343
111423
|
function resolveSlabPostLinks(div, doc, allDocs) {
|
|
111344
111424
|
if (!doc.zip?.isSlabExport) {
|
|
111345
111425
|
return;
|
|
111346
111426
|
}
|
|
111347
|
-
const index =
|
|
111427
|
+
const index = getSlabPostSlugIndex(doc.zip, allDocs);
|
|
111348
111428
|
Array.from(div.querySelectorAll("a[href]")).forEach((link2) => {
|
|
111349
111429
|
const href = link2.getAttribute("href");
|
|
111350
111430
|
if (!href || SLAB_TOPIC_URL_PATTERN.test(href)) {
|
|
@@ -114320,7 +114400,7 @@ var import_jszip5 = __toESM(require_lib3());
|
|
|
114320
114400
|
var import_url_join6 = __toESM(require_url_join());
|
|
114321
114401
|
|
|
114322
114402
|
// packages/import-engine/package.json
|
|
114323
|
-
var version = "0.1.
|
|
114403
|
+
var version = "0.1.3";
|
|
114324
114404
|
|
|
114325
114405
|
// src/docx-import/detectors.js
|
|
114326
114406
|
function isGoogleSitesDoc(div) {
|
|
@@ -114344,7 +114424,7 @@ var showError;
|
|
|
114344
114424
|
var updateLoader;
|
|
114345
114425
|
var showReport;
|
|
114346
114426
|
var docLinkIndex = /* @__PURE__ */ new Map();
|
|
114347
|
-
var toolVersion = true ? `${version}+${"
|
|
114427
|
+
var toolVersion = true ? `${version}+${"8671a17"}` : version;
|
|
114348
114428
|
var pendingUpload = null;
|
|
114349
114429
|
function confirmPendingUpload() {
|
|
114350
114430
|
const upload = pendingUpload;
|
|
@@ -114508,6 +114588,21 @@ async function processImage(doc, image2, imageIndex, newZip, resourceLookup = {}
|
|
|
114508
114588
|
}
|
|
114509
114589
|
});
|
|
114510
114590
|
}
|
|
114591
|
+
var resourceLookupSizes = /* @__PURE__ */ new WeakMap();
|
|
114592
|
+
function getResourceLookupSize(resourceLookup) {
|
|
114593
|
+
if (!resourceLookupSizes.has(resourceLookup)) {
|
|
114594
|
+
resourceLookupSizes.set(resourceLookup, Object.keys(resourceLookup).length);
|
|
114595
|
+
}
|
|
114596
|
+
return resourceLookupSizes.get(resourceLookup);
|
|
114597
|
+
}
|
|
114598
|
+
function addToResourceLookup(resourceLookup, unsafeResourceName, safeResourceName) {
|
|
114599
|
+
const size2 = getResourceLookupSize(resourceLookup);
|
|
114600
|
+
const isNewKey = !Object.hasOwn(resourceLookup, unsafeResourceName);
|
|
114601
|
+
resourceLookup[unsafeResourceName] = safeResourceName;
|
|
114602
|
+
if (isNewKey && Object.hasOwn(resourceLookup, unsafeResourceName)) {
|
|
114603
|
+
resourceLookupSizes.set(resourceLookup, size2 + 1);
|
|
114604
|
+
}
|
|
114605
|
+
}
|
|
114511
114606
|
async function resolveResource(element, doc, newZip, resourceLookup = {}) {
|
|
114512
114607
|
return new Promise(async function(resolve, reject2) {
|
|
114513
114608
|
try {
|
|
@@ -114536,10 +114631,10 @@ async function resolveResource(element, doc, newZip, resourceLookup = {}) {
|
|
|
114536
114631
|
} else {
|
|
114537
114632
|
safeResourceName = sanitizeFilename(unsafeResourceName);
|
|
114538
114633
|
if (safeResourceName !== unsafeResourceName) {
|
|
114539
|
-
const nextIndex =
|
|
114634
|
+
const nextIndex = getResourceLookupSize(resourceLookup);
|
|
114540
114635
|
safeResourceName = `file${nextIndex}_${safeResourceName}`;
|
|
114541
114636
|
}
|
|
114542
|
-
resourceLookup
|
|
114637
|
+
addToResourceLookup(resourceLookup, unsafeResourceName, safeResourceName);
|
|
114543
114638
|
}
|
|
114544
114639
|
const resourcePath = "resources/" + safeResourceName;
|
|
114545
114640
|
const fileData = await (import_jszip5.default.support.uint8array ? file.async("uint8array") : file.async("base64"));
|
|
@@ -114774,7 +114869,7 @@ async function preProcessDoc(doc, docTitleLookup = {}) {
|
|
|
114774
114869
|
doc.zip.source = source;
|
|
114775
114870
|
}
|
|
114776
114871
|
}
|
|
114777
|
-
doc.
|
|
114872
|
+
doc.htmlSource = serializeDocTree(div, doc);
|
|
114778
114873
|
updateLoader({
|
|
114779
114874
|
step: 1,
|
|
114780
114875
|
docIndex: doc.index,
|
|
@@ -114805,7 +114900,8 @@ async function postProcessDoc(newZip, doc, resourceLookup = {}, externalLookup =
|
|
|
114805
114900
|
writeCardToZip(newZip, doc, "");
|
|
114806
114901
|
return;
|
|
114807
114902
|
}
|
|
114808
|
-
const div = doc.
|
|
114903
|
+
const div = parseDocTree(doc.htmlSource, doc);
|
|
114904
|
+
delete doc.htmlSource;
|
|
114809
114905
|
updateLoader({
|
|
114810
114906
|
step: 1,
|
|
114811
114907
|
docIndex: doc.index,
|
|
@@ -114874,6 +114970,14 @@ async function postProcessDoc(newZip, doc, resourceLookup = {}, externalLookup =
|
|
|
114874
114970
|
}
|
|
114875
114971
|
writeCardToZip(newZip, doc, cleanUpHtml(div, doc));
|
|
114876
114972
|
}
|
|
114973
|
+
function releaseDocContent(doc, buffersReadFromZip) {
|
|
114974
|
+
delete doc.htmlSource;
|
|
114975
|
+
delete doc.originalContent;
|
|
114976
|
+
delete doc.recordedLinks;
|
|
114977
|
+
if (buffersReadFromZip.has(doc)) {
|
|
114978
|
+
delete doc.buffer;
|
|
114979
|
+
}
|
|
114980
|
+
}
|
|
114877
114981
|
function makeErrorHandler(progress) {
|
|
114878
114982
|
return function handleError(event) {
|
|
114879
114983
|
const message = event.reason?.message || event.message || event.error?.message || "Unknown error";
|
|
@@ -114957,6 +115061,7 @@ async function runProcessDocs(params, progress) {
|
|
|
114957
115061
|
zipToCheck.docxAnchorIndex = buildDocxAnchorIndex(docs, zipToCheck);
|
|
114958
115062
|
}
|
|
114959
115063
|
}
|
|
115064
|
+
const buffersReadFromZip = /* @__PURE__ */ new WeakSet();
|
|
114960
115065
|
await doAll(docs, async function(doc, docIndex, nextDoc) {
|
|
114961
115066
|
doc.index = docIndex;
|
|
114962
115067
|
try {
|
|
@@ -114965,6 +115070,7 @@ async function runProcessDocs(params, progress) {
|
|
|
114965
115070
|
} else if (doc.zip) {
|
|
114966
115071
|
const buffer = await doc.zip.file(doc.filename).async("arraybuffer");
|
|
114967
115072
|
doc.buffer = buffer;
|
|
115073
|
+
buffersReadFromZip.add(doc);
|
|
114968
115074
|
await preProcessDoc(doc, docTitleLookup);
|
|
114969
115075
|
} else {
|
|
114970
115076
|
await preProcessDoc(doc);
|
|
@@ -114972,6 +115078,7 @@ async function runProcessDocs(params, progress) {
|
|
|
114972
115078
|
} catch (err) {
|
|
114973
115079
|
recordFailure(doc, err);
|
|
114974
115080
|
} finally {
|
|
115081
|
+
delete doc.div;
|
|
114975
115082
|
nextDoc();
|
|
114976
115083
|
}
|
|
114977
115084
|
});
|
|
@@ -114981,6 +115088,9 @@ async function runProcessDocs(params, progress) {
|
|
|
114981
115088
|
if (zipToCheck.source === "confluence") {
|
|
114982
115089
|
zipToCheck.confluencePageIndex = buildConfluencePageIndex(docs, zipToCheck);
|
|
114983
115090
|
}
|
|
115091
|
+
if (zipToCheck.isSlabExport) {
|
|
115092
|
+
zipToCheck.slabPostSlugIndex = buildSlabPostSlugIndex(docs, zipToCheck);
|
|
115093
|
+
}
|
|
114984
115094
|
}
|
|
114985
115095
|
await doAll(docs, async function(doc, docIndex, nextDoc) {
|
|
114986
115096
|
try {
|
|
@@ -114988,6 +115098,7 @@ async function runProcessDocs(params, progress) {
|
|
|
114988
115098
|
} catch (err) {
|
|
114989
115099
|
recordFailure(doc, err);
|
|
114990
115100
|
} finally {
|
|
115101
|
+
releaseDocContent(doc, buffersReadFromZip);
|
|
114991
115102
|
nextDoc();
|
|
114992
115103
|
}
|
|
114993
115104
|
});
|
|
@@ -115155,6 +115266,91 @@ function setSubtract(a, b) {
|
|
|
115155
115266
|
return !b.includes(value);
|
|
115156
115267
|
});
|
|
115157
115268
|
}
|
|
115269
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
115270
|
+
var EXTERNAL_MANIFEST_MAX_BYTES = 1048576;
|
|
115271
|
+
var EXTERNAL_MAX_ENTRIES = 500;
|
|
115272
|
+
var EXTERNAL_NAME_RE = /^[\p{L}\p{N}._-]{1,128}$/u;
|
|
115273
|
+
var EXTERNAL_REFUSED = "the server won't fetch this image; the card will link to the original URL";
|
|
115274
|
+
function checkExternalImages(zip, task, report) {
|
|
115275
|
+
var state = { enabled: false, names: /* @__PURE__ */ new Set(), referenced: [] };
|
|
115276
|
+
report.externalImages = state;
|
|
115277
|
+
var collectionFile = zip.file("collection.yaml");
|
|
115278
|
+
var manifestFile = zip.file("resources/external.json");
|
|
115279
|
+
function readCollection() {
|
|
115280
|
+
if (!collectionFile) {
|
|
115281
|
+
return Promise.resolve();
|
|
115282
|
+
}
|
|
115283
|
+
return collectionFile.async("string").then(function(yamlString) {
|
|
115284
|
+
try {
|
|
115285
|
+
var collection = yaml.load(yamlString);
|
|
115286
|
+
state.enabled = !!collection && typeof collection == "object" && collection.FetchExternalImages === true;
|
|
115287
|
+
} catch (e) {
|
|
115288
|
+
}
|
|
115289
|
+
}, function() {
|
|
115290
|
+
});
|
|
115291
|
+
}
|
|
115292
|
+
function readManifest() {
|
|
115293
|
+
if (!manifestFile) {
|
|
115294
|
+
return Promise.resolve();
|
|
115295
|
+
}
|
|
115296
|
+
return manifestFile.async("string").then(function(text2) {
|
|
115297
|
+
var size2 = manifestFile._data && manifestFile._data.uncompressedSize || text2.length;
|
|
115298
|
+
var dropped = "The server will ignore the whole manifest, so no external images will be fetched";
|
|
115299
|
+
if (size2 > EXTERNAL_MANIFEST_MAX_BYTES) {
|
|
115300
|
+
report.error(`resources/external.json is larger than ${EXTERNAL_MANIFEST_MAX_BYTES} bytes. ${dropped}.`);
|
|
115301
|
+
return;
|
|
115302
|
+
}
|
|
115303
|
+
var manifest;
|
|
115304
|
+
try {
|
|
115305
|
+
manifest = JSON.parse(text2);
|
|
115306
|
+
} catch (e) {
|
|
115307
|
+
report.error(`resources/external.json is not valid JSON (${e.message}). ${dropped}.`);
|
|
115308
|
+
return;
|
|
115309
|
+
}
|
|
115310
|
+
if (!manifest || typeof manifest != "object" || Array.isArray(manifest)) {
|
|
115311
|
+
report.error(`resources/external.json must be a JSON object mapping file names to URLs. ${dropped}.`);
|
|
115312
|
+
return;
|
|
115313
|
+
}
|
|
115314
|
+
var keys2 = Object.keys(manifest);
|
|
115315
|
+
if (keys2.some(function(key) {
|
|
115316
|
+
return typeof manifest[key] != "string";
|
|
115317
|
+
})) {
|
|
115318
|
+
report.error(`resources/external.json must map every file name to a URL string. ${dropped}.`);
|
|
115319
|
+
return;
|
|
115320
|
+
}
|
|
115321
|
+
keys2.forEach(function(name, index) {
|
|
115322
|
+
state.names.add(name);
|
|
115323
|
+
var url = manifest[name];
|
|
115324
|
+
var label = `resources/external.json entry "${escapeQuotes(name)}"`;
|
|
115325
|
+
if (index >= EXTERNAL_MAX_ENTRIES) {
|
|
115326
|
+
report.warn(`${label} is past the first ${EXTERNAL_MAX_ENTRIES} entries: ${EXTERNAL_REFUSED}.`);
|
|
115327
|
+
} else if (!EXTERNAL_NAME_RE.test(name) || name.includes("..")) {
|
|
115328
|
+
report.warn(`${label} has an invalid file name: ${EXTERNAL_REFUSED}.`);
|
|
115329
|
+
} else if (url.trim() === "") {
|
|
115330
|
+
report.warn(`${label} has a blank URL: ${EXTERNAL_REFUSED}.`);
|
|
115331
|
+
} else if (!/^https:\/\//i.test(url.trim())) {
|
|
115332
|
+
report.warn(`${label} is not an https URL: ${EXTERNAL_REFUSED}.`);
|
|
115333
|
+
}
|
|
115334
|
+
if (zip.file("resources/" + name)) {
|
|
115335
|
+
report.info(`${label} also exists as resources/${escapeQuotes(name)} in the zip, so the server skips the fetch.`);
|
|
115336
|
+
}
|
|
115337
|
+
});
|
|
115338
|
+
}, function() {
|
|
115339
|
+
});
|
|
115340
|
+
}
|
|
115341
|
+
return readCollection().then(readManifest).then(function() {
|
|
115342
|
+
if (manifestFile && !state.enabled) {
|
|
115343
|
+
report.warn(`resources/external.json is included but collection.yaml doesn't set FetchExternalImages: true, so the server ignores it.`);
|
|
115344
|
+
}
|
|
115345
|
+
if (state.enabled && !manifestFile) {
|
|
115346
|
+
report.warn(`collection.yaml sets FetchExternalImages: true but the zip has no resources/external.json.`);
|
|
115347
|
+
}
|
|
115348
|
+
if (state.enabled) {
|
|
115349
|
+
report.syncError(`If this is a sync, FetchExternalImages is ignored (external images are only fetched on imports).`);
|
|
115350
|
+
}
|
|
115351
|
+
report.next();
|
|
115352
|
+
});
|
|
115353
|
+
}
|
|
115158
115354
|
function escapeQuotes(value) {
|
|
115159
115355
|
value = value || "";
|
|
115160
115356
|
return value.replace(/"/g, `\\"`);
|
|
@@ -115189,11 +115385,18 @@ function checkCardYaml(zip, task, report) {
|
|
|
115189
115385
|
return zip.file(task.filename).async("string").then(function(yamlString) {
|
|
115190
115386
|
try {
|
|
115191
115387
|
var card = yaml.load(yamlString);
|
|
115192
|
-
var possibleKeys = ["ExternalId", "ExternalUrl", "Title", "Tags", "externalLastUpdated"];
|
|
115388
|
+
var possibleKeys = ["ExternalId", "ExternalUrl", "Title", "Tags", "externalLastUpdated", "ID"];
|
|
115193
115389
|
var otherKeys = setSubtract(Object.keys(card), possibleKeys);
|
|
115194
115390
|
otherKeys.forEach(function(key) {
|
|
115195
115391
|
report.warn(`Unexpected property "${key}" in the card's yaml.`);
|
|
115196
115392
|
});
|
|
115393
|
+
if (card.ID !== void 0 && card.ID !== null) {
|
|
115394
|
+
if (typeof card.ID != "string" || !UUID_RE2.test(card.ID)) {
|
|
115395
|
+
report.error(`The card's ID property must be a UUID string (e.g. ID: "123e4567-e89b-12d3-a456-426614174000"), but it was: ${escapeHtml3(String(card.ID))}`);
|
|
115396
|
+
} else {
|
|
115397
|
+
report.info(`The card has an ID, so it updates the existing card with that ID in the same collection if one exists, otherwise a new card is created.`);
|
|
115398
|
+
}
|
|
115399
|
+
}
|
|
115197
115400
|
if (!card.Title) {
|
|
115198
115401
|
report.error(`A "Title" property is required in the card's yaml.`);
|
|
115199
115402
|
} else {
|
|
@@ -115258,7 +115461,17 @@ function checkCardHtml(zip, task, report) {
|
|
|
115258
115461
|
report.resourceReferences.push(reference2);
|
|
115259
115462
|
}
|
|
115260
115463
|
} else {
|
|
115261
|
-
report.
|
|
115464
|
+
var ext = report.externalImages || { enabled: false, names: /* @__PURE__ */ new Set(), referenced: [] };
|
|
115465
|
+
var extName = reference2.slice("resources/".length);
|
|
115466
|
+
if (ext.names.has(extName) && ext.enabled) {
|
|
115467
|
+
if (!ext.referenced.includes(extName)) {
|
|
115468
|
+
ext.referenced.push(extName);
|
|
115469
|
+
}
|
|
115470
|
+
} else if (ext.names.has(extName)) {
|
|
115471
|
+
report.error(`The referenced resource "${reference2}" is listed in resources/external.json but collection.yaml doesn't set FetchExternalImages: true, so it won't be fetched.`);
|
|
115472
|
+
} else {
|
|
115473
|
+
report.error(`The referenced resource "${reference2}" does not exist in the zip.`);
|
|
115474
|
+
}
|
|
115262
115475
|
}
|
|
115263
115476
|
} else if (reference2.startsWith("cards/")) {
|
|
115264
115477
|
if (zip.file(reference2 + ".yaml")) {
|
|
@@ -115515,7 +115728,7 @@ function checkCollectionYaml(zip, task, report) {
|
|
|
115515
115728
|
}
|
|
115516
115729
|
try {
|
|
115517
115730
|
var collection = yaml.load(yamlString);
|
|
115518
|
-
var possibleKeys = ["Items", "Tags", "Title", "Version"];
|
|
115731
|
+
var possibleKeys = ["Items", "Tags", "Title", "Version", "FetchExternalImages", "ReuseFolders"];
|
|
115519
115732
|
var otherKeys = setSubtract(Object.keys(collection), possibleKeys);
|
|
115520
115733
|
otherKeys.forEach(function(key) {
|
|
115521
115734
|
report.warn(`Unexpected property "${key}" in collection.yaml.`);
|
|
@@ -115532,6 +115745,14 @@ function checkCollectionYaml(zip, task, report) {
|
|
|
115532
115745
|
}
|
|
115533
115746
|
}
|
|
115534
115747
|
var isV2 = collection.Version == 2;
|
|
115748
|
+
["FetchExternalImages", "ReuseFolders"].forEach(function(key) {
|
|
115749
|
+
if (collection[key] !== void 0 && collection[key] !== null && typeof collection[key] != "boolean") {
|
|
115750
|
+
report.warn(`The collection's ${key} property must be true or false (${key} = ${escapeHtml3(String(collection[key]))}).`);
|
|
115751
|
+
}
|
|
115752
|
+
});
|
|
115753
|
+
if (collection.ReuseFolders === true && !isV2) {
|
|
115754
|
+
report.warn(`ReuseFolders is ignored unless the collection has "Version: 2" (it applies only to Version 2 non-sync imports).`);
|
|
115755
|
+
}
|
|
115535
115756
|
if (collection.Items) {
|
|
115536
115757
|
if (!Array.isArray(collection.Items)) {
|
|
115537
115758
|
report.error(`The collection's Items list is optional, but if provided it must be a list.`);
|
|
@@ -115635,7 +115856,16 @@ function checkResource(zip, task, report) {
|
|
|
115635
115856
|
} else {
|
|
115636
115857
|
report.resources += 1;
|
|
115637
115858
|
}
|
|
115638
|
-
if (
|
|
115859
|
+
if (task.filename == "resources/external.json") {
|
|
115860
|
+
var ext = report.externalImages;
|
|
115861
|
+
if (ext) {
|
|
115862
|
+
ext.names.forEach(function(name) {
|
|
115863
|
+
if (!ext.referenced.includes(name) && !report.resourceReferences.includes("resources/" + name)) {
|
|
115864
|
+
report.warn(`resources/external.json entry "${escapeQuotes(name)}" isn't referenced by any cards.`);
|
|
115865
|
+
}
|
|
115866
|
+
});
|
|
115867
|
+
}
|
|
115868
|
+
} else if (!report.resourceReferences.includes(task.filename)) {
|
|
115639
115869
|
report.warn(`Resource ${task.filename} is included in the zip but isn't referenced by any cards.`);
|
|
115640
115870
|
}
|
|
115641
115871
|
if (zip.file(task.filename)._data.uncompressedSize > 2e9) {
|
|
@@ -115732,6 +115962,7 @@ function checkZip(zip) {
|
|
|
115732
115962
|
collectionRoots: [],
|
|
115733
115963
|
tags: [],
|
|
115734
115964
|
resourceReferences: [],
|
|
115965
|
+
externalImages: { enabled: false, names: /* @__PURE__ */ new Set(), referenced: [] },
|
|
115735
115966
|
cardLinks: 0,
|
|
115736
115967
|
boardLinks: 0,
|
|
115737
115968
|
checkCount: 0,
|
|
@@ -115805,6 +116036,7 @@ function checkZip(zip) {
|
|
|
115805
116036
|
info(`Unexpected file ${fullPath}`);
|
|
115806
116037
|
}
|
|
115807
116038
|
}
|
|
116039
|
+
tasks.push({ func: checkExternalImages, context: "resources/external.json", checks: 3, priority: 0 });
|
|
115808
116040
|
tasks.push({ func: checkFolderTree, checks: 5, priority: 6 });
|
|
115809
116041
|
tasks.push({ func: checkStats, checks: 3, priority: 10 });
|
|
115810
116042
|
tasks.sort(function(a, b) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getguru/import-engine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Command-line engine that turns Notion, Confluence, Google, Word, PDF, Markdown and spreadsheet exports into Guru import zips.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"guru-import-engine": "docx-import-cli.js"
|