fs-extra#writeFile TypeScript Examples
The following examples show how to use
fs-extra#writeFile.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Exporter.ts From joplin-utils with MIT License | 6 votes |
async writeResource(list: ExportResource[]) {
await mkdirp(path.resolve(this.config.rootPath, 'resources'))
await AsyncArray.forEach(list, async (item) => {
await writeFile(
path.resolve(this.config.rootPath, 'resources', item.fileTitle),
await resourceApi.fileByResourceId(item.id),
)
})
}
Example #2
Source File: Application.ts From joplin-utils with MIT License | 6 votes |
writeNote(noteList: (CommonNote & { text: string })[]) {
return PromiseUtil.warpOnEvent(async (events: ProcessEvents) => {
let i = 0
await AsyncArray.forEach(noteList, async (item) => {
i++
events.process({ rate: i, all: noteList.length, title: item.title })
await writeFile(
path.resolve(this.handler.notePath, (this.handler.formatFileName ?? ((id) => id))(item.id) + '.md'),
item.text,
)
})
})
}
Example #3
Source File: Application.ts From joplin-utils with MIT License | 6 votes |
copyResources(resourceList: CommonResource[]) {
return PromiseUtil.warpOnEvent(async (events: ProcessEvents) => {
let i = 0
await AsyncArray.forEach(
resourceList,
asyncLimiting(async (resource: CommonResource) => {
i++
events.process({
rate: i,
all: resourceList.length,
title: resource.title,
})
const fileName = resource.id + '.' + resource.file_extension
await writeFile(
path.resolve(this.handler.resourcePath, fileName),
await resourceApi.fileByResourceId(resource.id),
)
}, 10),
)
})
}
Example #4
Source File: BinCommand.ts From joplin-blog with MIT License | 6 votes |
/**
* 生成类型定义
*/
async gen(options: { input?: string }) {
if (!options.input) {
return
}
const i18nFolderPath = path.resolve(options.input)
const list = await readdir(i18nFolderPath)
const i18nJsonPathList = list
.filter((name) => name.endsWith('.json'))
.map((name) => path.resolve(i18nFolderPath, name))
const jsonList = await AsyncArray.map(i18nJsonPathList, (filePath) =>
readJSON(filePath),
)
const translateHandler = new TranslateHandler()
const configList = translateHandler.parse(jsonList)
const dts = translateHandler.build(configList)
await writeFile(path.resolve(i18nFolderPath, 'index.d.ts'), dts)
}
Example #5
Source File: Sticker.ts From wa-sticker-formatter with MIT License | 6 votes |
/**
* Saves the sticker to a file
* @param [filename] - Filename to save the sticker to
* @returns filename
* @example
* const sticker = new Sticker('./image.png')
* sticker.toFile('./image.webp')
*/
public toFile = async (filename = this.defaultFilename): Promise<string> => {
await writeFile(filename, await this.build())
return filename
}
Example #6
Source File: write-properties-file.ts From relate with GNU General Public License v3.0 | 6 votes |
export function writePropertiesFile(path: string, properties: PropertyEntries): Promise<void> {
const asText = join(
map(properties, ([key, val]) => {
const nowhitespace = trim(val);
return nowhitespace ? join([key, val], PROPERTIES_SEPARATOR) : key;
}),
NEW_LINE,
);
return writeFile(path, asText, 'utf8');
}
Example #7
Source File: Exporter.ts From joplin-utils with MIT License | 6 votes |
async writeNote(list: ExportNote[]) {
await AsyncArray.forEach(list, async (item) => {
const notePath = path.resolve(
this.config.rootPath,
'notes',
item.filePath,
)
await writeFile(notePath, item.body)
})
}
Example #8
Source File: main.ts From DefinitelyTyped-tools with MIT License | 6 votes |
export async function withFileLock(lockFilePath: string, cb: () => Promise<void>): Promise<LockFileResult> {
console.log("Checking for lock file...");
if (await pathExists(lockFilePath)) {
const lastRunStartTimestamp = (await tryReadJson(lockFilePath, isLockfileFormat))?.timestamp || currentTimeStamp();
const elapsedSeconds = (Date.now() - Date.parse(lastRunStartTimestamp)) / 1000;
if (elapsedSeconds < getFunctionTimeoutSeconds()) {
console.log("Lock file exists; new run not triggered.");
return { triggered: false, timestamp: lastRunStartTimestamp };
}
}
console.log("Lock file does not exist; writing lock file and running.");
await writeFile(lockFilePath, JSON.stringify({ timestamp: currentTimeStamp() }));
cb().then(
() => remove(lockFilePath),
async (error) => {
console.error(error?.stack || error?.message || error);
applicationinsights.defaultClient.trackException({
exception: error,
});
await remove(lockFilePath);
process.exit(1);
}
);
return { triggered: true };
}
Example #9
Source File: dump.ts From cli with Apache License 2.0 | 6 votes |
private async writeChunks(allResults: SearchResult[]) {
const {flags} = await this.parse(Dump);
let currentChunk = 0;
while (allResults.length) {
const chunk = allResults.splice(0, flags.chunkSize);
const data = chunk.map((r) => r.raw);
const fields = without(
Object.keys(chunk[0].raw),
flags.fieldsToExclude || []
);
const parser = new Parser({fields});
await writeFile(
`${flags.destination}/${flags.name}${
currentChunk > 0 ? `_${currentChunk + 1}` : ''
}.csv`,
parser.parse(data)
);
currentChunk++;
}
}
Example #10
Source File: install-manager.ts From malagu with MIT License | 6 votes |
async render(): Promise<void> {
const pkg = require('../../package.json');
const packageJsonPath = resolve(this.outputDir, 'package.json');
let packageContent = await readFile(packageJsonPath, { encoding: 'utf8' });
packageContent = packageContent.replace(/{{ version }}/g, pkg.version);
if (this.opts.forceInstallingComponent) {
const runtimePkg = JSON.parse(packageContent);
if (runtimePkg.malagu?.components || runtimePkg.malagu?.devComponents) {
const { components, devComponents } = runtimePkg.malagu;
runtimePkg.dependencies = { ...runtimePkg.dependencies, ...components };
runtimePkg.devDependencies = { ...runtimePkg.devDependencies, ...devComponents };
packageContent = JSON.stringify(runtimePkg, undefined, 2);
}
}
await writeFile(packageJsonPath, packageContent);
}
Example #11
Source File: HandlerService.ts From joplin-utils with MIT License | 6 votes |
async openResource(id: string) {
const resource = await safePromise(resourceApi.get(id, ['id', 'title', 'filename', 'file_extension']))
if (!resource) {
vscode.window.showWarningMessage(i18n.t('Resource does not exist'))
return
}
if (GlobalContext.openResourceMap.has(id)) {
const filePath = GlobalContext.openResourceMap.get(id)!
await this.openFileService.openByVSCode(filePath)
return
}
// 如果标题包含后缀则不再拼接后缀名(后缀名其实也是不准的)
const fileName =
resource.filename ||
(/\..*$/.test(resource.title) ? resource.title : resource.title + '.' + resource.file_extension)
const tempResourceDirPath = path.resolve(GlobalContext.context.globalStorageUri.fsPath, '.tempResource')
const filePath = path.resolve(tempResourceDirPath, filenamify(fileName))
const buffer = await resourceApi.fileByResourceId(id)
await writeFile(filePath, buffer)
GlobalContext.openResourceMap.set(id, filePath)
console.log('open file: ', filePath)
await this.openFileService.openByVSCode(filePath)
}
Example #12
Source File: JoplinNoteCommandService.ts From joplin-utils with MIT License | 6 votes |
/**
* open note in vscode
* @param item
*/
async openNote(item: Omit<FolderOrNote, 'item'> & { item: JoplinListNote }) {
logger.info('openNote start', item)
// 如果已经打开了笔记,则应该切换并且保持 treeview 的焦点
if (GlobalContext.openNoteMap.has(item.id)) {
const filePath = GlobalContext.openNoteMap.get(item.id)!
if (vscode.window.activeTextEditor?.document.fileName !== filePath) {
await vscode.commands.executeCommand('vscode.open', vscode.Uri.file(filePath))
}
await this.focus(item.id)
return
}
const tempNoteDirPath = path.resolve(GlobalContext.context.globalStorageUri.fsPath, '.tempNote')
const filename = item.label + (GlobalContext.openNoteMap.get(item.label) ? item.id : '')
const tempNotePath = path.resolve(tempNoteDirPath, filenamify(`${filename}.md`))
const note = await noteApi.get(item.id, ['body', 'title'])
const content = note.body.startsWith('# ')
? note.body
: (note.title.startsWith('# ') ? '' : '# ') + note.title + '\n\n' + note.body
await writeFile(tempNotePath, content)
logger.info('openNote write tempFile', tempNotePath)
GlobalContext.openNoteMap.set(item.id, tempNotePath)
GlobalContext.openNoteResourceMap.set(item.id, await noteApi.resourcesById(item.id))
await vscode.commands.executeCommand('vscode.open', vscode.Uri.file(tempNotePath))
logger.info('openNote open tempFile')
}
Example #13
Source File: download-ui5-resources.ts From ui5-language-assistant with Apache License 2.0 | 6 votes |
async function writeUrlToFile(url: string, file: string): Promise<void> {
// Don't download the file if it already exists
if (await pathExists(file)) {
return;
}
log(`fetching from ${url}`);
const response = await fetch(url);
if (!response.ok) {
error(`error fetching from ${url}`);
return;
}
const text = await response.text();
if (text === "{}") {
// These files don't add anything to the model but they return an error in strict mode
log(`empty object returned from ${url}`);
return;
}
await writeFile(file, text);
}
Example #14
Source File: deleteDuplicateNote.test.ts From joplin-utils with MIT License | 6 votes |
describe('删除重复的笔记', () => {
const tempPath = path.resolve(__dirname, '.temp/exportDuplicationNoteList')
beforeEach(async () => {
await remove(tempPath)
await mkdirp(tempPath)
})
it('加载所有重复的笔记', async () => {
const noteList = await PageUtil.pageToAllList(noteApi.list, {
fields: ['id', 'title', 'user_updated_time', 'body'],
})
const map = groupBy(noteList, (note) => note.title)
const deleteNoteList = Object.entries(map)
.filter(([_, notes]) => notes.length > 1)
.map(
([_, notes]) =>
sortBy(
notes as Pick<
NoteProperties,
'user_updated_time' | 'title' | 'body' | 'id'
>[],
(note) => note.user_updated_time,
)[0],
)
await mkdirp(tempPath)
for (let note of deleteNoteList) {
const filePath = path.resolve(tempPath, note.title.trim() + '.md')
try {
await writeFile(filePath, note.body, {
encoding: 'utf-8',
})
await noteApi.remove(note.id)
} catch (e) {
console.log('删除失败: ', note.title)
}
}
})
})
Example #15
Source File: AttachmentsFilesService.ts From node-experience with MIT License | 6 votes |
static async getTempFilesAttachments(emailNotification: EmailNotification): Promise<IFilesAttachments[]>
{
const filesystem = FilesystemFactory.create();
emailNotification.tempFilesAttachments = await Promise.all(emailNotification.attachedFiles.map(async(_file) =>
{
const stream = await filesystem.downloadStreamFile(_file);
const fileName = `${_file.originalName}.${_file.extension}`;
const uqFileName = `${_file.name}.${_file.extension}`;
const tempDir = PATH.join(`${__dirname}/../../../temp`);
const dirName = PATH.join(`${tempDir}/${uqFileName}`);
// eslint-disable-next-line no-unused-expressions
!existsSync(tempDir) && mkdirSync(tempDir);
void await writeFile(dirName, '01011');
const ws = createWriteStream(dirName);
stream.pipe(ws);
return {
filename: fileName,
path:dirName
};
}));
return emailNotification.tempFilesAttachments;
}
Example #16
Source File: videoToGif.ts From wa-sticker-formatter with MIT License | 6 votes |
videoToGif = async (data: Buffer): Promise<Buffer> => {
const filename = `${tmpdir()}/${Math.random().toString(36)}`
const [video, gif] = ['video', 'gif'].map((ext) => `${filename}.${ext}`)
await writeFile(video, data)
await new Promise((resolve) => {
ffmpeg(video).save(gif).on('end', resolve)
})
const buffer = await readFile(gif)
;[video, gif].forEach((file) => unlink(file))
return buffer
}
Example #17
Source File: ResourceWriter.ts From joplin-blog with MIT License | 5 votes |
async write(note: CommonNote & { text: string }) {
await writeFile(
path.resolve(this.config.postPath, note.id + '.md'),
note.text,
)
}
Example #18
Source File: WikiDocsifyIntegrated.ts From joplin-utils with MIT License | 5 votes |
async init() {
await writeFile(path.resolve(this.config.rootPath, '_sidebar.md'), await this.buildSidebar())
}
Example #19
Source File: Application.test.ts From joplin-utils with MIT License | 5 votes |
describe('测试 Application', () => {
it.skip('单独测试 HexoIntegrated', async () => {
const hexoHandler = new BlogHexoIntegrated({
tag: 'blog',
rootPath: path.resolve(__dirname, '.temp/hexo-example'),
})
const noteId = '21a3eba7f4b445ccbc123bf52831d387'
const { user_created_time, user_updated_time, ...note } = await noteApi.get(noteId, [
'id',
'title',
'body',
'user_created_time',
'user_updated_time',
])
const tags = await noteApi.tagsById(noteId)
const resources = await noteApi.resourcesById(noteId, ['id', 'title', 'file_extension', 'user_updated_time'])
const res = hexoHandler.parse({
...note,
createdTime: user_created_time,
updatedTime: user_updated_time,
tags,
resources,
})
await writeFile(path.resolve(__dirname, '.temp/test.md'), res)
})
it('集成 HexoIntegrated', async () => {
const application = new Application(
{ token: config.token, baseUrl: config.baseUrl, tag: 'blog' },
new BlogHexoIntegrated({
tag: 'blog',
rootPath: path.resolve(__dirname, '.temp/hexo-example'),
}),
)
const generatorEvents = new GeneratorEventsImpl()
await application
.gen()
.on('readNoteAttachmentsAndTags', generatorEvents.readNoteAttachmentsAndTags)
.on('parseAndWriteNotes', generatorEvents.parseAndWriteNotes)
.on('writeNote', generatorEvents.writeNote)
.on('copyResources', generatorEvents.copyResources)
}, 100_000)
it('集成 VuepressIntegrated', async () => {
const application = new Application(
{
token: config.token,
baseUrl: config.baseUrl,
tag: 'blog',
},
new BlogVuepressIntegrated({
rootPath: path.resolve(__dirname, '.temp/vuepress-example'),
tag: 'blog',
}),
)
const generatorEvents = new GeneratorEventsImpl()
await application
.gen()
.on('readNoteAttachmentsAndTags', generatorEvents.readNoteAttachmentsAndTags)
.on('parseAndWriteNotes', generatorEvents.parseAndWriteNotes)
.on('writeNote', generatorEvents.writeNote)
.on('copyResources', generatorEvents.copyResources)
}, 100_000)
})
Example #20
Source File: wikiWorker.ts From TidGi-Desktop with Mozilla Public License 2.0 | 5 votes |
function executeZxScript(file: IZxFileInput, zxPath: string): Observable<IZxWorkerMessage> {
/** this will be observed in src/services/native/index.ts */
return new Observable<IZxWorkerMessage>((observer) => {
observer.next({ type: 'control', actions: ZxWorkerControlActions.start });
void (async function executeZxScriptIIFE() {
try {
let filePathToExecute = '';
if ('fileName' in file) {
const temporaryDirectory = await mkdtemp(`${tmpdir()}${path.sep}`);
filePathToExecute = path.join(temporaryDirectory, file.fileName);
await writeFile(filePathToExecute, file.fileContent);
} else if ('filePath' in file) {
filePathToExecute = file.filePath;
}
const execution = fork(zxPath, [filePathToExecute], { silent: true });
execution.on('close', function (code) {
observer.next({ type: 'control', actions: ZxWorkerControlActions.ended, message: `child process exited with code ${String(code)}` });
});
execution.stdout?.on('data', (stdout: Buffer) => {
// if there are multiple console.log, their output will be concatenated into this stdout. And some of them are not intended to be executed. We use TW_SCRIPT_SEPARATOR to allow user determine the range they want to execute in the $tw context.
const message = String(stdout);
const zxConsoleLogMessages = extractTWContextScripts(message);
// log and execute each different console.log result.
zxConsoleLogMessages.forEach(({ messageType, content }) => {
if (messageType === 'script') {
observer.next({ type: 'execution', message: content });
if (wikiInstance === undefined) {
observer.next({ type: 'stderr', message: `Error in executeZxScript(): $tw is undefined` });
} else {
const context = getTWVmContext(wikiInstance);
const twExecutionResult = executeScriptInTWContext(content, context);
observer.next({ type: 'stdout', message: twExecutionResult.join('\n\n') });
}
} else {
observer.next({ type: 'stdout', message: content });
}
});
});
execution.stderr?.on('data', (stdout: Buffer) => {
observer.next({ type: 'stderr', message: String(stdout) });
});
execution.on('error', (error) => {
observer.next({ type: 'stderr', message: `${error.message} ${error.stack ?? ''}` });
});
} catch (error) {
const message = `zx script's executeZxScriptIIFE() failed with error ${(error as Error).message} ${(error as Error).stack ?? ''}`;
observer.next({ type: 'control', actions: ZxWorkerControlActions.error, message });
}
})();
});
}
Example #21
Source File: WikiDocsifyIntegrated.ts From joplin-blog with MIT License | 5 votes |
async init() {
await this.resourceWriter.clean()
await writeFile(
path.resolve(this.config.rootPath, '_sidebar.md'),
await this.buildSidebar(),
)
}
Example #22
Source File: postInstall.ts From cli with MIT License | 5 votes |
postInstallModule = async (
moduleList: { name: string; version: string }[]
) => {
const info = await postInstall();
if (!info) {
return;
}
const { cwd, pkg } = info;
const { registry, npm } = findNpm();
const modules = [];
for (const { name, version } of moduleList) {
if (pkg?.dependencies?.[name] || pkg?.devDependencies?.[name]) {
continue;
}
console.log('[midway] auto install', name);
modules.push(name + '@' + version);
}
if (!modules.length) {
return;
}
const installingLock = join(
cwd,
`node_modules/.midwayjs-cli/postInstallLock/${modules
.join('_')
.replace(/\//g, '_')}.lock`
);
if (existsSync(installingLock)) {
return;
}
await ensureFile(installingLock);
await writeFile(installingLock, JSON.stringify({ cwd, npm, registry }));
await installNpm({
baseDir: cwd,
mode: ['save-dev'],
register: ['yarn'].includes(npm) ? 'npm' : npm,
registerPath: registry,
moduleName: modules.join(' '),
slience: true,
});
console.log('[midway] auto install complete');
return;
}
Example #23
Source File: yarn.ts From malagu with MIT License | 5 votes |
writeLockfile(lockfilePath: string, content: string) {
return writeFile(lockfilePath, content, 'utf8');
}
Example #24
Source File: convert.ts From wa-sticker-formatter with MIT License | 5 votes |
convert = async (
data: Buffer,
mime: string,
{ quality = 100, background = defaultBg, type = StickerTypes.DEFAULT }: IStickerOptions
): Promise<Buffer> => {
const isVideo = mime.startsWith('video')
let image = isVideo ? await videoToGif(data) : data
const isAnimated = isVideo || mime.includes('gif')
if (isAnimated && ['crop', 'circle'].includes(type)) {
const filename = `${tmpdir()}/${Math.random().toString(36)}.webp`
await writeFile(filename, image)
;[image, type] = [await crop(filename), type === 'circle' ? StickerTypes.CIRCLE : StickerTypes.DEFAULT]
}
const img = sharp(image, { animated: type !== 'circle' }).toFormat('webp')
if (type === 'crop')
img.resize(512, 512, {
fit: fit.cover
})
if (type === 'full')
img.resize(512, 512, {
fit: fit.contain,
background
})
if (type === 'circle') {
img.resize(512, 512, {
fit: fit.cover
}).composite([
{
input: Buffer.from(
`<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><circle cx="256" cy="256" r="256" fill="${background}"/></svg>`
),
blend: 'dest-in'
}
])
}
return await img
.webp({
quality,
lossless: false
})
.toBuffer()
}
Example #25
Source File: Application.test.ts From joplin-blog with MIT License | 4 votes |
describe('测试 Application', () => {
const joplinConfig: typeof config = {
token: process.env.token!,
port: Number.parseInt(process.env.port!),
}
it('单独测试 HexoIntegrated', async () => {
config.token = joplinConfig.token
config.port = joplinConfig.port
const hexoHandler = new BlogHexoIntegrated({
tag: 'blog',
rootPath: path.resolve(__dirname, 'temp/hexo-example'),
})
const noteId = '21a3eba7f4b445ccbc123bf52831d387'
const {
user_created_time,
user_updated_time,
...note
} = await noteApi.get(noteId, [
'id',
'title',
'body',
'user_created_time',
'user_updated_time',
])
const tags = await noteApi.tagsById(noteId)
const resources = await noteApi.resourcesById(noteId, [
'id',
'title',
'file_extension',
])
const res = hexoHandler.parse({
...note,
createdTime: user_created_time,
updatedTime: user_updated_time,
tags,
resources,
})
await writeFile(path.resolve(__dirname, 'temp/test.md'), res)
})
it('集成 HexoIntegrated', async () => {
const application = new Application(
{
token: joplinConfig.token,
port: joplinConfig.port,
tag: 'blog',
joplinProfilePath: path.resolve(
'C:/Users/rxliuli/.config/joplindev-desktop',
),
},
new BlogHexoIntegrated({
tag: 'blog',
rootPath: path.resolve(__dirname, 'temp/hexo-example'),
}),
)
const generatorEvents = new GeneratorEventsImpl()
await application
.gen()
.on(
'readNoteAttachmentsAndTags',
generatorEvents.readNoteAttachmentsAndTags,
)
.on('parseAndWriteNotes', generatorEvents.parseAndWriteNotes)
.on('writeNote', generatorEvents.writeNote)
.on('copyResources', generatorEvents.copyResources)
}, 100_000)
it('集成 VuepressIntegrated', async () => {
const application = new Application(
{
token: joplinConfig.token,
port: joplinConfig.port,
tag: 'blog',
joplinProfilePath: path.resolve(
'C:/Users/rxliuli/.config/joplindev-desktop',
),
},
new BlogVuepressIntegrated({
rootPath: path.resolve(__dirname, 'temp/vuepress-example'),
tag: 'blog',
}),
)
const generatorEvents = new GeneratorEventsImpl()
await application
.gen()
.on(
'readNoteAttachmentsAndTags',
generatorEvents.readNoteAttachmentsAndTags,
)
.on('parseAndWriteNotes', generatorEvents.parseAndWriteNotes)
.on('writeNote', generatorEvents.writeNote)
.on('copyResources', generatorEvents.copyResources)
}, 100_000)
})
Example #26
Source File: WindowDecorations.test.ts From dendron with GNU Affero General Public License v3.0 | 4 votes |
suite("GIVEN a text document with decorations", function () {
const CREATED = "1625648278263";
const UPDATED = "1625758878263";
const FNAME = "bar";
describe("AND GIVEN links ", () => {
function checkTimestampsDecorated({
decorations,
document,
}: {
decorations: Awaited<ReturnType<typeof updateDecorations>>;
document: vscode.TextDocument;
}) {
const { allDecorations } = decorations;
const timestampDecorations = getDecorations({
allDecorations,
decorationType: EDITOR_DECORATION_TYPES.timestamp,
});
expect(timestampDecorations!.length).toEqual(2);
// check that the decorations are at the right locations
checkDecoration({
text: CREATED,
decorations: timestampDecorations,
document,
});
checkDecoration({
text: UPDATED,
decorations: timestampDecorations,
document,
});
}
describeMultiWS(
"",
{
preSetupHook: async ({ wsRoot, vaults }) => {
await NoteTestUtilsV4.createNote({
fname: "withHeader",
vault: vaults[0],
wsRoot,
body: "## ipsam adipisci",
});
await NoteTestUtilsV4.createNote({
fname: "tags.bar",
vault: vaults[0],
wsRoot,
});
await NoteTestUtilsV4.createNote({
fname: FNAME,
body: [
"Ut incidunt id commodi. ^anchor-1",
"",
"* Et repudiandae optio ut suscipit illum hic vel.",
"* Aut suscipit veniam nobis veniam reiciendis. ^anchor-2",
" * Sit sed accusamus saepe voluptatem sint animi quis animi. ^anchor-3",
"* Dolores suscipit maiores nulla accusamus est.",
"",
"#foo",
"#bar",
"#foo",
"[[root]]",
"",
"@Hamilton.Margaret",
"",
"[[with alias|root]]",
"",
"![[root.*#head]]",
"",
"[[withHeader#ipsam-adipisci]]",
"[[withHeader#does-not-exist]]",
"",
"[[does.not.exist]]",
"",
"[[/test.txt]]",
"[[/test.txt#L3]]",
].join("\n"),
props: {
created: _.toInteger(CREATED),
updated: _.toInteger(UPDATED),
tags: ["foo", "bar"],
},
vault: vaults[0],
wsRoot,
});
await writeFile(
path.join(wsRoot, "test.txt"),
"et\nnam\nvelit\nlaboriosam\n"
);
},
},
() => {
// TODO: this is currently a regression from refactoring engine
test.skip("THEN links are decorated", async () => {
const { editor } = await getNote({ fname: FNAME });
const document = editor.document;
const decorations = (await updateDecorations(editor))!;
const { allDecorations } = decorations;
checkTimestampsDecorated({ decorations, document });
const blockAnchorDecorations = allDecorations!.get(
EDITOR_DECORATION_TYPES.blockAnchor
);
expect(blockAnchorDecorations!.length).toEqual(3);
// check that the decorations are at the right locations
expect(
isTextDecorated("^anchor-1", blockAnchorDecorations!, document)
).toBeTruthy();
expect(
isTextDecorated("^anchor-2", blockAnchorDecorations!, document)
).toBeTruthy();
expect(
isTextDecorated("^anchor-3", blockAnchorDecorations!, document)
).toBeTruthy();
const wikilinkDecorations = getDecorations({
allDecorations,
decorationType: EDITOR_DECORATION_TYPES.wikiLink,
});
expect(wikilinkDecorations!.length).toEqual(8);
expect(
isTextDecorated("[[root]]", wikilinkDecorations!, document)
).toBeTruthy();
expect(
isTextDecorated(
"[[with alias|root]]",
wikilinkDecorations!,
document
)
).toBeTruthy();
expect(
isTextDecorated("#bar", wikilinkDecorations!, document)
).toBeTruthy();
expect(
isTextDecorated("![[root.*#head]]", wikilinkDecorations!, document)
).toBeTruthy();
expect(
isTextDecorated(
"[[withHeader#ipsam-adipisci]]",
wikilinkDecorations!,
document
)
).toBeTruthy();
expect(
isTextDecorated("[[/test.txt]]", wikilinkDecorations!, document)
).toBeTruthy();
expect(
isTextDecorated("[[/test.txt#L3]]", wikilinkDecorations!, document)
).toBeTruthy();
const aliasDecorations = allDecorations!.get(
EDITOR_DECORATION_TYPES.alias
);
expect(aliasDecorations!.length).toEqual(1);
expect(
isTextDecorated("with alias", aliasDecorations!, document)
).toBeTruthy();
const brokenWikilinkDecorations = allDecorations!.get(
EDITOR_DECORATION_TYPES.brokenWikilink
);
expect(brokenWikilinkDecorations!.length).toEqual(5);
expect(
isTextDecorated(
"[[does.not.exist]]",
brokenWikilinkDecorations!,
document
)
).toBeTruthy();
expect(
isTextDecorated(
"[[withHeader#does-not-exist]]",
brokenWikilinkDecorations!,
document
)
).toBeTruthy();
expect(
isTextDecorated(
"@Hamilton.Margaret",
brokenWikilinkDecorations!,
document
)
).toBeTruthy();
expect(
isTextDecorated("#foo", brokenWikilinkDecorations!, document)
).toBeTruthy();
return;
});
}
);
});
describe("AND GIVEN task notes", () => {
describeMultiWS(
"",
{
preSetupHook: async ({ vaults, wsRoot }) => {
await NoteTestUtilsV4.createNote({
fname: "with.all",
vault: vaults[0],
wsRoot,
custom: {
status: "done",
owner: "grace",
priority: "H",
due: "2021.10.29",
tags: "foo",
},
});
await NoteTestUtilsV4.createNote({
fname: "without.status",
vault: vaults[0],
wsRoot,
custom: {
owner: "grace",
priority: "high",
tags: ["foo", "bar"],
},
});
await NoteTestUtilsV4.createNote({
fname: "without.due",
vault: vaults[0],
wsRoot,
custom: {
status: "",
priority: "low",
},
});
await NoteTestUtilsV4.createNote({
fname: "not.a.task",
vault: vaults[0],
wsRoot,
});
await NoteTestUtilsV4.createNote({
fname: FNAME,
body: [
"* [[with.all]]",
"* foo [[without.status]] bar",
"",
"[[without.due]]",
"",
"[[not.a.task]]",
"",
].join("\n"),
vault: vaults[0],
wsRoot,
});
},
},
() => {
test("THEN task notes are highlighted", async () => {
const { editor } = await getNote({ fname: FNAME });
const document = editor.document;
const { allDecorations } = (await updateDecorations(editor))!;
const taskDecorations = allDecorations!.get(
EDITOR_DECORATION_TYPES.taskNote
);
taskDecorations?.sort((decoration) => decoration.range.start.line); // for easier testing
expect(taskDecorations!.length).toEqual(3);
// check that the decorations are at the right locations
expect(
isTextDecorated("[[with.all]]", taskDecorations!, document)
).toBeTruthy();
expect(
isTextDecorated("[[without.status]]", taskDecorations!, document)
).toBeTruthy();
expect(
isTextDecorated("[[without.due]]", taskDecorations!, document)
).toBeTruthy();
expect(
taskDecorations![0].renderOptions?.before?.contentText
).toEqual("[ ] ");
expect(taskDecorations![0].renderOptions?.after?.contentText).toEqual(
" priority:low"
);
expect(
taskDecorations![1].renderOptions?.before?.contentText
).toEqual("[x] ");
expect(taskDecorations![1].renderOptions?.after?.contentText).toEqual(
" due:2021.10.29 @grace priority:high #foo"
);
expect(
taskDecorations![2].renderOptions?.before?.contentText
).toBeFalsy();
expect(taskDecorations![2].renderOptions?.after?.contentText).toEqual(
" @grace priority:high #foo #bar"
);
});
}
);
});
describe("AND GIVEN file with wikilinks to itself", () => {
describeMultiWS(
"",
{
preSetupHook: async ({ vaults, wsRoot }) => {
await NoteTestUtilsV4.createNote({
fname: FNAME,
body: [
"Ut incidunt id commodi. ^anchor-1",
"",
"[[#^anchor-1]]",
"[[#^anchor-not-exists]]",
"![[#^anchor-1]]",
"![[#^anchor-not-exists]]",
"![[#^anchor-1:#*]]",
"![[#^anchor-not-exists]]",
].join("\n"),
vault: vaults[0],
wsRoot,
});
},
},
() => {
test("THEN links are highlighted", async () => {
const { editor } = await getNote({ fname: FNAME });
const document = editor.document;
const { allDecorations } = (await updateDecorations(editor))!;
const wikilinkDecorations = allDecorations!.get(
EDITOR_DECORATION_TYPES.wikiLink
);
expect(wikilinkDecorations!.length).toEqual(3);
expect(
isTextDecorated("[[#^anchor-1]]", wikilinkDecorations!, document)
).toBeTruthy();
expect(
isTextDecorated("![[#^anchor-1]]", wikilinkDecorations!, document)
).toBeTruthy();
expect(
isTextDecorated(
"![[#^anchor-1:#*]]",
wikilinkDecorations!,
document
)
).toBeTruthy();
const brokenWikilinkDecorations = allDecorations!.get(
EDITOR_DECORATION_TYPES.brokenWikilink
);
expect(brokenWikilinkDecorations!.length).toEqual(3);
expect(
isTextDecorated(
"[[#^anchor-not-exists]]",
brokenWikilinkDecorations!,
document
)
).toBeTruthy();
expect(
isTextDecorated(
"![[#^anchor-not-exists]]",
brokenWikilinkDecorations!,
document
)
).toBeTruthy();
expect(
isTextDecorated(
"![[#^anchor-not-exists]]",
brokenWikilinkDecorations!,
document
)
).toBeTruthy();
});
}
);
});
describe("AND given wildcard references", () => {
describeMultiWS(
"",
{
preSetupHook: async ({ vaults, wsRoot }) => {
await NoteTestUtilsV4.createNote({
fname: FNAME,
body: ["![[foo.bar.*]]"].join("\n"),
vault: vaults[0],
wsRoot,
});
},
},
() => {
test("THEN links are highlighted", async () => {
const { editor } = await getNote({ fname: FNAME });
const document = editor.document;
const { allDecorations } = (await updateDecorations(editor))!;
const wikilinkDecorations = allDecorations!.get(
EDITOR_DECORATION_TYPES.wikiLink
);
expect(wikilinkDecorations!.length).toEqual(1);
expect(
isTextDecorated("![[foo.bar.*]]", wikilinkDecorations!, document)
).toBeTruthy();
});
}
);
});
describe("AND for long notes", () => {
const FNAME = "test.note";
const repeat = 228;
describeMultiWS(
"",
{
preSetupHook: async ({ vaults, wsRoot }) => {
await NoteTestUtilsV4.createNote({
fname: FNAME,
body: _.repeat("[[does.not.exist]] #does.not.exist\n", repeat),
vault: vaults[0],
wsRoot,
});
},
},
() => {
test("THEN only the visible range should be decorated", async () => {
const { editor } = await getNote({ fname: FNAME });
const document = editor.document;
const { allDecorations } = (await updateDecorations(editor))!;
// This note is really long, so not all links in it will be decorated (there are repeat * 2 many links)
const brokenWikilinkDecorations = allDecorations!.get(
EDITOR_DECORATION_TYPES.brokenWikilink
);
expect(brokenWikilinkDecorations!.length < repeat * 2).toBeTruthy();
expect(
isTextDecorated(
"[[does.not.exist]]",
brokenWikilinkDecorations!,
document
)
).toBeTruthy();
expect(
isTextDecorated(
"#does.not.exist",
brokenWikilinkDecorations!,
document
)
).toBeTruthy();
});
}
);
});
describe("AND WHEN disabled", () => {
describeMultiWS(
"",
{
modConfigCb: (config) => {
config.workspace!.enableEditorDecorations = false;
return config;
},
preSetupHook: async ({ vaults, wsRoot }) => {
await NoteTestUtilsV4.createNote({
fname: FNAME,
body: "[[does.not.exist]] #does.not.exist\n",
vault: vaults[0],
wsRoot,
});
},
},
() => {
test("THEN decorations are not displayed ", async () => {
const { editor } = await getNote({ fname: FNAME });
const { allDecorations, allWarnings } = (await updateDecorations(
editor
))!;
expect(allDecorations).toBeFalsy();
expect(allWarnings).toBeFalsy();
});
}
);
});
describe("AND GIVEN warnings in document", () => {
describeMultiWS(
"AND WHEN missing frontmatter",
{
preSetupHook: async ({ vaults, wsRoot }) => {
const note = await NoteTestUtilsV4.createNote({
fname: FNAME,
vault: vaults[0],
wsRoot,
});
// Empty out the note, getting rid of the frontmatter
const path = NoteUtils.getFullPath({ note, wsRoot });
await writeFile(path, "foo bar");
},
},
() => {
test("THEN show frontmatter missing warning", async () => {
const { editor } = await getNote({ fname: FNAME });
const { allWarnings } = (await updateDecorations(editor))!;
expect(allWarnings!.length).toEqual(1);
expect(
AssertUtils.assertInString({
body: allWarnings![0].message,
match: ["frontmatter", "missing"],
})
);
});
}
);
describeMultiWS(
"AND WHEN bad note id",
{
preSetupHook: async ({ vaults, wsRoot }) => {
await NoteTestUtilsV4.createNote({
fname: FNAME,
vault: vaults[0],
wsRoot,
props: {
id: "-foo",
},
});
},
},
() => {
test("THEN show frontmatter missing warning", async () => {
const { editor } = await getNote({ fname: FNAME });
const { allWarnings } = (await updateDecorations(editor))!;
expect(allWarnings!.length).toEqual(1);
expect(
AssertUtils.assertInString({
body: allWarnings![0].message,
match: ["id", "bad"],
})
);
});
}
);
describeMultiWS(
"AND WHEN note id is missing",
{
preSetupHook: async ({ vaults, wsRoot }) => {
const note = await NoteTestUtilsV4.createNote({
fname: FNAME,
vault: vaults[0],
wsRoot,
});
// Rewrite the file to have id missing in frontmatter
const path = NoteUtils.getFullPath({ note, wsRoot });
await writeFile(
path,
["---", "updated: 234", "created: 123", "---"].join("\n")
);
},
},
() => {
test("THEN show frontmatter missing warning", async () => {
const { editor } = await getNote({ fname: FNAME });
const { allWarnings } = (await updateDecorations(editor))!;
expect(allWarnings!.length).toEqual(1);
expect(
AssertUtils.assertInString({
body: allWarnings![0].message,
match: ["id", "missing"],
})
);
});
}
);
describeMultiWS("AND frontmatter is not visible", {}, () => {
before(async () => {
const { wsRoot, vaults, engine } = ExtensionProvider.getDWorkspace();
const note = await NoteTestUtilsV4.createNoteWithEngine({
fname: "foo",
vault: vaults[0],
wsRoot,
engine,
});
// Rewrite the file to have id missing in frontmatter
const path = NoteUtils.getFullPath({ note, wsRoot });
await writeFile(
path,
["---", "updated: 234", "created: 123", "---"]
.join("\n")
.concat("\n".repeat(200))
);
const editor = await WSUtils.openNote(note);
editor.revealRange(new vscode.Range(200, 0, 200, 0));
});
test("THEN still warns for frontmatter issues", async () => {
const { allWarnings } = (await updateDecorations(
VSCodeUtils.getActiveTextEditorOrThrow()
))!;
expect(allWarnings!.length).toEqual(1);
expect(
AssertUtils.assertInString({
body: allWarnings![0].message,
match: ["id", "missing"],
})
);
});
runTestButSkipForWindows()("", () => {
test("THEN don't warn for schemas", async () => {
const { wsRoot } = ExtensionProvider.getDWorkspace();
const engine = ExtensionProvider.getEngine();
const schema = engine.schemas.root;
const schemaFile = path.join(
wsRoot,
schema.vault.fsPath,
`${schema.fname}.schema.yml`
);
const schemaURI = vscode.Uri.parse(schemaFile);
const editor = await VSCodeUtils.openFileInEditor(schemaURI);
const { allDecorations, allWarnings } = (await updateDecorations(
editor!
))!;
expect(allWarnings).toEqual(undefined);
expect(allDecorations).toEqual(undefined);
});
});
});
});
});
Example #27
Source File: image-compressor.ts From image-optimizer with MIT License | 4 votes |
#processFile = (file: DroppedFile, output: string) => {
const originalSize = getFileSize(file.path)
return new Promise<void>((resolve, reject) => {
switch (file.type) {
case MIME_TYPE_ENUM.jpg: {
const { quality } = store.app.get('mozjpeg')
let originalFile: string
const isAddTempFile =
!store.app.get('addToSubfolder') && !store.app.get('addMinSuffix')
if (isAddTempFile) {
originalFile = output + '.tmp'
copyFileSync(file.path, originalFile)
} else {
originalFile = file.path
}
execFile(
mozjpeg,
['-quality', `${quality}`, '-outfile', output, originalFile],
err => {
if (err) {
console.log(err)
reject(err)
}
const compressedSize = getFileSize(output)
this.#sendToRenderer(file, originalSize, compressedSize)
if (isAddTempFile) unlinkSync(originalFile)
resolve()
}
)
break
}
case MIME_TYPE_ENUM.png: {
const { qualityMin, qualityMax } = store.app.get('pngquant')
execFile(
pngquant,
[
'--quality',
`${qualityMin}-${qualityMax}`,
'-fo',
output,
file.path
],
err => {
if (err) {
console.log(err)
reject(err)
}
const compressedSize = getFileSize(output)
this.#sendToRenderer(file, originalSize, compressedSize)
resolve()
}
)
break
}
case MIME_TYPE_ENUM.gif: {
execFile(gifsicle, ['-o', output, file.path], err => {
if (err) {
console.log(err)
reject(err)
}
const compressedSize = getFileSize(output)
this.#sendToRenderer(file, originalSize, compressedSize)
resolve()
})
break
}
case MIME_TYPE_ENUM.svg: {
readFile(file.path, (err, buffer) => {
if (err) {
console.log(err)
reject(err)
}
const { data } = svg.optimize(buffer)
writeFile(output, data, err => {
if (err) console.log(err)
const compressedSize = getFileSize(output)
this.#sendToRenderer(file, originalSize, compressedSize)
resolve()
})
})
break
}
}
})
}
Example #28
Source File: ui5-model-spec.ts From ui5-language-assistant with Apache License 2.0 | 4 votes |
describe("the UI5 language assistant ui5 model", () => {
// The default timeout is 2000ms and getSemanticModel can take ~3000-5000ms
const GET_MODEL_TIMEOUT = 10000;
const VERSION = "1.71.14";
const NO_CACHE_FOLDER = undefined;
function assertSemanticModel(ui5Model: UI5SemanticModel): void {
expect(ui5Model.version).to.equal(VERSION);
expect(Object.keys(ui5Model.classes).length).to.be.greaterThan(200);
expect(Object.keys(ui5Model.namespaces).length).to.be.greaterThan(200);
expect(Object.keys(ui5Model.interfaces).length).to.be.greaterThan(30);
expect(Object.keys(ui5Model.functions).length).to.be.greaterThan(30);
expect(Object.keys(ui5Model.enums).length).to.be.greaterThan(200);
expect(Object.keys(ui5Model.typedefs).length).to.be.greaterThan(10);
expect(Object.keys(ui5Model.classes)).to.include("sap.m.List");
expect(Object.keys(ui5Model.namespaces)).to.include("sap.m");
expect(Object.keys(ui5Model.interfaces)).to.include("sap.f.ICard");
expect(Object.keys(ui5Model.functions)).to.include(
"module:sap/base/assert"
);
expect(Object.keys(ui5Model.enums)).to.include("sap.m.ButtonType");
expect(Object.keys(ui5Model.typedefs)).to.include("sap.ui.fl.Selector");
// Dist layer
expect(Object.keys(ui5Model.classes)).to.include("sap.ui.vk.Camera");
expect(Object.keys(ui5Model.namespaces)).to.include("sap.apf.base");
expect(Object.keys(ui5Model.enums)).to.include(
"sap.ca.ui.charts.ChartSelectionMode"
);
}
it("will get UI5 semantic model", async () => {
const ui5Model = await getSemanticModel(NO_CACHE_FOLDER);
assertSemanticModel(ui5Model);
}).timeout(GET_MODEL_TIMEOUT);
it("doesn't fail if a file cannot be fetched", async () => {
const ui5Model = await getSemanticModelWithFetcher(async (url: string) => {
return {
ok: false,
json: (): never => {
throw new Error(`Cannot read from ${url}`);
},
};
}, NO_CACHE_FOLDER);
expect(ui5Model).to.exist;
});
describe("with cache", () => {
describe("cache in temp dir", () => {
let cachePath: string;
beforeEach(async () => {
({ path: cachePath } = await tempDir());
});
afterEach(async () => {
// The temp folder will contain files at the end so we remove it
// with rimraf instead of calling cleanup()
rimrafSync(cachePath);
});
it("caches the model the first time getSemanticModel is called", async () => {
const ui5Model = await getSemanticModel(cachePath);
assertSemanticModel(ui5Model);
// Check the files were created in the folder
const files = await readdir(cachePath);
expect(files).to.not.be.empty;
// Call getSemanticModel again with the same path and check it doesn't try to read from the URL
let fetcherCalled = false;
const ui5ModelFromCache = await getSemanticModelWithFetcher(
(url: string): never => {
fetcherCalled = true;
throw new Error(
`The files should be taken from the cache, got call for ${url}`
);
},
cachePath
);
expect(fetcherCalled).to.be.false;
// Make sure it's not the model itself that is cached
expect(ui5ModelFromCache).to.not.equal(ui5Model);
// Check we got the same result (we can't use deep equal so the check is shallow)
forEach(ui5Model, (value, key) => {
if (isPlainObject(value)) {
expect(
Object.keys(
ui5ModelFromCache[key as keyof UI5SemanticModel] as Record<
string,
unknown
>
)
).to.deep.equalInAnyOrder(
Object.keys(value as Record<string, unknown>)
);
}
});
assertSemanticModel(ui5ModelFromCache);
}).timeout(GET_MODEL_TIMEOUT);
it("doesn't fail when file cannot be written to the cache", async () => {
// Create a folder with the file name so the file will not be written
const cacheFilePath = getCacheFilePath(
getCacheFolder(cachePath, VERSION),
"sap.m"
);
expectExists(cacheFilePath, "cacheFilePath");
await mkdirs(cacheFilePath);
const ui5Model = await getSemanticModel(cachePath);
expect(ui5Model).to.exist;
// Check we still got the sap.m library data
expect(Object.keys(ui5Model.namespaces)).to.contain("sap.m");
expect(ui5Model.namespaces["sap.m"].library).to.equal("sap.m");
}).timeout(GET_MODEL_TIMEOUT);
it("doesn't fail when file cannot be read from the cache", async () => {
// Create a file with non-json content so the file will not be deserialized
const cacheFolder = getCacheFolder(cachePath, VERSION);
await mkdirs(cacheFolder);
const cacheFilePath = getCacheFilePath(cacheFolder, "sap.m");
expectExists(cacheFilePath, "cacheFilePath");
await writeFile(cacheFilePath, "not json");
const ui5Model = await getSemanticModel(cachePath);
expect(ui5Model).to.exist;
// Check we still got the sap.m library data
expect(Object.keys(ui5Model.namespaces)).to.contain("sap.m");
expect(ui5Model.namespaces["sap.m"].library).to.equal("sap.m");
}).timeout(GET_MODEL_TIMEOUT);
});
describe("cache path is a file", async () => {
let cachePath: string;
let cleanup: () => Promise<void>;
beforeEach(async () => {
({ path: cachePath, cleanup } = await tempFile());
});
afterEach(async () => {
await cleanup();
});
it("does not cache the model", async () => {
const ui5Model = await getSemanticModel(cachePath);
assertSemanticModel(ui5Model);
// Call getSemanticModel again with the same path and check it doesn't try to read from the URL
let fetcherCalled = false;
await getSemanticModelWithFetcher(async (): Promise<FetchResponse> => {
fetcherCalled = true;
return {
ok: true,
json: async (): Promise<unknown> => {
return {};
},
};
}, cachePath);
expect(fetcherCalled).to.be.true;
}).timeout(GET_MODEL_TIMEOUT);
});
});
});
Example #29
Source File: ResourceApi.test.ts From joplin-utils with MIT License | 4 votes |
describe('test ResourceApi', () => {
let id: string
beforeAll(async () => {
id = (await createTestResource()).id
})
afterAll(async () => {
await resourceApi.remove(id)
})
const tempPath = path.resolve(__dirname, '.temp')
beforeEach(async () => {
await remove(tempPath)
await mkdirp(tempPath)
})
it('test list', async () => {
const res = await resourceApi.list({ fields: ['id', 'title'] })
console.log(res)
expect(res.items.length).toBeGreaterThan(0)
})
it('test get', async () => {
const res = await resourceApi.get(id)
console.log(res)
expect(res.id).toBe(id)
})
/**
* TODO 一个官方未修复的 bug,参考:https://github.com/laurent22/joplin/issues/4575
*/
it.skip('test get filename', async () => {
const res = await resourceApi.get(id, ['id', 'filename'])
console.log(res)
expect(res.filename).not.toBe('')
})
describe('diff fetch and axios', () => {
const path = resolve(__dirname, '../resource/resourcesByFileId.png')
it('test create', async () => {
const title = 'image title'
const json = await resourceApi.create({
title,
data: createReadStream(path),
})
expect(json.title).toBe(title)
})
})
describe('test update', () => {
it('basic example', async () => {
const title = `new title ${Date.now()}`
const updateRes = await resourceApi.update({ id, title })
expect(updateRes.title).toBe(title)
})
it('update file', async () => {
const content = 'test'
const txtPath = path.resolve(tempPath, 'test.txt')
await writeFile(txtPath, content)
await resourceApi.update({ id, data: createReadStream(txtPath) })
const res = await resourceApi.fileByResourceId(id)
expect(res.toString()).toBe(content)
})
it('update properties and file', async () => {
const title = `new title ${Date.now()}`
const content = 'test'
const txtPath = path.resolve(tempPath, 'test.txt')
await writeFile(txtPath, content)
const updateRes = await resourceApi.update({ id, title, data: createReadStream(txtPath) })
expect(updateRes.title).toBe(title)
const res = await resourceApi.fileByResourceId(id)
expect(res.toString()).toBe(content)
})
it('update file only', async () => {
const content = 'test'
const txtPath = path.resolve(tempPath, 'test.txt')
await writeFile(txtPath, content)
const { title } = await resourceApi.get(id)
await resourceApi.update({ id, data: createReadStream(txtPath) })
const res = await resourceApi.fileByResourceId(id)
expect(res.toString()).toBe(content)
expect((await resourceApi.get(id)).title).toBe(title)
})
})
/**
* 已知错误
* https://discourse.joplinapp.org/t/pre-release-v2-8-is-now-available-updated-14-april/25158/10?u=rxliuli
*/
it.skip('test remove ', async () => {
const id = (await createTestResource()).id
await resourceApi.remove(id)
await expect(resourceApi.get(id)).rejects.toThrowError()
})
it('test fileByResourceId', async () => {
const res = await resourceApi.fileByResourceId(id)
console.log(typeof res)
const path = resolve(tempPath, 'resourcesByFileId.png')
await writeFile(path, res)
expect(pathExistsSync(path)).toBeTruthy()
})
it('test to get the size of the attachment resource', async () => {
const id = (await createTestResource()).id
const res = await resourceApi.get(id, ['id', 'title', 'size'])
const stats = await stat(path.resolve(__dirname, '../resource/resourcesByFileId.png'))
expect(res.size).toEqual(stats.size)
})
})