@getguru/import-engine 0.1.0 → 0.1.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/README.md +1 -1
- package/docx-import-cli.js +132 -13
- package/package.json +4 -4
package/README.md
CHANGED
package/docx-import-cli.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
2
|
var __create = Object.create;
|
|
4
3
|
var __defProp = Object.defineProperty;
|
|
5
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -114321,7 +114320,7 @@ var import_jszip5 = __toESM(require_lib3());
|
|
|
114321
114320
|
var import_url_join6 = __toESM(require_url_join());
|
|
114322
114321
|
|
|
114323
114322
|
// packages/import-engine/package.json
|
|
114324
|
-
var version = "0.1.
|
|
114323
|
+
var version = "0.1.2";
|
|
114325
114324
|
|
|
114326
114325
|
// src/docx-import/detectors.js
|
|
114327
114326
|
function isGoogleSitesDoc(div) {
|
|
@@ -114345,7 +114344,7 @@ var showError;
|
|
|
114345
114344
|
var updateLoader;
|
|
114346
114345
|
var showReport;
|
|
114347
114346
|
var docLinkIndex = /* @__PURE__ */ new Map();
|
|
114348
|
-
var toolVersion = true ? `${version}+${"
|
|
114347
|
+
var toolVersion = true ? `${version}+${"4d61d22"}` : version;
|
|
114349
114348
|
var pendingUpload = null;
|
|
114350
114349
|
function confirmPendingUpload() {
|
|
114351
114350
|
const upload = pendingUpload;
|
|
@@ -115156,6 +115155,91 @@ function setSubtract(a, b) {
|
|
|
115156
115155
|
return !b.includes(value);
|
|
115157
115156
|
});
|
|
115158
115157
|
}
|
|
115158
|
+
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
115159
|
+
var EXTERNAL_MANIFEST_MAX_BYTES = 1048576;
|
|
115160
|
+
var EXTERNAL_MAX_ENTRIES = 500;
|
|
115161
|
+
var EXTERNAL_NAME_RE = /^[\p{L}\p{N}._-]{1,128}$/u;
|
|
115162
|
+
var EXTERNAL_REFUSED = "the server won't fetch this image; the card will link to the original URL";
|
|
115163
|
+
function checkExternalImages(zip, task, report) {
|
|
115164
|
+
var state = { enabled: false, names: /* @__PURE__ */ new Set(), referenced: [] };
|
|
115165
|
+
report.externalImages = state;
|
|
115166
|
+
var collectionFile = zip.file("collection.yaml");
|
|
115167
|
+
var manifestFile = zip.file("resources/external.json");
|
|
115168
|
+
function readCollection() {
|
|
115169
|
+
if (!collectionFile) {
|
|
115170
|
+
return Promise.resolve();
|
|
115171
|
+
}
|
|
115172
|
+
return collectionFile.async("string").then(function(yamlString) {
|
|
115173
|
+
try {
|
|
115174
|
+
var collection = yaml.load(yamlString);
|
|
115175
|
+
state.enabled = !!collection && typeof collection == "object" && collection.FetchExternalImages === true;
|
|
115176
|
+
} catch (e) {
|
|
115177
|
+
}
|
|
115178
|
+
}, function() {
|
|
115179
|
+
});
|
|
115180
|
+
}
|
|
115181
|
+
function readManifest() {
|
|
115182
|
+
if (!manifestFile) {
|
|
115183
|
+
return Promise.resolve();
|
|
115184
|
+
}
|
|
115185
|
+
return manifestFile.async("string").then(function(text2) {
|
|
115186
|
+
var size2 = manifestFile._data && manifestFile._data.uncompressedSize || text2.length;
|
|
115187
|
+
var dropped = "The server will ignore the whole manifest, so no external images will be fetched";
|
|
115188
|
+
if (size2 > EXTERNAL_MANIFEST_MAX_BYTES) {
|
|
115189
|
+
report.error(`resources/external.json is larger than ${EXTERNAL_MANIFEST_MAX_BYTES} bytes. ${dropped}.`);
|
|
115190
|
+
return;
|
|
115191
|
+
}
|
|
115192
|
+
var manifest;
|
|
115193
|
+
try {
|
|
115194
|
+
manifest = JSON.parse(text2);
|
|
115195
|
+
} catch (e) {
|
|
115196
|
+
report.error(`resources/external.json is not valid JSON (${e.message}). ${dropped}.`);
|
|
115197
|
+
return;
|
|
115198
|
+
}
|
|
115199
|
+
if (!manifest || typeof manifest != "object" || Array.isArray(manifest)) {
|
|
115200
|
+
report.error(`resources/external.json must be a JSON object mapping file names to URLs. ${dropped}.`);
|
|
115201
|
+
return;
|
|
115202
|
+
}
|
|
115203
|
+
var keys2 = Object.keys(manifest);
|
|
115204
|
+
if (keys2.some(function(key) {
|
|
115205
|
+
return typeof manifest[key] != "string";
|
|
115206
|
+
})) {
|
|
115207
|
+
report.error(`resources/external.json must map every file name to a URL string. ${dropped}.`);
|
|
115208
|
+
return;
|
|
115209
|
+
}
|
|
115210
|
+
keys2.forEach(function(name, index) {
|
|
115211
|
+
state.names.add(name);
|
|
115212
|
+
var url = manifest[name];
|
|
115213
|
+
var label = `resources/external.json entry "${escapeQuotes(name)}"`;
|
|
115214
|
+
if (index >= EXTERNAL_MAX_ENTRIES) {
|
|
115215
|
+
report.warn(`${label} is past the first ${EXTERNAL_MAX_ENTRIES} entries: ${EXTERNAL_REFUSED}.`);
|
|
115216
|
+
} else if (!EXTERNAL_NAME_RE.test(name) || name.includes("..")) {
|
|
115217
|
+
report.warn(`${label} has an invalid file name: ${EXTERNAL_REFUSED}.`);
|
|
115218
|
+
} else if (url.trim() === "") {
|
|
115219
|
+
report.warn(`${label} has a blank URL: ${EXTERNAL_REFUSED}.`);
|
|
115220
|
+
} else if (!/^https:\/\//i.test(url.trim())) {
|
|
115221
|
+
report.warn(`${label} is not an https URL: ${EXTERNAL_REFUSED}.`);
|
|
115222
|
+
}
|
|
115223
|
+
if (zip.file("resources/" + name)) {
|
|
115224
|
+
report.info(`${label} also exists as resources/${escapeQuotes(name)} in the zip, so the server skips the fetch.`);
|
|
115225
|
+
}
|
|
115226
|
+
});
|
|
115227
|
+
}, function() {
|
|
115228
|
+
});
|
|
115229
|
+
}
|
|
115230
|
+
return readCollection().then(readManifest).then(function() {
|
|
115231
|
+
if (manifestFile && !state.enabled) {
|
|
115232
|
+
report.warn(`resources/external.json is included but collection.yaml doesn't set FetchExternalImages: true, so the server ignores it.`);
|
|
115233
|
+
}
|
|
115234
|
+
if (state.enabled && !manifestFile) {
|
|
115235
|
+
report.warn(`collection.yaml sets FetchExternalImages: true but the zip has no resources/external.json.`);
|
|
115236
|
+
}
|
|
115237
|
+
if (state.enabled) {
|
|
115238
|
+
report.syncError(`If this is a sync, FetchExternalImages is ignored (external images are only fetched on imports).`);
|
|
115239
|
+
}
|
|
115240
|
+
report.next();
|
|
115241
|
+
});
|
|
115242
|
+
}
|
|
115159
115243
|
function escapeQuotes(value) {
|
|
115160
115244
|
value = value || "";
|
|
115161
115245
|
return value.replace(/"/g, `\\"`);
|
|
@@ -115190,11 +115274,18 @@ function checkCardYaml(zip, task, report) {
|
|
|
115190
115274
|
return zip.file(task.filename).async("string").then(function(yamlString) {
|
|
115191
115275
|
try {
|
|
115192
115276
|
var card = yaml.load(yamlString);
|
|
115193
|
-
var possibleKeys = ["ExternalId", "ExternalUrl", "Title", "Tags", "externalLastUpdated"];
|
|
115277
|
+
var possibleKeys = ["ExternalId", "ExternalUrl", "Title", "Tags", "externalLastUpdated", "ID"];
|
|
115194
115278
|
var otherKeys = setSubtract(Object.keys(card), possibleKeys);
|
|
115195
115279
|
otherKeys.forEach(function(key) {
|
|
115196
115280
|
report.warn(`Unexpected property "${key}" in the card's yaml.`);
|
|
115197
115281
|
});
|
|
115282
|
+
if (card.ID !== void 0 && card.ID !== null) {
|
|
115283
|
+
if (typeof card.ID != "string" || !UUID_RE2.test(card.ID)) {
|
|
115284
|
+
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))}`);
|
|
115285
|
+
} else {
|
|
115286
|
+
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.`);
|
|
115287
|
+
}
|
|
115288
|
+
}
|
|
115198
115289
|
if (!card.Title) {
|
|
115199
115290
|
report.error(`A "Title" property is required in the card's yaml.`);
|
|
115200
115291
|
} else {
|
|
@@ -115259,7 +115350,17 @@ function checkCardHtml(zip, task, report) {
|
|
|
115259
115350
|
report.resourceReferences.push(reference2);
|
|
115260
115351
|
}
|
|
115261
115352
|
} else {
|
|
115262
|
-
report.
|
|
115353
|
+
var ext = report.externalImages || { enabled: false, names: /* @__PURE__ */ new Set(), referenced: [] };
|
|
115354
|
+
var extName = reference2.slice("resources/".length);
|
|
115355
|
+
if (ext.names.has(extName) && ext.enabled) {
|
|
115356
|
+
if (!ext.referenced.includes(extName)) {
|
|
115357
|
+
ext.referenced.push(extName);
|
|
115358
|
+
}
|
|
115359
|
+
} else if (ext.names.has(extName)) {
|
|
115360
|
+
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.`);
|
|
115361
|
+
} else {
|
|
115362
|
+
report.error(`The referenced resource "${reference2}" does not exist in the zip.`);
|
|
115363
|
+
}
|
|
115263
115364
|
}
|
|
115264
115365
|
} else if (reference2.startsWith("cards/")) {
|
|
115265
115366
|
if (zip.file(reference2 + ".yaml")) {
|
|
@@ -115342,7 +115443,7 @@ function checkBoardYaml(zip, task, report) {
|
|
|
115342
115443
|
}
|
|
115343
115444
|
}
|
|
115344
115445
|
if (board.Items) {
|
|
115345
|
-
let
|
|
115446
|
+
let checkCard = function(card) {
|
|
115346
115447
|
var possibleKeys = ["Type", "ID"];
|
|
115347
115448
|
var otherKeys = setSubtract(Object.keys(card), possibleKeys);
|
|
115348
115449
|
otherKeys.forEach(function(key) {
|
|
@@ -115358,7 +115459,7 @@ function checkBoardYaml(zip, task, report) {
|
|
|
115358
115459
|
if (!zip.files[`cards/${card.ID}.yaml`]) {
|
|
115359
115460
|
report.error(`This board references a card (ID = "${card.ID}") that does not seem to exist in this zip, we expect cards/${card.ID}.yaml would also exist.`);
|
|
115360
115461
|
}
|
|
115361
|
-
},
|
|
115462
|
+
}, checkSection = function(section) {
|
|
115362
115463
|
var possibleKeys = ["Type", "Items", "Title"];
|
|
115363
115464
|
var otherKeys = setSubtract(Object.keys(section), possibleKeys);
|
|
115364
115465
|
otherKeys.forEach(function(key) {
|
|
@@ -115377,13 +115478,12 @@ function checkBoardYaml(zip, task, report) {
|
|
|
115377
115478
|
} else if (item.Type != "card") {
|
|
115378
115479
|
report.error(`Section items must have Type = "card" but one has Type = "${item.Type}".`);
|
|
115379
115480
|
} else {
|
|
115380
|
-
|
|
115481
|
+
checkCard(item);
|
|
115381
115482
|
}
|
|
115382
115483
|
});
|
|
115383
115484
|
}
|
|
115384
115485
|
}
|
|
115385
115486
|
};
|
|
115386
|
-
var checkCard = checkCard2, checkSection = checkSection2;
|
|
115387
115487
|
var cardIds = [];
|
|
115388
115488
|
if (!Array.isArray(board.Items)) {
|
|
115389
115489
|
report.error(`The board's Items property is optional, but if it's provided it must be a list of objects.`);
|
|
@@ -115397,9 +115497,9 @@ function checkBoardYaml(zip, task, report) {
|
|
|
115397
115497
|
report.error(`Every item on the board needs a "Type" property.`);
|
|
115398
115498
|
} else {
|
|
115399
115499
|
if (item.Type == "card") {
|
|
115400
|
-
|
|
115500
|
+
checkCard(item);
|
|
115401
115501
|
} else if (item.Type == "section") {
|
|
115402
|
-
|
|
115502
|
+
checkSection(item);
|
|
115403
115503
|
} else {
|
|
115404
115504
|
report.error(`A board item has an unexpected Type value, we expect either "card" or "section" but got "${item.Type}" instead.`);
|
|
115405
115505
|
}
|
|
@@ -115517,7 +115617,7 @@ function checkCollectionYaml(zip, task, report) {
|
|
|
115517
115617
|
}
|
|
115518
115618
|
try {
|
|
115519
115619
|
var collection = yaml.load(yamlString);
|
|
115520
|
-
var possibleKeys = ["Items", "Tags", "Title", "Version"];
|
|
115620
|
+
var possibleKeys = ["Items", "Tags", "Title", "Version", "FetchExternalImages", "ReuseFolders"];
|
|
115521
115621
|
var otherKeys = setSubtract(Object.keys(collection), possibleKeys);
|
|
115522
115622
|
otherKeys.forEach(function(key) {
|
|
115523
115623
|
report.warn(`Unexpected property "${key}" in collection.yaml.`);
|
|
@@ -115534,6 +115634,14 @@ function checkCollectionYaml(zip, task, report) {
|
|
|
115534
115634
|
}
|
|
115535
115635
|
}
|
|
115536
115636
|
var isV2 = collection.Version == 2;
|
|
115637
|
+
["FetchExternalImages", "ReuseFolders"].forEach(function(key) {
|
|
115638
|
+
if (collection[key] !== void 0 && collection[key] !== null && typeof collection[key] != "boolean") {
|
|
115639
|
+
report.warn(`The collection's ${key} property must be true or false (${key} = ${escapeHtml3(String(collection[key]))}).`);
|
|
115640
|
+
}
|
|
115641
|
+
});
|
|
115642
|
+
if (collection.ReuseFolders === true && !isV2) {
|
|
115643
|
+
report.warn(`ReuseFolders is ignored unless the collection has "Version: 2" (it applies only to Version 2 non-sync imports).`);
|
|
115644
|
+
}
|
|
115537
115645
|
if (collection.Items) {
|
|
115538
115646
|
if (!Array.isArray(collection.Items)) {
|
|
115539
115647
|
report.error(`The collection's Items list is optional, but if provided it must be a list.`);
|
|
@@ -115637,7 +115745,16 @@ function checkResource(zip, task, report) {
|
|
|
115637
115745
|
} else {
|
|
115638
115746
|
report.resources += 1;
|
|
115639
115747
|
}
|
|
115640
|
-
if (
|
|
115748
|
+
if (task.filename == "resources/external.json") {
|
|
115749
|
+
var ext = report.externalImages;
|
|
115750
|
+
if (ext) {
|
|
115751
|
+
ext.names.forEach(function(name) {
|
|
115752
|
+
if (!ext.referenced.includes(name) && !report.resourceReferences.includes("resources/" + name)) {
|
|
115753
|
+
report.warn(`resources/external.json entry "${escapeQuotes(name)}" isn't referenced by any cards.`);
|
|
115754
|
+
}
|
|
115755
|
+
});
|
|
115756
|
+
}
|
|
115757
|
+
} else if (!report.resourceReferences.includes(task.filename)) {
|
|
115641
115758
|
report.warn(`Resource ${task.filename} is included in the zip but isn't referenced by any cards.`);
|
|
115642
115759
|
}
|
|
115643
115760
|
if (zip.file(task.filename)._data.uncompressedSize > 2e9) {
|
|
@@ -115734,6 +115851,7 @@ function checkZip(zip) {
|
|
|
115734
115851
|
collectionRoots: [],
|
|
115735
115852
|
tags: [],
|
|
115736
115853
|
resourceReferences: [],
|
|
115854
|
+
externalImages: { enabled: false, names: /* @__PURE__ */ new Set(), referenced: [] },
|
|
115737
115855
|
cardLinks: 0,
|
|
115738
115856
|
boardLinks: 0,
|
|
115739
115857
|
checkCount: 0,
|
|
@@ -115807,6 +115925,7 @@ function checkZip(zip) {
|
|
|
115807
115925
|
info(`Unexpected file ${fullPath}`);
|
|
115808
115926
|
}
|
|
115809
115927
|
}
|
|
115928
|
+
tasks.push({ func: checkExternalImages, context: "resources/external.json", checks: 3, priority: 0 });
|
|
115810
115929
|
tasks.push({ func: checkFolderTree, checks: 5, priority: 6 });
|
|
115811
115930
|
tasks.push({ func: checkStats, checks: 3, priority: 10 });
|
|
115812
115931
|
tasks.sort(function(a, b) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getguru/import-engine",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
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
|
-
"guru-import-engine": "
|
|
6
|
+
"guru-import-engine": "docx-import-cli.js"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
9
|
"docx-import-cli.js",
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
"LICENSE.md"
|
|
12
12
|
],
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"jsdom": "
|
|
14
|
+
"jsdom": "28.1.0"
|
|
15
15
|
},
|
|
16
16
|
"engines": {
|
|
17
|
-
"node": ">=22"
|
|
17
|
+
"node": ">=22.12"
|
|
18
18
|
},
|
|
19
19
|
"publishConfig": {
|
|
20
20
|
"access": "public"
|