diff --git a/lib/box/index.ts b/lib/box/index.ts index d2cbf7022b..4da7c69d4e 100644 --- a/lib/box/index.ts +++ b/lib/box/index.ts @@ -113,7 +113,7 @@ class Box extends EventEmitter { const src = join(this.base, path); return Cache.compareFile( - src.substring(ctx.base_dir.length), + escapeBackslash(src.substring(ctx.base_dir.length)), () => getHash(src), () => stat(src) ).then(result => ({ @@ -129,7 +129,7 @@ class Box extends EventEmitter { if (!stats.isDirectory()) return; // Check existing files in cache - const relativeBase = base.substring(ctx.base_dir.length); + const relativeBase = escapeBackslash(base.substring(ctx.base_dir.length)); const cacheFiles = Cache.filter(item => item._id.startsWith(relativeBase)).map(item => item._id.substring(relativeBase.length)); // Handle deleted files @@ -156,12 +156,11 @@ class Box extends EventEmitter { }); return BlueBirdPromise.reduce(this.processors, (count, processor) => { - // patten supports *nix style path only, replace backslashes on Windows - const params = processor.pattern.match(escapeBackslash(path)); + const params = processor.pattern.match(path); if (!params) return count; const file = new File({ - // source is used for file system path, keep backslashes on Windows + // source is used for filesystem path, keep backslashes on Windows source: join(base, path), // path is used for URL path, replace backslashes on Windows path: escapeBackslash(path), @@ -195,7 +194,7 @@ class Box extends EventEmitter { const { base } = this; function getPath(path) { - return path.substring(base.length); + return escapeBackslash(path.substring(base.length)); } return this.process().then(() => watch(base, this.options)).then(watcher => { @@ -215,7 +214,7 @@ class Box extends EventEmitter { watcher.on('addDir', path => { let prefix = getPath(path); - if (prefix) prefix += sep; + if (prefix) prefix += '/'; this._readDir(path, prefix); }); @@ -288,7 +287,7 @@ function readDirWalker(ctx: Hexo, base: string, results: any[], ignore: any, pre const prefixPath = `${prefix}${path}`; if (stats) { if (stats.isDirectory()) { - return readDirWalker(ctx, fullpath, results, ignore, prefixPath + sep); + return readDirWalker(ctx, fullpath, results, ignore, `${prefixPath}/`); } if (!isIgnoreMatch(fullpath, ignore)) { results.push(prefixPath); diff --git a/lib/plugins/processor/asset.ts b/lib/plugins/processor/asset.ts index 48ccd1401d..c56ff62052 100644 --- a/lib/plugins/processor/asset.ts +++ b/lib/plugins/processor/asset.ts @@ -109,7 +109,7 @@ function processPage(ctx: Hexo, file: _File) { } function processAsset(ctx: Hexo, file: _File) { - const id = relative(ctx.base_dir, file.source); + const id = relative(ctx.base_dir, file.source).replace(/\\/g, '/'); const Asset = ctx.model('Asset'); const doc = Asset.findById(id); diff --git a/lib/plugins/processor/post.ts b/lib/plugins/processor/post.ts index 969fad87a1..856fff5ba2 100644 --- a/lib/plugins/processor/post.ts +++ b/lib/plugins/processor/post.ts @@ -240,7 +240,7 @@ function scanAssetDir(ctx: Hexo, post) { if (err && err.code === 'ENOENT') return []; throw err; }).filter(item => !isExcludedFile(item, ctx.config)).map(item => { - const id = join(assetDir, item).substring(baseDirLength); + const id = join(assetDir, item).substring(baseDirLength).replace(/\\/g, '/'); const renderablePath = id.substring(sourceDirLength + 1); const asset = PostAsset.findById(id); @@ -274,7 +274,7 @@ function shouldSkipAsset(ctx: Hexo, post, asset) { function processAsset(ctx: Hexo, file: _File) { const PostAsset = ctx.model('PostAsset'); const Post = ctx.model('Post'); - const id = file.source.substring(ctx.base_dir.length); + const id = file.source.substring(ctx.base_dir.length).replace(/\\/g, '/'); const postAsset = PostAsset.findById(id); if (file.type === 'delete' || Post.length === 0) { diff --git a/lib/theme/processors/source.ts b/lib/theme/processors/source.ts index c82d4352c9..ac8c21a1fe 100644 --- a/lib/theme/processors/source.ts +++ b/lib/theme/processors/source.ts @@ -4,7 +4,7 @@ import type { _File } from '../../box'; function process(file: _File) { const Asset = this.model('Asset'); - const id = file.source.substring(this.base_dir.length); + const id = file.source.substring(this.base_dir.length).replace(/\\/g, '/'); const { path } = file.params; const doc = Asset.findById(id); diff --git a/test/scripts/box/box.ts b/test/scripts/box/box.ts index 55331677f2..d6d3d35b57 100644 --- a/test/scripts/box/box.ts +++ b/test/scripts/box/box.ts @@ -120,7 +120,7 @@ describe('Box', () => { const box = newBox('test'); const name = 'a.txt'; const path = join(box.base, name); - const cacheId = join('test/', name); + const cacheId = 'test/' + name; const processor = spy(); box.addProcessor(processor); @@ -144,7 +144,7 @@ describe('Box', () => { const box = newBox('test'); const name = 'a.txt'; const path = join(box.base, name); - const cacheId = join('test/', name); + const cacheId = 'test/' + name; const processor = spy(); box.addProcessor(processor); @@ -167,7 +167,7 @@ describe('Box', () => { const box = newBox('test'); const name = 'a.txt'; const path = join(box.base, name); - const cacheId = join('test/', name); + const cacheId = 'test/' + name; const processor = spy(); box.addProcessor(processor); @@ -190,7 +190,7 @@ describe('Box', () => { const box = newBox('test'); const name = 'a.txt'; const path = join(box.base, name); - const cacheId = join('test/', name); + const cacheId = 'test/' + name; const processor = spy(); box.addProcessor(processor); @@ -211,8 +211,7 @@ describe('Box', () => { it('process() - delete', async () => { const box = newBox('test'); - // join will replace backslashes on Windows - const cacheId = join('test/', 'a.txt'); + const cacheId = 'test/a.txt'; const processor = spy(); box.addProcessor(processor); diff --git a/test/scripts/processors/asset.ts b/test/scripts/processors/asset.ts index 127c9df08f..1e78bc44b1 100644 --- a/test/scripts/processors/asset.ts +++ b/test/scripts/processors/asset.ts @@ -80,7 +80,7 @@ describe('asset', () => { await writeFile(file.source, 'foo'); await process(file); - const id = join('source/', file.path); + const id = 'source/' + file.path; const asset = Asset.findById(id); asset._id.should.eql(id); @@ -103,7 +103,7 @@ describe('asset', () => { await writeFile(file.source, 'foo'); await process(file); - const id = join('../source/', 'foo.jpg'); // The id should a relative path, because the 'lib/models/assets.js' use asset path by joining base path with "_id" directly. + const id = '../source/foo.jpg'; // The id should a relative path,because the 'lib/models/assets.js' use asset path by joining base path with "_id" directly. const asset = Asset.findById(id); asset._id.should.eql(id); asset.path.should.eql(file.path); @@ -122,7 +122,7 @@ describe('asset', () => { renderable: false }); - const id = join('source/', file.path); + const id = 'source/' + file.path; await Promise.all([ writeFile(file.source, 'test'), @@ -153,7 +153,7 @@ describe('asset', () => { renderable: false }); - const id = join('source/', file.path); + const id = 'source/' + file.path; await Promise.all([ writeFile(file.source, 'test'), @@ -179,7 +179,7 @@ describe('asset', () => { renderable: false }); - const id = join('source/', file.path); + const id = 'source/' + file.path; await Asset.insert({ _id: id, @@ -197,7 +197,7 @@ describe('asset', () => { renderable: false }); - const id = join('source/', file.path); + const id = 'source/' + file.path; await process(file); should.not.exist(Asset.findById(id)); diff --git a/test/scripts/processors/post.ts b/test/scripts/processors/post.ts index 9fa83192e2..e3f1ff54c0 100644 --- a/test/scripts/processors/post.ts +++ b/test/scripts/processors/post.ts @@ -118,7 +118,7 @@ describe('post', () => { }); await process(file); - const id = join('source/', file.path); + const id = 'source/' + file.path; should.not.exist(PostAsset.findById(id)); }); @@ -141,7 +141,7 @@ describe('post', () => { const postId = doc._id; await process(file); - const id = join('source/', file.path); + const id = 'source/' + file.path; const asset = PostAsset.findById(id); asset._id.should.eql(id); @@ -165,7 +165,7 @@ describe('post', () => { renderable: false }); - const id = join('source/', file.path); + const id = 'source/' + file.path; const post = await Post.insert({ source: '_posts/foo.html', @@ -200,7 +200,7 @@ describe('post', () => { renderable: false }); - const id = join('source/', file.path); + const id = 'source/' + file.path; const post = await Post.insert({ source: '_posts/foo.html', @@ -235,7 +235,7 @@ describe('post', () => { renderable: false }); - const id = join('source/', file.path); + const id = 'source/' + file.path; const post = await Post.insert({ source: '_posts/foo.html', @@ -265,7 +265,7 @@ describe('post', () => { renderable: false }); - const id = join('source/', file.path); + const id = 'source/' + file.path; const post = await Post.insert({ source: '_posts/foo.html', @@ -290,7 +290,7 @@ describe('post', () => { renderable: false }); - const id = join('source/', file.path); + const id = 'source/' + file.path; await writeFile(file.source, 'test'); await process(file); @@ -309,7 +309,7 @@ describe('post', () => { renderable: false }); - const id = join('source/', file.path); + const id = 'source/' + file.path; await Promise.all([ writeFile(file.source, 'test'), @@ -992,7 +992,7 @@ describe('post', () => { '_fizz.jpg', '_buzz.jpg' ].map(filename => { - const id = join('source/_posts/foo/', filename); + const id = `source/_posts/foo/${filename}`; const path = join(hexo.base_dir, id); const contents = filename.replace(/\.\w+$/, ''); return { @@ -1048,8 +1048,7 @@ describe('post', () => { renderable: true }); - // join will replace backslashes on Windows - const assetId = join('source/_posts/foo/', 'bar.jpg'); + const assetId = 'source/_posts/foo/bar.jpg'; const assetPath = join(hexo.base_dir, assetId); await Promise.all([ @@ -1095,8 +1094,7 @@ describe('post', () => { renderable: true }); - // join will replace backslashes on Windows - const assetId = join('source/_posts/foo/', 'bar.jpg'); + const assetId = 'source/_posts/foo/bar.jpg'; const assetPath = join(hexo.base_dir, assetId); await Promise.all([ @@ -1134,8 +1132,7 @@ describe('post', () => { renderable: true }); - // join will replace backslashes on Windows - const assetId = join('source/_posts/foo/', 'bar.jpg'); + const assetId = 'source/_posts/foo/bar.jpg'; const assetPath = join(hexo.base_dir, assetId); await Promise.all([ @@ -1312,7 +1309,7 @@ describe('post', () => { writeFile(assetFile.source, 'test') ]); await process(file); - const id = join('source/', assetFile.path); + const id = 'source/' + assetFile.path; const post = Post.findOne({ source: file.path }); PostAsset.findById(id).renderable.should.be.true; @@ -1348,7 +1345,7 @@ describe('post', () => { writeFile(assetFile.source, 'test') ]); await process(file); - const id = join('source/', assetFile.path); + const id = 'source/' + assetFile.path; const post = Post.findOne({ source: file.path }); PostAsset.findById(id).renderable.should.be.false; diff --git a/test/scripts/theme_processors/source.ts b/test/scripts/theme_processors/source.ts index 5d9343b239..9b4f6f2979 100644 --- a/test/scripts/theme_processors/source.ts +++ b/test/scripts/theme_processors/source.ts @@ -56,7 +56,7 @@ describe('source', () => { type: 'create' }); - const id = join('themes/test/', file.path); + const id = 'themes/test/' + file.path; await writeFile(file.source, 'test'); await process(file); @@ -77,7 +77,7 @@ describe('source', () => { type: 'update' }); - const id = join('themes/test/', file.path); + const id = 'themes/test/' + file.path; await Promise.all([ writeFile(file.source, 'test'), @@ -104,7 +104,7 @@ describe('source', () => { type: 'skip' }); - const id = join('themes/test/', file.path); + const id = 'themes/test/' + file.path; await Promise.all([ writeFile(file.source, 'test'), @@ -130,7 +130,7 @@ describe('source', () => { type: 'delete' }); - const id = join('themes/test/', file.path); + const id = 'themes/test/' + file.path; await Asset.insert({ _id: id, @@ -146,7 +146,7 @@ describe('source', () => { type: 'delete' }); - const id = join('themes/test/', file.path); + const id = 'themes/test/' + file.path; await process(file); should.not.exist(Asset.findById(id));