@onozaty/growi-uploader 1.3.0 → 1.4.0

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 CHANGED
@@ -194,6 +194,8 @@ All referenced files (`logo.png`, `screenshot.png`, and `banner.png`) will be up
194
194
  [File](./docs/my%20file.pdf) # URL-encoded space
195
195
  [File](<./path/file (1).png>) # Special chars with angle brackets
196
196
  ![Image](./path/file\\(1\\).png) # Special chars with escaping
197
+ <img src="./images/logo.png" alt="Logo"> # HTML img tag (double quotes)
198
+ <img src='./images/logo.png' alt='Logo'> # HTML img tag (single quotes)
197
199
  ```
198
200
 
199
201
  **Excluded from detection:**
package/dist/index.mjs CHANGED
@@ -8,7 +8,7 @@ import { lookup } from "mime-types";
8
8
  import { glob } from "glob";
9
9
 
10
10
  //#region package.json
11
- var version = "1.3.0";
11
+ var version = "1.4.0";
12
12
 
13
13
  //#endregion
14
14
  //#region src/config.ts
@@ -215,6 +215,37 @@ const uploadAttachment = async (attachment, pageId, sourceDir) => {
215
215
  //#endregion
216
216
  //#region src/scanner.ts
217
217
  /**
218
+ * Process a link path and convert it to an AttachmentFile if it exists
219
+ *
220
+ * @param linkPath The link path from markdown
221
+ * @param originalLinkPath The original format of the link (for replacement)
222
+ * @param markdownFilePath Path to the markdown file (relative to sourceDir)
223
+ * @param sourceDir Source directory (absolute path)
224
+ * @returns AttachmentFile if the path resolves to an existing file, null otherwise
225
+ */
226
+ const processLinkPath = (linkPath, originalLinkPath, markdownFilePath, sourceDir) => {
227
+ if (linkPath.startsWith("http://") || linkPath.startsWith("https://")) return null;
228
+ if (linkPath.endsWith(".md")) return null;
229
+ const unescapedPath = linkPath.replace(/\\([\\`*_{}[\]()#+\-.!])/g, "$1");
230
+ let decodedPath;
231
+ try {
232
+ decodedPath = decodeURIComponent(unescapedPath);
233
+ } catch {
234
+ decodedPath = unescapedPath;
235
+ }
236
+ let absolutePath;
237
+ if (linkPath.startsWith("/")) absolutePath = resolve(sourceDir, decodedPath.slice(1));
238
+ else absolutePath = resolve(dirname(join(sourceDir, markdownFilePath)), decodedPath);
239
+ if (!existsSync(absolutePath)) return null;
240
+ const normalizedPath = relative(sourceDir, absolutePath).replace(/\\/g, "/");
241
+ return {
242
+ localPath: normalizedPath,
243
+ fileName: basename(normalizedPath),
244
+ detectionPattern: "link",
245
+ originalLinkPaths: [originalLinkPath]
246
+ };
247
+ };
248
+ /**
218
249
  * Extract attachment files from markdown links
219
250
  *
220
251
  * Scans markdown content for image and link references, resolves their paths,
@@ -243,27 +274,15 @@ const extractLinkedAttachments = (content, markdownFilePath, sourceDir) => {
243
274
  const { anglePath, regularPath } = match.groups;
244
275
  const linkPath = anglePath || regularPath;
245
276
  if (!linkPath) continue;
246
- const originalLinkPath = anglePath ? `<${anglePath}>` : regularPath;
247
- if (linkPath.startsWith("http://") || linkPath.startsWith("https://")) continue;
248
- if (linkPath.endsWith(".md")) continue;
249
- const unescapedPath = linkPath.replace(/\\([\\`*_{}[\]()#+\-.!])/g, "$1");
250
- let decodedPath;
251
- try {
252
- decodedPath = decodeURIComponent(unescapedPath);
253
- } catch {
254
- decodedPath = unescapedPath;
255
- }
256
- let absolutePath;
257
- if (linkPath.startsWith("/")) absolutePath = resolve(sourceDir, decodedPath.slice(1));
258
- else absolutePath = resolve(dirname(join(sourceDir, markdownFilePath)), decodedPath);
259
- if (!existsSync(absolutePath)) continue;
260
- const normalizedPath = relative(sourceDir, absolutePath).replace(/\\/g, "/");
261
- attachments.push({
262
- localPath: normalizedPath,
263
- fileName: basename(normalizedPath),
264
- detectionPattern: "link",
265
- originalLinkPaths: [originalLinkPath]
266
- });
277
+ const attachment = processLinkPath(linkPath, anglePath ? `<${anglePath}>` : regularPath, markdownFilePath, sourceDir);
278
+ if (attachment) attachments.push(attachment);
279
+ }
280
+ const imgTagRegex = /<img\s+[^>]*src=(?<quote>["'])(?<src>.*?)\k<quote>[^>]*>/gi;
281
+ while ((match = imgTagRegex.exec(content)) !== null) {
282
+ const { src } = match.groups;
283
+ if (!src) continue;
284
+ const attachment = processLinkPath(src, src, markdownFilePath, sourceDir);
285
+ if (attachment) attachments.push(attachment);
267
286
  }
268
287
  return attachments;
269
288
  };
@@ -368,6 +387,11 @@ const replaceAttachmentLinks = (markdown, attachments, pageName) => {
368
387
  replaced = true;
369
388
  result = result.replace(linkRegex, `[$1](${growiPath})`);
370
389
  }
390
+ const imgTagRegex = new RegExp(`(<img\\s+[^>]*src=)(["'])${pattern}\\2([^>]*>)`, "gi");
391
+ if (imgTagRegex.test(result)) {
392
+ replaced = true;
393
+ result = result.replace(imgTagRegex, `$1$2${growiPath}$2$3`);
394
+ }
371
395
  }
372
396
  }
373
397
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onozaty/growi-uploader",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "A content uploader for GROWI",
5
5
  "type": "module",
6
6
  "bin": {