mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
3d8577a689
- For now, supports Markdown-it plugins - Also fixed slow rendering of notes in some cases - Simplified how Markdown-It plugins are created and cleaned MdToHtml code commit89576de289
Merge:c75aa21f
5292fc14
Author: Laurent Cozic <laurent@cozic.net> Date: Wed Oct 21 00:23:00 2020 +0100 Merge branch 'release-1.3' into plugin_content_scripts commitc75aa21ffd
Author: Laurent Cozic <laurent@cozic.net> Date: Wed Oct 21 00:19:52 2020 +0100 Fixed tests commit075187729d
Author: Laurent Cozic <laurent@cozic.net> Date: Wed Oct 21 00:11:53 2020 +0100 Fixed tests commit14696b8c65
Author: Laurent Cozic <laurent@cozic.net> Date: Tue Oct 20 23:27:58 2020 +0100 Fixed slow rendering of note commit61c09f5bf8
Author: Laurent Cozic <laurent@cozic.net> Date: Tue Oct 20 22:35:21 2020 +0100 Clean up commit9f7ea7d865
Author: Laurent Cozic <laurent@cozic.net> Date: Tue Oct 20 20:05:31 2020 +0100 Updated doc commit98bf3bde8d
Author: Laurent Cozic <laurent@cozic.net> Date: Tue Oct 20 19:56:34 2020 +0100 Finished converting plugins commitfe90d92e01
Author: Laurent Cozic <laurent@cozic.net> Date: Tue Oct 20 17:52:02 2020 +0100 Simplified how Markdown-It plugins are created commit47c7b864cb
Author: Laurent Cozic <laurent@cozic.net> Date: Mon Oct 19 16:40:11 2020 +0100 Clean up rules commitd927a238bb
Author: Laurent Cozic <laurent@cozic.net> Date: Mon Oct 19 14:29:40 2020 +0100 Fixed tests commit388a56c5dd
Author: Laurent Cozic <laurent@cozic.net> Date: Mon Oct 19 14:00:47 2020 +0100 Add support for content scripts
209 lines
5.7 KiB
TypeScript
209 lines
5.7 KiB
TypeScript
import { resolve as nodeResolve } from 'path';
|
|
|
|
const fs = require('fs-extra');
|
|
const { time } = require('lib/time-utils.js');
|
|
const FsDriverBase = require('lib/fs-driver-base');
|
|
|
|
export default class FsDriverNode extends FsDriverBase {
|
|
|
|
private fsErrorToJsError_(error:any, path:string = null) {
|
|
let msg = error.toString();
|
|
if (path !== null) msg += `. Path: ${path}`;
|
|
const output:any = new Error(msg);
|
|
if (error.code) output.code = error.code;
|
|
return output;
|
|
}
|
|
|
|
public appendFileSync(path:string, string:string) {
|
|
return fs.appendFileSync(path, string);
|
|
}
|
|
|
|
public async appendFile(path:string, string:string, encoding:string = 'base64') {
|
|
try {
|
|
return await fs.appendFile(path, string, { encoding: encoding });
|
|
} catch (error) {
|
|
throw this.fsErrorToJsError_(error, path);
|
|
}
|
|
}
|
|
|
|
public async writeBinaryFile(path:string, content:any) {
|
|
try {
|
|
// let buffer = new Buffer(content);
|
|
const buffer = Buffer.from(content);
|
|
return await fs.writeFile(path, buffer);
|
|
} catch (error) {
|
|
throw this.fsErrorToJsError_(error, path);
|
|
}
|
|
}
|
|
|
|
public async writeFile(path:string, string:string, encoding:string = 'base64') {
|
|
try {
|
|
if (encoding === 'buffer') {
|
|
return await fs.writeFile(path, string);
|
|
} else {
|
|
return await fs.writeFile(path, string, { encoding: encoding });
|
|
}
|
|
} catch (error) {
|
|
throw this.fsErrorToJsError_(error, path);
|
|
}
|
|
}
|
|
|
|
// same as rm -rf
|
|
public async remove(path:string) {
|
|
try {
|
|
const r = await fs.remove(path);
|
|
return r;
|
|
} catch (error) {
|
|
throw this.fsErrorToJsError_(error, path);
|
|
}
|
|
}
|
|
|
|
public async move(source:string, dest:string) {
|
|
let lastError = null;
|
|
|
|
for (let i = 0; i < 5; i++) {
|
|
try {
|
|
const output = await fs.move(source, dest, { overwrite: true });
|
|
return output;
|
|
} catch (error) {
|
|
lastError = error;
|
|
// Normally cannot happen with the `overwrite` flag but sometime it still does.
|
|
// In this case, retry.
|
|
if (error.code == 'EEXIST') {
|
|
await time.sleep(1);
|
|
continue;
|
|
}
|
|
throw this.fsErrorToJsError_(error);
|
|
}
|
|
}
|
|
|
|
throw lastError;
|
|
}
|
|
|
|
public exists(path:string) {
|
|
return fs.pathExists(path);
|
|
}
|
|
|
|
public async mkdir(path:string) {
|
|
// Note that mkdirp() does not throw an error if the directory
|
|
// could not be created. This would make the synchroniser to
|
|
// incorrectly try to sync with a non-existing dir:
|
|
// https://github.com/laurent22/joplin/issues/2117
|
|
const r = await fs.mkdirp(path);
|
|
if (!(await this.exists(path))) throw new Error(`Could not create directory: ${path}`);
|
|
return r;
|
|
}
|
|
|
|
public async stat(path:string) {
|
|
try {
|
|
const stat = await fs.stat(path);
|
|
return {
|
|
birthtime: stat.birthtime,
|
|
mtime: stat.mtime,
|
|
isDirectory: () => stat.isDirectory(),
|
|
path: path,
|
|
size: stat.size,
|
|
};
|
|
} catch (error) {
|
|
if (error.code == 'ENOENT') return null;
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
public async setTimestamp(path:string, timestampDate:any) {
|
|
return fs.utimes(path, timestampDate, timestampDate);
|
|
}
|
|
|
|
public async readDirStats(path:string, options:any = null) {
|
|
if (!options) options = {};
|
|
if (!('recursive' in options)) options.recursive = false;
|
|
|
|
let items = [];
|
|
try {
|
|
items = await fs.readdir(path);
|
|
} catch (error) {
|
|
throw this.fsErrorToJsError_(error);
|
|
}
|
|
|
|
let output = [];
|
|
for (let i = 0; i < items.length; i++) {
|
|
const item = items[i];
|
|
const stat = await this.stat(`${path}/${item}`);
|
|
if (!stat) continue; // Has been deleted between the readdir() call and now
|
|
stat.path = stat.path.substr(path.length + 1);
|
|
output.push(stat);
|
|
|
|
output = await this.readDirStatsHandleRecursion_(path, stat, output, options);
|
|
}
|
|
return output;
|
|
}
|
|
|
|
public async open(path:string, mode:any) {
|
|
try {
|
|
return await fs.open(path, mode);
|
|
} catch (error) {
|
|
throw this.fsErrorToJsError_(error, path);
|
|
}
|
|
}
|
|
|
|
public async close(handle:any) {
|
|
try {
|
|
return await fs.close(handle);
|
|
} catch (error) {
|
|
throw this.fsErrorToJsError_(error, '');
|
|
}
|
|
}
|
|
|
|
public async readFile(path:string, encoding:string = 'utf8') {
|
|
try {
|
|
if (encoding === 'Buffer') return await fs.readFile(path); // Returns the raw buffer
|
|
return await fs.readFile(path, encoding);
|
|
} catch (error) {
|
|
throw this.fsErrorToJsError_(error, path);
|
|
}
|
|
}
|
|
|
|
// Always overwrite destination
|
|
public async copy(source:string, dest:string) {
|
|
try {
|
|
return await fs.copy(source, dest, { overwrite: true });
|
|
} catch (error) {
|
|
throw this.fsErrorToJsError_(error, source);
|
|
}
|
|
}
|
|
|
|
public async unlink(path:string) {
|
|
try {
|
|
await fs.unlink(path);
|
|
} catch (error) {
|
|
if (error.code === 'ENOENT') return; // Don't throw if the file does not exist
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
public async readFileChunk(handle:any, length:number, encoding:string = 'base64') {
|
|
// let buffer = new Buffer(length);
|
|
let buffer = Buffer.alloc(length);
|
|
const result = await fs.read(handle, buffer, 0, length, null);
|
|
if (!result.bytesRead) return null;
|
|
buffer = buffer.slice(0, result.bytesRead);
|
|
if (encoding === 'base64') return buffer.toString('base64');
|
|
if (encoding === 'ascii') return buffer.toString('ascii');
|
|
throw new Error(`Unsupported encoding: ${encoding}`);
|
|
}
|
|
|
|
public resolve(path:string) {
|
|
return require('path').resolve(path);
|
|
}
|
|
|
|
// Resolves the provided relative path to an absolute path within baseDir. The function
|
|
// also checks that the absolute path is within baseDir, to avoid security issues.
|
|
// It is expected that baseDir is a safe path (not user-provided).
|
|
public resolveRelativePathWithinDir(baseDir:string, relativePath:string) {
|
|
const resolvedPath = nodeResolve(baseDir, relativePath);
|
|
if (resolvedPath.indexOf(baseDir) !== 0) throw new Error('Resolved path for relative path "' + relativePath + '" is not within base directory "' + baseDir + '"');
|
|
return resolvedPath;
|
|
}
|
|
|
|
}
|