Skip to content

Commit aba8654

Browse files
committed
feat(PrismCode): react renderer * 3
1 parent 37b8f4a commit aba8654

File tree

2 files changed

+216
-17
lines changed

2 files changed

+216
-17
lines changed

src/components/content/PrismCode/PrismCode.tsx

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// prism-react-renderer
2-
import { Highlight, Prism as RendererPrism } from 'prism-react-renderer';
1+
import { Highlight } from 'prism-react-renderer';
32
import { forwardRef } from 'react';
43

54
import {
@@ -10,16 +9,7 @@ import {
109
tasty,
1110
} from '../../../tasty';
1211

13-
// Bridge the Prism instance used by `prism-react-renderer` **before** we load
14-
// any additional grammars so that those grammars augment this exact object.
15-
(globalThis as any).Prism = RendererPrism;
16-
17-
import('prismjs/components/prism-diff');
18-
import('prismjs/components/prism-sql');
19-
import('prismjs/plugins/diff-highlight/prism-diff-highlight');
20-
// already bundled in most cases, but kept for completeness
21-
import('prismjs/components/prism-javascript');
22-
import('prismjs/components/prism-yaml');
12+
import { Prism } from './prismSetup';
2313

2414
const PreElement = tasty({
2515
as: 'pre',
@@ -103,11 +93,7 @@ function PrismCode(props: CubePrismCodeProps, ref) {
10393

10494
return (
10595
<PreElement ref={ref} {...otherProps}>
106-
<Highlight
107-
prism={RendererPrism}
108-
code={code}
109-
language={grammarLang as any}
110-
>
96+
<Highlight prism={Prism} code={code} language={grammarLang as any}>
11197
{({ className, tokens, getLineProps, getTokenProps }) => (
11298
<code
11399
data-element="Code"
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
/* eslint-disable */
2+
/* @ts-nocheck */
3+
// This file patches Prism with extra languages & plugins for prism-react-renderer
4+
// Its content is mostly vanilla JS copied from Prism, so type-checking is disabled above.
5+
import { Prism as RendererPrism } from 'prism-react-renderer';
6+
7+
// Bridge the Prism instance used by `prism-react-renderer` **before** we load
8+
// any additional grammars so that those grammars augment this exact object.
9+
(globalThis as any).Prism = RendererPrism;
10+
11+
RendererPrism.languages.sql = {
12+
comment: {
13+
pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,
14+
lookbehind: true,
15+
},
16+
variable: [
17+
{
18+
pattern: /@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,
19+
greedy: true,
20+
},
21+
/@[\w.$]+/,
22+
],
23+
string: {
24+
pattern: /(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,
25+
greedy: true,
26+
lookbehind: true,
27+
},
28+
identifier: {
29+
pattern: /(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,
30+
greedy: true,
31+
lookbehind: true,
32+
inside: {
33+
punctuation: /^`|`$/,
34+
},
35+
},
36+
function:
37+
/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i, // Should we highlight user defined functions too?
38+
keyword:
39+
/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,
40+
boolean: /\b(?:FALSE|NULL|TRUE)\b/i,
41+
number: /\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,
42+
operator:
43+
/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,
44+
punctuation: /[;[\]()`,.]/,
45+
};
46+
47+
(function (Prism) {
48+
Prism.languages.diff = {
49+
coord: [
50+
// Match all kinds of coord lines (prefixed by "+++", "---" or "***").
51+
/^(?:\*{3}|-{3}|\+{3}).*$/m,
52+
// Match "@@ ... @@" coord lines in unified diff.
53+
/^@@.*@@$/m,
54+
// Match coord lines in normal diff (starts with a number).
55+
/^\d.*$/m,
56+
],
57+
58+
// deleted, inserted, unchanged, diff
59+
};
60+
61+
/**
62+
* A map from the name of a block to its line prefix.
63+
*
64+
* @type {Object<string, string>}
65+
*/
66+
var PREFIXES = {
67+
'deleted-sign': '-',
68+
'deleted-arrow': '<',
69+
'inserted-sign': '+',
70+
'inserted-arrow': '>',
71+
unchanged: ' ',
72+
diff: '!',
73+
};
74+
75+
// add a token for each prefix
76+
Object.keys(PREFIXES).forEach(function (name) {
77+
var prefix = PREFIXES[name];
78+
79+
var alias = [];
80+
if (!/^\w+$/.test(name)) {
81+
// "deleted-sign" -> "deleted"
82+
alias.push(/\w+/.exec(name)[0]);
83+
}
84+
if (name === 'diff') {
85+
alias.push('bold');
86+
}
87+
88+
Prism.languages.diff[name] = {
89+
pattern: RegExp('^(?:[' + prefix + '].*(?:\r\n?|\n|(?![\\s\\S])))+', 'm'),
90+
alias: alias,
91+
inside: {
92+
line: {
93+
pattern: /(.)(?=[\s\S]).*(?:\r\n?|\n)?/,
94+
lookbehind: true,
95+
},
96+
prefix: {
97+
pattern: /[\s\S]/,
98+
alias: /\w+/.exec(name)[0],
99+
},
100+
},
101+
};
102+
});
103+
104+
// make prefixes available to Diff plugin
105+
Object.defineProperty(Prism.languages.diff, 'PREFIXES', {
106+
value: PREFIXES,
107+
});
108+
})(RendererPrism);
109+
110+
(function (Prism) {
111+
if (typeof Prism === 'undefined') {
112+
return;
113+
}
114+
115+
var LANGUAGE_REGEX = /^diff-([\w-]+)/i;
116+
var HTML_TAG =
117+
/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/g;
118+
//this will match a line plus the line break while ignoring the line breaks HTML tags may contain.
119+
var HTML_LINE = RegExp(
120+
/(?:__|[^\r\n<])*(?:\r\n?|\n|(?:__|[^\r\n<])(?![^\r\n]))/.source.replace(
121+
/__/g,
122+
function () {
123+
return HTML_TAG.source;
124+
},
125+
),
126+
'gi',
127+
);
128+
129+
var warningLogged = false;
130+
131+
Prism.hooks.add('before-sanity-check', function (env) {
132+
var lang = env.language;
133+
if (LANGUAGE_REGEX.test(lang) && !env.grammar) {
134+
env.grammar = Prism.languages[lang] = Prism.languages.diff;
135+
}
136+
});
137+
Prism.hooks.add('before-tokenize', function (env) {
138+
if (!warningLogged && !Prism.languages.diff && !Prism.plugins.autoloader) {
139+
warningLogged = true;
140+
console.warn(
141+
"Prism's Diff Highlight plugin requires the Diff language definition (prism-diff.js)." +
142+
"Make sure the language definition is loaded or use Prism's Autoloader plugin.",
143+
);
144+
}
145+
146+
var lang = env.language;
147+
if (LANGUAGE_REGEX.test(lang) && !Prism.languages[lang]) {
148+
Prism.languages[lang] = Prism.languages.diff;
149+
}
150+
});
151+
152+
Prism.hooks.add('wrap', function (env) {
153+
var diffLanguage;
154+
var diffGrammar;
155+
156+
if (env.language !== 'diff') {
157+
var langMatch = LANGUAGE_REGEX.exec(env.language);
158+
if (!langMatch) {
159+
return; // not a language specific diff
160+
}
161+
162+
diffLanguage = langMatch[1];
163+
diffGrammar = Prism.languages[diffLanguage];
164+
}
165+
166+
var PREFIXES = Prism.languages.diff && Prism.languages.diff.PREFIXES;
167+
168+
// one of the diff tokens without any nested tokens
169+
if (PREFIXES && env.type in PREFIXES) {
170+
/** @type {string} */
171+
var content = env.content.replace(HTML_TAG, ''); // remove all HTML tags
172+
173+
/** @type {string} */
174+
var decoded = content.replace(/&lt;/g, '<').replace(/&amp;/g, '&');
175+
176+
// remove any one-character prefix
177+
var code = decoded.replace(/(^|[\r\n])./g, '$1');
178+
179+
// highlight, if possible
180+
var highlighted;
181+
if (diffGrammar) {
182+
highlighted = Prism.highlight(code, diffGrammar, diffLanguage);
183+
} else {
184+
highlighted = Prism.util.encode(code);
185+
}
186+
187+
// get the HTML source of the prefix token
188+
var prefixToken = new Prism.Token('prefix', PREFIXES[env.type], [
189+
/\w+/.exec(env.type)[0],
190+
]);
191+
var prefix = Prism.Token.stringify(prefixToken, env.language);
192+
193+
// add prefix
194+
var lines = [];
195+
var m;
196+
HTML_LINE.lastIndex = 0;
197+
while ((m = HTML_LINE.exec(highlighted))) {
198+
lines.push(prefix + m[0]);
199+
}
200+
if (/(?:^|[\r\n]).$/.test(decoded)) {
201+
// because both "+a\n+" and "+a\n" will map to "a\n" after the line prefixes are removed
202+
lines.push(prefix);
203+
}
204+
env.content = lines.join('');
205+
206+
if (diffGrammar) {
207+
env.classes.push('language-' + diffLanguage);
208+
}
209+
}
210+
});
211+
})(RendererPrism);
212+
213+
export { RendererPrism as Prism };

0 commit comments

Comments
 (0)