mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-24 20:26:08 +00:00
Start encapsulating slugifier
This commit is contained in:
@@ -3,11 +3,11 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
import { Slug } from './tableOfContentsProvider';
|
||||
import { MarkdownIt, Token } from 'markdown-it';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import { MarkdownContributions } from './markdownExtensions';
|
||||
import { stripSlugifier } from './slugify';
|
||||
|
||||
const FrontMatterRegex = /^---\s*[^]*?(-{3}|\.{3})\s*/;
|
||||
|
||||
@@ -49,7 +49,7 @@ export class MarkdownEngine {
|
||||
return `<pre class="hljs"><code><div>${this.md!.utils.escapeHtml(str)}</div></code></pre>`;
|
||||
}
|
||||
}).use(mdnh, {
|
||||
slugify: (header: string) => Slug.fromHeading(header).value
|
||||
slugify: (header: string) => stripSlugifier.fromHeading(header).value
|
||||
});
|
||||
|
||||
for (const plugin of this.extensionPreviewResourceProvider.markdownItPlugins) {
|
||||
@@ -145,13 +145,13 @@ export class MarkdownEngine {
|
||||
|
||||
if (fragment) {
|
||||
uri = uri.with({
|
||||
fragment: Slug.fromHeading(fragment).value
|
||||
fragment: stripSlugifier.fromHeading(fragment).value
|
||||
});
|
||||
}
|
||||
return normalizeLink(uri.with({ scheme: 'vscode-resource' }).toString(true));
|
||||
} else if (!uri.scheme && !uri.path && uri.fragment) {
|
||||
return normalizeLink(uri.with({
|
||||
fragment: Slug.fromHeading(uri.fragment).value
|
||||
fragment: stripSlugifier.fromHeading(uri.fragment).value
|
||||
}).toString(true));
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
35
extensions/markdown-language-features/src/slugify.ts
Normal file
35
extensions/markdown-language-features/src/slugify.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export class Slug {
|
||||
public constructor(
|
||||
public readonly value: string
|
||||
) { }
|
||||
|
||||
public equals(other: Slug): boolean {
|
||||
return this.value === other.value;
|
||||
}
|
||||
}
|
||||
|
||||
export interface Slugifier {
|
||||
fromHeading(heading: string): Slug;
|
||||
}
|
||||
|
||||
export const stripSlugifier: Slugifier = new class implements Slugifier {
|
||||
private readonly specialChars: any = { 'à': 'a', 'ä': 'a', 'ã': 'a', 'á': 'a', 'â': 'a', 'æ': 'a', 'å': 'a', 'ë': 'e', 'è': 'e', 'é': 'e', 'ê': 'e', 'î': 'i', 'ï': 'i', 'ì': 'i', 'í': 'i', 'ò': 'o', 'ó': 'o', 'ö': 'o', 'ô': 'o', 'ø': 'o', 'ù': 'o', 'ú': 'u', 'ü': 'u', 'û': 'u', 'ñ': 'n', 'ç': 'c', 'ß': 's', 'ÿ': 'y', 'œ': 'o', 'ŕ': 'r', 'ś': 's', 'ń': 'n', 'ṕ': 'p', 'ẃ': 'w', 'ǵ': 'g', 'ǹ': 'n', 'ḿ': 'm', 'ǘ': 'u', 'ẍ': 'x', 'ź': 'z', 'ḧ': 'h', '·': '-', '/': '-', '_': '-', ',': '-', ':': '-', ';': '-', 'З': '3', 'з': '3' };
|
||||
|
||||
public fromHeading(heading: string): Slug {
|
||||
const slugifiedHeading = encodeURI(heading.trim()
|
||||
.toLowerCase()
|
||||
.replace(/./g, c => this.specialChars[c] || c)
|
||||
.replace(/[\]\[\!\'\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~\`]/g, '')
|
||||
.replace(/\s+/g, '-') // Replace whitespace with -
|
||||
.replace(/[^\w\-]+/g, '') // Remove remaining non-word chars
|
||||
.replace(/^\-+/, '') // Remove leading -
|
||||
.replace(/\-+$/, '') // Remove trailing -
|
||||
);
|
||||
return new Slug(slugifiedHeading);
|
||||
}
|
||||
};
|
||||
@@ -4,34 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { MarkdownEngine } from './markdownEngine';
|
||||
|
||||
export class Slug {
|
||||
private static specialChars: any = { 'à': 'a', 'ä': 'a', 'ã': 'a', 'á': 'a', 'â': 'a', 'æ': 'a', 'å': 'a', 'ë': 'e', 'è': 'e', 'é': 'e', 'ê': 'e', 'î': 'i', 'ï': 'i', 'ì': 'i', 'í': 'i', 'ò': 'o', 'ó': 'o', 'ö': 'o', 'ô': 'o', 'ø': 'o', 'ù': 'o', 'ú': 'u', 'ü': 'u', 'û': 'u', 'ñ': 'n', 'ç': 'c', 'ß': 's', 'ÿ': 'y', 'œ': 'o', 'ŕ': 'r', 'ś': 's', 'ń': 'n', 'ṕ': 'p', 'ẃ': 'w', 'ǵ': 'g', 'ǹ': 'n', 'ḿ': 'm', 'ǘ': 'u', 'ẍ': 'x', 'ź': 'z', 'ḧ': 'h', '·': '-', '/': '-', '_': '-', ',': '-', ':': '-', ';': '-', 'З': '3', 'з': '3' };
|
||||
|
||||
public static fromHeading(heading: string): Slug {
|
||||
const slugifiedHeading = encodeURI(heading.trim()
|
||||
.toLowerCase()
|
||||
.replace(/./g, c => Slug.specialChars[c] || c)
|
||||
.replace(/[\]\[\!\'\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~\`]/g, '')
|
||||
.replace(/\s+/g, '-') // Replace whitespace with -
|
||||
.replace(/[^\w\-]+/g, '') // Remove remaining non-word chars
|
||||
.replace(/^\-+/, '') // Remove leading -
|
||||
.replace(/\-+$/, '') // Remove trailing -
|
||||
);
|
||||
|
||||
return new Slug(slugifiedHeading);
|
||||
}
|
||||
|
||||
private constructor(
|
||||
public readonly value: string
|
||||
) { }
|
||||
|
||||
public equals(other: Slug): boolean {
|
||||
return this.value === other.value;
|
||||
}
|
||||
}
|
||||
import { Slug, stripSlugifier } from './slugify';
|
||||
|
||||
export interface TocEntry {
|
||||
readonly slug: Slug;
|
||||
@@ -62,7 +36,7 @@ export class TableOfContentsProvider {
|
||||
|
||||
public async lookup(fragment: string): Promise<TocEntry | undefined> {
|
||||
const toc = await this.getToc();
|
||||
const slug = Slug.fromHeading(fragment);
|
||||
const slug = stripSlugifier.fromHeading(fragment);
|
||||
return toc.find(entry => entry.slug.equals(slug));
|
||||
}
|
||||
|
||||
@@ -74,7 +48,7 @@ export class TableOfContentsProvider {
|
||||
const lineNumber = heading.map[0];
|
||||
const line = document.lineAt(lineNumber);
|
||||
toc.push({
|
||||
slug: Slug.fromHeading(line.text),
|
||||
slug: stripSlugifier.fromHeading(line.text),
|
||||
text: TableOfContentsProvider.getHeaderText(line.text),
|
||||
level: TableOfContentsProvider.getHeaderLevel(heading.markup),
|
||||
line: lineNumber,
|
||||
|
||||
Reference in New Issue
Block a user