Skip to content

Commit b0444c6

Browse files
committed
move all regexps
1 parent f3111f0 commit b0444c6

File tree

4 files changed

+96
-92
lines changed

4 files changed

+96
-92
lines changed

src/Lexer.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export class _Lexer {
8686
*/
8787
lex(src: string) {
8888
src = src
89-
.replace(/\r\n|\r/g, '\n');
89+
.replace(other.carriageReturn, '\n');
9090

9191
this.blockTokens(src, this.tokens);
9292

@@ -106,7 +106,7 @@ export class _Lexer {
106106
blockTokens(src: string, tokens?: TokensList, lastParagraphClipped?: boolean): TokensList;
107107
blockTokens(src: string, tokens: Token[] = [], lastParagraphClipped = false) {
108108
if (this.options.pedantic) {
109-
src = src.replace(/\t/g, ' ').replace(/^ +$/gm, '');
109+
src = src.replace(other.tabCharGlobal, ' ').replace(other.spaceLine, '');
110110
}
111111

112112
let token: Tokens.Generic | undefined;

src/Renderer.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
cleanUrl,
44
escape,
55
} from './helpers.ts';
6+
import { other } from './rules.ts';
67
import type { MarkedOptions } from './MarkedOptions.ts';
78
import type { Tokens } from './Tokens.ts';
89
import type { _Parser } from './Parser.ts';
@@ -22,9 +23,9 @@ export class _Renderer {
2223
}
2324

2425
code({ text, lang, escaped }: Tokens.Code): string {
25-
const langString = (lang || '').match(/^\S*/)?.[0];
26+
const langString = (lang || '').match(other.notSpaceStart)?.[0];
2627

27-
const code = text.replace(/\n$/, '') + '\n';
28+
const code = text.replace(other.endingNewline, '') + '\n';
2829

2930
if (!langString) {
3031
return '<pre><code>'

src/helpers.ts

+11-36
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1+
import { other } from './rules.ts';
2+
13
/**
24
* Helpers
35
*/
4-
const escapeTest = /[&<>"']/;
5-
const escapeReplace = new RegExp(escapeTest.source, 'g');
6-
const escapeTestNoEncode = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/;
7-
const escapeReplaceNoEncode = new RegExp(escapeTestNoEncode.source, 'g');
86
const escapeReplacements: { [index: string]: string } = {
97
'&': '&amp;',
108
'<': '&lt;',
@@ -16,23 +14,21 @@ const getEscapeReplacement = (ch: string) => escapeReplacements[ch];
1614

1715
export function escape(html: string, encode?: boolean) {
1816
if (encode) {
19-
if (escapeTest.test(html)) {
20-
return html.replace(escapeReplace, getEscapeReplacement);
17+
if (other.escapeTest.test(html)) {
18+
return html.replace(other.escapeReplace, getEscapeReplacement);
2119
}
2220
} else {
23-
if (escapeTestNoEncode.test(html)) {
24-
return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
21+
if (other.escapeTestNoEncode.test(html)) {
22+
return html.replace(other.escapeReplaceNoEncode, getEscapeReplacement);
2523
}
2624
}
2725

2826
return html;
2927
}
3028

31-
const unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
32-
3329
export function unescape(html: string) {
3430
// explicitly match decimal, hex, and named HTML entities
35-
return html.replace(unescapeTest, (_, n) => {
31+
return html.replace(other.unescapeTest, (_, n) => {
3632
n = n.toLowerCase();
3733
if (n === 'colon') return ':';
3834
if (n.charAt(0) === '#') {
@@ -44,40 +40,19 @@ export function unescape(html: string) {
4440
});
4541
}
4642

47-
const caret = /(^|[^\[])\^/g;
48-
49-
export function edit(regex: string | RegExp, opt?: string) {
50-
let source = typeof regex === 'string' ? regex : regex.source;
51-
opt = opt || '';
52-
const obj = {
53-
replace: (name: string | RegExp, val: string | RegExp) => {
54-
let valSource = typeof val === 'string' ? val : val.source;
55-
valSource = valSource.replace(caret, '$1');
56-
source = source.replace(name, valSource);
57-
return obj;
58-
},
59-
getRegex: () => {
60-
return new RegExp(source, opt);
61-
},
62-
};
63-
return obj;
64-
}
65-
6643
export function cleanUrl(href: string) {
6744
try {
68-
href = encodeURI(href).replace(/%25/g, '%');
45+
href = encodeURI(href).replace(other.percentDecode, '%');
6946
} catch {
7047
return null;
7148
}
7249
return href;
7350
}
7451

75-
export const noopTest = { exec: () => null } as unknown as RegExp;
76-
7752
export function splitCells(tableRow: string, count?: number) {
7853
// ensure that every cell-delimiting pipe has a space
7954
// before it to distinguish it from an escaped pipe
80-
const row = tableRow.replace(/\|/g, (match, offset, str) => {
55+
const row = tableRow.replace(other.findPipe, (match, offset, str) => {
8156
let escaped = false;
8257
let curr = offset;
8358
while (--curr >= 0 && str[curr] === '\\') escaped = !escaped;
@@ -90,7 +65,7 @@ export function splitCells(tableRow: string, count?: number) {
9065
return ' |';
9166
}
9267
}),
93-
cells = row.split(/ \|/);
68+
cells = row.split(other.splitPipe);
9469
let i = 0;
9570

9671
// First/last cell in a row cannot be empty if it has no leading/trailing pipe
@@ -111,7 +86,7 @@ export function splitCells(tableRow: string, count?: number) {
11186

11287
for (; i < cells.length; i++) {
11388
// leading or trailing whitespace is ignored per the gfm spec
114-
cells[i] = cells[i].trim().replace(/\\\|/g, '|');
89+
cells[i] = cells[i].trim().replace(other.slashPipe, '|');
11590
}
11691
return cells;
11792
}

src/rules.ts

+80-52
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,83 @@
1-
import {
2-
edit, noopTest,
3-
} from './helpers.ts';
1+
export const noopTest = { exec: () => null } as unknown as RegExp;
2+
3+
export function edit(regex: string | RegExp, opt?: string) {
4+
let source = typeof regex === 'string' ? regex : regex.source;
5+
opt = opt || '';
6+
const obj = {
7+
replace: (name: string | RegExp, val: string | RegExp) => {
8+
let valSource = typeof val === 'string' ? val : val.source;
9+
valSource = valSource.replace(other.caret, '$1');
10+
source = source.replace(name, valSource);
11+
return obj;
12+
},
13+
getRegex: () => {
14+
return new RegExp(source, opt);
15+
},
16+
};
17+
return obj;
18+
}
19+
/**
20+
* Other Rules
21+
*/
22+
23+
export const other = {
24+
codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm,
25+
outputLinkReplace: /\\([\[\]])/g,
26+
indentCodeCompensation: /^(\s+)(?:```)/,
27+
beginningSpace: /^\s+/,
28+
endingHash: /#$/,
29+
startingSpaceChar: /^ /,
30+
endingSpaceChar: / $/,
31+
nonSpaceChar: /[^ ]/,
32+
newLineCharGlobal: /\n/g,
33+
tabCharGlobal: /\t/g,
34+
multipleSpaceGlobal: /\s+/g,
35+
blankLine: /^[ \t]*$/,
36+
doubleBlankLine: /\n[ \t]*\n[ \t]*$/,
37+
blockquoteStart: /^ {0,3}>/,
38+
blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g,
39+
blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm,
40+
listReplaceTabs: /^\t+/,
41+
listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g,
42+
listIsTask: /^\[[ xX]\] /,
43+
listReplaceTask: /^\[[ xX]\] +/,
44+
anyLine: /\n.*\n/,
45+
hrefBrackets: /^<(.*)>$/,
46+
tableDelimiter: /[:|]/,
47+
tableAlignChars: /^\||\| *$/g,
48+
tableRowBlankLine: /\n[ \t]*$/,
49+
tableAlignRight: /^ *-+: *$/,
50+
tableAlignCenter: /^ *:-+: *$/,
51+
tableAlignLeft: /^ *:-+ *$/,
52+
startATag: /^<a /i,
53+
endATag: /^<\/a>/i,
54+
startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i,
55+
endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i,
56+
startAngleBracket: /^</,
57+
endAngleBracket: />$/,
58+
pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/,
59+
unicodeAlphaNumeric: /[\p{L}\p{N}]/u,
60+
escapeTest: /[&<>"']/,
61+
escapeReplace: /[&<>"']/g,
62+
escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,
63+
escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g,
64+
unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig,
65+
caret: /(^|[^\[])\^/g,
66+
percentDecode: /%25/g,
67+
findPipe: /\|/g,
68+
splitPipe: / \|/,
69+
slashPipe: /\\\|/g,
70+
carriageReturn: /\r\n|\r/g,
71+
spaceLine: /^ +$/gm,
72+
notSpaceStart: /^\S*/,
73+
endingNewline: /\n$/,
74+
listItemRegex: (bull: string) => new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`),
75+
nextBulletRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`),
76+
hrRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),
77+
fencesBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`),
78+
headingBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`),
79+
htmlBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<[a-z].*>`, 'i'),
80+
};
481

582
/**
683
* Block-Level Grammar
@@ -322,55 +399,6 @@ const inlineBreaks: Record<InlineKeys, RegExp> = {
322399
* exports
323400
*/
324401

325-
/**
326-
* Other Rules
327-
*/
328-
329-
export const other = {
330-
codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm,
331-
outputLinkReplace: /\\([\[\]])/g,
332-
indentCodeCompensation: /^(\s+)(?:```)/,
333-
beginningSpace: /^\s+/,
334-
endingHash: /#$/,
335-
startingSpaceChar: /^ /,
336-
endingSpaceChar: / $/,
337-
nonSpaceChar: /[^ ]/,
338-
newLineCharGlobal: /\n/g,
339-
tabCharGlobal: /\t/g,
340-
multipleSpaceGlobal: /\s+/g,
341-
blankLine: /^[ \t]*$/,
342-
doubleBlankLine: /\n[ \t]*\n[ \t]*$/,
343-
blockquoteStart: /^ {0,3}>/,
344-
blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g,
345-
blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm,
346-
listReplaceTabs: /^\t+/,
347-
listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g,
348-
listIsTask: /^\[[ xX]\] /,
349-
listReplaceTask: /^\[[ xX]\] +/,
350-
anyLine: /\n.*\n/,
351-
hrefBrackets: /^<(.*)>$/,
352-
tableDelimiter: /[:|]/,
353-
tableAlignChars: /^\||\| *$/g,
354-
tableRowBlankLine: /\n[ \t]*$/,
355-
tableAlignRight: /^ *-+: *$/,
356-
tableAlignCenter: /^ *:-+: *$/,
357-
tableAlignLeft: /^ *:-+ *$/,
358-
startATag: /^<a /i,
359-
endATag: /^<\/a>/i,
360-
startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i,
361-
endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i,
362-
startAngleBracket: /^</,
363-
endAngleBracket: />$/,
364-
pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/,
365-
unicodeAlphaNumeric: /[\p{L}\p{N}]/u,
366-
listItemRegex: (bull: string) => new RegExp(`^( {0,3}${bull})((?:[\t ][^\\n]*)?(?:\\n|$))`),
367-
nextBulletRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`),
368-
hrRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),
369-
fencesBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`),
370-
headingBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`),
371-
htmlBeginRegex: (indent: number) => new RegExp(`^ {0,${Math.min(3, indent - 1)}}<[a-z].*>`, 'i'),
372-
};
373-
374402
export const block = {
375403
normal: blockNormal,
376404
gfm: blockGfm,

0 commit comments

Comments
 (0)