Skip to content

Commit 9268bb3

Browse files
committed
🐛 Fix: migrate bug when url isn't with extname suffix && windows style path
ISSUES CLOSED: #5, #57, #64, #65
1 parent c1d7732 commit 9268bb3

File tree

8 files changed

+79
-17
lines changed

8 files changed

+79
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ yarn-error.log
55
temp.js
66
package-lock.json
77
test/test_new.md
8+
.serena/

AGENTS.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Repository Guidelines
2+
3+
## Project Structure & Module Organization
4+
- `src/index.ts` is the plugin entry that wires PicGo CLI/GUI commands, config schema, and migration flow.
5+
- `src/lib/Migrater.ts` orchestrates URL discovery and upload; `src/lib/FileHandler.ts` reads/writes markdown and rewrites URLs; `src/utils.ts` hosts small helpers.
6+
- `src/i18n` holds locale strings; keep keys stable when adding translations.
7+
- `src/types` contains type declarations used by the compiler.
8+
- `dist/` is the compiled output from TypeScript—do not edit by hand.
9+
- `test/` includes sample markdown/assets, and `test.js` is a Node integration script that exercises `dist/index.js`.
10+
11+
## Build, Test, and Development Commands
12+
```bash
13+
pnpm install # install deps (uses pnpm-lock.yaml)
14+
pnpm build # compile TypeScript to dist/
15+
pnpm dev # watch & rebuild during development
16+
pnpm lint # eslint on src + type-check (tsc --noEmit)
17+
pnpm test # runs test.js against dist; run build first
18+
```
19+
Run commands from the repo root. Avoid editing `dist/` manually; regenerate via `pnpm build` when needed.
20+
21+
## Coding Style & Naming Conventions
22+
- TypeScript, CommonJS target es2017; 2-space indentation and single quotes to match existing files.
23+
- Classes in PascalCase (e.g., `FileHandler`), functions/variables in camelCase, constants in SCREAMING_SNAKE_CASE.
24+
- Keep plugin config keys under `picgo-plugin-pic-migrater.*`; prefer explicit types and early returns.
25+
- ESLint extends `eslint-config-love`; `pnpm lint` is the source of truth—fix or annotate intentionally justified cases.
26+
27+
## Testing Guidelines
28+
- `pnpm test` migrates `test/test.md` via compiled `dist/`; ensure `pnpm build` has run and sample files remain intact.
29+
- When adding tests, prefer integration-style checks in `test/` that assert rewritten markdown output and file creation.
30+
- If adding new migration cases, include minimal fixtures and document expected suffixes (`newFileSuffix`) to avoid accidental overwrites.
31+
32+
## Commit & Pull Request Guidelines
33+
- Use commitizen for messages: `pnpm cz`. Commitlint follows the PicGo convention (emoji scopes such as `:bug: Fix: ...`, `:tada: Release: ...`); keep messages imperative and scoped.
34+
- Keep commits small and focused; only update `dist/` for releases or when explicitly required.
35+
- PRs should describe the change, link related issues, and note how to reproduce or verify. Provide CLI output or screenshots/gifs when affecting user-facing flows (CLI help, GUI notifications).
36+
37+
## Security & Configuration Tips
38+
- The plugin reads/writes markdown files; double-check glob patterns before running migrations to avoid unwanted edits.
39+
- Avoid logging sensitive paths or credentials in PicGo configs; sanitize sample configs in docs and tests.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,8 @@
6464
"compare-versions": "^5.0.0",
6565
"globby": "^9.0.0",
6666
"image-size": "^1.0.2"
67+
},
68+
"engines": {
69+
"node": ">=14.13.1"
6770
}
6871
}

