From 51d65f594978d30ee049feda710c3ce52ab64bad Mon Sep 17 00:00:00 2001 From: Svyat Sobol Date: Sat, 8 Aug 2020 14:57:35 +0300 Subject: [PATCH] fix: Make links working better with dot files and explicit md extension in the link --- package.json | 7 +- src/commands/openDailyNote.spec.ts | 4 +- src/features/ReferenceHoverProvider.spec.ts | 46 +++++- src/features/ReferenceHoverProvider.ts | 11 +- src/features/extendMarkdownIt.spec.ts | 90 +++++++---- src/features/extendMarkdownIt.ts | 12 +- src/features/fsWatcher.spec.ts | 6 +- src/test/testUtils.ts | 11 +- src/utils/utils.spec.ts | 32 ++++ src/utils/utils.ts | 15 +- yarn.lock | 171 +++++++++++++++++--- 11 files changed, 328 insertions(+), 77 deletions(-) diff --git a/package.json b/package.json index efed604f..488bfdef 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,7 @@ "vscode:prepublish": "webpack --mode production", "deploy": "vsce publish --yarn", "package": "vsce package --yarn", - "clean": "rimraf dist out", + "clean": "del dist out", "lint": "eslint src --ext ts", "compile": "webpack --mode development", "compile:tests": "tsc -p ./ && yarn run webpack --mode development", @@ -147,6 +147,7 @@ "devDependencies": { "@commitlint/cli": "^9.1.1", "@commitlint/config-conventional": "^9.1.1", + "@types/del": "^4.0.0", "@types/glob": "^7.1.1", "@types/jest": "^26.0.9", "@types/lodash.debounce": "^4.0.6", @@ -156,11 +157,12 @@ "@types/moment": "^2.13.0", "@types/node": "^14.0.27", "@types/open": "^6.2.1", - "@types/rimraf": "^3.0.0", "@types/vscode": "^1.47.0", "@typescript-eslint/eslint-plugin": "^3.8.0", "@typescript-eslint/parser": "^3.8.0", "cross-env": "^7.0.2", + "del": "^5.1.0", + "del-cli": "^3.0.1", "eslint": "^7.6.0", "eslint-config-prettier": "^6.11.0", "eslint-plugin-import": "^2.22.0", @@ -172,7 +174,6 @@ "jest-extended": "^0.11.5", "lint-staged": "^10.2.9", "prettier": "^2.0.5", - "rimraf": "^3.0.2", "standard-version": "^8.0.2", "ts-jest": "^26.1.4", "ts-loader": "^8.0.2", diff --git a/src/commands/openDailyNote.spec.ts b/src/commands/openDailyNote.spec.ts index 61d06dde..bd275cde 100644 --- a/src/commands/openDailyNote.spec.ts +++ b/src/commands/openDailyNote.spec.ts @@ -10,9 +10,7 @@ describe('openDailyNote command', () => { afterEach(closeEditorsAndCleanWorkspace); it('should not fail on direct call', async () => { - expect(() => { - openDailyNote(); - }).not.toThrow(); + expect(() => openDailyNote()).not.toThrow(); await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); }); diff --git a/src/features/ReferenceHoverProvider.spec.ts b/src/features/ReferenceHoverProvider.spec.ts index d6d16cbe..206fd7d5 100644 --- a/src/features/ReferenceHoverProvider.spec.ts +++ b/src/features/ReferenceHoverProvider.spec.ts @@ -61,7 +61,7 @@ describe('ReferenceHoverProvider', () => { const referenceHoverProvider = new ReferenceHoverProvider(); - const imagePath = `${path.join(getWorkspaceFolder()!, name1)}.png`; + const imagePath = path.join(getWorkspaceFolder()!, `${name1}.png`); expect( toPlainObject(referenceHoverProvider.provideHover(doc, new vscode.Position(0, 4))), @@ -193,4 +193,48 @@ describe('ReferenceHoverProvider', () => { expect(referenceHoverProvider.provideHover(doc, new vscode.Position(0, 4))).toBeNull(); }); + + it('should provide hover for a link to dot file note', async () => { + const name0 = rndName(); + const name1 = rndName(); + + await createFile(`${name0}.md`, `[[.${name1}]]`); + await createFile(`.${name1}.md`, '# Hello world'); + + const doc = await openTextDocument(`${name0}.md`); + + const referenceHoverProvider = new ReferenceHoverProvider(); + + expect( + toPlainObject(referenceHoverProvider.provideHover(doc, new vscode.Position(0, 4))), + ).toEqual({ + contents: ['# Hello world'], + range: [ + { character: expect.any(Number), line: 0 }, + { character: expect.any(Number), line: 0 }, + ], + }); + }); + + it('should provide hover for a link with explicit markdown extension in the ref', async () => { + const name0 = rndName(); + const name1 = rndName(); + + await createFile(`${name0}.md`, `[[${name1}.md]]`); + await createFile(`${name1}.md.md`, '# Hello world'); + + const doc = await openTextDocument(`${name0}.md`); + + const referenceHoverProvider = new ReferenceHoverProvider(); + + expect( + toPlainObject(referenceHoverProvider.provideHover(doc, new vscode.Position(0, 4))), + ).toEqual({ + contents: ['# Hello world'], + range: [ + { character: expect.any(Number), line: 0 }, + { character: expect.any(Number), line: 0 }, + ], + }); + }); }); diff --git a/src/features/ReferenceHoverProvider.ts b/src/features/ReferenceHoverProvider.ts index 65589162..f845899b 100644 --- a/src/features/ReferenceHoverProvider.ts +++ b/src/features/ReferenceHoverProvider.ts @@ -25,7 +25,10 @@ export default class ReferenceHoverProvider implements vscode.HoverProvider { new vscode.Position(range.end.line, range.end.character - 2), ); - if (containsUnknownExt(ref)) { + const uris = getWorkspaceCache().allUris; + const foundUri = findUriByRef(uris, ref); + + if (!foundUri && containsUnknownExt(ref)) { return new vscode.Hover( `Link contains unknown extension: ${ path.parse(ref).ext @@ -34,12 +37,8 @@ export default class ReferenceHoverProvider implements vscode.HoverProvider { ); } - const uris = getWorkspaceCache().allUris; - const imagePreviewMaxHeight = Math.max(getConfigProperty('imagePreviewMaxHeight', 200), 10); - - const foundUri = findUriByRef(uris, ref); - if (foundUri && fs.existsSync(foundUri.fsPath)) { + const imagePreviewMaxHeight = Math.max(getConfigProperty('imagePreviewMaxHeight', 200), 10); const getContent = () => { if (containsImageExt(foundUri.fsPath)) { return `![${ diff --git a/src/features/extendMarkdownIt.spec.ts b/src/features/extendMarkdownIt.spec.ts index 9b8ee8a3..e8b70838 100644 --- a/src/features/extendMarkdownIt.spec.ts +++ b/src/features/extendMarkdownIt.spec.ts @@ -6,7 +6,6 @@ import { createFile, rndName, getWorkspaceFolder, - cacheWorkspace, closeEditorsAndCleanWorkspace, getImgUrlForMarkdownPreview, getFileUrlForMarkdownPreview, @@ -27,8 +26,6 @@ describe('extendMarkdownIt feature', () => { it('should render html link with tooltip about broken reference to note', async () => { const md = extendMarkdownIt(MarkdownIt()); - await cacheWorkspace(); - expect(md.render('[[invalid-link]]')).toMatchInlineSnapshot(` "

invalid-link

" @@ -42,8 +39,6 @@ describe('extendMarkdownIt feature', () => { const md = extendMarkdownIt(MarkdownIt()); - await cacheWorkspace(); - const notePath = `${path.join(getWorkspaceFolder()!, name)}.md`; const url = getFileUrlForMarkdownPreview(notePath); @@ -58,8 +53,6 @@ describe('extendMarkdownIt feature', () => { const md = extendMarkdownIt(MarkdownIt()); - await cacheWorkspace(); - const notePath = `${path.join(getWorkspaceFolder()!, `${name}.md`)}`; const url = getFileUrlForMarkdownPreview(notePath); @@ -69,6 +62,51 @@ describe('extendMarkdownIt feature', () => { ); }); + it('should render html link to the existing note with preceding dot', async () => { + const name = rndName(); + + await createFile(`${name}.any.md`); + + const md = extendMarkdownIt(MarkdownIt()); + + const notePath = `${path.join(getWorkspaceFolder()!, `${name}.any.md`)}`; + + const url = getFileUrlForMarkdownPreview(notePath); + + expect(md.render(`[[${name}.any|Test Label]]`)).toBe( + `

Test Label

\n`, + ); + }); + + it('should render html link to the existing dot note', async () => { + const name = rndName(); + + await createFile(`.${name}.md`); + + const md = extendMarkdownIt(MarkdownIt()); + + const notePath = `${path.join(getWorkspaceFolder()!, `.${name}.md`)}`; + + const url = getFileUrlForMarkdownPreview(notePath); + + expect(md.render(`[[.${name}|Test Label]]`)).toBe( + `

Test Label

\n`, + ); + }); + + it('should not render html link to dot file', async () => { + const name = rndName(); + + await createFile(`.${name}`); + + const md = extendMarkdownIt(MarkdownIt()); + + expect(md.render(`[[.${name}|Test Label]]`)).toMatchInlineSnapshot(` + "

Test Label

+ " + `); + }); + it('should render html link to the existing image without a label', async () => { const name = rndName(); @@ -76,8 +114,6 @@ describe('extendMarkdownIt feature', () => { const md = extendMarkdownIt(MarkdownIt()); - await cacheWorkspace(); - const imagePath = `${path.join(getWorkspaceFolder()!, name)}.png`; const url = getFileUrlForMarkdownPreview(imagePath); @@ -87,6 +123,22 @@ describe('extendMarkdownIt feature', () => { ); }); + it('should render html link to the existing dot image', async () => { + const name = rndName(); + + await createFile(`.${name}.png`); + + const md = extendMarkdownIt(MarkdownIt()); + + const imagePath = path.join(getWorkspaceFolder()!, `.${name}.png`); + + const url = getFileUrlForMarkdownPreview(imagePath); + + expect(md.render(`[[.${name}.png]]`)).toBe( + `

.${name}.png

\n`, + ); + }); + it('should render html link to the existing image with a label', async () => { const name = rndName(); @@ -94,9 +146,7 @@ describe('extendMarkdownIt feature', () => { const md = extendMarkdownIt(MarkdownIt()); - await cacheWorkspace(); - - const imagePath = `${path.join(getWorkspaceFolder()!, name)}.png`; + const imagePath = path.join(getWorkspaceFolder()!, `${name}.png`); const url = getFileUrlForMarkdownPreview(imagePath); @@ -108,8 +158,6 @@ describe('extendMarkdownIt feature', () => { it('should render html link with tooltip about broken reference to an image', async () => { const md = extendMarkdownIt(MarkdownIt()); - await cacheWorkspace(); - expect(md.render('[[invalid-link.png]]')).toMatchInlineSnapshot(` "

invalid-link.png

" @@ -123,8 +171,6 @@ describe('extendMarkdownIt feature', () => { const md = extendMarkdownIt(MarkdownIt()); - await cacheWorkspace(); - expect(md.render(`![[${name}.png]]`)).toBe( `

{ const md = extendMarkdownIt(MarkdownIt()); - await cacheWorkspace(); - const notePath = `${path.join(getWorkspaceFolder()!, 'b', name)}.md`; const url = getFileUrlForMarkdownPreview(notePath); @@ -201,8 +239,6 @@ describe('extendMarkdownIt feature', () => { const md = extendMarkdownIt(MarkdownIt()); - await cacheWorkspace(); - const notePath = `${path.join(getWorkspaceFolder()!, name)}.md`; const url = getFileUrlForMarkdownPreview(notePath); @@ -367,8 +403,6 @@ describe('extendMarkdownIt feature', () => { it('should render html link with tooltip about unknown extension', async () => { const md = extendMarkdownIt(MarkdownIt()); - await cacheWorkspace(); - expect(md.render('[[link.unknown]]')).toMatchInlineSnapshot(` "

link.unknown

" diff --git a/src/features/extendMarkdownIt.ts b/src/features/extendMarkdownIt.ts index 4464d0c5..fa01503a 100644 --- a/src/features/extendMarkdownIt.ts +++ b/src/features/extendMarkdownIt.ts @@ -46,12 +46,12 @@ const extendMarkdownIt = (md: MarkdownIt) => { } } - if (containsUnknownExt(ref)) { + const fsPath = findUriByRef(getWorkspaceCache().markdownUris, ref)?.fsPath; + + if (!fsPath && containsUnknownExt(ref)) { return getUnknownExtRefAnchor(label || ref, ref); } - const fsPath = findUriByRef(getWorkspaceCache().markdownUris, ref)?.fsPath; - if (!fsPath || !fs.existsSync(fsPath)) { return getInvalidRefAnchor(label || ref); } @@ -98,12 +98,12 @@ const extendMarkdownIt = (md: MarkdownIt) => { replace: (rawRef: string) => { const { ref, label } = parseRef(rawRef); - if (containsUnknownExt(ref)) { + const fsPath = findUriByRef(getWorkspaceCache().allUris, ref)?.fsPath; + + if (!fsPath && containsUnknownExt(ref)) { return getUnknownExtRefAnchor(label || ref, ref); } - const fsPath = findUriByRef(getWorkspaceCache().allUris, ref)?.fsPath; - if (!fsPath) { return getInvalidRefAnchor(label || ref); } diff --git a/src/features/fsWatcher.spec.ts b/src/features/fsWatcher.spec.ts index 5a5f7164..8c912dc9 100644 --- a/src/features/fsWatcher.spec.ts +++ b/src/features/fsWatcher.spec.ts @@ -300,11 +300,11 @@ describe('fsWatcher feature', () => { await createFile(`${noteName}.md`, '', false); await waitForExpect(async () => { - const workspaceCache0 = await utils.getWorkspaceCache(); + const workspaceCache = await utils.getWorkspaceCache(); - expect([...workspaceCache0.markdownUris, ...workspaceCache0.imageUris]).toHaveLength(1); + expect([...workspaceCache.markdownUris, ...workspaceCache.imageUris]).toHaveLength(1); expect( - [...workspaceCache0.markdownUris, ...workspaceCache0.imageUris].map(({ fsPath }) => + [...workspaceCache.markdownUris, ...workspaceCache.imageUris].map(({ fsPath }) => path.basename(fsPath), ), ).toContain(`${noteName}.md`); diff --git a/src/test/testUtils.ts b/src/test/testUtils.ts index c008aaa9..41087a3c 100644 --- a/src/test/testUtils.ts +++ b/src/test/testUtils.ts @@ -1,4 +1,4 @@ -import rimraf from 'rimraf'; +import del from 'del'; import fs from 'fs'; import path from 'path'; import { workspace, Uri, commands, ConfigurationTarget } from 'vscode'; @@ -27,7 +27,9 @@ export const cleanWorkspace = () => { const workspaceFolder = utils.getWorkspaceFolder(); if (workspaceFolder) { - rimraf.sync(path.join(workspaceFolder, '*')); + del.sync([path.join(workspaceFolder, '{*,.*}'), `!${path.join(workspaceFolder, '.vscode')}`], { + force: true, + }); } }; @@ -37,7 +39,7 @@ export const cacheWorkspace = async () => { }; export const cleanWorkspaceCache = async () => { - await utils.cleanWorkspaceCache(); + utils.cleanWorkspaceCache(); await commands.executeCommand('_memo.cleanWorkspaceCache'); }; @@ -139,4 +141,5 @@ export const closeEditorsAndCleanWorkspace = async () => { export const getWorkspaceCache = async (): Promise => (await commands.executeCommand('_memo.getWorkspaceCache')) as WorkspaceCache; -export const toPlainObject = (value: unknown): R => JSON.parse(JSON.stringify(value)); +export const toPlainObject = (value: unknown): R => + value !== undefined ? JSON.parse(JSON.stringify(value)) : value; diff --git a/src/utils/utils.spec.ts b/src/utils/utils.spec.ts index 3a36a078..23599215 100644 --- a/src/utils/utils.spec.ts +++ b/src/utils/utils.spec.ts @@ -1360,6 +1360,38 @@ describe('findUriByRef()', () => { getWorkspaceFolderMock.mockRestore(); }); + + it('should find uri by ref with explicit markdown extension in ref', async () => { + expect( + toPlainObject(await findUriByRef([Uri.file('/Users/Memo/Diary/File.md.md')], 'File.md')), + ).toEqual( + expect.objectContaining({ + $mid: 1, + fsPath: expect.toEndWith('File.md.md'), + path: expect.toEndWith('File.md.md'), + scheme: 'file', + }), + ); + }); + + it('should find uri from a ref with unknown extension', async () => { + expect( + toPlainObject(await findUriByRef([Uri.file('/Users/Memo/Diary/File.any.md')], 'File.any')), + ).toEqual( + expect.objectContaining({ + $mid: 1, + fsPath: expect.toEndWith('File.any.md'), + path: expect.toEndWith('File.any.md'), + scheme: 'file', + }), + ); + }); + + it('should not find a dot file', async () => { + expect( + toPlainObject(await findUriByRef([Uri.file('/Users/Memo/Diary/.md')], '.md')), + ).toBeUndefined(); + }); }); describe('ensureDirectoryExists()', () => { diff --git a/src/utils/utils.ts b/src/utils/utils.ts index a66a627a..53581a64 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -51,11 +51,14 @@ export const commonExtsHint = export const refPattern = '(\\[\\[)([^\\[\\]]+?)(\\]\\])'; -export const containsImageExt = (path: string): boolean => !!imageExtsRegex.exec(path); +export const containsImageExt = (pathParam: string): boolean => + !!imageExtsRegex.exec(path.parse(pathParam).ext); -export const containsMarkdownExt = (path: string): boolean => !!markdownExtRegex.exec(path); +export const containsMarkdownExt = (pathParam: string): boolean => + !!markdownExtRegex.exec(path.parse(pathParam).ext); -export const containsOtherKnownExts = (path: string): boolean => !!otherExtsRegex.exec(path); +export const containsOtherKnownExts = (pathParam: string): boolean => + !!otherExtsRegex.exec(path.parse(pathParam).ext); export const containsUnknownExt = (pathParam: string): boolean => path.parse(pathParam).ext !== '' && @@ -368,7 +371,11 @@ export const findUriByRef = (uris: vscode.Uri[], ref: string): vscode.Uri | unde return normalizeSlashes(relativeFsPath).endsWith(ref.toLowerCase()); } - return path.basename(uri.fsPath).toLowerCase() === ref.toLowerCase(); + const basenameLowerCased = path.basename(uri.fsPath).toLowerCase(); + + return ( + basenameLowerCased === ref.toLowerCase() || basenameLowerCased === `${ref.toLowerCase()}.md` + ); } if (isLongRef(ref)) { diff --git a/yarn.lock b/yarn.lock index 9fb4cc18..c584e806 100644 --- a/yarn.lock +++ b/yarn.lock @@ -657,6 +657,27 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + "@sinonjs/commons@^1.7.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.0.tgz#c8d68821a854c555bba172f3b06959a0039b236d" @@ -709,19 +730,18 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/del@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/del/-/del-4.0.0.tgz#0d0b5a02e66a96d410d19241557ab25cded9eb16" + integrity sha512-LDE5atstX5kKnTobWknpmGHC52DH/tp8pIVsD2SSxaOFqW3AQr0EpdzYIfkZ331xe7l9Vn9NlJsBG6viU3mjBA== + dependencies: + del "*" + "@types/eslint-visitor-keys@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== -"@types/glob@*": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.2.tgz#06ca26521353a545d94a0adc74f38a59d232c987" - integrity sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - "@types/glob@^7.1.1": version "7.1.3" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" @@ -863,14 +883,6 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.0.2.tgz#5bb52ee68d0f8efa9cc0099920e56be6cc4e37f3" integrity sha512-IkVfat549ggtkZUthUzEX49562eGikhSYeVGX97SkMFn+sTZrgRewXjQ4tPKFPCykZHkX1Zfd9OoELGqKU2jJA== -"@types/rimraf@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-3.0.0.tgz#b9d03f090ece263671898d57bb7bb007023ac19f" - integrity sha512-7WhJ0MdpFgYQPXlF4Dx+DhgvlPCfz/x5mHaeDQAKhcenvQP1KCpLQ18JklAqeGMYSAT2PxLpzd0g2/HE7fj7hQ== - dependencies: - "@types/glob" "*" - "@types/node" "*" - "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -1300,6 +1312,11 @@ array-includes@^3.1.1: es-abstract "^1.17.0" is-string "^1.0.5" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -2512,6 +2529,28 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +del-cli@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/del-cli/-/del-cli-3.0.1.tgz#2d27ff260204b5104cadeda86f78f180a4ebe89a" + integrity sha512-BLHItGr82rUbHhjMu41d+vw9Md49i81jmZSV00HdTq4t+RTHywmEht/23mNFpUl2YeLYJZJyGz4rdlMAyOxNeg== + dependencies: + del "^5.1.0" + meow "^6.1.1" + +del@*, del@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/del/-/del-5.1.0.tgz#d9487c94e367410e6eff2925ee58c0c84a75b3a7" + integrity sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA== + dependencies: + globby "^10.0.1" + graceful-fs "^4.2.2" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.1" + p-map "^3.0.0" + rimraf "^3.0.0" + slash "^3.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -2569,6 +2608,13 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" @@ -3129,6 +3175,18 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== +fast-glob@^3.0.3: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -3139,6 +3197,13 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fastq@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" + integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + dependencies: + reusify "^1.0.4" + fb-watchman@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" @@ -3485,7 +3550,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0, glob-parent@~5.1.0: +glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== @@ -3559,7 +3624,21 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: +globby@^10.0.1: + version "10.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== @@ -3787,6 +3866,11 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.1.1: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + import-fresh@^3.0.0, import-fresh@^3.1.0: version "3.2.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" @@ -4036,6 +4120,16 @@ is-obj@^1.0.0, is-obj@^1.0.1: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-inside@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" + integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== + is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -5189,6 +5283,23 @@ meow@^4.0.0: redent "^2.0.0" trim-newlines "^2.0.0" +meow@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/meow/-/meow-6.1.1.tgz#1ad64c4b76b2a24dfb2f635fddcadf320d251467" + integrity sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "^4.0.2" + normalize-package-data "^2.5.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.13.1" + yargs-parser "^18.1.3" + meow@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/meow/-/meow-7.0.1.tgz#1ed4a0a50b3844b451369c48362eb0515f04c1dc" @@ -5213,6 +5324,11 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== +merge2@^1.2.3, merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -5725,6 +5841,13 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -6514,6 +6637,11 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -6528,7 +6656,7 @@ rimraf@^2.5.4, rimraf@^2.6.3: dependencies: glob "^7.1.3" -rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -6548,6 +6676,11 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"