mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 04:49:35 +00:00
Add skipPaths option for markdown link validation (#149859)
The new `markdown.experimental.validate.fileLinks.skipPaths` setting lets you specify a list of paths (as globs) that should not be validation This is useful since markdown is used in a range of environments, and sometimes you may need to link to paths that don't exist on disk but will exist on deployment A few other changes here: - Adds a quick fix that adds paths to `skipPaths` - Rename existing settings to use the `.enabled` prefix
This commit is contained in:
parent
fd3a84fdfc
commit
daf0d5e551
|
@ -420,10 +420,10 @@
|
|||
"description": "%configuration.markdown.experimental.validate.enabled.description%",
|
||||
"default": false
|
||||
},
|
||||
"markdown.experimental.validate.referenceLinks": {
|
||||
"markdown.experimental.validate.referenceLinks.enabled": {
|
||||
"type": "string",
|
||||
"scope": "resource",
|
||||
"markdownDescription": "%configuration.markdown.experimental.validate.referenceLinks.description%",
|
||||
"markdownDescription": "%configuration.markdown.experimental.validate.referenceLinks.enabled.description%",
|
||||
"default": "warning",
|
||||
"enum": [
|
||||
"ignore",
|
||||
|
@ -431,10 +431,10 @@
|
|||
"error"
|
||||
]
|
||||
},
|
||||
"markdown.experimental.validate.headerLinks": {
|
||||
"markdown.experimental.validate.headerLinks.enabled": {
|
||||
"type": "string",
|
||||
"scope": "resource",
|
||||
"markdownDescription": "%configuration.markdown.experimental.validate.headerLinks.description%",
|
||||
"markdownDescription": "%configuration.markdown.experimental.validate.headerLinks.enabled.description%",
|
||||
"default": "warning",
|
||||
"enum": [
|
||||
"ignore",
|
||||
|
@ -442,16 +442,24 @@
|
|||
"error"
|
||||
]
|
||||
},
|
||||
"markdown.experimental.validate.fileLinks": {
|
||||
"markdown.experimental.validate.fileLinks.enabled": {
|
||||
"type": "string",
|
||||
"scope": "resource",
|
||||
"markdownDescription": "%configuration.markdown.experimental.validate.fileLinks.description%",
|
||||
"markdownDescription": "%configuration.markdown.experimental.validate.fileLinks.enabled.description%",
|
||||
"default": "warning",
|
||||
"enum": [
|
||||
"ignore",
|
||||
"warning",
|
||||
"error"
|
||||
]
|
||||
},
|
||||
"markdown.experimental.validate.fileLinks.skipPaths": {
|
||||
"type": "array",
|
||||
"scope": "resource",
|
||||
"markdownDescription": "%configuration.markdown.experimental.validate.fileLinks.skipPaths.description%",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -504,6 +512,7 @@
|
|||
"markdown-it": "^12.3.2",
|
||||
"markdown-it-front-matter": "^0.2.1",
|
||||
"morphdom": "^2.6.1",
|
||||
"picomatch": "^2.3.1",
|
||||
"vscode-languageserver-textdocument": "^1.0.4",
|
||||
"vscode-nls": "^5.0.0",
|
||||
"vscode-uri": "^3.0.3"
|
||||
|
@ -512,6 +521,7 @@
|
|||
"@types/dompurify": "^2.3.1",
|
||||
"@types/lodash.throttle": "^4.1.3",
|
||||
"@types/markdown-it": "12.2.3",
|
||||
"@types/picomatch": "^2.3.0",
|
||||
"@types/vscode-notebook-renderer": "^1.60.0",
|
||||
"@types/vscode-webview": "^1.57.0",
|
||||
"lodash.throttle": "^4.1.1"
|
||||
|
|
|
@ -30,8 +30,9 @@
|
|||
"configuration.markdown.suggest.paths.enabled.description": "Enable/disable path suggestions for markdown links",
|
||||
"configuration.markdown.editor.drop.enabled": "Enable/disable dropping into the markdown editor to insert shift. Requires enabling `#workbenck.experimental.editor.dropIntoEditor.enabled#`.",
|
||||
"configuration.markdown.experimental.validate.enabled.description": "Enable/disable all error reporting in Markdown files.",
|
||||
"configuration.markdown.experimental.validate.referenceLinks.description": "Validate reference links in Markdown files, e.g. `[link][ref]`. Requires enabling `#markdown.experimental.validate.enabled#`.",
|
||||
"configuration.markdown.experimental.validate.headerLinks.description": "Validate links to headers in Markdown files, e.g. `[link](#header)`. Requires enabling `#markdown.experimental.validate.enabled#`.",
|
||||
"configuration.markdown.experimental.validate.fileLinks.description": "Validate links to other files in Markdown files, e.g. `[link](/path/to/file.md)`. This checks that the target files exists. Requires enabling `#markdown.experimental.validate.enabled#`.",
|
||||
"configuration.markdown.experimental.validate.referenceLinks.enabled.description": "Validate reference links in Markdown files, e.g. `[link][ref]`. Requires enabling `#markdown.experimental.validate.enabled#`.",
|
||||
"configuration.markdown.experimental.validate.headerLinks.enabled.description": "Validate links to headers in Markdown files, e.g. `[link](#header)`. Requires enabling `#markdown.experimental.validate.enabled#`.",
|
||||
"configuration.markdown.experimental.validate.fileLinks.enabled.description": "Validate links to other files in Markdown files, e.g. `[link](/path/to/file.md)`. This checks that the target files exists. Requires enabling `#markdown.experimental.validate.enabled#`.",
|
||||
"configuration.markdown.experimental.validate.fileLinks.skipPaths.description": "Configure glob patterns for links to treat as valid, even if they don't exist in the workspace. For example `/about` would make the link `[about](/about)` valid, while the glob `/assets/**/*.svg` would let you link to any `.svg` asset under the `assets` directory",
|
||||
"workspaceTrust": "Required for loading styles configured in the workspace."
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ function registerMarkdownLanguageFeatures(
|
|||
vscode.languages.registerRenameProvider(selector, new MdRenameProvider(referencesProvider, workspaceContents, githubSlugifier)),
|
||||
vscode.languages.registerDefinitionProvider(selector, new MdDefinitionProvider(referencesProvider)),
|
||||
MdPathCompletionProvider.register(selector, engine, linkProvider),
|
||||
registerDiagnostics(engine, workspaceContents, linkProvider),
|
||||
registerDiagnostics(selector, engine, workspaceContents, linkProvider, commandManager),
|
||||
registerDropIntoEditor(selector),
|
||||
registerFindFileReferences(commandManager, referencesProvider),
|
||||
);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as picomatch from 'picomatch';
|
||||
import { MarkdownEngine } from '../markdownEngine';
|
||||
import { TableOfContents } from '../tableOfContents';
|
||||
import { Delayer } from '../util/async';
|
||||
|
@ -14,6 +15,7 @@ import { Limiter } from '../util/limiter';
|
|||
import { MdWorkspaceContents, SkinnyTextDocument } from '../workspaceContents';
|
||||
import { InternalHref, LinkDefinitionSet, MdLink, MdLinkProvider, MdLinkSource } from './documentLinkProvider';
|
||||
import { tryFindMdDocumentForLink } from './references';
|
||||
import { CommandManager } from '../commandManager';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
|
@ -37,6 +39,7 @@ export interface DiagnosticOptions {
|
|||
readonly validateReferences: DiagnosticLevel;
|
||||
readonly validateOwnHeaders: DiagnosticLevel;
|
||||
readonly validateFilePaths: DiagnosticLevel;
|
||||
readonly skipPaths: readonly string[];
|
||||
}
|
||||
|
||||
function toSeverity(level: DiagnosticLevel): vscode.DiagnosticSeverity | undefined {
|
||||
|
@ -56,7 +59,13 @@ class VSCodeDiagnosticConfiguration extends Disposable implements DiagnosticConf
|
|||
super();
|
||||
|
||||
this._register(vscode.workspace.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('markdown.experimental.validate.enabled')) {
|
||||
if (
|
||||
e.affectsConfiguration('markdown.experimental.validate.enabled')
|
||||
|| e.affectsConfiguration('markdown.experimental.validate.referenceLinks.enabled')
|
||||
|| e.affectsConfiguration('markdown.experimental.validate.headerLinks.enabled')
|
||||
|| e.affectsConfiguration('markdown.experimental.validate.fileLinks.enabled')
|
||||
|| e.affectsConfiguration('markdown.experimental.validate.fileLinks.skipPaths')
|
||||
) {
|
||||
this._onDidChange.fire();
|
||||
}
|
||||
}));
|
||||
|
@ -66,9 +75,10 @@ class VSCodeDiagnosticConfiguration extends Disposable implements DiagnosticConf
|
|||
const config = vscode.workspace.getConfiguration('markdown', resource);
|
||||
return {
|
||||
enabled: config.get<boolean>('experimental.validate.enabled', false),
|
||||
validateReferences: config.get<DiagnosticLevel>('experimental.validate.referenceLinks', DiagnosticLevel.ignore),
|
||||
validateOwnHeaders: config.get<DiagnosticLevel>('experimental.validate.headerLinks', DiagnosticLevel.ignore),
|
||||
validateFilePaths: config.get<DiagnosticLevel>('experimental.validate.fileLinks', DiagnosticLevel.ignore),
|
||||
validateReferences: config.get<DiagnosticLevel>('experimental.validate.referenceLinks.enabled', DiagnosticLevel.ignore),
|
||||
validateOwnHeaders: config.get<DiagnosticLevel>('experimental.validate.headerLinks.enabled', DiagnosticLevel.ignore),
|
||||
validateFilePaths: config.get<DiagnosticLevel>('experimental.validate.fileLinks.enabled', DiagnosticLevel.ignore),
|
||||
skipPaths: config.get('experimental.validate.fileLinks.skipPaths', []),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -206,6 +216,16 @@ class LinkWatcher extends Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
class FileDoesNotExistDiagnostic extends vscode.Diagnostic {
|
||||
|
||||
public readonly path: string;
|
||||
|
||||
constructor(range: vscode.Range, message: string, severity: vscode.DiagnosticSeverity, path: string) {
|
||||
super(range, message, severity);
|
||||
this.path = path;
|
||||
}
|
||||
}
|
||||
|
||||
export class DiagnosticManager extends Disposable {
|
||||
|
||||
private readonly collection: vscode.DiagnosticCollection;
|
||||
|
@ -459,9 +479,11 @@ export class DiagnosticComputer {
|
|||
}
|
||||
|
||||
if (!hrefDoc && !await this.workspaceContents.pathExists(path)) {
|
||||
const msg = localize('invalidPathLink', 'File does not exist at path: {0}', path.toString(true));
|
||||
const msg = localize('invalidPathLink', 'File does not exist at path: {0}', path.fsPath);
|
||||
for (const link of links) {
|
||||
diagnostics.push(new vscode.Diagnostic(link.source.hrefRange, msg, severity));
|
||||
if (!options.skipPaths.some(glob => picomatch.isMatch(link.source.pathText, glob))) {
|
||||
diagnostics.push(new FileDoesNotExistDiagnostic(link.source.hrefRange, msg, severity, link.source.pathText));
|
||||
}
|
||||
}
|
||||
} else if (hrefDoc) {
|
||||
// Validate each of the links to headers in the file
|
||||
|
@ -482,12 +504,64 @@ export class DiagnosticComputer {
|
|||
}
|
||||
}
|
||||
|
||||
class AddToSkipPathsQuickFixProvider implements vscode.CodeActionProvider {
|
||||
|
||||
private static readonly _addToSkipPathsCommandId = '_markdown.addToSkipPaths';
|
||||
|
||||
private static readonly metadata: vscode.CodeActionProviderMetadata = {
|
||||
providedCodeActionKinds: [
|
||||
vscode.CodeActionKind.QuickFix
|
||||
],
|
||||
};
|
||||
|
||||
public static register(selector: vscode.DocumentSelector, commandManager: CommandManager): vscode.Disposable {
|
||||
const reg = vscode.languages.registerCodeActionsProvider(selector, new AddToSkipPathsQuickFixProvider(), AddToSkipPathsQuickFixProvider.metadata);
|
||||
const commandReg = commandManager.register({
|
||||
id: AddToSkipPathsQuickFixProvider._addToSkipPathsCommandId,
|
||||
execute(resource: vscode.Uri, path: string) {
|
||||
const settingId = 'experimental.validate.fileLinks.skipPaths';
|
||||
const config = vscode.workspace.getConfiguration('markdown', resource);
|
||||
const paths = new Set(config.get<string[]>(settingId, []));
|
||||
paths.add(path);
|
||||
config.update(settingId, [...paths], vscode.ConfigurationTarget.WorkspaceFolder);
|
||||
}
|
||||
});
|
||||
return vscode.Disposable.from(reg, commandReg);
|
||||
}
|
||||
|
||||
provideCodeActions(document: vscode.TextDocument, _range: vscode.Range | vscode.Selection, context: vscode.CodeActionContext, _token: vscode.CancellationToken): vscode.ProviderResult<(vscode.CodeAction | vscode.Command)[]> {
|
||||
const fixes: vscode.CodeAction[] = [];
|
||||
|
||||
for (const diagnostic of context.diagnostics) {
|
||||
if (diagnostic instanceof FileDoesNotExistDiagnostic) {
|
||||
const fix = new vscode.CodeAction(
|
||||
localize('skipPathsQuickFix.title', "Add '{0}' to paths that skip link validation.", diagnostic.path),
|
||||
vscode.CodeActionKind.QuickFix);
|
||||
|
||||
fix.command = {
|
||||
command: AddToSkipPathsQuickFixProvider._addToSkipPathsCommandId,
|
||||
title: '',
|
||||
arguments: [document.uri, diagnostic.path]
|
||||
};
|
||||
fixes.push(fix);
|
||||
}
|
||||
}
|
||||
|
||||
return fixes;
|
||||
}
|
||||
}
|
||||
|
||||
export function register(
|
||||
selector: vscode.DocumentSelector,
|
||||
engine: MarkdownEngine,
|
||||
workspaceContents: MdWorkspaceContents,
|
||||
linkProvider: MdLinkProvider,
|
||||
commandManager: CommandManager,
|
||||
): vscode.Disposable {
|
||||
const configuration = new VSCodeDiagnosticConfiguration();
|
||||
const manager = new DiagnosticManager(new DiagnosticComputer(engine, workspaceContents, linkProvider), configuration);
|
||||
return vscode.Disposable.from(configuration, manager);
|
||||
return vscode.Disposable.from(
|
||||
configuration,
|
||||
manager,
|
||||
AddToSkipPathsQuickFixProvider.register(selector, commandManager));
|
||||
}
|
||||
|
|
|
@ -93,7 +93,16 @@ function getWorkspaceFolder(document: SkinnyTextDocument) {
|
|||
}
|
||||
|
||||
export interface MdLinkSource {
|
||||
/**
|
||||
* The original text of the link destination in code.
|
||||
*/
|
||||
readonly text: string;
|
||||
|
||||
/**
|
||||
* The original text of just the link's path in code.
|
||||
*/
|
||||
readonly pathText: string;
|
||||
|
||||
readonly resource: vscode.Uri;
|
||||
readonly hrefRange: vscode.Range;
|
||||
readonly fragmentRange: vscode.Range | undefined;
|
||||
|
@ -138,7 +147,7 @@ function extractDocumentLink(
|
|||
text: link,
|
||||
resource: document.uri,
|
||||
hrefRange: new vscode.Range(linkStart, linkEnd),
|
||||
fragmentRange: getFragmentRange(link, linkStart, linkEnd),
|
||||
...getLinkSourceFragmentInfo(document, link, linkStart, linkEnd),
|
||||
}
|
||||
};
|
||||
} catch {
|
||||
|
@ -154,6 +163,14 @@ function getFragmentRange(text: string, start: vscode.Position, end: vscode.Posi
|
|||
return new vscode.Range(start.translate({ characterDelta: index + 1 }), end);
|
||||
}
|
||||
|
||||
function getLinkSourceFragmentInfo(document: SkinnyTextDocument, link: string, linkStart: vscode.Position, linkEnd: vscode.Position): { fragmentRange: vscode.Range | undefined; pathText: string } {
|
||||
const fragmentRange = getFragmentRange(link, linkStart, linkEnd);
|
||||
return {
|
||||
pathText: document.getText(new vscode.Range(linkStart, fragmentRange ? fragmentRange.start.translate(0, -1) : linkEnd)),
|
||||
fragmentRange,
|
||||
};
|
||||
}
|
||||
|
||||
const angleBracketLinkRe = /^<(.*)>$/;
|
||||
|
||||
/**
|
||||
|
@ -314,7 +331,7 @@ export class MdLinkProvider implements vscode.DocumentLinkProvider {
|
|||
text: link,
|
||||
resource: document.uri,
|
||||
hrefRange: new vscode.Range(linkStart, linkEnd),
|
||||
fragmentRange: getFragmentRange(link, linkStart, linkEnd),
|
||||
...getLinkSourceFragmentInfo(document, link, linkStart, linkEnd),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -350,6 +367,7 @@ export class MdLinkProvider implements vscode.DocumentLinkProvider {
|
|||
kind: 'link',
|
||||
source: {
|
||||
text: reference,
|
||||
pathText: reference,
|
||||
resource: document.uri,
|
||||
hrefRange,
|
||||
fragmentRange: undefined,
|
||||
|
@ -402,7 +420,7 @@ export class MdLinkProvider implements vscode.DocumentLinkProvider {
|
|||
text: link,
|
||||
resource: document.uri,
|
||||
hrefRange,
|
||||
fragmentRange: getFragmentRange(link, linkStart, linkEnd),
|
||||
...getLinkSourceFragmentInfo(document, link, linkStart, linkEnd),
|
||||
},
|
||||
ref: { text: reference, range: refRange },
|
||||
href: target,
|
||||
|
|
|
@ -26,6 +26,7 @@ async function getComputedDiagnostics(doc: InMemoryDocument, workspaceContents:
|
|||
validateFilePaths: DiagnosticLevel.warning,
|
||||
validateOwnHeaders: DiagnosticLevel.warning,
|
||||
validateReferences: DiagnosticLevel.warning,
|
||||
skipPaths: [],
|
||||
}, noopToken)
|
||||
).diagnostics;
|
||||
}
|
||||
|
@ -43,6 +44,7 @@ class MemoryDiagnosticConfiguration implements DiagnosticConfiguration {
|
|||
|
||||
constructor(
|
||||
private readonly enabled: boolean = true,
|
||||
private readonly skipPaths: string[] = [],
|
||||
) { }
|
||||
|
||||
getOptions(_resource: vscode.Uri): DiagnosticOptions {
|
||||
|
@ -52,6 +54,7 @@ class MemoryDiagnosticConfiguration implements DiagnosticConfiguration {
|
|||
validateFilePaths: DiagnosticLevel.ignore,
|
||||
validateOwnHeaders: DiagnosticLevel.ignore,
|
||||
validateReferences: DiagnosticLevel.ignore,
|
||||
skipPaths: this.skipPaths,
|
||||
};
|
||||
}
|
||||
return {
|
||||
|
@ -59,6 +62,7 @@ class MemoryDiagnosticConfiguration implements DiagnosticConfiguration {
|
|||
validateFilePaths: DiagnosticLevel.warning,
|
||||
validateOwnHeaders: DiagnosticLevel.warning,
|
||||
validateReferences: DiagnosticLevel.warning,
|
||||
skipPaths: this.skipPaths,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -179,4 +183,61 @@ suite('markdown: Diagnostics', () => {
|
|||
const diagnostics = await getComputedDiagnostics(doc1, new InMemoryWorkspaceMarkdownDocuments([doc1]));
|
||||
assert.deepStrictEqual(diagnostics.length, 0);
|
||||
});
|
||||
|
||||
test('Should allow ignoring invalid file link using glob', async () => {
|
||||
const doc1 = new InMemoryDocument(workspacePath('doc1.md'), joinLines(
|
||||
`[text](/no-such-file)`,
|
||||
`![img](/no-such-file)`,
|
||||
`[text]: /no-such-file`,
|
||||
));
|
||||
|
||||
const manager = createDiagnosticsManager(new InMemoryWorkspaceMarkdownDocuments([doc1]), new MemoryDiagnosticConfiguration(true, ['/no-such-file']));
|
||||
const { diagnostics } = await manager.recomputeDiagnosticState(doc1, noopToken);
|
||||
assert.deepStrictEqual(diagnostics.length, 0);
|
||||
});
|
||||
|
||||
test('skipPaths should allow skipping non-existent file', async () => {
|
||||
const doc1 = new InMemoryDocument(workspacePath('doc1.md'), joinLines(
|
||||
`[text](/no-such-file#header)`,
|
||||
));
|
||||
|
||||
const manager = createDiagnosticsManager(new InMemoryWorkspaceMarkdownDocuments([doc1]), new MemoryDiagnosticConfiguration(true, ['/no-such-file']));
|
||||
const { diagnostics } = await manager.recomputeDiagnosticState(doc1, noopToken);
|
||||
assert.deepStrictEqual(diagnostics.length, 0);
|
||||
});
|
||||
|
||||
test('skipPaths should not consider link fragment', async () => {
|
||||
const doc1 = new InMemoryDocument(workspacePath('doc1.md'), joinLines(
|
||||
`[text](/no-such-file#header)`,
|
||||
));
|
||||
|
||||
const manager = createDiagnosticsManager(new InMemoryWorkspaceMarkdownDocuments([doc1]), new MemoryDiagnosticConfiguration(true, ['/no-such-file']));
|
||||
const { diagnostics } = await manager.recomputeDiagnosticState(doc1, noopToken);
|
||||
assert.deepStrictEqual(diagnostics.length, 0);
|
||||
});
|
||||
|
||||
test('skipPaths should support globs', async () => {
|
||||
const doc1 = new InMemoryDocument(workspacePath('doc1.md'), joinLines(
|
||||
`![i](/images/aaa.png)`,
|
||||
`![i](/images/sub/bbb.png)`,
|
||||
`![i](/images/sub/sub2/ccc.png)`,
|
||||
));
|
||||
|
||||
const manager = createDiagnosticsManager(new InMemoryWorkspaceMarkdownDocuments([doc1]), new MemoryDiagnosticConfiguration(true, ['/images/**/*.png']));
|
||||
const { diagnostics } = await manager.recomputeDiagnosticState(doc1, noopToken);
|
||||
assert.deepStrictEqual(diagnostics.length, 0);
|
||||
});
|
||||
|
||||
test('skipPaths should resolve relative to file', async () => {
|
||||
const doc1 = new InMemoryDocument(workspacePath('sub', 'doc1.md'), joinLines(
|
||||
`![i](images/aaa.png)`,
|
||||
`![i](images/sub/bbb.png)`,
|
||||
`![i](images/sub/sub2/ccc.png)`,
|
||||
`![i](/images/sub/sub2/ccc.png)`,
|
||||
));
|
||||
|
||||
const manager = createDiagnosticsManager(new InMemoryWorkspaceMarkdownDocuments([doc1]), new MemoryDiagnosticConfiguration(true, ['images/**/*.png']));
|
||||
const { diagnostics } = await manager.recomputeDiagnosticState(doc1, noopToken);
|
||||
assert.deepStrictEqual(diagnostics.length, 0);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -39,6 +39,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9"
|
||||
integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==
|
||||
|
||||
"@types/picomatch@^2.3.0":
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/picomatch/-/picomatch-2.3.0.tgz#75db5e75a713c5a83d5b76780c3da84a82806003"
|
||||
integrity sha512-O397rnSS9iQI4OirieAtsDqvCj4+3eY1J+EPdNTKuHuRWIfUoGyzX294o8C4KJYaLqgSrd2o60c5EqCU8Zv02g==
|
||||
|
||||
"@types/trusted-types@*":
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756"
|
||||
|
@ -117,6 +122,11 @@ morphdom@^2.6.1:
|
|||
resolved "https://registry.yarnpkg.com/morphdom/-/morphdom-2.6.1.tgz#e868e24f989fa3183004b159aed643e628b4306e"
|
||||
integrity sha512-Y8YRbAEP3eKykroIBWrjcfMw7mmwJfjhqdpSvoqinu8Y702nAwikpXcNFDiIkyvfCLxLM9Wu95RZqo4a9jFBaA==
|
||||
|
||||
picomatch@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||
|
|
Loading…
Reference in a new issue