src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ const replaceAll = (content: string, originText: string, replaceText: string): s
1111
if (originText === replaceText) {
1212
return content
1313
}
14-
content = content.replace(new RegExp(originText, 'g'), replaceText)
15-
return content
14+
return content.split(originText).join(replaceText)
1615
}
1716
const checkVersion = (ctx: PicGo, guiApi: any): void => {
1817
if (guiApi) {

src/lib/Migrater.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import fs from 'node:fs'
44
import path from 'node:path'
55
import { IImgInfo, PicGo } from 'picgo'
6-
import { getImageSize, isUrl, isUrlEncode } from '../utils'
6+
import { getImageSize, isUrl, isUrlEncode, normalizePath } from '../utils'
77

88
class Migrater {
99
ctx: PicGo
@@ -88,12 +88,17 @@ class Migrater {
8888
}
8989
}
9090

91-
result.urls = output.filter(item => item.imgUrl && item.imgUrl !== item.origin).map(item => {
91+
result.urls = output.map((item, index) => {
92+
const original = toUploadImgs[index]?.origin ?? item.origin
93+
if (!item.imgUrl || !original || item.imgUrl === original) {
94+
return null
95+
}
9296
return {
93-
original: item.origin,
94-
new: item.imgUrl as string
97+
original,
98+
new: item.imgUrl
9599
}
96-
})
100+
}).filter((item) => item !== null)
101+
97102
result.success = result.urls.length
98103

99104
this.ctx.setConfig({
@@ -104,22 +109,22 @@ class Migrater {
104109
}
105110

106111
getLocalPath (imgPath: string): string | false {
107-
let localPath = imgPath
112+
let localPath = normalizePath(imgPath)
108113
if (!path.isAbsolute(localPath)) {
109-
localPath = path.join(this.baseDir, localPath)
114+
localPath = normalizePath(path.join(this.baseDir, localPath))
110115
}
111116
if (fs.existsSync(localPath)) {
112-
console.log('1', localPath)
117+
console.log('exist absolute local path', localPath)
113118
return localPath
114119
} else {
115120
// if path is url encode, try decode
116121
if (isUrlEncode(imgPath)) {
117-
localPath = decodeURI(imgPath)
122+
localPath = normalizePath(decodeURI(imgPath))
118123
if (!path.isAbsolute(localPath)) {
119-
localPath = path.join(this.baseDir, localPath)
124+
localPath = normalizePath(path.join(this.baseDir, localPath))
120125
}
121126
if (fs.existsSync(localPath)) {
122-
console.log('2', localPath)
127+
console.log('exist related local path', localPath)
123128
return localPath
124129
}
125130
}
@@ -156,17 +161,19 @@ class Migrater {
156161
}
157162

158163
async handlePicFromURL (url: string): Promise<IImgInfo | undefined> {
164+
const rawFileName = path.basename(url.split('?')[0].split('#')[0]) || 'image'
159165
try {
160166
const buffer = await this.getPicFromURL(url)
161-
const fileName = path.basename(url).split('?')[0].split('#')[0]
162167
const imgSize = getImageSize(buffer)
163-
console.log(imgSize)
168+
const imgType = (imgSize.type ?? 'png').replace(/^\./, '')
169+
const extname = `.${imgType}`
170+
const fileName = path.extname(rawFileName) ? rawFileName : `${rawFileName}${extname}`
164171
return {
165172
buffer,
166173
fileName,
167174
width: imgSize.width,
168175
height: imgSize.height,
169-
extname: `.${imgSize.type ?? 'png'}`,
176+
extname,
170177
origin: url
171178
}
172179
} catch (e) {

src/utils.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import sizeOf from 'image-size'
22
import { IImgSize } from 'picgo'
3+
import path from 'node:path'
34

45
interface IImgSizeInfo extends IImgSize {
56
type?: string
@@ -42,3 +43,5 @@ export const handleUrlEncode = (url: string): string => {
4243
}
4344
return url
4445
}
46+
47+
export const normalizePath = (p: string): string => path.normalize(p.replace(/\\+/g, '/'))

test.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const { PicGo } = require('picgo')
22
const PluginMigrater = require('./dist/index')
3+
const assert = require('assert')
34

45
const picgo = new PicGo()
56

@@ -11,9 +12,11 @@ picgo.setConfig({
1112
}
1213
})
1314

14-
const plugin = PluginMigrater(picgo);
15+
const plugin = picgo.use(PluginMigrater);
1516

1617
(async () => {
1718
const res = await plugin.migrateFiles(['./test/test.md']) // { total: number, success: number }
1819
console.log(res)
20+
assert.strictEqual(res.success, 6)
21+
assert.strictEqual(res.total, 7)
1922
})();

test/test.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
## Test case
22

3+
Hello. How are you?
4+
35
### url
46

57
![](https://raw.githubusercontent.com/Molunerfinn/test/master/img/logo__2022-08-08%2B17_34_11.jpeg)
68

79
<img alt="test" src="https://raw.githubusercontent.com/Molunerfinn/test/master/test/picgo-logo.png">
810

11+
<img alt="test" src="https://mmbiz.qpic.cn/mmbiz_png/n8UWicng6vIA4usX2sOyd5NibTrl07M89U5MMpQsicyoiatWVlib95H1w1Sricw08C6oQ2PicufjA073In29F9zEY5vdg/640?wx_fmt=png">
12+
13+
<img alt="test" src="https://mmbiz.qpic.cn/mmbiz_png/error_image">
14+
915
### local file
1016

1117
![](./picgo-logo.png)
18+
![](.\picgo-logo.png)
1219

1320
<img alt="test" src="./picgo%20logo.png">

0 commit comments

Comments
 (0)