chore: use codemirror for editor (#18482)
This commit is contained in:
parent
c56877032d
commit
2183d9e9a2
62
package-lock.json
generated
62
package-lock.json
generated
|
|
@ -21,6 +21,7 @@
|
|||
"@babel/plugin-transform-modules-commonjs": "^7.17.9",
|
||||
"@babel/plugin-transform-typescript": "^7.16.8",
|
||||
"@babel/preset-react": "^7.16.7",
|
||||
"@types/codemirror": "^5.60.5",
|
||||
"@types/formidable": "^2.0.4",
|
||||
"@types/node": "=14.18.24",
|
||||
"@types/react": "^18.0.12",
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
"@zip.js/zip.js": "^2.4.2",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"chokidar": "^3.5.3",
|
||||
"codemirror": "^5.65.9",
|
||||
"colors": "^1.4.0",
|
||||
"commonmark": "^0.30.0",
|
||||
"concurrently": "^6.2.1",
|
||||
|
|
@ -1035,6 +1037,21 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/codemirror": {
|
||||
"version": "5.60.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.5.tgz",
|
||||
"integrity": "sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/tern": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
|
||||
"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/formidable": {
|
||||
"version": "2.0.4",
|
||||
"dev": true,
|
||||
|
|
@ -1090,6 +1107,15 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/tern": {
|
||||
"version": "0.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
|
||||
"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
|
||||
|
|
@ -1939,6 +1965,12 @@
|
|||
"mimic-response": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/codemirror": {
|
||||
"version": "5.65.9",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.9.tgz",
|
||||
"integrity": "sha512-19Jox5sAKpusTDgqgKB5dawPpQcY+ipQK7xoEI+MVucEF9qqFaXpeqY1KaoyGBso/wHQoDa4HMMxMjdsS3Zzzw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"license": "MIT",
|
||||
|
|
@ -6729,6 +6761,21 @@
|
|||
"defer-to-connect": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"@types/codemirror": {
|
||||
"version": "5.60.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.5.tgz",
|
||||
"integrity": "sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/tern": "*"
|
||||
}
|
||||
},
|
||||
"@types/estree": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
|
||||
"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/formidable": {
|
||||
"version": "2.0.4",
|
||||
"dev": true,
|
||||
|
|
@ -6775,6 +6822,15 @@
|
|||
"version": "0.16.1",
|
||||
"dev": true
|
||||
},
|
||||
"@types/tern": {
|
||||
"version": "0.23.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
|
||||
"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"@types/ws": {
|
||||
"version": "8.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
|
||||
|
|
@ -7322,6 +7378,12 @@
|
|||
"mimic-response": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"codemirror": {
|
||||
"version": "5.65.9",
|
||||
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.9.tgz",
|
||||
"integrity": "sha512-19Jox5sAKpusTDgqgKB5dawPpQcY+ipQK7xoEI+MVucEF9qqFaXpeqY1KaoyGBso/wHQoDa4HMMxMjdsS3Zzzw==",
|
||||
"dev": true
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"requires": {
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
"@babel/plugin-transform-modules-commonjs": "^7.17.9",
|
||||
"@babel/plugin-transform-typescript": "^7.16.8",
|
||||
"@babel/preset-react": "^7.16.7",
|
||||
"@types/codemirror": "^5.60.5",
|
||||
"@types/formidable": "^2.0.4",
|
||||
"@types/node": "=14.18.24",
|
||||
"@types/react": "^18.0.12",
|
||||
|
|
@ -70,6 +71,7 @@
|
|||
"@zip.js/zip.js": "^2.4.2",
|
||||
"ansi-to-html": "^0.7.2",
|
||||
"chokidar": "^3.5.3",
|
||||
"codemirror": "^5.65.9",
|
||||
"colors": "^1.4.0",
|
||||
"commonmark": "^0.30.0",
|
||||
"concurrently": "^6.2.1",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ This project incorporates components from the projects listed below. The origina
|
|||
- balanced-match@1.0.2 (https://github.com/juliangruber/balanced-match)
|
||||
- brace-expansion@1.1.11 (https://github.com/juliangruber/brace-expansion)
|
||||
- buffer-crc32@0.2.13 (https://github.com/brianloveswords/buffer-crc32)
|
||||
- codemirror@5.65.9 (https://github.com/codemirror/CodeMirror)
|
||||
- colors@1.4.0 (https://github.com/Marak/colors.js)
|
||||
- commander@8.3.0 (https://github.com/tj/commander.js)
|
||||
- concat-map@0.0.1 (https://github.com/substack/node-concat-map)
|
||||
|
|
@ -328,6 +329,32 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEAL
|
|||
=========================================
|
||||
END OF buffer-crc32@0.2.13 AND INFORMATION
|
||||
|
||||
%% codemirror@5.65.9 NOTICES AND INFORMATION BEGIN HERE
|
||||
=========================================
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
=========================================
|
||||
END OF codemirror@5.65.9 AND INFORMATION
|
||||
|
||||
%% colors@1.4.0 NOTICES AND INFORMATION BEGIN HERE
|
||||
=========================================
|
||||
MIT License
|
||||
|
|
@ -1614,6 +1641,6 @@ END OF yazl@2.5.1 AND INFORMATION
|
|||
|
||||
SUMMARY BEGIN HERE
|
||||
=========================================
|
||||
Total Packages: 45
|
||||
Total Packages: 46
|
||||
=========================================
|
||||
END OF SUMMARY
|
||||
|
|
@ -84,6 +84,7 @@ This project incorporates components from the projects listed below. The origina
|
|||
- caniuse-lite@1.0.30001346 (https://github.com/browserslist/caniuse-lite)
|
||||
- chalk@2.4.2 (https://github.com/chalk/chalk)
|
||||
- chalk@4.1.2 (https://github.com/chalk/chalk)
|
||||
- codemirror@5.65.9 (https://github.com/codemirror/CodeMirror)
|
||||
- color-convert@1.9.3 (https://github.com/Qix-/color-convert)
|
||||
- color-convert@2.0.1 (https://github.com/Qix-/color-convert)
|
||||
- color-name@1.1.3 (https://github.com/dfcreative/color-name)
|
||||
|
|
@ -2744,6 +2745,32 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|||
=========================================
|
||||
END OF chalk@4.1.2 AND INFORMATION
|
||||
|
||||
%% codemirror@5.65.9 NOTICES AND INFORMATION BEGIN HERE
|
||||
=========================================
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2017 by Marijn Haverbeke <marijnh@gmail.com> and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
=========================================
|
||||
END OF codemirror@5.65.9 AND INFORMATION
|
||||
|
||||
%% color-convert@1.9.3 NOTICES AND INFORMATION BEGIN HERE
|
||||
=========================================
|
||||
Copyright (c) 2011-2016 Heather Arthur <fayearthur@gmail.com>
|
||||
|
|
@ -4029,6 +4056,6 @@ END OF to-regex-range@5.0.1 AND INFORMATION
|
|||
|
||||
SUMMARY BEGIN HERE
|
||||
=========================================
|
||||
Total Packages: 138
|
||||
Total Packages: 139
|
||||
=========================================
|
||||
END OF SUMMARY
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build && tsc",
|
||||
"build-sw": "vite --config vite.sw.config.ts build && tsc",
|
||||
"preview": "vite preview"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@
|
|||
outline: 1px solid var(--vscode-focusBorder);
|
||||
}
|
||||
|
||||
.action-list-content:focus .action-entry.selected * {
|
||||
color: var(--vscode-list-activeSelectionForeground);
|
||||
}
|
||||
|
||||
.action-title {
|
||||
flex: auto;
|
||||
display: block;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import type { StackFrame } from '@protocol/channels';
|
|||
import type { ActionTraceEvent } from '@trace/trace';
|
||||
import { Source as SourceView } from '@web/components/source';
|
||||
import { SplitView } from '@web/components/splitView';
|
||||
import '@web/third_party/highlightjs/highlightjs/github.css';
|
||||
import * as React from 'react';
|
||||
import { useAsyncMemo } from './helpers';
|
||||
import './sourceTab.css';
|
||||
|
|
|
|||
|
|
@ -37,12 +37,8 @@ export default defineConfig({
|
|||
outDir: path.resolve(__dirname, '../playwright-core/lib/webpack/traceViewer'),
|
||||
emptyOutDir: true,
|
||||
rollupOptions: {
|
||||
input: {
|
||||
main: path.resolve(__dirname, 'index.html'),
|
||||
sw: path.resolve(__dirname, 'src/sw.ts'),
|
||||
},
|
||||
output: {
|
||||
entryFileNames: info => info.name === 'sw' ? '[name].bundle.js' : '[name].[hash].js',
|
||||
entryFileNames: () => '[name].[hash].js',
|
||||
assetFileNames: () => '[name].[hash][extname]',
|
||||
manualChunks: undefined,
|
||||
},
|
||||
|
|
|
|||
49
packages/trace-viewer/vite.sw.config.ts
Normal file
49
packages/trace-viewer/vite.sw.config.ts
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import { bundle } from './bundle';
|
||||
import * as path from 'path';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
base: '',
|
||||
plugins: [
|
||||
react(),
|
||||
bundle()
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@isomorphic': path.resolve(__dirname, '../playwright-core/src/server/isomorphic'),
|
||||
'@protocol': path.resolve(__dirname, '../protocol/src'),
|
||||
'@web': path.resolve(__dirname, '../web/src'),
|
||||
},
|
||||
},
|
||||
build: {
|
||||
outDir: path.resolve(__dirname, '../playwright-core/lib/webpack/traceViewer'),
|
||||
rollupOptions: {
|
||||
input: {
|
||||
sw: path.resolve(__dirname, 'src/sw.ts'),
|
||||
},
|
||||
output: {
|
||||
entryFileNames: info => '[name].bundle.js',
|
||||
assetFileNames: () => '[name].[hash][extname]',
|
||||
manualChunks: undefined,
|
||||
},
|
||||
},
|
||||
}
|
||||
});
|
||||
|
|
@ -15,8 +15,6 @@
|
|||
*/
|
||||
|
||||
@import '../third_party/vscode/colors.css';
|
||||
@import '../third_party/highlightjs/highlightjs/github.css';
|
||||
@import '../third_party/highlightjs/highlightjs/github-dark.css' (prefers-color-scheme: dark);
|
||||
|
||||
.source {
|
||||
display: flex;
|
||||
|
|
@ -32,21 +30,6 @@
|
|||
color: var(--vscode-editor-foreground);
|
||||
}
|
||||
|
||||
.source-line {
|
||||
display: flex;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.source-line-number {
|
||||
color: #555;
|
||||
padding: 0 8px;
|
||||
width: 40px;
|
||||
margin-right: 3px;
|
||||
text-align: right;
|
||||
user-select: none;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.source-line-running {
|
||||
background-color: #b3dbff7f;
|
||||
z-index: 2;
|
||||
|
|
@ -63,3 +46,118 @@
|
|||
outline: 1px solid #ff5656;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.cm-wrapper, .cm-wrapper > div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-meta {
|
||||
color: var(--vscode-editor-foreground);
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-number {
|
||||
color: var(--vscode-debugTokenExpression-number);
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-keyword {
|
||||
color: var(--vscode-debugTokenExpression-name);
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-operator {
|
||||
color: var(--vscode-editor-foreground);
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-string {
|
||||
color: var(--vscode-debugTokenExpression-string);
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-string-2 {
|
||||
color: var(--vscode-debugTokenExpression-string);
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-error {
|
||||
color: var(--vscode-errorForeground);
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-def, .CodeMirror span.cm-tag {
|
||||
color: #0070c1;
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-comment, .CodeMirror span.cm-link {
|
||||
color: #008000;
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-variable, .CodeMirror span.cm-variable-2, .CodeMirror span.cm-atom {
|
||||
color: #0070c1;
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-property, .CodeMirror span.cm-qualifier, .CodeMirror span.cm-attribute {
|
||||
color: #001080;
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-variable-3,
|
||||
.CodeMirror span.cm-type {
|
||||
color: #267f99;
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: dark) {
|
||||
|
||||
.CodeMirror span.cm-def, .CodeMirror span.cm-tag {
|
||||
color: var(--vscode-debugView-valueChangedHighlight);
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-comment, .CodeMirror span.cm-link {
|
||||
color: #6a9955;
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-variable, .CodeMirror span.cm-variable-2, .CodeMirror span.cm-atom {
|
||||
color: #4fc1ff;
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-property, .CodeMirror span.cm-qualifier, .CodeMirror span.cm-attribute {
|
||||
color: #9cdcfe;
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-variable-3,
|
||||
.CodeMirror span.cm-type {
|
||||
color: #4ec9b0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.CodeMirror span.cm-bracket {
|
||||
color: var(--vscode-editorBracketHighlight-foreground3);
|
||||
}
|
||||
|
||||
.CodeMirror-cursor {
|
||||
border-left: 1px solid #bebebe;
|
||||
}
|
||||
|
||||
.CodeMirror div.CodeMirror-selected {
|
||||
background: var(--vscode-terminal-inactiveSelectionBackground);
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-gutters {
|
||||
background: var(--vscode-editor-background);
|
||||
border-right: 1px solid var(--vscode-editorGroup-border);
|
||||
color: var(--vscode-editorLineNumber-foreground);
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-matchingbracket {
|
||||
background-color: var(--vscode-editorBracketPairGuide-background1);
|
||||
color: var(--vscode-editorBracketHighlight-foreground1) !important;
|
||||
}
|
||||
|
||||
/* .CodeMirror-line,
|
||||
.CodeMirror-line-like {
|
||||
color: var(--vscode-editor-foreground) !important;
|
||||
} */
|
||||
|
||||
.CodeMirror {
|
||||
font-family: var(--vscode-editor-font-family) !important;
|
||||
color: var(--vscode-editor-foreground) !important;
|
||||
background-color: var(--vscode-editor-background) !important;
|
||||
font-weight: var(--vscode-editor-font-weight) !important;
|
||||
font-size: var(--vscode-editor-font-size) !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,22 +71,22 @@ class Program
|
|||
|
||||
test('highlight JavaScript', async ({ mount }) => {
|
||||
const component = await mount(<Source text={javascriptSnippet} language='javascript'></Source>);
|
||||
await expect(component.locator('text="async"').first()).toHaveClass('hljs-keyword');
|
||||
await expect(component.locator('text="async"').first()).toHaveClass('cm-keyword');
|
||||
});
|
||||
|
||||
test('highlight Python', async ({ mount }) => {
|
||||
const component = await mount(<Source text={pythonSnippet} language='python'></Source>);
|
||||
await expect(component.locator('text="async"').first()).toHaveClass('hljs-keyword');
|
||||
await expect(component.locator('text="async"').first()).toHaveClass('cm-keyword');
|
||||
});
|
||||
|
||||
test('highlight Java', async ({ mount }) => {
|
||||
const component = await mount(<Source text={javaSnippet} language='java'></Source>);
|
||||
await expect(component.locator('text="public"').first()).toHaveClass('hljs-keyword');
|
||||
await expect(component.locator('text="public"').first()).toHaveClass('cm-keyword');
|
||||
});
|
||||
|
||||
test('highlight C#', async ({ mount }) => {
|
||||
const component = await mount(<Source text={csharpSnippet} language='csharp'></Source>);
|
||||
await expect(component.locator('text="public"').first()).toHaveClass('hljs-keyword');
|
||||
await expect(component.locator('text="public"').first()).toHaveClass('cm-keyword');
|
||||
});
|
||||
|
||||
test('highlight lines', async ({ mount }) => {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,11 @@
|
|||
|
||||
import './source.css';
|
||||
import * as React from 'react';
|
||||
import highlightjs from '../third_party/highlightjs/highlightjs';
|
||||
import CodeMirror from 'codemirror';
|
||||
import 'codemirror/mode/javascript/javascript';
|
||||
import 'codemirror/mode/python/python';
|
||||
import 'codemirror/mode/clike/clike';
|
||||
import 'codemirror/lib/codemirror.css';
|
||||
|
||||
export type SourceHighlight = {
|
||||
line: number;
|
||||
|
|
@ -37,32 +41,51 @@ export const Source: React.FC<SourceProps> = ({
|
|||
highlight = [],
|
||||
revealLine
|
||||
}) => {
|
||||
const lines = React.useMemo<string[]>(() => {
|
||||
const result = [];
|
||||
let continuation: any;
|
||||
for (const line of text.split('\n')) {
|
||||
const highlighted = highlightjs.highlight(language, line, true, continuation);
|
||||
continuation = highlighted.top;
|
||||
result.push(highlighted.value);
|
||||
}
|
||||
return result;
|
||||
}, [text, language]);
|
||||
const codemirrorElement = React.createRef<HTMLDivElement>();
|
||||
const [codemirror, setCodemirror] = React.useState<CodeMirror.Editor>();
|
||||
|
||||
const revealedLineRef = React.createRef<HTMLDivElement>();
|
||||
React.useLayoutEffect(() => {
|
||||
if (typeof revealLine === 'number' && revealedLineRef.current)
|
||||
revealedLineRef.current.scrollIntoView({ block: 'center', inline: 'nearest' });
|
||||
}, [revealedLineRef, revealLine]);
|
||||
React.useEffect(() => {
|
||||
let mode;
|
||||
if (language === 'javascript')
|
||||
mode = 'javascript';
|
||||
if (language === 'python')
|
||||
mode = 'python';
|
||||
if (language === 'java')
|
||||
mode = 'text/x-java';
|
||||
if (language === 'csharp')
|
||||
mode = 'text/x-csharp';
|
||||
|
||||
return <div className='source'>{
|
||||
lines.map((markup, index) => {
|
||||
const lineNumber = index + 1;
|
||||
const lineHighlight = highlight.find(h => h.line === lineNumber);
|
||||
const lineClass = lineHighlight ? `source-line source-line-${lineHighlight.type}` : 'source-line';
|
||||
return <div key={lineNumber} className={lineClass} ref={revealLine === lineNumber ? revealedLineRef : null}>
|
||||
<div className='source-line-number'>{lineNumber}</div>
|
||||
<div className='source-code' dangerouslySetInnerHTML={{ __html: markup }}></div>
|
||||
</div>;
|
||||
})
|
||||
}</div>;
|
||||
if (codemirror && codemirror.getOption('mode') === mode)
|
||||
return;
|
||||
|
||||
if (!codemirrorElement.current)
|
||||
return;
|
||||
if (codemirror)
|
||||
codemirror.getWrapperElement().remove();
|
||||
|
||||
const cm = CodeMirror(codemirrorElement.current, {
|
||||
value: '',
|
||||
mode,
|
||||
readOnly: true,
|
||||
lineNumbers: true,
|
||||
});
|
||||
setCodemirror(cm);
|
||||
updateEditor(cm, text, highlight, revealLine);
|
||||
}, [codemirror, codemirrorElement, text, language, highlight, revealLine]);
|
||||
|
||||
if (codemirror)
|
||||
updateEditor(codemirror, text, highlight, revealLine);
|
||||
|
||||
return <div className='cm-wrapper' ref={codemirrorElement}></div>;
|
||||
};
|
||||
|
||||
function updateEditor(cm: CodeMirror.Editor, text: string, highlight: SourceHighlight[], revealLine: number | undefined) {
|
||||
if (cm.getValue() !== text)
|
||||
cm.setValue(text);
|
||||
for (let i = 0; i < cm.lineCount(); ++i)
|
||||
cm.removeLineClass(i, 'wrap');
|
||||
for (const h of highlight)
|
||||
cm.addLineClass(h.line - 1, 'wrap', `source-line-${h.type}`);
|
||||
if (revealLine)
|
||||
cm.scrollIntoView({ line: revealLine - 1, ch: 0 }, 50);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
# Highlight.js
|
||||
|
||||
This is a small build of [highlight.js](https://github.com/highlightjs/highlight.js).
|
||||
Pick a [stable release](https://github.com/highlightjs/highlight.js/releases) revision and use `roll.sh` to update.
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2006, Ivan Sagalaev.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,10 +0,0 @@
|
|||
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
|
||||
Theme: GitHub Dark
|
||||
Description: Dark theme as seen on github.com
|
||||
Author: github.com
|
||||
Maintainer: @Hirse
|
||||
Updated: 2021-05-15
|
||||
|
||||
Outdated base version: https://github.com/primer/github-syntax-dark
|
||||
Current colors taken from GitHub's CSS
|
||||
*/.hljs{color:#c9d1d9;background:#0d1117}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#ff7b72}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#d2a8ff}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#79c0ff}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#a5d6ff}.hljs-built_in,.hljs-symbol{color:#ffa657}.hljs-code,.hljs-comment,.hljs-formula{color:#8b949e}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#7ee787}.hljs-subst{color:#c9d1d9}.hljs-section{color:#1f6feb;font-weight:700}.hljs-bullet{color:#f2cc60}.hljs-emphasis{color:#c9d1d9;font-style:italic}.hljs-strong{color:#c9d1d9;font-weight:700}.hljs-addition{color:#aff5b4;background-color:#033a16}.hljs-deletion{color:#ffdcd7;background-color:#67060c}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*!
|
||||
Theme: GitHub
|
||||
Description: Light theme as seen on github.com
|
||||
Author: github.com
|
||||
Maintainer: @Hirse
|
||||
Updated: 2021-05-15
|
||||
|
||||
Outdated base version: https://github.com/primer/github-syntax-light
|
||||
Current colors taken from GitHub's CSS
|
||||
*/.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import core from './core';
|
||||
import javascript from './languages/javascript';
|
||||
import python from './languages/python';
|
||||
import csharp from './languages/csharp';
|
||||
import java from './languages/java';
|
||||
|
||||
core.registerLanguage('javascript', javascript);
|
||||
core.registerLanguage('python', python);
|
||||
core.registerLanguage('csharp', csharp);
|
||||
core.registerLanguage('java', java);
|
||||
|
||||
export default core;
|
||||
|
|
@ -1,398 +0,0 @@
|
|||
/*
|
||||
Language: C#
|
||||
Author: Jason Diamond <jason@diamond.name>
|
||||
Contributor: Nicolas LLOBERA <nllobera@gmail.com>, Pieter Vantorre <pietervantorre@gmail.com>, David Pine <david.pine@microsoft.com>
|
||||
Website: https://docs.microsoft.com/dotnet/csharp/
|
||||
Category: common
|
||||
*/
|
||||
|
||||
/** @type LanguageFn */
|
||||
export default function csharp(hljs) {
|
||||
const BUILT_IN_KEYWORDS = [
|
||||
'bool',
|
||||
'byte',
|
||||
'char',
|
||||
'decimal',
|
||||
'delegate',
|
||||
'double',
|
||||
'dynamic',
|
||||
'enum',
|
||||
'float',
|
||||
'int',
|
||||
'long',
|
||||
'nint',
|
||||
'nuint',
|
||||
'object',
|
||||
'sbyte',
|
||||
'short',
|
||||
'string',
|
||||
'ulong',
|
||||
'uint',
|
||||
'ushort'
|
||||
];
|
||||
const FUNCTION_MODIFIERS = [
|
||||
'public',
|
||||
'private',
|
||||
'protected',
|
||||
'static',
|
||||
'internal',
|
||||
'protected',
|
||||
'abstract',
|
||||
'async',
|
||||
'extern',
|
||||
'override',
|
||||
'unsafe',
|
||||
'virtual',
|
||||
'new',
|
||||
'sealed',
|
||||
'partial'
|
||||
];
|
||||
const LITERAL_KEYWORDS = [
|
||||
'default',
|
||||
'false',
|
||||
'null',
|
||||
'true'
|
||||
];
|
||||
const NORMAL_KEYWORDS = [
|
||||
'abstract',
|
||||
'as',
|
||||
'base',
|
||||
'break',
|
||||
'case',
|
||||
'catch',
|
||||
'class',
|
||||
'const',
|
||||
'continue',
|
||||
'do',
|
||||
'else',
|
||||
'event',
|
||||
'explicit',
|
||||
'extern',
|
||||
'finally',
|
||||
'fixed',
|
||||
'for',
|
||||
'foreach',
|
||||
'goto',
|
||||
'if',
|
||||
'implicit',
|
||||
'in',
|
||||
'interface',
|
||||
'internal',
|
||||
'is',
|
||||
'lock',
|
||||
'namespace',
|
||||
'new',
|
||||
'operator',
|
||||
'out',
|
||||
'override',
|
||||
'params',
|
||||
'private',
|
||||
'protected',
|
||||
'public',
|
||||
'readonly',
|
||||
'record',
|
||||
'ref',
|
||||
'return',
|
||||
'scoped',
|
||||
'sealed',
|
||||
'sizeof',
|
||||
'stackalloc',
|
||||
'static',
|
||||
'struct',
|
||||
'switch',
|
||||
'this',
|
||||
'throw',
|
||||
'try',
|
||||
'typeof',
|
||||
'unchecked',
|
||||
'unsafe',
|
||||
'using',
|
||||
'virtual',
|
||||
'void',
|
||||
'volatile',
|
||||
'while'
|
||||
];
|
||||
const CONTEXTUAL_KEYWORDS = [
|
||||
'add',
|
||||
'alias',
|
||||
'and',
|
||||
'ascending',
|
||||
'async',
|
||||
'await',
|
||||
'by',
|
||||
'descending',
|
||||
'equals',
|
||||
'from',
|
||||
'get',
|
||||
'global',
|
||||
'group',
|
||||
'init',
|
||||
'into',
|
||||
'join',
|
||||
'let',
|
||||
'nameof',
|
||||
'not',
|
||||
'notnull',
|
||||
'on',
|
||||
'or',
|
||||
'orderby',
|
||||
'partial',
|
||||
'remove',
|
||||
'select',
|
||||
'set',
|
||||
'unmanaged',
|
||||
'value|0',
|
||||
'var',
|
||||
'when',
|
||||
'where',
|
||||
'with',
|
||||
'yield'
|
||||
];
|
||||
|
||||
const KEYWORDS = {
|
||||
keyword: NORMAL_KEYWORDS.concat(CONTEXTUAL_KEYWORDS),
|
||||
built_in: BUILT_IN_KEYWORDS,
|
||||
literal: LITERAL_KEYWORDS
|
||||
};
|
||||
const TITLE_MODE = hljs.inherit(hljs.TITLE_MODE, { begin: '[a-zA-Z](\\.?\\w)*' });
|
||||
const NUMBERS = {
|
||||
className: 'number',
|
||||
variants: [
|
||||
{ begin: '\\b(0b[01\']+)' },
|
||||
{ begin: '(-?)\\b([\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)(u|U|l|L|ul|UL|f|F|b|B)' },
|
||||
{ begin: '(-?)(\\b0[xX][a-fA-F0-9\']+|(\\b[\\d\']+(\\.[\\d\']*)?|\\.[\\d\']+)([eE][-+]?[\\d\']+)?)' }
|
||||
],
|
||||
relevance: 0
|
||||
};
|
||||
const VERBATIM_STRING = {
|
||||
className: 'string',
|
||||
begin: '@"',
|
||||
end: '"',
|
||||
contains: [ { begin: '""' } ]
|
||||
};
|
||||
const VERBATIM_STRING_NO_LF = hljs.inherit(VERBATIM_STRING, { illegal: /\n/ });
|
||||
const SUBST = {
|
||||
className: 'subst',
|
||||
begin: /\{/,
|
||||
end: /\}/,
|
||||
keywords: KEYWORDS
|
||||
};
|
||||
const SUBST_NO_LF = hljs.inherit(SUBST, { illegal: /\n/ });
|
||||
const INTERPOLATED_STRING = {
|
||||
className: 'string',
|
||||
begin: /\$"/,
|
||||
end: '"',
|
||||
illegal: /\n/,
|
||||
contains: [
|
||||
{ begin: /\{\{/ },
|
||||
{ begin: /\}\}/ },
|
||||
hljs.BACKSLASH_ESCAPE,
|
||||
SUBST_NO_LF
|
||||
]
|
||||
};
|
||||
const INTERPOLATED_VERBATIM_STRING = {
|
||||
className: 'string',
|
||||
begin: /\$@"/,
|
||||
end: '"',
|
||||
contains: [
|
||||
{ begin: /\{\{/ },
|
||||
{ begin: /\}\}/ },
|
||||
{ begin: '""' },
|
||||
SUBST
|
||||
]
|
||||
};
|
||||
const INTERPOLATED_VERBATIM_STRING_NO_LF = hljs.inherit(INTERPOLATED_VERBATIM_STRING, {
|
||||
illegal: /\n/,
|
||||
contains: [
|
||||
{ begin: /\{\{/ },
|
||||
{ begin: /\}\}/ },
|
||||
{ begin: '""' },
|
||||
SUBST_NO_LF
|
||||
]
|
||||
});
|
||||
SUBST.contains = [
|
||||
INTERPOLATED_VERBATIM_STRING,
|
||||
INTERPOLATED_STRING,
|
||||
VERBATIM_STRING,
|
||||
hljs.APOS_STRING_MODE,
|
||||
hljs.QUOTE_STRING_MODE,
|
||||
NUMBERS,
|
||||
hljs.C_BLOCK_COMMENT_MODE
|
||||
];
|
||||
SUBST_NO_LF.contains = [
|
||||
INTERPOLATED_VERBATIM_STRING_NO_LF,
|
||||
INTERPOLATED_STRING,
|
||||
VERBATIM_STRING_NO_LF,
|
||||
hljs.APOS_STRING_MODE,
|
||||
hljs.QUOTE_STRING_MODE,
|
||||
NUMBERS,
|
||||
hljs.inherit(hljs.C_BLOCK_COMMENT_MODE, { illegal: /\n/ })
|
||||
];
|
||||
const STRING = { variants: [
|
||||
INTERPOLATED_VERBATIM_STRING,
|
||||
INTERPOLATED_STRING,
|
||||
VERBATIM_STRING,
|
||||
hljs.APOS_STRING_MODE,
|
||||
hljs.QUOTE_STRING_MODE
|
||||
] };
|
||||
|
||||
const GENERIC_MODIFIER = {
|
||||
begin: "<",
|
||||
end: ">",
|
||||
contains: [
|
||||
{ beginKeywords: "in out" },
|
||||
TITLE_MODE
|
||||
]
|
||||
};
|
||||
const TYPE_IDENT_RE = hljs.IDENT_RE + '(<' + hljs.IDENT_RE + '(\\s*,\\s*' + hljs.IDENT_RE + ')*>)?(\\[\\])?';
|
||||
const AT_IDENTIFIER = {
|
||||
// prevents expressions like `@class` from incorrect flagging
|
||||
// `class` as a keyword
|
||||
begin: "@" + hljs.IDENT_RE,
|
||||
relevance: 0
|
||||
};
|
||||
|
||||
return {
|
||||
name: 'C#',
|
||||
aliases: [
|
||||
'cs',
|
||||
'c#'
|
||||
],
|
||||
keywords: KEYWORDS,
|
||||
illegal: /::/,
|
||||
contains: [
|
||||
hljs.COMMENT(
|
||||
'///',
|
||||
'$',
|
||||
{
|
||||
returnBegin: true,
|
||||
contains: [
|
||||
{
|
||||
className: 'doctag',
|
||||
variants: [
|
||||
{
|
||||
begin: '///',
|
||||
relevance: 0
|
||||
},
|
||||
{ begin: '<!--|-->' },
|
||||
{
|
||||
begin: '</?',
|
||||
end: '>'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
),
|
||||
hljs.C_LINE_COMMENT_MODE,
|
||||
hljs.C_BLOCK_COMMENT_MODE,
|
||||
{
|
||||
className: 'meta',
|
||||
begin: '#',
|
||||
end: '$',
|
||||
keywords: { keyword: 'if else elif endif define undef warning error line region endregion pragma checksum' }
|
||||
},
|
||||
STRING,
|
||||
NUMBERS,
|
||||
{
|
||||
beginKeywords: 'class interface',
|
||||
relevance: 0,
|
||||
end: /[{;=]/,
|
||||
illegal: /[^\s:,]/,
|
||||
contains: [
|
||||
{ beginKeywords: "where class" },
|
||||
TITLE_MODE,
|
||||
GENERIC_MODIFIER,
|
||||
hljs.C_LINE_COMMENT_MODE,
|
||||
hljs.C_BLOCK_COMMENT_MODE
|
||||
]
|
||||
},
|
||||
{
|
||||
beginKeywords: 'namespace',
|
||||
relevance: 0,
|
||||
end: /[{;=]/,
|
||||
illegal: /[^\s:]/,
|
||||
contains: [
|
||||
TITLE_MODE,
|
||||
hljs.C_LINE_COMMENT_MODE,
|
||||
hljs.C_BLOCK_COMMENT_MODE
|
||||
]
|
||||
},
|
||||
{
|
||||
beginKeywords: 'record',
|
||||
relevance: 0,
|
||||
end: /[{;=]/,
|
||||
illegal: /[^\s:]/,
|
||||
contains: [
|
||||
TITLE_MODE,
|
||||
GENERIC_MODIFIER,
|
||||
hljs.C_LINE_COMMENT_MODE,
|
||||
hljs.C_BLOCK_COMMENT_MODE
|
||||
]
|
||||
},
|
||||
{
|
||||
// [Attributes("")]
|
||||
className: 'meta',
|
||||
begin: '^\\s*\\[(?=[\\w])',
|
||||
excludeBegin: true,
|
||||
end: '\\]',
|
||||
excludeEnd: true,
|
||||
contains: [
|
||||
{
|
||||
className: 'string',
|
||||
begin: /"/,
|
||||
end: /"/
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
// Expression keywords prevent 'keyword Name(...)' from being
|
||||
// recognized as a function definition
|
||||
beginKeywords: 'new return throw await else',
|
||||
relevance: 0
|
||||
},
|
||||
{
|
||||
className: 'function',
|
||||
begin: '(' + TYPE_IDENT_RE + '\\s+)+' + hljs.IDENT_RE + '\\s*(<[^=]+>\\s*)?\\(',
|
||||
returnBegin: true,
|
||||
end: /\s*[{;=]/,
|
||||
excludeEnd: true,
|
||||
keywords: KEYWORDS,
|
||||
contains: [
|
||||
// prevents these from being highlighted `title`
|
||||
{
|
||||
beginKeywords: FUNCTION_MODIFIERS.join(" "),
|
||||
relevance: 0
|
||||
},
|
||||
{
|
||||
begin: hljs.IDENT_RE + '\\s*(<[^=]+>\\s*)?\\(',
|
||||
returnBegin: true,
|
||||
contains: [
|
||||
hljs.TITLE_MODE,
|
||||
GENERIC_MODIFIER
|
||||
],
|
||||
relevance: 0
|
||||
},
|
||||
{ match: /\(\)/ },
|
||||
{
|
||||
className: 'params',
|
||||
begin: /\(/,
|
||||
end: /\)/,
|
||||
excludeBegin: true,
|
||||
excludeEnd: true,
|
||||
keywords: KEYWORDS,
|
||||
relevance: 0,
|
||||
contains: [
|
||||
STRING,
|
||||
NUMBERS,
|
||||
hljs.C_BLOCK_COMMENT_MODE
|
||||
]
|
||||
},
|
||||
hljs.C_LINE_COMMENT_MODE,
|
||||
hljs.C_BLOCK_COMMENT_MODE
|
||||
]
|
||||
},
|
||||
AT_IDENTIFIER
|
||||
]
|
||||
};
|
||||
}
|
||||
|
|
@ -1,284 +0,0 @@
|
|||
// https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10
|
||||
var decimalDigits = '[0-9](_*[0-9])*';
|
||||
var frac = `\\.(${decimalDigits})`;
|
||||
var hexDigits = '[0-9a-fA-F](_*[0-9a-fA-F])*';
|
||||
var NUMERIC = {
|
||||
className: 'number',
|
||||
variants: [
|
||||
// DecimalFloatingPointLiteral
|
||||
// including ExponentPart
|
||||
{ begin: `(\\b(${decimalDigits})((${frac})|\\.)?|(${frac}))` +
|
||||
`[eE][+-]?(${decimalDigits})[fFdD]?\\b` },
|
||||
// excluding ExponentPart
|
||||
{ begin: `\\b(${decimalDigits})((${frac})[fFdD]?\\b|\\.([fFdD]\\b)?)` },
|
||||
{ begin: `(${frac})[fFdD]?\\b` },
|
||||
{ begin: `\\b(${decimalDigits})[fFdD]\\b` },
|
||||
|
||||
// HexadecimalFloatingPointLiteral
|
||||
{ begin: `\\b0[xX]((${hexDigits})\\.?|(${hexDigits})?\\.(${hexDigits}))` +
|
||||
`[pP][+-]?(${decimalDigits})[fFdD]?\\b` },
|
||||
|
||||
// DecimalIntegerLiteral
|
||||
{ begin: '\\b(0|[1-9](_*[0-9])*)[lL]?\\b' },
|
||||
|
||||
// HexIntegerLiteral
|
||||
{ begin: `\\b0[xX](${hexDigits})[lL]?\\b` },
|
||||
|
||||
// OctalIntegerLiteral
|
||||
{ begin: '\\b0(_*[0-7])*[lL]?\\b' },
|
||||
|
||||
// BinaryIntegerLiteral
|
||||
{ begin: '\\b0[bB][01](_*[01])*[lL]?\\b' },
|
||||
],
|
||||
relevance: 0
|
||||
};
|
||||
|
||||
/*
|
||||
Language: Java
|
||||
Author: Vsevolod Solovyov <vsevolod.solovyov@gmail.com>
|
||||
Category: common, enterprise
|
||||
Website: https://www.java.com/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allows recursive regex expressions to a given depth
|
||||
*
|
||||
* ie: recurRegex("(abc~~~)", /~~~/g, 2) becomes:
|
||||
* (abc(abc(abc)))
|
||||
*
|
||||
* @param {string} re
|
||||
* @param {RegExp} substitution (should be a g mode regex)
|
||||
* @param {number} depth
|
||||
* @returns {string}``
|
||||
*/
|
||||
function recurRegex(re, substitution, depth) {
|
||||
if (depth === -1) return "";
|
||||
|
||||
return re.replace(substitution, _ => {
|
||||
return recurRegex(re, substitution, depth - 1);
|
||||
});
|
||||
}
|
||||
|
||||
/** @type LanguageFn */
|
||||
export default function java(hljs) {
|
||||
const regex = hljs.regex;
|
||||
const JAVA_IDENT_RE = '[\u00C0-\u02B8a-zA-Z_$][\u00C0-\u02B8a-zA-Z_$0-9]*';
|
||||
const GENERIC_IDENT_RE = JAVA_IDENT_RE
|
||||
+ recurRegex('(?:<' + JAVA_IDENT_RE + '~~~(?:\\s*,\\s*' + JAVA_IDENT_RE + '~~~)*>)?', /~~~/g, 2);
|
||||
const MAIN_KEYWORDS = [
|
||||
'synchronized',
|
||||
'abstract',
|
||||
'private',
|
||||
'var',
|
||||
'static',
|
||||
'if',
|
||||
'const ',
|
||||
'for',
|
||||
'while',
|
||||
'strictfp',
|
||||
'finally',
|
||||
'protected',
|
||||
'import',
|
||||
'native',
|
||||
'final',
|
||||
'void',
|
||||
'enum',
|
||||
'else',
|
||||
'break',
|
||||
'transient',
|
||||
'catch',
|
||||
'instanceof',
|
||||
'volatile',
|
||||
'case',
|
||||
'assert',
|
||||
'package',
|
||||
'default',
|
||||
'public',
|
||||
'try',
|
||||
'switch',
|
||||
'continue',
|
||||
'throws',
|
||||
'protected',
|
||||
'public',
|
||||
'private',
|
||||
'module',
|
||||
'requires',
|
||||
'exports',
|
||||
'do',
|
||||
'sealed'
|
||||
];
|
||||
|
||||
const BUILT_INS = [
|
||||
'super',
|
||||
'this'
|
||||
];
|
||||
|
||||
const LITERALS = [
|
||||
'false',
|
||||
'true',
|
||||
'null'
|
||||
];
|
||||
|
||||
const TYPES = [
|
||||
'char',
|
||||
'boolean',
|
||||
'long',
|
||||
'float',
|
||||
'int',
|
||||
'byte',
|
||||
'short',
|
||||
'double'
|
||||
];
|
||||
|
||||
const KEYWORDS = {
|
||||
keyword: MAIN_KEYWORDS,
|
||||
literal: LITERALS,
|
||||
type: TYPES,
|
||||
built_in: BUILT_INS
|
||||
};
|
||||
|
||||
const ANNOTATION = {
|
||||
className: 'meta',
|
||||
begin: '@' + JAVA_IDENT_RE,
|
||||
contains: [
|
||||
{
|
||||
begin: /\(/,
|
||||
end: /\)/,
|
||||
contains: [ "self" ] // allow nested () inside our annotation
|
||||
}
|
||||
]
|
||||
};
|
||||
const PARAMS = {
|
||||
className: 'params',
|
||||
begin: /\(/,
|
||||
end: /\)/,
|
||||
keywords: KEYWORDS,
|
||||
relevance: 0,
|
||||
contains: [ hljs.C_BLOCK_COMMENT_MODE ],
|
||||
endsParent: true
|
||||
};
|
||||
|
||||
return {
|
||||
name: 'Java',
|
||||
aliases: [ 'jsp' ],
|
||||
keywords: KEYWORDS,
|
||||
illegal: /<\/|#/,
|
||||
contains: [
|
||||
hljs.COMMENT(
|
||||
'/\\*\\*',
|
||||
'\\*/',
|
||||
{
|
||||
relevance: 0,
|
||||
contains: [
|
||||
{
|
||||
// eat up @'s in emails to prevent them to be recognized as doctags
|
||||
begin: /\w+@/,
|
||||
relevance: 0
|
||||
},
|
||||
{
|
||||
className: 'doctag',
|
||||
begin: '@[A-Za-z]+'
|
||||
}
|
||||
]
|
||||
}
|
||||
),
|
||||
// relevance boost
|
||||
{
|
||||
begin: /import java\.[a-z]+\./,
|
||||
keywords: "import",
|
||||
relevance: 2
|
||||
},
|
||||
hljs.C_LINE_COMMENT_MODE,
|
||||
hljs.C_BLOCK_COMMENT_MODE,
|
||||
{
|
||||
begin: /"""/,
|
||||
end: /"""/,
|
||||
className: "string",
|
||||
contains: [ hljs.BACKSLASH_ESCAPE ]
|
||||
},
|
||||
hljs.APOS_STRING_MODE,
|
||||
hljs.QUOTE_STRING_MODE,
|
||||
{
|
||||
match: [
|
||||
/\b(?:class|interface|enum|extends|implements|new)/,
|
||||
/\s+/,
|
||||
JAVA_IDENT_RE
|
||||
],
|
||||
className: {
|
||||
1: "keyword",
|
||||
3: "title.class"
|
||||
}
|
||||
},
|
||||
{
|
||||
// Exceptions for hyphenated keywords
|
||||
match: /non-sealed/,
|
||||
scope: "keyword"
|
||||
},
|
||||
{
|
||||
begin: [
|
||||
regex.concat(/(?!else)/, JAVA_IDENT_RE),
|
||||
/\s+/,
|
||||
JAVA_IDENT_RE,
|
||||
/\s+/,
|
||||
/=(?!=)/
|
||||
],
|
||||
className: {
|
||||
1: "type",
|
||||
3: "variable",
|
||||
5: "operator"
|
||||
}
|
||||
},
|
||||
{
|
||||
begin: [
|
||||
/record/,
|
||||
/\s+/,
|
||||
JAVA_IDENT_RE
|
||||
],
|
||||
className: {
|
||||
1: "keyword",
|
||||
3: "title.class"
|
||||
},
|
||||
contains: [
|
||||
PARAMS,
|
||||
hljs.C_LINE_COMMENT_MODE,
|
||||
hljs.C_BLOCK_COMMENT_MODE
|
||||
]
|
||||
},
|
||||
{
|
||||
// Expression keywords prevent 'keyword Name(...)' from being
|
||||
// recognized as a function definition
|
||||
beginKeywords: 'new throw return else',
|
||||
relevance: 0
|
||||
},
|
||||
{
|
||||
begin: [
|
||||
'(?:' + GENERIC_IDENT_RE + '\\s+)',
|
||||
hljs.UNDERSCORE_IDENT_RE,
|
||||
/\s*(?=\()/
|
||||
],
|
||||
className: { 2: "title.function" },
|
||||
keywords: KEYWORDS,
|
||||
contains: [
|
||||
{
|
||||
className: 'params',
|
||||
begin: /\(/,
|
||||
end: /\)/,
|
||||
keywords: KEYWORDS,
|
||||
relevance: 0,
|
||||
contains: [
|
||||
ANNOTATION,
|
||||
hljs.APOS_STRING_MODE,
|
||||
hljs.QUOTE_STRING_MODE,
|
||||
NUMERIC,
|
||||
hljs.C_BLOCK_COMMENT_MODE
|
||||
]
|
||||
},
|
||||
hljs.C_LINE_COMMENT_MODE,
|
||||
hljs.C_BLOCK_COMMENT_MODE
|
||||
]
|
||||
},
|
||||
NUMERIC,
|
||||
ANNOTATION
|
||||
]
|
||||
};
|
||||
}
|
||||
|
|
@ -1,733 +0,0 @@
|
|||
const IDENT_RE = '[A-Za-z$_][0-9A-Za-z$_]*';
|
||||
const KEYWORDS = [
|
||||
"as", // for exports
|
||||
"in",
|
||||
"of",
|
||||
"if",
|
||||
"for",
|
||||
"while",
|
||||
"finally",
|
||||
"var",
|
||||
"new",
|
||||
"function",
|
||||
"do",
|
||||
"return",
|
||||
"void",
|
||||
"else",
|
||||
"break",
|
||||
"catch",
|
||||
"instanceof",
|
||||
"with",
|
||||
"throw",
|
||||
"case",
|
||||
"default",
|
||||
"try",
|
||||
"switch",
|
||||
"continue",
|
||||
"typeof",
|
||||
"delete",
|
||||
"let",
|
||||
"yield",
|
||||
"const",
|
||||
"class",
|
||||
// JS handles these with a special rule
|
||||
// "get",
|
||||
// "set",
|
||||
"debugger",
|
||||
"async",
|
||||
"await",
|
||||
"static",
|
||||
"import",
|
||||
"from",
|
||||
"export",
|
||||
"extends"
|
||||
];
|
||||
const LITERALS = [
|
||||
"true",
|
||||
"false",
|
||||
"null",
|
||||
"undefined",
|
||||
"NaN",
|
||||
"Infinity"
|
||||
];
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects
|
||||
const TYPES = [
|
||||
// Fundamental objects
|
||||
"Object",
|
||||
"Function",
|
||||
"Boolean",
|
||||
"Symbol",
|
||||
// numbers and dates
|
||||
"Math",
|
||||
"Date",
|
||||
"Number",
|
||||
"BigInt",
|
||||
// text
|
||||
"String",
|
||||
"RegExp",
|
||||
// Indexed collections
|
||||
"Array",
|
||||
"Float32Array",
|
||||
"Float64Array",
|
||||
"Int8Array",
|
||||
"Uint8Array",
|
||||
"Uint8ClampedArray",
|
||||
"Int16Array",
|
||||
"Int32Array",
|
||||
"Uint16Array",
|
||||
"Uint32Array",
|
||||
"BigInt64Array",
|
||||
"BigUint64Array",
|
||||
// Keyed collections
|
||||
"Set",
|
||||
"Map",
|
||||
"WeakSet",
|
||||
"WeakMap",
|
||||
// Structured data
|
||||
"ArrayBuffer",
|
||||
"SharedArrayBuffer",
|
||||
"Atomics",
|
||||
"DataView",
|
||||
"JSON",
|
||||
// Control abstraction objects
|
||||
"Promise",
|
||||
"Generator",
|
||||
"GeneratorFunction",
|
||||
"AsyncFunction",
|
||||
// Reflection
|
||||
"Reflect",
|
||||
"Proxy",
|
||||
// Internationalization
|
||||
"Intl",
|
||||
// WebAssembly
|
||||
"WebAssembly"
|
||||
];
|
||||
|
||||
const ERROR_TYPES = [
|
||||
"Error",
|
||||
"EvalError",
|
||||
"InternalError",
|
||||
"RangeError",
|
||||
"ReferenceError",
|
||||
"SyntaxError",
|
||||
"TypeError",
|
||||
"URIError"
|
||||
];
|
||||
|
||||
const BUILT_IN_GLOBALS = [
|
||||
"setInterval",
|
||||
"setTimeout",
|
||||
"clearInterval",
|
||||
"clearTimeout",
|
||||
|
||||
"require",
|
||||
"exports",
|
||||
|
||||
"eval",
|
||||
"isFinite",
|
||||
"isNaN",
|
||||
"parseFloat",
|
||||
"parseInt",
|
||||
"decodeURI",
|
||||
"decodeURIComponent",
|
||||
"encodeURI",
|
||||
"encodeURIComponent",
|
||||
"escape",
|
||||
"unescape"
|
||||
];
|
||||
|
||||
const BUILT_IN_VARIABLES = [
|
||||
"arguments",
|
||||
"this",
|
||||
"super",
|
||||
"console",
|
||||
"window",
|
||||
"document",
|
||||
"localStorage",
|
||||
"module",
|
||||
"global" // Node.js
|
||||
];
|
||||
|
||||
const BUILT_INS = [].concat(
|
||||
BUILT_IN_GLOBALS,
|
||||
TYPES,
|
||||
ERROR_TYPES
|
||||
);
|
||||
|
||||
/*
|
||||
Language: JavaScript
|
||||
Description: JavaScript (JS) is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions.
|
||||
Category: common, scripting, web
|
||||
Website: https://developer.mozilla.org/en-US/docs/Web/JavaScript
|
||||
*/
|
||||
|
||||
/** @type LanguageFn */
|
||||
export default function javascript(hljs) {
|
||||
const regex = hljs.regex;
|
||||
/**
|
||||
* Takes a string like "<Booger" and checks to see
|
||||
* if we can find a matching "</Booger" later in the
|
||||
* content.
|
||||
* @param {RegExpMatchArray} match
|
||||
* @param {{after:number}} param1
|
||||
*/
|
||||
const hasClosingTag = (match, { after }) => {
|
||||
const tag = "</" + match[0].slice(1);
|
||||
const pos = match.input.indexOf(tag, after);
|
||||
return pos !== -1;
|
||||
};
|
||||
|
||||
const IDENT_RE$1 = IDENT_RE;
|
||||
const FRAGMENT = {
|
||||
begin: '<>',
|
||||
end: '</>'
|
||||
};
|
||||
// to avoid some special cases inside isTrulyOpeningTag
|
||||
const XML_SELF_CLOSING = /<[A-Za-z0-9\\._:-]+\s*\/>/;
|
||||
const XML_TAG = {
|
||||
begin: /<[A-Za-z0-9\\._:-]+/,
|
||||
end: /\/[A-Za-z0-9\\._:-]+>|\/>/,
|
||||
/**
|
||||
* @param {RegExpMatchArray} match
|
||||
* @param {CallbackResponse} response
|
||||
*/
|
||||
isTrulyOpeningTag: (match, response) => {
|
||||
const afterMatchIndex = match[0].length + match.index;
|
||||
const nextChar = match.input[afterMatchIndex];
|
||||
if (
|
||||
// HTML should not include another raw `<` inside a tag
|
||||
// nested type?
|
||||
// `<Array<Array<number>>`, etc.
|
||||
nextChar === "<" ||
|
||||
// the , gives away that this is not HTML
|
||||
// `<T, A extends keyof T, V>`
|
||||
nextChar === ",") {
|
||||
response.ignoreMatch();
|
||||
return;
|
||||
}
|
||||
|
||||
// `<something>`
|
||||
// Quite possibly a tag, lets look for a matching closing tag...
|
||||
if (nextChar === ">") {
|
||||
// if we cannot find a matching closing tag, then we
|
||||
// will ignore it
|
||||
if (!hasClosingTag(match, { after: afterMatchIndex })) {
|
||||
response.ignoreMatch();
|
||||
}
|
||||
}
|
||||
|
||||
// `<blah />` (self-closing)
|
||||
// handled by simpleSelfClosing rule
|
||||
|
||||
// `<From extends string>`
|
||||
// technically this could be HTML, but it smells like a type
|
||||
let m;
|
||||
const afterMatch = match.input.substring(afterMatchIndex);
|
||||
// NOTE: This is ugh, but added specifically for https://github.com/highlightjs/highlight.js/issues/3276
|
||||
if ((m = afterMatch.match(/^\s+extends\s+/))) {
|
||||
if (m.index === 0) {
|
||||
response.ignoreMatch();
|
||||
// eslint-disable-next-line no-useless-return
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const KEYWORDS$1 = {
|
||||
$pattern: IDENT_RE,
|
||||
keyword: KEYWORDS,
|
||||
literal: LITERALS,
|
||||
built_in: BUILT_INS,
|
||||
"variable.language": BUILT_IN_VARIABLES
|
||||
};
|
||||
|
||||
// https://tc39.es/ecma262/#sec-literals-numeric-literals
|
||||
const decimalDigits = '[0-9](_?[0-9])*';
|
||||
const frac = `\\.(${decimalDigits})`;
|
||||
// DecimalIntegerLiteral, including Annex B NonOctalDecimalIntegerLiteral
|
||||
// https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals
|
||||
const decimalInteger = `0|[1-9](_?[0-9])*|0[0-7]*[89][0-9]*`;
|
||||
const NUMBER = {
|
||||
className: 'number',
|
||||
variants: [
|
||||
// DecimalLiteral
|
||||
{ begin: `(\\b(${decimalInteger})((${frac})|\\.)?|(${frac}))` +
|
||||
`[eE][+-]?(${decimalDigits})\\b` },
|
||||
{ begin: `\\b(${decimalInteger})\\b((${frac})\\b|\\.)?|(${frac})\\b` },
|
||||
|
||||
// DecimalBigIntegerLiteral
|
||||
{ begin: `\\b(0|[1-9](_?[0-9])*)n\\b` },
|
||||
|
||||
// NonDecimalIntegerLiteral
|
||||
{ begin: "\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*n?\\b" },
|
||||
{ begin: "\\b0[bB][0-1](_?[0-1])*n?\\b" },
|
||||
{ begin: "\\b0[oO][0-7](_?[0-7])*n?\\b" },
|
||||
|
||||
// LegacyOctalIntegerLiteral (does not include underscore separators)
|
||||
// https://tc39.es/ecma262/#sec-additional-syntax-numeric-literals
|
||||
{ begin: "\\b0[0-7]+n?\\b" },
|
||||
],
|
||||
relevance: 0
|
||||
};
|
||||
|
||||
const SUBST = {
|
||||
className: 'subst',
|
||||
begin: '\\$\\{',
|
||||
end: '\\}',
|
||||
keywords: KEYWORDS$1,
|
||||
contains: [] // defined later
|
||||
};
|
||||
const HTML_TEMPLATE = {
|
||||
begin: 'html`',
|
||||
end: '',
|
||||
starts: {
|
||||
end: '`',
|
||||
returnEnd: false,
|
||||
contains: [
|
||||
hljs.BACKSLASH_ESCAPE,
|
||||
SUBST
|
||||
],
|
||||
subLanguage: 'xml'
|
||||
}
|
||||
};
|
||||
const CSS_TEMPLATE = {
|
||||
begin: 'css`',
|
||||
end: '',
|
||||
starts: {
|
||||
end: '`',
|
||||
returnEnd: false,
|
||||
contains: [
|
||||
hljs.BACKSLASH_ESCAPE,
|
||||
SUBST
|
||||
],
|
||||
subLanguage: 'css'
|
||||
}
|
||||
};
|
||||
const TEMPLATE_STRING = {
|
||||
className: 'string',
|
||||
begin: '`',
|
||||
end: '`',
|
||||
contains: [
|
||||
hljs.BACKSLASH_ESCAPE,
|
||||
SUBST
|
||||
]
|
||||
};
|
||||
const JSDOC_COMMENT = hljs.COMMENT(
|
||||
/\/\*\*(?!\/)/,
|
||||
'\\*/',
|
||||
{
|
||||
relevance: 0,
|
||||
contains: [
|
||||
{
|
||||
begin: '(?=@[A-Za-z]+)',
|
||||
relevance: 0,
|
||||
contains: [
|
||||
{
|
||||
className: 'doctag',
|
||||
begin: '@[A-Za-z]+'
|
||||
},
|
||||
{
|
||||
className: 'type',
|
||||
begin: '\\{',
|
||||
end: '\\}',
|
||||
excludeEnd: true,
|
||||
excludeBegin: true,
|
||||
relevance: 0
|
||||
},
|
||||
{
|
||||
className: 'variable',
|
||||
begin: IDENT_RE$1 + '(?=\\s*(-)|$)',
|
||||
endsParent: true,
|
||||
relevance: 0
|
||||
},
|
||||
// eat spaces (not newlines) so we can find
|
||||
// types or variables
|
||||
{
|
||||
begin: /(?=[^\n])\s/,
|
||||
relevance: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
const COMMENT = {
|
||||
className: "comment",
|
||||
variants: [
|
||||
JSDOC_COMMENT,
|
||||
hljs.C_BLOCK_COMMENT_MODE,
|
||||
hljs.C_LINE_COMMENT_MODE
|
||||
]
|
||||
};
|
||||
const SUBST_INTERNALS = [
|
||||
hljs.APOS_STRING_MODE,
|
||||
hljs.QUOTE_STRING_MODE,
|
||||
HTML_TEMPLATE,
|
||||
CSS_TEMPLATE,
|
||||
TEMPLATE_STRING,
|
||||
NUMBER,
|
||||
// This is intentional:
|
||||
// See https://github.com/highlightjs/highlight.js/issues/3288
|
||||
// hljs.REGEXP_MODE
|
||||
];
|
||||
SUBST.contains = SUBST_INTERNALS
|
||||
.concat({
|
||||
// we need to pair up {} inside our subst to prevent
|
||||
// it from ending too early by matching another }
|
||||
begin: /\{/,
|
||||
end: /\}/,
|
||||
keywords: KEYWORDS$1,
|
||||
contains: [
|
||||
"self"
|
||||
].concat(SUBST_INTERNALS)
|
||||
});
|
||||
const SUBST_AND_COMMENTS = [].concat(COMMENT, SUBST.contains);
|
||||
const PARAMS_CONTAINS = SUBST_AND_COMMENTS.concat([
|
||||
// eat recursive parens in sub expressions
|
||||
{
|
||||
begin: /\(/,
|
||||
end: /\)/,
|
||||
keywords: KEYWORDS$1,
|
||||
contains: ["self"].concat(SUBST_AND_COMMENTS)
|
||||
}
|
||||
]);
|
||||
const PARAMS = {
|
||||
className: 'params',
|
||||
begin: /\(/,
|
||||
end: /\)/,
|
||||
excludeBegin: true,
|
||||
excludeEnd: true,
|
||||
keywords: KEYWORDS$1,
|
||||
contains: PARAMS_CONTAINS
|
||||
};
|
||||
|
||||
// ES6 classes
|
||||
const CLASS_OR_EXTENDS = {
|
||||
variants: [
|
||||
// class Car extends vehicle
|
||||
{
|
||||
match: [
|
||||
/class/,
|
||||
/\s+/,
|
||||
IDENT_RE$1,
|
||||
/\s+/,
|
||||
/extends/,
|
||||
/\s+/,
|
||||
regex.concat(IDENT_RE$1, "(", regex.concat(/\./, IDENT_RE$1), ")*")
|
||||
],
|
||||
scope: {
|
||||
1: "keyword",
|
||||
3: "title.class",
|
||||
5: "keyword",
|
||||
7: "title.class.inherited"
|
||||
}
|
||||
},
|
||||
// class Car
|
||||
{
|
||||
match: [
|
||||
/class/,
|
||||
/\s+/,
|
||||
IDENT_RE$1
|
||||
],
|
||||
scope: {
|
||||
1: "keyword",
|
||||
3: "title.class"
|
||||
}
|
||||
},
|
||||
|
||||
]
|
||||
};
|
||||
|
||||
const CLASS_REFERENCE = {
|
||||
relevance: 0,
|
||||
match:
|
||||
regex.either(
|
||||
// Hard coded exceptions
|
||||
/\bJSON/,
|
||||
// Float32Array, OutT
|
||||
/\b[A-Z][a-z]+([A-Z][a-z]*|\d)*/,
|
||||
// CSSFactory, CSSFactoryT
|
||||
/\b[A-Z]{2,}([A-Z][a-z]+|\d)+([A-Z][a-z]*)*/,
|
||||
// FPs, FPsT
|
||||
/\b[A-Z]{2,}[a-z]+([A-Z][a-z]+|\d)*([A-Z][a-z]*)*/,
|
||||
// P
|
||||
// single letters are not highlighted
|
||||
// BLAH
|
||||
// this will be flagged as a UPPER_CASE_CONSTANT instead
|
||||
),
|
||||
className: "title.class",
|
||||
keywords: {
|
||||
_: [
|
||||
// se we still get relevance credit for JS library classes
|
||||
...TYPES,
|
||||
...ERROR_TYPES
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
const USE_STRICT = {
|
||||
label: "use_strict",
|
||||
className: 'meta',
|
||||
relevance: 10,
|
||||
begin: /^\s*['"]use (strict|asm)['"]/
|
||||
};
|
||||
|
||||
const FUNCTION_DEFINITION = {
|
||||
variants: [
|
||||
{
|
||||
match: [
|
||||
/function/,
|
||||
/\s+/,
|
||||
IDENT_RE$1,
|
||||
/(?=\s*\()/
|
||||
]
|
||||
},
|
||||
// anonymous function
|
||||
{
|
||||
match: [
|
||||
/function/,
|
||||
/\s*(?=\()/
|
||||
]
|
||||
}
|
||||
],
|
||||
className: {
|
||||
1: "keyword",
|
||||
3: "title.function"
|
||||
},
|
||||
label: "func.def",
|
||||
contains: [ PARAMS ],
|
||||
illegal: /%/
|
||||
};
|
||||
|
||||
const UPPER_CASE_CONSTANT = {
|
||||
relevance: 0,
|
||||
match: /\b[A-Z][A-Z_0-9]+\b/,
|
||||
className: "variable.constant"
|
||||
};
|
||||
|
||||
function noneOf(list) {
|
||||
return regex.concat("(?!", list.join("|"), ")");
|
||||
}
|
||||
|
||||
const FUNCTION_CALL = {
|
||||
match: regex.concat(
|
||||
/\b/,
|
||||
noneOf([
|
||||
...BUILT_IN_GLOBALS,
|
||||
"super"
|
||||
]),
|
||||
IDENT_RE$1, regex.lookahead(/\(/)),
|
||||
className: "title.function",
|
||||
relevance: 0
|
||||
};
|
||||
|
||||
const PROPERTY_ACCESS = {
|
||||
begin: regex.concat(/\./, regex.lookahead(
|
||||
regex.concat(IDENT_RE$1, /(?![0-9A-Za-z$_(])/)
|
||||
)),
|
||||
end: IDENT_RE$1,
|
||||
excludeBegin: true,
|
||||
keywords: "prototype",
|
||||
className: "property",
|
||||
relevance: 0
|
||||
};
|
||||
|
||||
const GETTER_OR_SETTER = {
|
||||
match: [
|
||||
/get|set/,
|
||||
/\s+/,
|
||||
IDENT_RE$1,
|
||||
/(?=\()/
|
||||
],
|
||||
className: {
|
||||
1: "keyword",
|
||||
3: "title.function"
|
||||
},
|
||||
contains: [
|
||||
{ // eat to avoid empty params
|
||||
begin: /\(\)/
|
||||
},
|
||||
PARAMS
|
||||
]
|
||||
};
|
||||
|
||||
const FUNC_LEAD_IN_RE = '(\\(' +
|
||||
'[^()]*(\\(' +
|
||||
'[^()]*(\\(' +
|
||||
'[^()]*' +
|
||||
'\\)[^()]*)*' +
|
||||
'\\)[^()]*)*' +
|
||||
'\\)|' + hljs.UNDERSCORE_IDENT_RE + ')\\s*=>';
|
||||
|
||||
const FUNCTION_VARIABLE = {
|
||||
match: [
|
||||
/const|var|let/, /\s+/,
|
||||
IDENT_RE$1, /\s*/,
|
||||
/=\s*/,
|
||||
/(async\s*)?/, // async is optional
|
||||
regex.lookahead(FUNC_LEAD_IN_RE)
|
||||
],
|
||||
keywords: "async",
|
||||
className: {
|
||||
1: "keyword",
|
||||
3: "title.function"
|
||||
},
|
||||
contains: [
|
||||
PARAMS
|
||||
]
|
||||
};
|
||||
|
||||
return {
|
||||
name: 'Javascript',
|
||||
aliases: ['js', 'jsx', 'mjs', 'cjs'],
|
||||
keywords: KEYWORDS$1,
|
||||
// this will be extended by TypeScript
|
||||
exports: { PARAMS_CONTAINS, CLASS_REFERENCE },
|
||||
illegal: /#(?![$_A-z])/,
|
||||
contains: [
|
||||
hljs.SHEBANG({
|
||||
label: "shebang",
|
||||
binary: "node",
|
||||
relevance: 5
|
||||
}),
|
||||
USE_STRICT,
|
||||
hljs.APOS_STRING_MODE,
|
||||
hljs.QUOTE_STRING_MODE,
|
||||
HTML_TEMPLATE,
|
||||
CSS_TEMPLATE,
|
||||
TEMPLATE_STRING,
|
||||
COMMENT,
|
||||
NUMBER,
|
||||
CLASS_REFERENCE,
|
||||
{
|
||||
className: 'attr',
|
||||
begin: IDENT_RE$1 + regex.lookahead(':'),
|
||||
relevance: 0
|
||||
},
|
||||
FUNCTION_VARIABLE,
|
||||
{ // "value" container
|
||||
begin: '(' + hljs.RE_STARTERS_RE + '|\\b(case|return|throw)\\b)\\s*',
|
||||
keywords: 'return throw case',
|
||||
relevance: 0,
|
||||
contains: [
|
||||
COMMENT,
|
||||
hljs.REGEXP_MODE,
|
||||
{
|
||||
className: 'function',
|
||||
// we have to count the parens to make sure we actually have the
|
||||
// correct bounding ( ) before the =>. There could be any number of
|
||||
// sub-expressions inside also surrounded by parens.
|
||||
begin: FUNC_LEAD_IN_RE,
|
||||
returnBegin: true,
|
||||
end: '\\s*=>',
|
||||
contains: [
|
||||
{
|
||||
className: 'params',
|
||||
variants: [
|
||||
{
|
||||
begin: hljs.UNDERSCORE_IDENT_RE,
|
||||
relevance: 0
|
||||
},
|
||||
{
|
||||
className: null,
|
||||
begin: /\(\s*\)/,
|
||||
skip: true
|
||||
},
|
||||
{
|
||||
begin: /\(/,
|
||||
end: /\)/,
|
||||
excludeBegin: true,
|
||||
excludeEnd: true,
|
||||
keywords: KEYWORDS$1,
|
||||
contains: PARAMS_CONTAINS
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{ // could be a comma delimited list of params to a function call
|
||||
begin: /,/,
|
||||
relevance: 0
|
||||
},
|
||||
{
|
||||
match: /\s+/,
|
||||
relevance: 0
|
||||
},
|
||||
{ // JSX
|
||||
variants: [
|
||||
{ begin: FRAGMENT.begin, end: FRAGMENT.end },
|
||||
{ match: XML_SELF_CLOSING },
|
||||
{
|
||||
begin: XML_TAG.begin,
|
||||
// we carefully check the opening tag to see if it truly
|
||||
// is a tag and not a false positive
|
||||
'on:begin': XML_TAG.isTrulyOpeningTag,
|
||||
end: XML_TAG.end
|
||||
}
|
||||
],
|
||||
subLanguage: 'xml',
|
||||
contains: [
|
||||
{
|
||||
begin: XML_TAG.begin,
|
||||
end: XML_TAG.end,
|
||||
skip: true,
|
||||
contains: ['self']
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
FUNCTION_DEFINITION,
|
||||
{
|
||||
// prevent this from getting swallowed up by function
|
||||
// since they appear "function like"
|
||||
beginKeywords: "while if switch catch for"
|
||||
},
|
||||
{
|
||||
// we have to count the parens to make sure we actually have the correct
|
||||
// bounding ( ). There could be any number of sub-expressions inside
|
||||
// also surrounded by parens.
|
||||
begin: '\\b(?!function)' + hljs.UNDERSCORE_IDENT_RE +
|
||||
'\\(' + // first parens
|
||||
'[^()]*(\\(' +
|
||||
'[^()]*(\\(' +
|
||||
'[^()]*' +
|
||||
'\\)[^()]*)*' +
|
||||
'\\)[^()]*)*' +
|
||||
'\\)\\s*\\{', // end parens
|
||||
returnBegin:true,
|
||||
label: "func.def",
|
||||
contains: [
|
||||
PARAMS,
|
||||
hljs.inherit(hljs.TITLE_MODE, { begin: IDENT_RE$1, className: "title.function" })
|
||||
]
|
||||
},
|
||||
// catch ... so it won't trigger the property rule below
|
||||
{
|
||||
match: /\.\.\./,
|
||||
relevance: 0
|
||||
},
|
||||
PROPERTY_ACCESS,
|
||||
// hack: prevents detection of keywords in some circumstances
|
||||
// .keyword()
|
||||
// $keyword = x
|
||||
{
|
||||
match: '\\$' + IDENT_RE$1,
|
||||
relevance: 0
|
||||
},
|
||||
{
|
||||
match: [ /\bconstructor(?=\s*\()/ ],
|
||||
className: { 1: "title.function" },
|
||||
contains: [ PARAMS ]
|
||||
},
|
||||
FUNCTION_CALL,
|
||||
UPPER_CASE_CONSTANT,
|
||||
CLASS_OR_EXTENDS,
|
||||
GETTER_OR_SETTER,
|
||||
{
|
||||
match: /\$[(.]/ // relevance booster for a pattern common to JS libs: `$(something)` and `$.something`
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
|
@ -1,432 +0,0 @@
|
|||
/*
|
||||
Language: Python
|
||||
Description: Python is an interpreted, object-oriented, high-level programming language with dynamic semantics.
|
||||
Website: https://www.python.org
|
||||
Category: common
|
||||
*/
|
||||
|
||||
export default function python(hljs) {
|
||||
const regex = hljs.regex;
|
||||
const IDENT_RE = /[\p{XID_Start}_]\p{XID_Continue}*/u;
|
||||
const RESERVED_WORDS = [
|
||||
'and',
|
||||
'as',
|
||||
'assert',
|
||||
'async',
|
||||
'await',
|
||||
'break',
|
||||
'case',
|
||||
'class',
|
||||
'continue',
|
||||
'def',
|
||||
'del',
|
||||
'elif',
|
||||
'else',
|
||||
'except',
|
||||
'finally',
|
||||
'for',
|
||||
'from',
|
||||
'global',
|
||||
'if',
|
||||
'import',
|
||||
'in',
|
||||
'is',
|
||||
'lambda',
|
||||
'match',
|
||||
'nonlocal|10',
|
||||
'not',
|
||||
'or',
|
||||
'pass',
|
||||
'raise',
|
||||
'return',
|
||||
'try',
|
||||
'while',
|
||||
'with',
|
||||
'yield'
|
||||
];
|
||||
|
||||
const BUILT_INS = [
|
||||
'__import__',
|
||||
'abs',
|
||||
'all',
|
||||
'any',
|
||||
'ascii',
|
||||
'bin',
|
||||
'bool',
|
||||
'breakpoint',
|
||||
'bytearray',
|
||||
'bytes',
|
||||
'callable',
|
||||
'chr',
|
||||
'classmethod',
|
||||
'compile',
|
||||
'complex',
|
||||
'delattr',
|
||||
'dict',
|
||||
'dir',
|
||||
'divmod',
|
||||
'enumerate',
|
||||
'eval',
|
||||
'exec',
|
||||
'filter',
|
||||
'float',
|
||||
'format',
|
||||
'frozenset',
|
||||
'getattr',
|
||||
'globals',
|
||||
'hasattr',
|
||||
'hash',
|
||||
'help',
|
||||
'hex',
|
||||
'id',
|
||||
'input',
|
||||
'int',
|
||||
'isinstance',
|
||||
'issubclass',
|
||||
'iter',
|
||||
'len',
|
||||
'list',
|
||||
'locals',
|
||||
'map',
|
||||
'max',
|
||||
'memoryview',
|
||||
'min',
|
||||
'next',
|
||||
'object',
|
||||
'oct',
|
||||
'open',
|
||||
'ord',
|
||||
'pow',
|
||||
'print',
|
||||
'property',
|
||||
'range',
|
||||
'repr',
|
||||
'reversed',
|
||||
'round',
|
||||
'set',
|
||||
'setattr',
|
||||
'slice',
|
||||
'sorted',
|
||||
'staticmethod',
|
||||
'str',
|
||||
'sum',
|
||||
'super',
|
||||
'tuple',
|
||||
'type',
|
||||
'vars',
|
||||
'zip'
|
||||
];
|
||||
|
||||
const LITERALS = [
|
||||
'__debug__',
|
||||
'Ellipsis',
|
||||
'False',
|
||||
'None',
|
||||
'NotImplemented',
|
||||
'True'
|
||||
];
|
||||
|
||||
// https://docs.python.org/3/library/typing.html
|
||||
// TODO: Could these be supplemented by a CamelCase matcher in certain
|
||||
// contexts, leaving these remaining only for relevance hinting?
|
||||
const TYPES = [
|
||||
"Any",
|
||||
"Callable",
|
||||
"Coroutine",
|
||||
"Dict",
|
||||
"List",
|
||||
"Literal",
|
||||
"Generic",
|
||||
"Optional",
|
||||
"Sequence",
|
||||
"Set",
|
||||
"Tuple",
|
||||
"Type",
|
||||
"Union"
|
||||
];
|
||||
|
||||
const KEYWORDS = {
|
||||
$pattern: /[A-Za-z]\w+|__\w+__/,
|
||||
keyword: RESERVED_WORDS,
|
||||
built_in: BUILT_INS,
|
||||
literal: LITERALS,
|
||||
type: TYPES
|
||||
};
|
||||
|
||||
const PROMPT = {
|
||||
className: 'meta',
|
||||
begin: /^(>>>|\.\.\.) /
|
||||
};
|
||||
|
||||
const SUBST = {
|
||||
className: 'subst',
|
||||
begin: /\{/,
|
||||
end: /\}/,
|
||||
keywords: KEYWORDS,
|
||||
illegal: /#/
|
||||
};
|
||||
|
||||
const LITERAL_BRACKET = {
|
||||
begin: /\{\{/,
|
||||
relevance: 0
|
||||
};
|
||||
|
||||
const STRING = {
|
||||
className: 'string',
|
||||
contains: [ hljs.BACKSLASH_ESCAPE ],
|
||||
variants: [
|
||||
{
|
||||
begin: /([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,
|
||||
end: /'''/,
|
||||
contains: [
|
||||
hljs.BACKSLASH_ESCAPE,
|
||||
PROMPT
|
||||
],
|
||||
relevance: 10
|
||||
},
|
||||
{
|
||||
begin: /([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,
|
||||
end: /"""/,
|
||||
contains: [
|
||||
hljs.BACKSLASH_ESCAPE,
|
||||
PROMPT
|
||||
],
|
||||
relevance: 10
|
||||
},
|
||||
{
|
||||
begin: /([fF][rR]|[rR][fF]|[fF])'''/,
|
||||
end: /'''/,
|
||||
contains: [
|
||||
hljs.BACKSLASH_ESCAPE,
|
||||
PROMPT,
|
||||
LITERAL_BRACKET,
|
||||
SUBST
|
||||
]
|
||||
},
|
||||
{
|
||||
begin: /([fF][rR]|[rR][fF]|[fF])"""/,
|
||||
end: /"""/,
|
||||
contains: [
|
||||
hljs.BACKSLASH_ESCAPE,
|
||||
PROMPT,
|
||||
LITERAL_BRACKET,
|
||||
SUBST
|
||||
]
|
||||
},
|
||||
{
|
||||
begin: /([uU]|[rR])'/,
|
||||
end: /'/,
|
||||
relevance: 10
|
||||
},
|
||||
{
|
||||
begin: /([uU]|[rR])"/,
|
||||
end: /"/,
|
||||
relevance: 10
|
||||
},
|
||||
{
|
||||
begin: /([bB]|[bB][rR]|[rR][bB])'/,
|
||||
end: /'/
|
||||
},
|
||||
{
|
||||
begin: /([bB]|[bB][rR]|[rR][bB])"/,
|
||||
end: /"/
|
||||
},
|
||||
{
|
||||
begin: /([fF][rR]|[rR][fF]|[fF])'/,
|
||||
end: /'/,
|
||||
contains: [
|
||||
hljs.BACKSLASH_ESCAPE,
|
||||
LITERAL_BRACKET,
|
||||
SUBST
|
||||
]
|
||||
},
|
||||
{
|
||||
begin: /([fF][rR]|[rR][fF]|[fF])"/,
|
||||
end: /"/,
|
||||
contains: [
|
||||
hljs.BACKSLASH_ESCAPE,
|
||||
LITERAL_BRACKET,
|
||||
SUBST
|
||||
]
|
||||
},
|
||||
hljs.APOS_STRING_MODE,
|
||||
hljs.QUOTE_STRING_MODE
|
||||
]
|
||||
};
|
||||
|
||||
// https://docs.python.org/3.9/reference/lexical_analysis.html#numeric-literals
|
||||
const digitpart = '[0-9](_?[0-9])*';
|
||||
const pointfloat = `(\\b(${digitpart}))?\\.(${digitpart})|\\b(${digitpart})\\.`;
|
||||
// Whitespace after a number (or any lexical token) is needed only if its absence
|
||||
// would change the tokenization
|
||||
// https://docs.python.org/3.9/reference/lexical_analysis.html#whitespace-between-tokens
|
||||
// We deviate slightly, requiring a word boundary or a keyword
|
||||
// to avoid accidentally recognizing *prefixes* (e.g., `0` in `0x41` or `08` or `0__1`)
|
||||
const lookahead = `\\b|${RESERVED_WORDS.join('|')}`;
|
||||
const NUMBER = {
|
||||
className: 'number',
|
||||
relevance: 0,
|
||||
variants: [
|
||||
// exponentfloat, pointfloat
|
||||
// https://docs.python.org/3.9/reference/lexical_analysis.html#floating-point-literals
|
||||
// optionally imaginary
|
||||
// https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals
|
||||
// Note: no leading \b because floats can start with a decimal point
|
||||
// and we don't want to mishandle e.g. `fn(.5)`,
|
||||
// no trailing \b for pointfloat because it can end with a decimal point
|
||||
// and we don't want to mishandle e.g. `0..hex()`; this should be safe
|
||||
// because both MUST contain a decimal point and so cannot be confused with
|
||||
// the interior part of an identifier
|
||||
{
|
||||
begin: `(\\b(${digitpart})|(${pointfloat}))[eE][+-]?(${digitpart})[jJ]?(?=${lookahead})`
|
||||
},
|
||||
{
|
||||
begin: `(${pointfloat})[jJ]?`
|
||||
},
|
||||
|
||||
// decinteger, bininteger, octinteger, hexinteger
|
||||
// https://docs.python.org/3.9/reference/lexical_analysis.html#integer-literals
|
||||
// optionally "long" in Python 2
|
||||
// https://docs.python.org/2.7/reference/lexical_analysis.html#integer-and-long-integer-literals
|
||||
// decinteger is optionally imaginary
|
||||
// https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals
|
||||
{
|
||||
begin: `\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${lookahead})`
|
||||
},
|
||||
{
|
||||
begin: `\\b0[bB](_?[01])+[lL]?(?=${lookahead})`
|
||||
},
|
||||
{
|
||||
begin: `\\b0[oO](_?[0-7])+[lL]?(?=${lookahead})`
|
||||
},
|
||||
{
|
||||
begin: `\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${lookahead})`
|
||||
},
|
||||
|
||||
// imagnumber (digitpart-based)
|
||||
// https://docs.python.org/3.9/reference/lexical_analysis.html#imaginary-literals
|
||||
{
|
||||
begin: `\\b(${digitpart})[jJ](?=${lookahead})`
|
||||
}
|
||||
]
|
||||
};
|
||||
const COMMENT_TYPE = {
|
||||
className: "comment",
|
||||
begin: regex.lookahead(/# type:/),
|
||||
end: /$/,
|
||||
keywords: KEYWORDS,
|
||||
contains: [
|
||||
{ // prevent keywords from coloring `type`
|
||||
begin: /# type:/
|
||||
},
|
||||
// comment within a datatype comment includes no keywords
|
||||
{
|
||||
begin: /#/,
|
||||
end: /\b\B/,
|
||||
endsWithParent: true
|
||||
}
|
||||
]
|
||||
};
|
||||
const PARAMS = {
|
||||
className: 'params',
|
||||
variants: [
|
||||
// Exclude params in functions without params
|
||||
{
|
||||
className: "",
|
||||
begin: /\(\s*\)/,
|
||||
skip: true
|
||||
},
|
||||
{
|
||||
begin: /\(/,
|
||||
end: /\)/,
|
||||
excludeBegin: true,
|
||||
excludeEnd: true,
|
||||
keywords: KEYWORDS,
|
||||
contains: [
|
||||
'self',
|
||||
PROMPT,
|
||||
NUMBER,
|
||||
STRING,
|
||||
hljs.HASH_COMMENT_MODE
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
SUBST.contains = [
|
||||
STRING,
|
||||
NUMBER,
|
||||
PROMPT
|
||||
];
|
||||
|
||||
return {
|
||||
name: 'Python',
|
||||
aliases: [
|
||||
'py',
|
||||
'gyp',
|
||||
'ipython'
|
||||
],
|
||||
unicodeRegex: true,
|
||||
keywords: KEYWORDS,
|
||||
illegal: /(<\/|->|\?)|=>/,
|
||||
contains: [
|
||||
PROMPT,
|
||||
NUMBER,
|
||||
{
|
||||
// very common convention
|
||||
begin: /\bself\b/
|
||||
},
|
||||
{
|
||||
// eat "if" prior to string so that it won't accidentally be
|
||||
// labeled as an f-string
|
||||
beginKeywords: "if",
|
||||
relevance: 0
|
||||
},
|
||||
STRING,
|
||||
COMMENT_TYPE,
|
||||
hljs.HASH_COMMENT_MODE,
|
||||
{
|
||||
match: [
|
||||
/\bdef/, /\s+/,
|
||||
IDENT_RE,
|
||||
],
|
||||
scope: {
|
||||
1: "keyword",
|
||||
3: "title.function"
|
||||
},
|
||||
contains: [ PARAMS ]
|
||||
},
|
||||
{
|
||||
variants: [
|
||||
{
|
||||
match: [
|
||||
/\bclass/, /\s+/,
|
||||
IDENT_RE, /\s*/,
|
||||
/\(\s*/, IDENT_RE,/\s*\)/
|
||||
],
|
||||
},
|
||||
{
|
||||
match: [
|
||||
/\bclass/, /\s+/,
|
||||
IDENT_RE
|
||||
],
|
||||
}
|
||||
],
|
||||
scope: {
|
||||
1: "keyword",
|
||||
3: "title.class",
|
||||
6: "title.class.inherited",
|
||||
}
|
||||
},
|
||||
{
|
||||
className: 'meta',
|
||||
begin: /^[\t ]*@/,
|
||||
end: /(?=#)|$/,
|
||||
contains: [
|
||||
NUMBER,
|
||||
PARAMS,
|
||||
STRING
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
33
packages/web/src/third_party/highlightjs/roll.sh
vendored
33
packages/web/src/third_party/highlightjs/roll.sh
vendored
|
|
@ -1,33 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
set +x
|
||||
|
||||
# Pick a stable release revision from here:
|
||||
# https://github.com/highlightjs/highlight.js/releases
|
||||
RELEASE_REVISION="bed790f3f3515ebcb92896ab23a518f835008233"
|
||||
LANGUAGES="javascript python csharp java"
|
||||
STYLES="github*.css"
|
||||
|
||||
trap "cd $(pwd -P)" EXIT
|
||||
SCRIPT_PATH="$(cd "$(dirname "$0")" ; pwd -P)"
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
rm -rf ./output
|
||||
mkdir -p ./output
|
||||
|
||||
cd ./output
|
||||
git clone git@github.com:highlightjs/highlight.js.git
|
||||
cd ./highlight.js
|
||||
git checkout ${RELEASE_REVISION}
|
||||
npm install
|
||||
node tools/build.js -t node ${LANGUAGES}
|
||||
|
||||
cd ../..
|
||||
rm -rf ./highlightjs
|
||||
mkdir -p ./highlightjs
|
||||
cp -R output/highlight.js/build/lib/* highlightjs/
|
||||
cp output/highlight.js/build/LICENSE highlightjs/
|
||||
cp output/highlight.js/build/types/index.d.ts highlightjs/
|
||||
cp output/highlight.js/build/styles/${STYLES} highlightjs/
|
||||
echo $'\n'"export = hljs;"$'\n' >> highlightjs/index.d.ts
|
||||
rm -rf ./output
|
||||
|
|
@ -89,7 +89,7 @@ it.describe('pause', () => {
|
|||
await page.pause();
|
||||
})();
|
||||
const recorderPage = await recorderPageGetter();
|
||||
const source = await recorderPage.textContent('.source-line-paused .source-code');
|
||||
const source = await recorderPage.textContent('.source-line-paused');
|
||||
expect(source).toContain('page.pause()');
|
||||
await recorderPage.click('[title="Resume (F8)"]');
|
||||
await scriptPromise;
|
||||
|
|
|
|||
|
|
@ -542,10 +542,6 @@ test('should show action source', async ({ showTraceViewer }) => {
|
|||
const page = traceViewer.page;
|
||||
|
||||
await page.click('text=Source');
|
||||
await expect(page.locator('.source-line')).toContainText([
|
||||
/async.*function.*doClick/,
|
||||
/page\.click/
|
||||
]);
|
||||
await expect(page.locator('.source-line-running')).toContainText('await page.getByText(\'Click\').click()');
|
||||
await expect(page.locator('.stack-trace-frame.selected')).toHaveText(/doClick.*trace-viewer\.spec\.ts:[\d]+/);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@ test('should show trace source', async ({ runInlineTest, page, showReport }) =>
|
|||
await page.click('.action-title >> text=page.evaluate');
|
||||
await page.click('text=Source');
|
||||
|
||||
await expect(page.locator('.source-line')).toContainText([
|
||||
await expect(page.locator('.CodeMirror-line')).toContainText([
|
||||
/const.*pwt;/,
|
||||
/page\.evaluate/
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -291,6 +291,21 @@ for (const webPackage of ['html-reporter', 'recorder', 'trace-viewer']) {
|
|||
});
|
||||
}
|
||||
|
||||
// Rebuild web projects service workers on change.
|
||||
for (const webPackage of ['trace-viewer']) {
|
||||
onChanges.push({
|
||||
committed: false,
|
||||
inputs: [
|
||||
`packages/${webPackage}/src/`,
|
||||
`packages/${webPackage}/view.sw.config.ts`,
|
||||
`packages/web/src/`,
|
||||
],
|
||||
command: 'npx',
|
||||
args: ['vite', '--config', 'vite.sw.config.ts', 'build', ...(watchMode ? ['--sourcemap'] : [])],
|
||||
cwd: path.join(__dirname, '..', '..', 'packages', webPackage),
|
||||
});
|
||||
}
|
||||
|
||||
// The recorder and trace viewer have an app_icon.png that needs to be copied.
|
||||
copyFiles.push({
|
||||
files: 'packages/playwright-core/src/server/chromium/*.png',
|
||||
|
|
|
|||
|
|
@ -19,6 +19,23 @@ const fs = require('fs');
|
|||
const path = require('path');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
async function checkDir(dir) {
|
||||
return await new Promise((f, r) => {
|
||||
checker.init({
|
||||
start: dir,
|
||||
production: true,
|
||||
customPath: {
|
||||
licenseText: '',
|
||||
}
|
||||
}, function(err, packages) {
|
||||
if (err)
|
||||
r(err);
|
||||
else
|
||||
f(packages);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
(async () => {
|
||||
for (const project of ['playwright-core', 'playwright-test']) {
|
||||
const lines = [];
|
||||
|
|
@ -35,26 +52,19 @@ This project incorporates components from the projects listed below. The origina
|
|||
for (const bundle of fs.readdirSync(bundlesDir)) {
|
||||
const dir = path.join(bundlesDir, bundle);
|
||||
execSync('npm ci', { cwd: dir });
|
||||
const packages = await new Promise((f, r) => {
|
||||
checker.init({
|
||||
start: dir,
|
||||
production: true,
|
||||
customPath: {
|
||||
licenseText: '',
|
||||
}
|
||||
}, function(err, packages) {
|
||||
if (err)
|
||||
r(err);
|
||||
else
|
||||
f(packages);
|
||||
});
|
||||
});
|
||||
const packages = await checkDir(dir);
|
||||
for (const [key, value] of Object.entries(packages)) {
|
||||
if (value.licenseText)
|
||||
allPackages[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
const packages = await checkDir('node_modules/codemirror');
|
||||
for (const [key, value] of Object.entries(packages)) {
|
||||
if (value.licenseText)
|
||||
allPackages[key] = value;
|
||||
}
|
||||
|
||||
const keys = Object.keys(allPackages).sort();
|
||||
for (const key of keys)
|
||||
lines.push(`-\t${key} (${allPackages[key].repository})`);
|
||||
|
|
|
|||
Loading…
Reference in a new issue