@getguru/import-engine 0.1.1 → 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.
Files changed (2) hide show
  1. package/docx-import-cli.js +127 -6
  2. package/package.json +1 -1
@@ -114320,7 +114320,7 @@ var import_jszip5 = __toESM(require_lib3());
114320
114320
  var import_url_join6 = __toESM(require_url_join());
114321
114321
 
114322
114322
  // packages/import-engine/package.json
114323
- var version = "0.1.1";
114323
+ var version = "0.1.2";
114324
114324
 
114325
114325
  // src/docx-import/detectors.js
114326
114326
  function isGoogleSitesDoc(div) {
@@ -114344,7 +114344,7 @@ var showError;
114344
114344
  var updateLoader;
114345
114345
  var showReport;
114346
114346
  var docLinkIndex = /* @__PURE__ */ new Map();
114347
- var toolVersion = true ? `${version}+${"e19020c"}` : version;
114347
+ var toolVersion = true ? `${version}+${"4d61d22"}` : version;
114348
114348
  var pendingUpload = null;
114349
114349
  function confirmPendingUpload() {
114350
114350
  const upload = pendingUpload;
@@ -115155,6 +115155,91 @@ function setSubtract(a, b) {
115155
115155
  return !b.includes(value);
115156
115156
  });
115157
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
+ }
115158
115243
  function escapeQuotes(value) {
115159
115244
  value = value || "";
115160
115245
  return value.replace(/"/g, `\\"`);
@@ -115189,11 +115274,18 @@ function checkCardYaml(zip, task, report) {
115189
115274
  return zip.file(task.filename).async("string").then(function(yamlString) {
115190
115275
  try {
115191
115276
  var card = yaml.load(yamlString);
115192
- var possibleKeys = ["ExternalId", "ExternalUrl", "Title", "Tags", "externalLastUpdated"];
115277
+ var possibleKeys = ["ExternalId", "ExternalUrl", "Title", "Tags", "externalLastUpdated", "ID"];
115193
115278
  var otherKeys = setSubtract(Object.keys(card), possibleKeys);
115194
115279
  otherKeys.forEach(function(key) {
115195
115280
  report.warn(`Unexpected property "${key}" in the card's yaml.`);
115196
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
+ }
115197
115289
  if (!card.Title) {
115198
115290
  report.error(`A "Title" property is required in the card's yaml.`);
115199
115291
  } else {
@@ -115258,7 +115350,17 @@ function checkCardHtml(zip, task, report) {
115258
115350
  report.resourceReferences.push(reference2);
115259
115351
  }
115260
115352
  } else {
115261
- report.error(`The referenced resource "${reference2}" does not exist in the zip.`);
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
+ }
115262
115364
  }
115263
115365
  } else if (reference2.startsWith("cards/")) {
115264
115366
  if (zip.file(reference2 + ".yaml")) {
@@ -115515,7 +115617,7 @@ function checkCollectionYaml(zip, task, report) {
115515
115617
  }
115516
115618
  try {
115517
115619
  var collection = yaml.load(yamlString);
115518
- var possibleKeys = ["Items", "Tags", "Title", "Version"];
115620
+ var possibleKeys = ["Items", "Tags", "Title", "Version", "FetchExternalImages", "ReuseFolders"];
115519
115621
  var otherKeys = setSubtract(Object.keys(collection), possibleKeys);
115520
115622
  otherKeys.forEach(function(key) {
115521
115623
  report.warn(`Unexpected property "${key}" in collection.yaml.`);
@@ -115532,6 +115634,14 @@ function checkCollectionYaml(zip, task, report) {
115532
115634
  }
115533
115635
  }
115534
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
+ }
115535
115645
  if (collection.Items) {
115536
115646
  if (!Array.isArray(collection.Items)) {
115537
115647
  report.error(`The collection's Items list is optional, but if provided it must be a list.`);
@@ -115635,7 +115745,16 @@ function checkResource(zip, task, report) {
115635
115745
  } else {
115636
115746
  report.resources += 1;
115637
115747
  }
115638
- if (!report.resourceReferences.includes(task.filename)) {
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)) {
115639
115758
  report.warn(`Resource ${task.filename} is included in the zip but isn't referenced by any cards.`);
115640
115759
  }
115641
115760
  if (zip.file(task.filename)._data.uncompressedSize > 2e9) {
@@ -115732,6 +115851,7 @@ function checkZip(zip) {
115732
115851
  collectionRoots: [],
115733
115852
  tags: [],
115734
115853
  resourceReferences: [],
115854
+ externalImages: { enabled: false, names: /* @__PURE__ */ new Set(), referenced: [] },
115735
115855
  cardLinks: 0,
115736
115856
  boardLinks: 0,
115737
115857
  checkCount: 0,
@@ -115805,6 +115925,7 @@ function checkZip(zip) {
115805
115925
  info(`Unexpected file ${fullPath}`);
115806
115926
  }
115807
115927
  }
115928
+ tasks.push({ func: checkExternalImages, context: "resources/external.json", checks: 3, priority: 0 });
115808
115929
  tasks.push({ func: checkFolderTree, checks: 5, priority: 6 });
115809
115930
  tasks.push({ func: checkStats, checks: 3, priority: 10 });
115810
115931
  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.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
6
  "guru-import-engine": "docx-import-cli.js"