generated from dellevin/template
原生epub阅读
This commit is contained in:
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
["@babel/preset-env", {
|
||||
"targets": {
|
||||
"android": "7",
|
||||
"chrome": "70",
|
||||
"safari": "12",
|
||||
"ios": "12"
|
||||
},
|
||||
"useBuiltIns": "entry",
|
||||
"corejs": 3,
|
||||
"modules": "auto"
|
||||
}]
|
||||
],
|
||||
"plugins": [
|
||||
["@babel/plugin-transform-runtime", {
|
||||
"regenerator": true,
|
||||
"corejs": false,
|
||||
"helpers": true,
|
||||
"useESModules": false
|
||||
}],
|
||||
"@babel/plugin-transform-class-properties",
|
||||
"@babel/plugin-transform-private-methods",
|
||||
"@babel/plugin-transform-nullish-coalescing-operator",
|
||||
"@babel/plugin-transform-optional-chaining"
|
||||
]
|
||||
}
|
||||
1
assets/foliate-js/.gitattributes
vendored
1
assets/foliate-js/.gitattributes
vendored
@@ -1 +0,0 @@
|
||||
vendor/* linguist-vendored=true
|
||||
1
assets/foliate-js/.gitignore
vendored
1
assets/foliate-js/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
node_modules/
|
||||
@@ -1,2 +0,0 @@
|
||||
This folder forked from [Foliate-js](https://github.com/johnfactotum/foliate-js) which is MIT licensed.
|
||||
Some changes also come from [readest/foliate-js](https://github.com/readest/foliate-js) which is MIT licensed.
|
||||
@@ -1,233 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<title>Anx Reader Debug</title>
|
||||
<style>
|
||||
html {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
user-select: none;
|
||||
margin: 0 !important;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#footnote-dialog {
|
||||
position: fixed;
|
||||
width: 80vw;
|
||||
height: 80vh;
|
||||
max-width: 400px;
|
||||
max-height: 200px;
|
||||
min-width: 300px;
|
||||
min-height: 200px;
|
||||
border-radius: 15px;
|
||||
border: 1px solid grey;
|
||||
user-select: none;
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
outline: none;
|
||||
z-index: 1000;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#footnote-dialog main {
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#debug-controls {
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: white;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.translated-text {
|
||||
display: block !important;
|
||||
font-style: italic;
|
||||
color: #666;
|
||||
font-size: 0.9em;
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
|
||||
.translated-text.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="debug-controls">
|
||||
<div>
|
||||
<button onclick="window.prevPage()">Prev</button>
|
||||
<button onclick="window.nextPage()">Next</button>
|
||||
<button onclick="window.goToPercent(0.5)">50%</button>
|
||||
</div>
|
||||
<!-- <div style="margin-top: 10px;">
|
||||
<label>Translation:</label><br>
|
||||
<button onclick="setTranslationMode('off')">Off</button>
|
||||
<button onclick="setTranslationMode('bilingual')">Bilingual</button>
|
||||
<button onclick="setTranslationMode('translation-only')">Trans Only</button>
|
||||
<button onclick="setTranslationMode('original-only')">Orig Only</button>
|
||||
</div>
|
||||
<div style="margin-top: 10px;">
|
||||
<button onclick="testCFIPreservation()">Test CFI</button>
|
||||
<div id="cfi-result" style="font-size: 0.8em; margin-top: 5px;"></div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<div id="footnote-dialog">
|
||||
<main></main>
|
||||
</div>
|
||||
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"core-js/stable": "https://esm.sh/core-js@3/stable"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
console.log("AnxUA", navigator.userAgent);
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (!urlParams.has('url')) {
|
||||
const mockParams = {
|
||||
importing: false,
|
||||
url: '../local/xyz.epub',
|
||||
initialCfi: "epubcfi(/6/14!/4,/2[CHP4]/1:1,/16/1:43)",
|
||||
style: {
|
||||
fontSize: 1.4,
|
||||
fontName: "book",
|
||||
fontPath: "",
|
||||
fontWeight: 400.0,
|
||||
letterSpacing: 0.0,
|
||||
spacing: 1.5,
|
||||
paragraphSpacing: 1.0,
|
||||
textIndent: 2.0,
|
||||
fontColor: "#111111ff",
|
||||
backgroundColor: "#fefefeff",
|
||||
topMargin: 20.0,
|
||||
bottomMargin: 50.0,
|
||||
sideMargin: 15.0,
|
||||
justify: true,
|
||||
hyphenate: true,
|
||||
// 'slide' 'scroll' 'noAnimation'
|
||||
pageTurnStyle: "slide",
|
||||
// pageTurnStyle: "slide",
|
||||
maxColumnCount: 1,
|
||||
// auto 'horizontal-tb' 'vertical-rl'
|
||||
// writingMode: "vertical-rl",
|
||||
writingMode: "auto",
|
||||
backgroundImage: "none",
|
||||
|
||||
// true, false
|
||||
allowScript: true,
|
||||
},
|
||||
readingRules: {
|
||||
convertChineseMode: "none",
|
||||
bionicReadingMode: false
|
||||
}
|
||||
};
|
||||
|
||||
const params = new URLSearchParams();
|
||||
params.set('importing', JSON.stringify(mockParams.importing));
|
||||
params.set('url', JSON.stringify(mockParams.url));
|
||||
params.set('initialCfi', JSON.stringify(mockParams.initialCfi));
|
||||
params.set('style', JSON.stringify(mockParams.style));
|
||||
params.set('readingRules', JSON.stringify(mockParams.readingRules));
|
||||
|
||||
window.location.href = window.location.pathname + '?' + params.toString();
|
||||
}
|
||||
|
||||
window.flutter_inappwebview = {
|
||||
callHandler: (name, data) => {
|
||||
console.log(`Flutter Handler Called: ${name}`, data);
|
||||
// Mock translation response for testing
|
||||
if (name === 'translateText') {
|
||||
return Promise.resolve(`TRANS: ${data}`);
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
};
|
||||
|
||||
// available types: highlight, underline, bookmark
|
||||
const anno = [
|
||||
{ id: 1, type: 'highlight', value: "epubcfi(/6/14!/4,/10/1:0,/16/1:12)", color: 'blue', note: 'this is' },
|
||||
// { id: 2, type: 'ubderline', value: "epubcfi(/6/6!/4/2[pgepubid00003]/18,/3:300,/5:102)", color: '#66ccff', note: 'this is' },
|
||||
// { id: 3, type: 'underline', value: "epubcfi(/6/6!/4/2[pgepubid00003]/18/6,/1:1,/1:8)", color: 'red', note: 'this is' },
|
||||
]
|
||||
|
||||
setTimeout(() => {
|
||||
reader.renderAnnotation(anno)
|
||||
}, 1000)
|
||||
|
||||
// Translation testing functions
|
||||
function setTranslationMode(mode) {
|
||||
if (reader.view && reader.view.setTranslationMode) {
|
||||
reader.view.setTranslationMode(mode);
|
||||
console.log('Translation mode set to:', mode);
|
||||
} else {
|
||||
console.warn('Translation mode not available');
|
||||
}
|
||||
}
|
||||
|
||||
function testCFIPreservation() {
|
||||
if (!reader.view) {
|
||||
document.getElementById('cfi-result').textContent = 'View not ready';
|
||||
return;
|
||||
}
|
||||
|
||||
const testCFI = "epubcfi(/6/6!/4/2[pgepubid00003],/16/1:223,/20/7:170)";
|
||||
const resultDiv = document.getElementById('cfi-result');
|
||||
|
||||
try {
|
||||
// Test 1: Get current location before translation
|
||||
const beforeLocation = reader.view.getCFI();
|
||||
resultDiv.innerHTML = `Before: ${beforeLocation}<br>`;
|
||||
|
||||
// Test 2: Enable translation
|
||||
setTranslationMode('bilingual');
|
||||
|
||||
setTimeout(() => {
|
||||
// Test 3: Get location after translation
|
||||
const afterLocation = reader.view.getCFI();
|
||||
resultDiv.innerHTML += `After: ${afterLocation}<br>`;
|
||||
|
||||
// Test 4: Navigate to specific CFI
|
||||
reader.view.goTo(testCFI);
|
||||
|
||||
setTimeout(() => {
|
||||
const finalLocation = reader.view.getCFI();
|
||||
resultDiv.innerHTML += `Final: ${finalLocation}<br>`;
|
||||
|
||||
if (beforeLocation && afterLocation && finalLocation) {
|
||||
resultDiv.innerHTML += `<span style="color: ${beforeLocation === afterLocation ? 'green' : 'orange'};">CFI Stable: ${beforeLocation === afterLocation}</span>`;
|
||||
}
|
||||
}, 1000);
|
||||
}, 2000);
|
||||
|
||||
} catch (error) {
|
||||
resultDiv.textContent = `Error: ${error.message}`;
|
||||
console.error('CFI test error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Make functions globally available
|
||||
window.setTranslationMode = setTranslationMode;
|
||||
window.testCFIPreservation = testCFIPreservation;
|
||||
</script>
|
||||
|
||||
<script src="./src/book.js" type="module"></script>
|
||||
<script src="./src/vendor/pdfjs/pdf.js"></script>
|
||||
</html>
|
||||
2
assets/foliate-js/dist/bundle.js
vendored
2
assets/foliate-js/dist/bundle.js
vendored
File diff suppressed because one or more lines are too long
1
assets/foliate-js/dist/bundle.js.LICENSE.txt
vendored
1
assets/foliate-js/dist/bundle.js.LICENSE.txt
vendored
@@ -1 +0,0 @@
|
||||
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
|
||||
2
assets/foliate-js/dist/pdf-legacy.js
vendored
2
assets/foliate-js/dist/pdf-legacy.js
vendored
File diff suppressed because one or more lines are too long
21
assets/foliate-js/dist/pdf-legacy.js.LICENSE.txt
vendored
21
assets/foliate-js/dist/pdf-legacy.js.LICENSE.txt
vendored
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @licstart The following is the entire license notice for the
|
||||
* JavaScript code in this page
|
||||
*
|
||||
* Copyright 2023 Mozilla Foundation
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @licend The above is the entire license notice for the
|
||||
* JavaScript code in this page
|
||||
*/
|
||||
2
assets/foliate-js/dist/pdf-legacy.worker.js
vendored
2
assets/foliate-js/dist/pdf-legacy.worker.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @licstart The following is the entire license notice for the
|
||||
* JavaScript code in this page
|
||||
*
|
||||
* Copyright 2023 Mozilla Foundation
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @licend The above is the entire license notice for the
|
||||
* JavaScript code in this page
|
||||
*/
|
||||
@@ -1,22 +0,0 @@
|
||||
import js from '@eslint/js'
|
||||
import globals from 'globals'
|
||||
|
||||
export default [js.configs.recommended, { ignores: ['vendor'] }, {
|
||||
languageOptions: {
|
||||
globals: globals.browser,
|
||||
},
|
||||
linterOptions: {
|
||||
reportUnusedDisableDirectives: true,
|
||||
},
|
||||
rules: {
|
||||
semi: ['error', 'never'],
|
||||
indent: ['warn', 4, { flatTernaryExpressions: true, SwitchCase: 1 }],
|
||||
quotes: ['warn', 'single', { avoidEscape: true }],
|
||||
'comma-dangle': ['warn', 'always-multiline'],
|
||||
'no-trailing-spaces': 'warn',
|
||||
'no-unused-vars': 'warn',
|
||||
'no-console': ['warn', { allow: ['debug', 'warn', 'error', 'assert'] }],
|
||||
'no-constant-condition': ['error', { checkLoops: false }],
|
||||
'no-empty': ['error', { allowEmptyCatch: true }],
|
||||
},
|
||||
}]
|
||||
@@ -1,95 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
||||
<title>Anx Reader</title>
|
||||
<style>
|
||||
html {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
user-select: none;
|
||||
margin: 0 !important;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
|
||||
#footnote-dialog {
|
||||
/*
|
||||
padding: var(safe-area-inset-top) var(safe-area-inset-right) var(safe-area-inset-bottom) var(safe-area-inset-left);
|
||||
*/
|
||||
position: fixed;
|
||||
width: 80vw;
|
||||
height: 80vh;
|
||||
max-width: 400px;
|
||||
max-height: 200px;
|
||||
min-width: 300px;
|
||||
min-height: 200px;
|
||||
border-radius: 15px;
|
||||
border: 1px solid grey;
|
||||
user-select: none;
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
outline: none;
|
||||
z-index: 1000;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#footnote-dialog main {
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
<div id="footnote-dialog">
|
||||
<main></main>
|
||||
</div>
|
||||
<script>
|
||||
// Prevent the default WebView2 right-click context menu on Windows.
|
||||
document.addEventListener('contextmenu', e => { e.preventDefault(); });
|
||||
</script>
|
||||
<script>
|
||||
(function () {
|
||||
const ua = navigator.userAgent || '';
|
||||
const platform = navigator.platform || '';
|
||||
console.log('AnxUA', ua);
|
||||
|
||||
const isAppleDevice = /iPad|iPhone|iPod/.test(ua)
|
||||
|| (/Mac/.test(platform) && navigator.maxTouchPoints > 1)
|
||||
|| /Mac OS X/.test(ua);
|
||||
|
||||
const chromeMatch = ua.match(/Chrome\/(\d+)/);
|
||||
const chromeVersion = chromeMatch ? parseInt(chromeMatch[1], 10) : NaN;
|
||||
const shouldUseModernBundle = isAppleDevice || (!Number.isNaN(chromeVersion) && chromeVersion >= 100);
|
||||
|
||||
const loadScript = (src, options = {}) => new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
if (options.type) script.type = options.type;
|
||||
if (options.async !== undefined) script.async = options.async;
|
||||
if (options.defer !== undefined) script.defer = options.defer;
|
||||
script.onload = () => resolve();
|
||||
script.onerror = (err) => {
|
||||
console.error('Failed to load script', src, err);
|
||||
reject(err);
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
|
||||
(async () => {
|
||||
if (shouldUseModernBundle) {
|
||||
await loadScript('./src/vendor/pdfjs/pdf.js', { async: false, defer: false });
|
||||
await loadScript('./src/book.js', { type: 'module' });
|
||||
return;
|
||||
}
|
||||
|
||||
await loadScript('./dist/bundle.js', { type: 'module' });
|
||||
await loadScript('./dist/pdf-legacy.js', { async: false, defer: false });
|
||||
})();
|
||||
})();
|
||||
</script>
|
||||
3904
assets/foliate-js/package-lock.json
generated
3904
assets/foliate-js/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"name": "foliate",
|
||||
"version": "1.0.0",
|
||||
"description": "This folder forked from [Foliate-js](https://github.com/johnfactotum/foliate-js) which is MIT licensed.",
|
||||
"main": "book.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "rm -rf dist && webpack",
|
||||
"debug": "http-server . -p 3000 -c-1 --cors -o debug.html",
|
||||
"dev": "http-server . -p 3000 -c-1 --cors"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.23.0",
|
||||
"@babel/plugin-transform-class-properties": "^7.27.1",
|
||||
"@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1",
|
||||
"@babel/plugin-transform-optional-chaining": "^7.27.1",
|
||||
"@babel/plugin-transform-private-methods": "^7.27.1",
|
||||
"@babel/plugin-transform-runtime": "^7.23.0",
|
||||
"@babel/preset-env": "^7.23.0",
|
||||
"babel-loader": "^9.1.3",
|
||||
"core-js": "^3.33.0",
|
||||
"http-server": "^14.1.1",
|
||||
"webpack": "^5.99.7",
|
||||
"webpack-cli": "^6.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.0",
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,45 +0,0 @@
|
||||
export const makeComicBook = ({ entries, loadBlob, getSize }, file) => {
|
||||
const cache = new Map()
|
||||
const urls = new Map()
|
||||
const load = async name => {
|
||||
if (cache.has(name)) return cache.get(name)
|
||||
const src = URL.createObjectURL(await loadBlob(name))
|
||||
const page = URL.createObjectURL(
|
||||
new Blob([`<img src="${src}">`], { type: 'text/html' }))
|
||||
urls.set(name, [src, page])
|
||||
cache.set(name, page)
|
||||
return page
|
||||
}
|
||||
const unload = name => {
|
||||
urls.get(name)?.forEach?.(url => URL.revokeObjectURL(url))
|
||||
urls.delete(name)
|
||||
cache.delete(name)
|
||||
}
|
||||
|
||||
const exts = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg', '.jxl', '.avif']
|
||||
const files = entries
|
||||
.map(entry => entry.filename)
|
||||
.filter(name => exts.some(ext => name.endsWith(ext)))
|
||||
.sort()
|
||||
if (!files.length) throw new Error('No supported image files in archive')
|
||||
|
||||
const book = {}
|
||||
book.getCover = () => loadBlob(files[0])
|
||||
book.metadata = { title: file.name }
|
||||
book.sections = files.map(name => ({
|
||||
id: name,
|
||||
load: () => load(name),
|
||||
unload: () => unload(name),
|
||||
size: getSize(name),
|
||||
}))
|
||||
book.toc = files.map(name => ({ label: name, href: name }))
|
||||
book.rendition = { layout: 'pre-paginated' }
|
||||
book.resolveHref = href => ({ index: book.sections.findIndex(s => s.id === href) })
|
||||
book.splitTOCHref = href => [href, null]
|
||||
book.getTOCFragment = doc => doc.documentElement
|
||||
book.destroy = () => {
|
||||
for (const arr of urls.values())
|
||||
for (const url of arr) URL.revokeObjectURL(url)
|
||||
}
|
||||
return book
|
||||
}
|
||||
@@ -1,241 +0,0 @@
|
||||
const decoder = new TextDecoder()
|
||||
const decode = decoder.decode.bind(decoder)
|
||||
|
||||
const concatTypedArray = (a, b) => {
|
||||
const result = new a.constructor(a.length + b.length)
|
||||
result.set(a)
|
||||
result.set(b, a.length)
|
||||
return result
|
||||
}
|
||||
|
||||
const strcmp = (a, b) => {
|
||||
a = a.toLowerCase(), b = b.toLowerCase()
|
||||
return a < b ? -1 : a > b ? 1 : 0
|
||||
}
|
||||
|
||||
class DictZip {
|
||||
#chlen
|
||||
#chunks
|
||||
#compressed
|
||||
inflate
|
||||
async load(file) {
|
||||
const header = new DataView(await file.slice(0, 12).arrayBuffer())
|
||||
if (header.getUint8(0) !== 31 || header.getUint8(1) !== 139
|
||||
|| header.getUint8(2) !== 8) throw new Error('Not a DictZip file')
|
||||
const flg = header.getUint8(3)
|
||||
if (!flg & 0b100) throw new Error('Missing FEXTRA flag')
|
||||
|
||||
const xlen = header.getUint16(10, true)
|
||||
const extra = new DataView(await file.slice(12, 12 + xlen).arrayBuffer())
|
||||
if (extra.getUint8(0) !== 82 || extra.getUint8(1) !== 65)
|
||||
throw new Error('Subfield ID should be RA')
|
||||
if (extra.getUint16(4, true) !== 1) throw new Error('Unsupported version')
|
||||
|
||||
this.#chlen = extra.getUint16(6, true)
|
||||
const chcnt = extra.getUint16(8, true)
|
||||
this.#chunks = []
|
||||
for (let i = 0, chunkOffset = 0; i < chcnt; i++) {
|
||||
const chunkSize = extra.getUint16(10 + 2 * i, true)
|
||||
this.#chunks.push([chunkOffset, chunkSize])
|
||||
chunkOffset = chunkOffset + chunkSize
|
||||
}
|
||||
|
||||
// skip to compressed data
|
||||
let offset = 12 + xlen
|
||||
const max = Math.min(offset + 512, file.size)
|
||||
const strArr = new Uint8Array(await file.slice(0, max).arrayBuffer())
|
||||
if (flg & 0b1000) { // fname
|
||||
const i = strArr.indexOf(0, offset)
|
||||
if (i < 0) throw new Error('Header too long')
|
||||
offset = i + 1
|
||||
}
|
||||
if (flg & 0b10000) { // fcomment
|
||||
const i = strArr.indexOf(0, offset)
|
||||
if (i < 0) throw new Error('Header too long')
|
||||
offset = i + 1
|
||||
}
|
||||
if (flg & 0b10) offset += 2 // fhcrc
|
||||
this.#compressed = file.slice(offset)
|
||||
}
|
||||
async read(offset, size) {
|
||||
const chunks = this.#chunks
|
||||
const startIndex = Math.trunc(offset / this.#chlen)
|
||||
const endIndex = Math.trunc((offset + size) / this.#chlen)
|
||||
const buf = await this.#compressed.slice(chunks[startIndex][0],
|
||||
chunks[endIndex][0] + chunks[endIndex][1]).arrayBuffer()
|
||||
let arr = new Uint8Array()
|
||||
for (let pos = 0, i = startIndex; i <= endIndex; i++) {
|
||||
const data = new Uint8Array(buf, pos, chunks[i][1])
|
||||
arr = concatTypedArray(arr, await this.inflate(data))
|
||||
pos += chunks[i][1]
|
||||
}
|
||||
const startOffset = offset - startIndex * this.#chlen
|
||||
return arr.subarray(startOffset, startOffset + size)
|
||||
}
|
||||
}
|
||||
|
||||
class Index {
|
||||
strcmp = strcmp
|
||||
// binary search
|
||||
bisect(query, start = 0, end = this.words.length - 1) {
|
||||
if (end - start === 1) {
|
||||
if (!this.strcmp(query, this.getWord(start))) return start
|
||||
if (!this.strcmp(query, this.getWord(end))) return end
|
||||
return null
|
||||
}
|
||||
const mid = Math.floor(start + (end - start) / 2)
|
||||
const cmp = this.strcmp(query, this.getWord(mid))
|
||||
if (cmp < 0) return this.bisect(query, start, mid)
|
||||
if (cmp > 0) return this.bisect(query, mid, end)
|
||||
return mid
|
||||
}
|
||||
// check for multiple definitions
|
||||
checkAdjacent(query, i) {
|
||||
if (i == null) return []
|
||||
let j = i
|
||||
const equals = i => {
|
||||
const word = this.getWord(i)
|
||||
return word ? this.strcmp(query, word) === 0 : false
|
||||
}
|
||||
while (equals(j - 1)) j--
|
||||
let k = i
|
||||
while (equals(k + 1)) k++
|
||||
return j === k ? [i] : Array.from({ length: k + 1 - j }, (_, i) => j + i)
|
||||
}
|
||||
lookup(query) {
|
||||
return this.checkAdjacent(query, this.bisect(query))
|
||||
}
|
||||
}
|
||||
|
||||
const decodeBase64Number = str => {
|
||||
const { length } = str
|
||||
let n = 0
|
||||
for (let i = 0; i < length; i++) {
|
||||
const c = str.charCodeAt(i)
|
||||
n += (c === 43 ? 62 // "+"
|
||||
: c === 47 ? 63 // "/"
|
||||
: c < 58 ? c + 4 // 0-9 -> 52-61
|
||||
: c < 91 ? c - 65 // A-Z -> 0-25
|
||||
: c - 71 // a-z -> 26-51
|
||||
) * 64 ** (length - 1 - i)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
class DictdIndex extends Index {
|
||||
getWord(i) {
|
||||
return this.words[i]
|
||||
}
|
||||
async load(file) {
|
||||
const words = []
|
||||
const offsets = []
|
||||
const sizes = []
|
||||
for (const line of decode(await file.arrayBuffer()).split('\n')) {
|
||||
const a = line.split('\t')
|
||||
words.push(a[0])
|
||||
offsets.push(decodeBase64Number(a[1]))
|
||||
sizes.push(decodeBase64Number(a[2]))
|
||||
}
|
||||
this.words = words
|
||||
this.offsets = offsets
|
||||
this.sizes = sizes
|
||||
}
|
||||
}
|
||||
|
||||
export class DictdDict {
|
||||
#dict = new DictZip()
|
||||
#idx = new DictdIndex()
|
||||
loadDict(file, inflate) {
|
||||
this.#dict.inflate = inflate
|
||||
return this.#dict.load(file)
|
||||
}
|
||||
async #readWord(i) {
|
||||
const word = this.#idx.getWord(i)
|
||||
const offset = this.#idx.offsets[i]
|
||||
const size = this.#idx.sizes[i]
|
||||
return { word, data: ['m', this.#dict.read(offset, size)] }
|
||||
}
|
||||
#readWords(arr) {
|
||||
return Promise.all(arr.map(this.#readWord.bind(this)))
|
||||
}
|
||||
lookup(query) {
|
||||
return this.#readWords(this.#idx.lookup(query))
|
||||
}
|
||||
}
|
||||
|
||||
class StarDictIndex extends Index {
|
||||
isSyn
|
||||
#arr
|
||||
getWord(i) {
|
||||
const word = this.words[i]
|
||||
if (!word) return
|
||||
return decode(this.#arr.subarray(word[0], word[1]))
|
||||
}
|
||||
async load(file) {
|
||||
const { isSyn } = this
|
||||
const buf = await file.arrayBuffer()
|
||||
const arr = new Uint8Array(buf)
|
||||
this.#arr = arr
|
||||
const view = new DataView(buf)
|
||||
const words = []
|
||||
const offsets = []
|
||||
const sizes = []
|
||||
for (let i = 0; i < arr.length;) {
|
||||
const newI = arr.subarray(0, i + 256).indexOf(0, i)
|
||||
if (newI < 0) throw new Error('Word too big')
|
||||
words.push([i, newI])
|
||||
offsets.push(view.getUint32(newI + 1))
|
||||
if (isSyn) i = newI + 5
|
||||
else {
|
||||
sizes.push(view.getUint32(newI + 5))
|
||||
i = newI + 9
|
||||
}
|
||||
}
|
||||
this.words = words
|
||||
this.offsets = offsets
|
||||
this.sizes = sizes
|
||||
}
|
||||
}
|
||||
|
||||
export class StarDict {
|
||||
#dict = new DictZip()
|
||||
#idx = new StarDictIndex()
|
||||
#syn = Object.assign(new StarDictIndex(), { isSyn: true })
|
||||
async loadIfo(file) {
|
||||
const str = decode(await file.arrayBuffer())
|
||||
this.ifo = Object.fromEntries(str.split('\n').map(line => {
|
||||
const sep = line.indexOf('=')
|
||||
if (sep < 0) return
|
||||
return [line.slice(0, sep), line.slice(sep + 1)]
|
||||
}).filter(x => x))
|
||||
}
|
||||
loadDict(file, inflate) {
|
||||
this.#dict.inflate = inflate
|
||||
return this.#dict.load(file)
|
||||
}
|
||||
loadIdx(file) {
|
||||
return this.#idx.load(file)
|
||||
}
|
||||
loadSyn(file) {
|
||||
if (file) return this.#syn.load(file)
|
||||
}
|
||||
async #readWord(i) {
|
||||
const word = this.#idx.getWord(i)
|
||||
const offset = this.#idx.offsets[i]
|
||||
const size = this.#idx.sizes[i]
|
||||
const data = await this.#dict.read(offset, size)
|
||||
const seq = this.ifo.sametypesequence
|
||||
if (!seq) throw new Error('TODO')
|
||||
if (seq.length === 1) return { word, data: [[seq[0], data]] }
|
||||
throw new Error('TODO')
|
||||
}
|
||||
#readWords(arr) {
|
||||
return Promise.all(arr.map(this.#readWord.bind(this)))
|
||||
}
|
||||
lookup(query) {
|
||||
return this.#readWords(this.#idx.lookup(query))
|
||||
}
|
||||
synonyms(query) {
|
||||
return this.#readWords(this.#syn.lookup(query).map(i => this.#syn.offsets[i]))
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,345 +0,0 @@
|
||||
const findIndices = (arr, f) => arr
|
||||
.map((x, i, a) => f(x, i, a) ? i : null).filter(x => x != null)
|
||||
const splitAt = (arr, is) => [-1, ...is, arr.length].reduce(({ xs, a }, b) =>
|
||||
({ xs: xs?.concat([arr.slice(a + 1, b)]) ?? [], a: b }), {}).xs
|
||||
const concatArrays = (a, b) =>
|
||||
a.slice(0, -1).concat([a[a.length - 1].concat(b[0])]).concat(b.slice(1))
|
||||
|
||||
const isNumber = /\d/
|
||||
export const isCFI = /^epubcfi\((.*)\)$/
|
||||
const escapeCFI = str => str.replace(/[\^[\](),;=]/g, '^$&')
|
||||
|
||||
const wrap = x => isCFI.test(x) ? x : `epubcfi(${x})`
|
||||
const unwrap = x => x.match(isCFI)?.[1] ?? x
|
||||
const lift = f => (...xs) =>
|
||||
`epubcfi(${f(...xs.map(x => x.match(isCFI)?.[1] ?? x))})`
|
||||
export const joinIndir = lift((...xs) => xs.join('!'))
|
||||
|
||||
const tokenizer = str => {
|
||||
const tokens = []
|
||||
let state, escape, value = ''
|
||||
const push = x => (tokens.push(x), state = null, value = '')
|
||||
const cat = x => (value += x, escape = false)
|
||||
for (const char of Array.from(str.trim()).concat('')) {
|
||||
if (char === '^' && !escape) {
|
||||
escape = true
|
||||
continue
|
||||
}
|
||||
if (state === '!') push(['!'])
|
||||
else if (state === ',') push([','])
|
||||
else if (state === '/' || state === ':') {
|
||||
if (isNumber.test(char)) {
|
||||
cat(char)
|
||||
continue
|
||||
} else push([state, parseInt(value)])
|
||||
} else if (state === '~') {
|
||||
if (isNumber.test(char) || char === '.') {
|
||||
cat(char)
|
||||
continue
|
||||
} else push(['~', parseFloat(value)])
|
||||
} else if (state === '@') {
|
||||
if (char === ':') {
|
||||
push(['@', parseFloat(value)])
|
||||
state = '@'
|
||||
continue
|
||||
}
|
||||
if (isNumber.test(char) || char === '.') {
|
||||
cat(char)
|
||||
continue
|
||||
} else push(['@', parseFloat(value)])
|
||||
} else if (state === '[') {
|
||||
if (char === ';' && !escape) {
|
||||
push(['[', value])
|
||||
state = ';'
|
||||
} else if (char === ',' && !escape) {
|
||||
push(['[', value])
|
||||
state = '['
|
||||
} else if (char === ']' && !escape) push(['[', value])
|
||||
else cat(char)
|
||||
continue
|
||||
} else if (state?.startsWith(';')) {
|
||||
if (char === '=' && !escape) {
|
||||
state = `;${value}`
|
||||
value = ''
|
||||
} else if (char === ';' && !escape) {
|
||||
push([state, value])
|
||||
state = ';'
|
||||
} else if (char === ']' && !escape) push([state, value])
|
||||
else cat(char)
|
||||
continue
|
||||
}
|
||||
if (char === '/' || char === ':' || char === '~' || char === '@'
|
||||
|| char === '[' || char === '!' || char === ',') state = char
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
const findTokens = (tokens, x) => findIndices(tokens, ([t]) => t === x)
|
||||
|
||||
const parser = tokens => {
|
||||
const parts = []
|
||||
let state
|
||||
for (const [type, val] of tokens) {
|
||||
if (type === '/') parts.push({ index: val })
|
||||
else {
|
||||
const last = parts[parts.length - 1]
|
||||
if (type === ':') last.offset = val
|
||||
else if (type === '~') last.temporal = val
|
||||
else if (type === '@') last.spatial = (last.spatial ?? []).concat(val)
|
||||
else if (type === ';s') last.side = val
|
||||
else if (type === '[') {
|
||||
if (state === '/' && val) last.id = val
|
||||
else {
|
||||
last.text = (last.text ?? []).concat(val)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
state = type
|
||||
}
|
||||
return parts
|
||||
}
|
||||
|
||||
// split at step indirections, then parse each part
|
||||
const parserIndir = tokens =>
|
||||
splitAt(tokens, findTokens(tokens, '!')).map(parser)
|
||||
|
||||
export const parse = cfi => {
|
||||
const tokens = tokenizer(unwrap(cfi))
|
||||
const commas = findTokens(tokens, ',')
|
||||
if (!commas.length) return parserIndir(tokens)
|
||||
const [parent, start, end] = splitAt(tokens, commas).map(parserIndir)
|
||||
return { parent, start, end }
|
||||
}
|
||||
|
||||
const partToString = ({ index, id, offset, temporal, spatial, text, side }) => {
|
||||
const param = side ? `;s=${side}` : ''
|
||||
return `/${index}`
|
||||
+ (id ? `[${escapeCFI(id)}${param}]` : '')
|
||||
// "CFI expressions [..] SHOULD include an explicit character offset"
|
||||
+ (offset != null && index % 2 ? `:${offset}` : '')
|
||||
+ (temporal ? `~${temporal}` : '')
|
||||
+ (spatial ? `@${spatial.join(':')}` : '')
|
||||
+ (text || (!id && side) ? '['
|
||||
+ (text?.map(escapeCFI)?.join(',') ?? '')
|
||||
+ param + ']' : '')
|
||||
}
|
||||
|
||||
const toInnerString = parsed => parsed.parent
|
||||
? [parsed.parent, parsed.start, parsed.end].map(toInnerString).join(',')
|
||||
: parsed.map(parts => parts.map(partToString).join('')).join('!')
|
||||
|
||||
const toString = parsed => wrap(toInnerString(parsed))
|
||||
|
||||
export const collapse = (x, toEnd) => typeof x === 'string'
|
||||
? toString(collapse(parse(x), toEnd))
|
||||
: x.parent ? concatArrays(x.parent, x[toEnd ? 'end' : 'start']) : x
|
||||
|
||||
// create range CFI from two CFIs
|
||||
const buildRange = (from, to) => {
|
||||
if (typeof from === 'string') from = parse(from)
|
||||
if (typeof to === 'string') to = parse(to)
|
||||
from = collapse(from)
|
||||
to = collapse(to, true)
|
||||
// ranges across multiple documents are not allowed; handle local paths only
|
||||
const localFrom = from[from.length - 1], localTo = to[to.length - 1]
|
||||
const localParent = [], localStart = [], localEnd = []
|
||||
let pushToParent = true
|
||||
const len = Math.max(localFrom.length, localTo.length)
|
||||
for (let i = 0; i < len; i++) {
|
||||
const a = localFrom[i], b = localTo[i]
|
||||
pushToParent &&= a?.index === b?.index && !a?.offset && !b?.offset
|
||||
if (pushToParent) localParent.push(a)
|
||||
else {
|
||||
if (a) localStart.push(a)
|
||||
if (b) localEnd.push(b)
|
||||
}
|
||||
}
|
||||
// copy non-local paths from `from`
|
||||
const parent = from.slice(0, -1).concat([localParent])
|
||||
return toString({ parent, start: [localStart], end: [localEnd] })
|
||||
}
|
||||
|
||||
export const compare = (a, b) => {
|
||||
if (typeof a === 'string') a = parse(a)
|
||||
if (typeof b === 'string') b = parse(b)
|
||||
if (a.start || b.start) return compare(collapse(a), collapse(b))
|
||||
|| compare(collapse(a, true), collapse(b, true))
|
||||
|
||||
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
||||
const p = a[i], q = b[i]
|
||||
const maxIndex = Math.max(p.length, q.length) - 1
|
||||
for (let i = 0; i <= maxIndex; i++) {
|
||||
const x = p[i], y = q[i]
|
||||
if (!x) return -1
|
||||
if (!y) return 1
|
||||
if (x.index > y.index) return 1
|
||||
if (x.index < y.index) return -1
|
||||
if (i === maxIndex) {
|
||||
// TODO: compare temporal & spatial offsets
|
||||
if (x.offset > y.offset) return 1
|
||||
if (x.offset < y.offset) return -1
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
const isTextNode = ({ nodeType }) => nodeType === 3 || nodeType === 4
|
||||
const isElementNode = ({ nodeType }) => nodeType === 1
|
||||
|
||||
const getChildNodes = (node, filter) => {
|
||||
const nodes = Array.from(node.childNodes)
|
||||
// "content other than element and character data is ignored"
|
||||
.filter(node => isTextNode(node) || isElementNode(node))
|
||||
return filter ? nodes.map(node => {
|
||||
const accept = filter(node)
|
||||
if (accept === NodeFilter.FILTER_REJECT) return null
|
||||
else if (accept === NodeFilter.FILTER_SKIP) return getChildNodes(node, filter)
|
||||
else return node
|
||||
}).flat().filter(x => x) : nodes
|
||||
}
|
||||
|
||||
// child nodes are organized such that the result is always
|
||||
// [element, text, element, text, ..., element],
|
||||
// regardless of the actual structure in the document;
|
||||
// so multiple text nodes need to be combined, and nonexistent ones counted;
|
||||
// see "Step Reference to Child Element or Character Data (/)" in EPUB CFI spec
|
||||
const indexChildNodes = (node, filter) => {
|
||||
const nodes = getChildNodes(node, filter)
|
||||
.reduce((arr, node) => {
|
||||
let last = arr[arr.length - 1]
|
||||
if (!last) arr.push(node)
|
||||
// "there is one chunk between each pair of child elements"
|
||||
else if (isTextNode(node)) {
|
||||
if (Array.isArray(last)) last.push(node)
|
||||
else if (isTextNode(last)) arr[arr.length - 1] = [last, node]
|
||||
else arr.push(node)
|
||||
} else {
|
||||
if (isElementNode(last)) arr.push(null, node)
|
||||
else arr.push(node)
|
||||
}
|
||||
return arr
|
||||
}, [])
|
||||
// "the first chunk is located before the first child element"
|
||||
if (isElementNode(nodes[0])) nodes.unshift('first')
|
||||
// "the last chunk is located after the last child element"
|
||||
if (isElementNode(nodes[nodes.length - 1])) nodes.push('last')
|
||||
// "'virtual' elements"
|
||||
nodes.unshift('before') // "0 is a valid index"
|
||||
nodes.push('after') // "n+2 is a valid index"
|
||||
return nodes
|
||||
}
|
||||
|
||||
const partsToNode = (node, parts, filter) => {
|
||||
const { id } = parts[parts.length - 1]
|
||||
if (id) {
|
||||
const el = node.ownerDocument.getElementById(id)
|
||||
if (el) return { node: el, offset: 0 }
|
||||
}
|
||||
for (const { index } of parts) {
|
||||
const newNode = node ? indexChildNodes(node, filter)[index] : null
|
||||
// handle non-existent nodes
|
||||
if (newNode === 'first') return { node: node.firstChild ?? node }
|
||||
if (newNode === 'last') return { node: node.lastChild ?? node }
|
||||
if (newNode === 'before') return { node, before: true }
|
||||
if (newNode === 'after') return { node, after: true }
|
||||
node = newNode
|
||||
}
|
||||
const { offset } = parts[parts.length - 1]
|
||||
if (!Array.isArray(node)) return { node, offset }
|
||||
// get underlying text node and offset from the chunk
|
||||
let sum = 0
|
||||
for (const n of node) {
|
||||
const { length } = n.nodeValue
|
||||
if (sum + length >= offset) return { node: n, offset: offset - sum }
|
||||
sum += length
|
||||
}
|
||||
}
|
||||
|
||||
const nodeToParts = (node, offset, filter) => {
|
||||
const { parentNode, id } = node
|
||||
const indexed = indexChildNodes(parentNode, filter)
|
||||
const index = indexed.findIndex(x =>
|
||||
Array.isArray(x) ? x.some(x => x === node) : x === node)
|
||||
// adjust offset as if merging the text nodes in the chunk
|
||||
const chunk = indexed[index]
|
||||
if (Array.isArray(chunk)) {
|
||||
let sum = 0
|
||||
for (const x of chunk) {
|
||||
if (x === node) {
|
||||
sum += offset
|
||||
break
|
||||
} else sum += x.nodeValue.length
|
||||
}
|
||||
offset = sum
|
||||
}
|
||||
const part = { id, index, offset }
|
||||
return (parentNode !== node.ownerDocument.documentElement
|
||||
? nodeToParts(parentNode, null, filter).concat(part) : [part])
|
||||
// remove ignored nodes
|
||||
.filter(x => x.index !== -1)
|
||||
}
|
||||
|
||||
export const fromRange = (range, filter) => {
|
||||
const { startContainer, startOffset, endContainer, endOffset } = range
|
||||
const start = nodeToParts(startContainer, startOffset, filter)
|
||||
if (range.collapsed) return toString([start])
|
||||
const end = nodeToParts(endContainer, endOffset, filter)
|
||||
return buildRange([start], [end])
|
||||
}
|
||||
|
||||
export const toRange = (doc, parts, filter) => {
|
||||
const startParts = collapse(parts)
|
||||
const endParts = collapse(parts, true)
|
||||
|
||||
const root = doc.documentElement
|
||||
const start = partsToNode(root, startParts[0], filter)
|
||||
const end = partsToNode(root, endParts[0], filter)
|
||||
|
||||
const range = doc.createRange()
|
||||
|
||||
if (start.before) range.setStartBefore(start.node)
|
||||
else if (start.after) range.setStartAfter(start.node)
|
||||
else range.setStart(start.node, start.offset)
|
||||
|
||||
if (end.before) range.setEndBefore(end.node)
|
||||
else if (end.after) range.setEndAfter(end.node)
|
||||
else range.setEnd(end.node, end.offset)
|
||||
return range
|
||||
}
|
||||
|
||||
// faster way of getting CFIs for sorted elements in a single parent
|
||||
export const fromElements = elements => {
|
||||
const results = []
|
||||
const { parentNode } = elements[0]
|
||||
const parts = nodeToParts(parentNode)
|
||||
for (const [index, node] of indexChildNodes(parentNode).entries()) {
|
||||
const el = elements[results.length]
|
||||
if (node === el)
|
||||
results.push(toString([parts.concat({ id: el.id, index })]))
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
export const toElement = (doc, parts) =>
|
||||
partsToNode(doc.documentElement, collapse(parts)).node
|
||||
|
||||
// turn indices into standard CFIs when you don't have an actual package document
|
||||
export const fake = {
|
||||
fromIndex: index => wrap(`/6/${(index + 1) * 2}`),
|
||||
toIndex: parts => parts?.at(-1).index / 2 - 1,
|
||||
}
|
||||
|
||||
// get CFI from Calibre bookmarks
|
||||
// see https://github.com/johnfactotum/foliate/issues/849
|
||||
export const fromCalibrePos = pos => {
|
||||
const [parts] = parse(pos)
|
||||
const item = parts.shift()
|
||||
parts.shift()
|
||||
return toString([[{ index: 6 }, item], parts])
|
||||
}
|
||||
export const fromCalibreHighlight = ({ spine_index, start_cfi, end_cfi }) => {
|
||||
const pre = fake.fromIndex(spine_index) + '!'
|
||||
return buildRange(pre + start_cfi.slice(2), pre + end_cfi.slice(2))
|
||||
}
|
||||
@@ -1,347 +0,0 @@
|
||||
const normalizeWhitespace = str => str ? str
|
||||
.replace(/[\t\n\f\r ]+/g, ' ')
|
||||
.replace(/^[\t\n\f\r ]+/, '')
|
||||
.replace(/[\t\n\f\r ]+$/, '') : ''
|
||||
const getElementText = el => normalizeWhitespace(el?.textContent)
|
||||
|
||||
const NS = {
|
||||
XLINK: 'http://www.w3.org/1999/xlink',
|
||||
EPUB: 'http://www.idpf.org/2007/ops',
|
||||
}
|
||||
|
||||
const MIME = {
|
||||
XML: 'application/xml',
|
||||
XHTML: 'application/xhtml+xml',
|
||||
}
|
||||
|
||||
const STYLE = {
|
||||
'strong': ['strong', 'self'],
|
||||
'emphasis': ['em', 'self'],
|
||||
'style': ['span', 'self'],
|
||||
'a': 'anchor',
|
||||
'strikethrough': ['s', 'self'],
|
||||
'sub': ['sub', 'self'],
|
||||
'sup': ['sup', 'self'],
|
||||
'code': ['code', 'self'],
|
||||
'image': 'image',
|
||||
}
|
||||
|
||||
const TABLE = {
|
||||
'tr': ['tr', ['align']],
|
||||
'th': ['th', ['colspan', 'rowspan', 'align', 'valign']],
|
||||
'td': ['td', ['colspan', 'rowspan', 'align', 'valign']],
|
||||
}
|
||||
|
||||
const POEM = {
|
||||
'epigraph': ['blockquote'],
|
||||
'subtitle': ['h2', STYLE],
|
||||
'text-author': ['p', STYLE],
|
||||
'date': ['p', STYLE],
|
||||
'stanza': 'stanza',
|
||||
}
|
||||
|
||||
const SECTION = {
|
||||
'title': ['header', {
|
||||
'p': ['h1', STYLE],
|
||||
'empty-line': ['br'],
|
||||
}],
|
||||
'epigraph': ['blockquote', 'self'],
|
||||
'image': 'image',
|
||||
'annotation': ['aside'],
|
||||
'section': ['section', 'self'],
|
||||
'p': ['p', STYLE],
|
||||
'poem': ['blockquote', POEM],
|
||||
'subtitle': ['h2', STYLE],
|
||||
'cite': ['blockquote', 'self'],
|
||||
'empty-line': ['br'],
|
||||
'table': ['table', TABLE],
|
||||
'text-author': ['p', STYLE],
|
||||
}
|
||||
POEM['epigraph'].push(SECTION)
|
||||
|
||||
const BODY = {
|
||||
'image': 'image',
|
||||
'title': ['section', {
|
||||
'p': ['h1', STYLE],
|
||||
'empty-line': ['br'],
|
||||
}],
|
||||
'epigraph': ['section', SECTION],
|
||||
'section': ['section', SECTION],
|
||||
}
|
||||
|
||||
const getImageSrc = el => {
|
||||
const href = el.getAttributeNS(NS.XLINK, 'href')
|
||||
const [, id] = href.split('#')
|
||||
const bin = el.getRootNode().getElementById(id)
|
||||
return bin
|
||||
? `data:${bin.getAttribute('content-type')};base64,${bin.textContent}`
|
||||
: href
|
||||
}
|
||||
|
||||
class FB2Converter {
|
||||
constructor(fb2) {
|
||||
this.fb2 = fb2
|
||||
this.doc = document.implementation.createDocument(NS.XHTML, 'html')
|
||||
}
|
||||
image(node) {
|
||||
const el = this.doc.createElement('img')
|
||||
el.alt = node.getAttribute('alt')
|
||||
el.title = node.getAttribute('title')
|
||||
el.setAttribute('src', getImageSrc(node))
|
||||
return el
|
||||
}
|
||||
anchor(node) {
|
||||
const el = this.convert(node, { 'a': ['a', STYLE] })
|
||||
el.setAttribute('href', node.getAttributeNS(NS.XLINK, 'href'))
|
||||
if (node.getAttribute('type') === 'note')
|
||||
el.setAttributeNS(NS.EPUB, 'epub:type', 'noteref')
|
||||
return el
|
||||
}
|
||||
stanza(node) {
|
||||
const el = this.convert(node, {
|
||||
'stanza': ['p', {
|
||||
'title': ['header', {
|
||||
'p': ['strong', STYLE],
|
||||
'empty-line': ['br'],
|
||||
}],
|
||||
'subtitle': ['p', STYLE],
|
||||
}],
|
||||
})
|
||||
for (const child of node.children) if (child.nodeName === 'v') {
|
||||
el.append(this.doc.createTextNode(child.textContent))
|
||||
el.append(this.doc.createElement('br'))
|
||||
}
|
||||
return el
|
||||
}
|
||||
convert(node, def) {
|
||||
// not an element; return text content
|
||||
if (node.nodeType === 3) return this.doc.createTextNode(node.textContent)
|
||||
if (node.nodeType === 4) return this.doc.createCDATASection(node.textContent)
|
||||
if (node.nodeType === 8) return this.doc.createComment(node.textContent)
|
||||
|
||||
const d = def?.[node.nodeName]
|
||||
if (!d) return null
|
||||
if (typeof d === 'string') return this[d](node)
|
||||
|
||||
const [name, opts] = d
|
||||
const el = this.doc.createElement(name)
|
||||
|
||||
// copy the ID, and set class name from original element name
|
||||
if (node.id) el.id = node.id
|
||||
el.classList.add(node.nodeName)
|
||||
|
||||
// copy attributes
|
||||
if (Array.isArray(opts)) for (const attr of opts)
|
||||
el.setAttribute(attr, node.getAttribute(attr))
|
||||
|
||||
// process child elements recursively
|
||||
const childDef = opts === 'self' ? def : Array.isArray(opts) ? null : opts
|
||||
let child = node.firstChild
|
||||
while (child) {
|
||||
const childEl = this.convert(child, childDef)
|
||||
if (childEl) el.append(childEl)
|
||||
child = child.nextSibling
|
||||
}
|
||||
return el
|
||||
}
|
||||
}
|
||||
|
||||
const parseXML = async blob => {
|
||||
const buffer = await blob.arrayBuffer()
|
||||
const str = new TextDecoder('utf-8').decode(buffer)
|
||||
const parser = new DOMParser()
|
||||
const doc = parser.parseFromString(str, MIME.XML)
|
||||
const encoding = doc.xmlEncoding
|
||||
// `Document.xmlEncoding` is deprecated, and already removed in Firefox
|
||||
// so parse the XML declaration manually
|
||||
|| str.match(/^<\?xml\s+version\s*=\s*["']1.\d+"\s+encoding\s*=\s*["']([A-Za-z0-9._-]*)["']/)?.[1]
|
||||
if (encoding && encoding.toLowerCase() !== 'utf-8') {
|
||||
const str = new TextDecoder(encoding).decode(buffer)
|
||||
return parser.parseFromString(str, MIME.XML)
|
||||
}
|
||||
return doc
|
||||
}
|
||||
|
||||
const style = URL.createObjectURL(new Blob([`
|
||||
@namespace epub "http://www.idpf.org/2007/ops";
|
||||
body > img, section > img {
|
||||
display: block;
|
||||
margin: auto;
|
||||
}
|
||||
.title h1 {
|
||||
text-align: center;
|
||||
}
|
||||
body > section > .title, body.notesBodyType > .title {
|
||||
margin: 3em 0;
|
||||
}
|
||||
body.notesBodyType > section .title h1 {
|
||||
text-align: start;
|
||||
}
|
||||
body.notesBodyType > section .title {
|
||||
margin: 1em 0;
|
||||
}
|
||||
p {
|
||||
text-indent: 1em;
|
||||
margin: 0;
|
||||
}
|
||||
:not(p) + p, p:first-child {
|
||||
text-indent: 0;
|
||||
}
|
||||
.poem p {
|
||||
text-indent: 0;
|
||||
margin: 1em 0;
|
||||
}
|
||||
.text-author, .date {
|
||||
text-align: end;
|
||||
}
|
||||
.text-author:before {
|
||||
content: "—";
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
td, th {
|
||||
padding: .25em;
|
||||
}
|
||||
a[epub|type~="noteref"] {
|
||||
font-size: .75em;
|
||||
vertical-align: super;
|
||||
}
|
||||
body:not(.notesBodyType) > .title, body:not(.notesBodyType) > .epigraph {
|
||||
margin: 3em 0;
|
||||
}
|
||||
`], { type: 'text/css' }))
|
||||
|
||||
const template = html => `<?xml version="1.0" encoding="utf-8"?>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head><link href="${style}" rel="stylesheet" type="text/css"/></head>
|
||||
<body>${html}</body>
|
||||
</html>`
|
||||
|
||||
// name of custom ID attribute for TOC items
|
||||
const dataID = 'data-foliate-id'
|
||||
|
||||
export const makeFB2 = async blob => {
|
||||
const book = {}
|
||||
const doc = await parseXML(blob)
|
||||
const converter = new FB2Converter(doc)
|
||||
|
||||
const $ = x => doc.querySelector(x)
|
||||
const $$ = x => [...doc.querySelectorAll(x)]
|
||||
const getPerson = el => {
|
||||
const nick = getElementText(el.querySelector('nickname'))
|
||||
if (nick) return nick
|
||||
const first = getElementText(el.querySelector('first-name'))
|
||||
const middle = getElementText(el.querySelector('middle-name'))
|
||||
const last = getElementText(el.querySelector('last-name'))
|
||||
const name = [first, middle, last].filter(x => x).join(' ')
|
||||
const sortAs = last
|
||||
? [last, [first, middle].filter(x => x).join(' ')].join(', ')
|
||||
: null
|
||||
return { name, sortAs }
|
||||
}
|
||||
const getDate = el => el?.getAttribute('value') ?? getElementText(el)
|
||||
const annotation = $('title-info annotation')
|
||||
book.metadata = {
|
||||
title: getElementText($('title-info book-title')),
|
||||
identifier: getElementText($('document-info id')),
|
||||
language: getElementText($('title-info lang')),
|
||||
author: $$('title-info author').map(getPerson),
|
||||
translator: $$('title-info translator').map(getPerson),
|
||||
producer: $$('document-info author').map(getPerson)
|
||||
.concat($$('document-info program-used').map(getElementText)),
|
||||
publisher: getElementText($('publish-info publisher')),
|
||||
published: getDate($('title-info date')),
|
||||
modified: getDate($('document-info date')),
|
||||
description: annotation ? converter.convert(annotation,
|
||||
{ annotation: ['div', SECTION] }).innerHTML : null,
|
||||
subject: $$('title-info genre').map(getElementText),
|
||||
}
|
||||
if ($('coverpage image')) {
|
||||
const src = getImageSrc($('coverpage image'))
|
||||
book.getCover = () => fetch(src).then(res => res.blob())
|
||||
} else book.getCover = () => null
|
||||
|
||||
// get convert each body
|
||||
const bodyData = Array.from(doc.querySelectorAll('body'), body => {
|
||||
const converted = converter.convert(body, { body: ['body', BODY] })
|
||||
return [Array.from(converted.children, el => {
|
||||
// get list of IDs in the section
|
||||
const ids = [el, ...el.querySelectorAll('[id]')].map(el => el.id)
|
||||
return { el, ids }
|
||||
}), converted]
|
||||
})
|
||||
|
||||
const urls = []
|
||||
const sectionData = bodyData[0][0]
|
||||
// make a separate section for each section in the first body
|
||||
.map(({ el, ids }) => {
|
||||
// set up titles for TOC
|
||||
const titles = Array.from(
|
||||
el.querySelectorAll(':scope > section > .title'),
|
||||
(el, index) => {
|
||||
el.setAttribute(dataID, index)
|
||||
return { title: getElementText(el), index }
|
||||
})
|
||||
return { ids, titles, el }
|
||||
})
|
||||
// for additional bodies, only make one section for each body
|
||||
.concat(bodyData.slice(1).map(([sections, body]) => {
|
||||
const ids = sections.map(s => s.ids).flat()
|
||||
body.classList.add('notesBodyType')
|
||||
return { ids, el: body, linear: 'no' }
|
||||
}))
|
||||
.map(({ ids, titles, el, linear }) => {
|
||||
const str = template(el.outerHTML)
|
||||
const blob = new Blob([str], { type: MIME.XHTML })
|
||||
const url = URL.createObjectURL(blob)
|
||||
urls.push(url)
|
||||
const title = normalizeWhitespace(
|
||||
el.querySelector('.title, .subtitle, p')?.textContent
|
||||
?? (el.classList.contains('title') ? el.textContent : ''))
|
||||
return {
|
||||
ids, title, titles, load: () => url,
|
||||
createDocument: () => new DOMParser().parseFromString(str, MIME.XHTML),
|
||||
// doo't count image data as it'd skew the size too much
|
||||
size: blob.size - Array.from(el.querySelectorAll('[src]'),
|
||||
el => el.getAttribute('src')?.length ?? 0)
|
||||
.reduce((a, b) => a + b, 0),
|
||||
linear,
|
||||
}
|
||||
})
|
||||
|
||||
const idMap = new Map()
|
||||
book.sections = sectionData.map((section, index) => {
|
||||
const { ids, load, createDocument, size, linear } = section
|
||||
for (const id of ids) if (id) idMap.set(id, index)
|
||||
return { id: index, load, createDocument, size, linear }
|
||||
})
|
||||
|
||||
book.toc = sectionData.map(({ title, titles }, index) => {
|
||||
const id = index.toString()
|
||||
return {
|
||||
label: title,
|
||||
href: id,
|
||||
subitems: titles?.length ? titles.map(({ title, index }) => ({
|
||||
label: title,
|
||||
href: `${id}#${index}`,
|
||||
})) : null,
|
||||
}
|
||||
}).filter(item => item)
|
||||
|
||||
book.resolveHref = href => {
|
||||
const [a, b] = href.split('#')
|
||||
return a
|
||||
// the link is from the TOC
|
||||
? { index: Number(a), anchor: doc => doc.querySelector(`[${dataID}="${b}"]`) }
|
||||
// link from within the page
|
||||
: { index: idMap.get(b), anchor: doc => doc.getElementById(b) }
|
||||
}
|
||||
book.splitTOCHref = href => href?.split('#')?.map(x => Number(x)) ?? []
|
||||
book.getTOCFragment = (doc, id) => doc.querySelector(`[${dataID}="${id}"]`)
|
||||
|
||||
book.destroy = () => {
|
||||
for (const url of urls) URL.revokeObjectURL(url)
|
||||
}
|
||||
return book
|
||||
}
|
||||
@@ -1,297 +0,0 @@
|
||||
const parseViewport = str => str
|
||||
?.split(/[,;\s]/) // NOTE: technically, only the comma is valid
|
||||
?.filter(x => x)
|
||||
?.map(x => x.split('=').map(x => x.trim()))
|
||||
|
||||
const getViewport = (doc, viewport) => {
|
||||
// use `viewBox` for SVG
|
||||
if (doc.documentElement.localName === 'svg') {
|
||||
const [, , width, height] = doc.documentElement
|
||||
.getAttribute('viewBox')?.split(/\s/) ?? []
|
||||
return { width, height }
|
||||
}
|
||||
|
||||
// get `viewport` `meta` element
|
||||
const meta = parseViewport(doc.querySelector('meta[name="viewport"]')
|
||||
?.getAttribute('content'))
|
||||
if (meta) return Object.fromEntries(meta)
|
||||
|
||||
// fallback to book's viewport
|
||||
if (typeof viewport === 'string') return parseViewport(viewport)
|
||||
if (viewport) return viewport
|
||||
|
||||
// if no viewport (possibly with image directly in spine), get image size
|
||||
const img = doc.querySelector('img')
|
||||
if (img) return { width: img.naturalWidth, height: img.naturalHeight }
|
||||
|
||||
// just show *something*, i guess...
|
||||
console.warn(new Error('Missing viewport properties'))
|
||||
return { width: 1000, height: 2000 }
|
||||
}
|
||||
|
||||
export class FixedLayout extends HTMLElement {
|
||||
#root = this.attachShadow({ mode: 'closed' })
|
||||
#observer = new ResizeObserver(() => this.#render())
|
||||
#spreads
|
||||
#index = -1
|
||||
defaultViewport
|
||||
spread
|
||||
#portrait = false
|
||||
#left
|
||||
#right
|
||||
#center
|
||||
#side
|
||||
constructor() {
|
||||
super()
|
||||
|
||||
const sheet = new CSSStyleSheet()
|
||||
this.#root.adoptedStyleSheets = [sheet]
|
||||
sheet.replaceSync(`:host {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}`)
|
||||
|
||||
this.#observer.observe(this)
|
||||
}
|
||||
async #createFrame(position, { index, src }) {
|
||||
const element = document.createElement('div')
|
||||
const iframe = document.createElement('iframe')
|
||||
element.append(iframe)
|
||||
Object.assign(iframe.style, {
|
||||
border: '0',
|
||||
display: 'none',
|
||||
overflow: 'hidden',
|
||||
})
|
||||
// `allow-scripts` is needed for events because of WebKit bug
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=218086
|
||||
iframe.setAttribute('sandbox', 'allow-same-origin allow-scripts')
|
||||
iframe.setAttribute('scrolling', 'no')
|
||||
iframe.setAttribute('part', 'filter')
|
||||
this.#root.append(element)
|
||||
if (!src) return { blank: true, element, iframe }
|
||||
return new Promise(resolve => {
|
||||
const onload = () => {
|
||||
iframe.removeEventListener('load', onload)
|
||||
const doc = iframe.contentDocument
|
||||
doc.position = position
|
||||
this.dispatchEvent(new CustomEvent('load', { detail: { doc, index } }))
|
||||
const { width, height } = getViewport(doc, this.defaultViewport)
|
||||
resolve({
|
||||
element, iframe,
|
||||
width: parseFloat(width),
|
||||
height: parseFloat(height),
|
||||
})
|
||||
}
|
||||
iframe.addEventListener('load', onload)
|
||||
iframe.src = src
|
||||
})
|
||||
}
|
||||
#render(side = this.#side) {
|
||||
if (!side) return
|
||||
const left = this.#left ?? {}
|
||||
const right = this.#center ?? this.#right
|
||||
const target = side === 'left' ? left : right
|
||||
const { width, height } = this.getBoundingClientRect()
|
||||
const portrait = this.spread !== 'both' && this.spread !== 'portrait'
|
||||
&& height > width
|
||||
this.#portrait = portrait
|
||||
const blankWidth = left.width ?? right.width
|
||||
const blankHeight = left.height ?? right.height
|
||||
|
||||
const scale = portrait || this.#center
|
||||
? Math.min(
|
||||
width / (target.width ?? blankWidth),
|
||||
height / (target.height ?? blankHeight))
|
||||
: Math.min(
|
||||
width / ((left.width ?? blankWidth) + (right.width ?? blankWidth)),
|
||||
height / Math.max(
|
||||
left.height ?? blankHeight,
|
||||
right.height ?? blankHeight))
|
||||
|
||||
const transform = frame => {
|
||||
const { element, iframe, width, height, blank } = frame
|
||||
iframe.contentDocument.scale = scale
|
||||
Object.assign(iframe.style, {
|
||||
width: `${width}px`,
|
||||
height: `${height}px`,
|
||||
transform: `scale(${scale})`,
|
||||
transformOrigin: 'top left',
|
||||
display: blank ? 'none' : 'block',
|
||||
})
|
||||
Object.assign(element.style, {
|
||||
width: `${(width ?? blankWidth) * scale}px`,
|
||||
height: `${(height ?? blankHeight) * scale}px`,
|
||||
overflow: 'hidden',
|
||||
display: 'block',
|
||||
})
|
||||
if (portrait && frame !== target) {
|
||||
element.style.display = 'none'
|
||||
}
|
||||
}
|
||||
if (this.#center) {
|
||||
transform(this.#center)
|
||||
} else {
|
||||
transform(left)
|
||||
transform(right)
|
||||
}
|
||||
}
|
||||
async #showSpread({ left, right, center, side }) {
|
||||
this.#root.replaceChildren()
|
||||
this.#left = null
|
||||
this.#right = null
|
||||
this.#center = null
|
||||
if (center) {
|
||||
this.#center = await this.#createFrame('center', center)
|
||||
this.#side = 'center'
|
||||
this.#render()
|
||||
} else {
|
||||
this.#left = await this.#createFrame('left', left)
|
||||
this.#right = await this.#createFrame('right', right)
|
||||
this.#side = this.#left.blank ? 'right'
|
||||
: this.#right.blank ? 'left' : side
|
||||
this.#render()
|
||||
}
|
||||
}
|
||||
#goLeft() {
|
||||
if (this.#center || this.#left?.blank) return
|
||||
if (this.#portrait && this.#left?.element?.style?.display === 'none') {
|
||||
this.#right.element.style.display = 'none'
|
||||
this.#left.element.style.display = 'block'
|
||||
this.#side = 'left'
|
||||
return true
|
||||
}
|
||||
}
|
||||
#goRight() {
|
||||
if (this.#center || this.#right?.blank) return
|
||||
if (this.#portrait && this.#right?.element?.style?.display === 'none') {
|
||||
this.#left.element.style.display = 'none'
|
||||
this.#right.element.style.display = 'block'
|
||||
this.#side = 'right'
|
||||
return true
|
||||
}
|
||||
}
|
||||
open(book) {
|
||||
this.book = book
|
||||
const { rendition } = book
|
||||
this.spread = rendition?.spread
|
||||
this.defaultViewport = rendition?.viewport
|
||||
|
||||
const rtl = book.dir === 'rtl'
|
||||
const ltr = !rtl
|
||||
this.rtl = rtl
|
||||
|
||||
if (rendition?.spread === 'none')
|
||||
this.#spreads = book.sections.map(section => ({ center: section }))
|
||||
else this.#spreads = book.sections.reduce((arr, section) => {
|
||||
const last = arr[arr.length - 1]
|
||||
const { linear, pageSpread } = section
|
||||
if (linear === 'no') return arr
|
||||
const newSpread = () => {
|
||||
const spread = {}
|
||||
arr.push(spread)
|
||||
return spread
|
||||
}
|
||||
if (pageSpread === 'center') {
|
||||
const spread = last.left || last.right ? newSpread() : last
|
||||
spread.center = section
|
||||
}
|
||||
else if (pageSpread === 'left') {
|
||||
const spread = last.center || last.left || ltr ? newSpread() : last
|
||||
spread.left = section
|
||||
}
|
||||
else if (pageSpread === 'right') {
|
||||
const spread = last.center || last.right || rtl ? newSpread() : last
|
||||
spread.right = section
|
||||
}
|
||||
else if (ltr) {
|
||||
if (last.center || last.right) newSpread().left = section
|
||||
else if (last.left) last.right = section
|
||||
else last.left = section
|
||||
}
|
||||
else {
|
||||
if (last.center || last.left) newSpread().right = section
|
||||
else if (last.right) last.left = section
|
||||
else last .right = section
|
||||
}
|
||||
return arr
|
||||
}, [{}])
|
||||
}
|
||||
get index() {
|
||||
const spread = this.#spreads[this.#index]
|
||||
const section = spread?.center ?? (this.side === 'left'
|
||||
? spread.left ?? spread.right : spread.right ?? spread.left)
|
||||
return this.book.sections.indexOf(section)
|
||||
}
|
||||
#reportLocation(reason) {
|
||||
this.dispatchEvent(new CustomEvent('relocate', { detail:
|
||||
{ reason, range: null, index: this.index, fraction: 0, size: 1 } }))
|
||||
}
|
||||
getSpreadOf(section) {
|
||||
const spreads = this.#spreads
|
||||
for (let index = 0; index < spreads.length; index++) {
|
||||
const { left, right, center } = spreads[index]
|
||||
if (left === section) return { index, side: 'left' }
|
||||
if (right === section) return { index, side: 'right' }
|
||||
if (center === section) return { index, side: 'center' }
|
||||
}
|
||||
}
|
||||
async goToSpread(index, side, reason) {
|
||||
if (index < 0 || index > this.#spreads.length - 1) return
|
||||
if (index === this.#index) {
|
||||
this.#render(side)
|
||||
return
|
||||
}
|
||||
this.#index = index
|
||||
const spread = this.#spreads[index]
|
||||
if (spread.center) {
|
||||
const index = this.book.sections.indexOf(spread.center)
|
||||
const src = await spread.center?.load?.()
|
||||
await this.#showSpread({ center: { index, src } })
|
||||
} else {
|
||||
const indexL = this.book.sections.indexOf(spread.left)
|
||||
const indexR = this.book.sections.indexOf(spread.right)
|
||||
const srcL = await spread.left?.load?.()
|
||||
const srcR = await spread.right?.load?.()
|
||||
const left = { index: indexL, src: srcL }
|
||||
const right = { index: indexR, src: srcR }
|
||||
await this.#showSpread({ left, right, side })
|
||||
}
|
||||
this.#reportLocation(reason)
|
||||
}
|
||||
async select(target) {
|
||||
await this.goTo(target)
|
||||
// TODO
|
||||
}
|
||||
async goTo(target) {
|
||||
const { book } = this
|
||||
const resolved = await target
|
||||
const section = book.sections[resolved.index]
|
||||
if (!section) return
|
||||
const { index, side } = this.getSpreadOf(section)
|
||||
await this.goToSpread(index, side)
|
||||
}
|
||||
async next() {
|
||||
const s = this.rtl ? this.#goLeft() : this.#goRight()
|
||||
if (s) this.#reportLocation('page')
|
||||
else return this.goToSpread(this.#index + 1, this.rtl ? 'right' : 'left', 'page')
|
||||
}
|
||||
async prev() {
|
||||
const s = this.rtl ? this.#goRight() : this.#goLeft()
|
||||
if (s) this.#reportLocation('page')
|
||||
else return this.goToSpread(this.#index - 1, this.rtl ? 'left' : 'right', 'page')
|
||||
}
|
||||
getContents() {
|
||||
return Array.from(this.#root.querySelectorAll('iframe'), frame => ({
|
||||
doc: frame.contentDocument,
|
||||
// TODO: index, overlayer
|
||||
}))
|
||||
}
|
||||
destroy() {
|
||||
this.#observer.unobserve(this)
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('foliate-fxl', FixedLayout)
|
||||
@@ -1,99 +0,0 @@
|
||||
const getTypes = el => new Set(el?.getAttributeNS?.('http://www.idpf.org/2007/ops', 'type')?.split(' '))
|
||||
const getRoles = el => new Set(el?.getAttribute?.('role')?.split(' '))
|
||||
|
||||
const isSuper = el => {
|
||||
const { verticalAlign } = getComputedStyle(el)
|
||||
return verticalAlign === 'super' || /^\d/.test(verticalAlign)
|
||||
}
|
||||
|
||||
const refTypes = ['biblioref', 'glossref', 'noteref']
|
||||
const refRoles = ['doc-biblioref', 'doc-glossref', 'doc-noteref']
|
||||
const isFootnoteReference = a => {
|
||||
const types = getTypes(a)
|
||||
const roles = getRoles(a)
|
||||
return {
|
||||
yes: refRoles.some(r => roles.has(r)) || refTypes.some(t => types.has(t)),
|
||||
maybe: () => !types.has('backlink') && !roles.has('doc-backlink')
|
||||
&& (isSuper(a) || a.children.length === 1 && isSuper(a.children[0])
|
||||
|| isSuper(a.parentElement)),
|
||||
}
|
||||
}
|
||||
|
||||
const getReferencedType = el => {
|
||||
const types = getTypes(el)
|
||||
const roles = getRoles(el)
|
||||
return roles.has('doc-biblioentry') || types.has('biblioentry') ? 'biblioentry'
|
||||
: roles.has('definition') || types.has('glossdef') ? 'definition'
|
||||
: roles.has('doc-endnote') || types.has('endnote') || types.has('rearnote') ? 'endnote'
|
||||
: roles.has('doc-footnote') || types.has('footnote') ? 'footnote'
|
||||
: roles.has('note') || types.has('note') ? 'note' : null
|
||||
}
|
||||
|
||||
const isInline = 'a, span, sup, sub, em, strong, i, b, small, big'
|
||||
const extractFootnote = (doc, anchor) => {
|
||||
let el = anchor(doc)
|
||||
const target = el
|
||||
while (el.matches(isInline)) {
|
||||
const parent = el.parentElement
|
||||
if (!parent) break
|
||||
el = parent
|
||||
}
|
||||
if (el === doc.body) {
|
||||
const sibling = target.nextElementSibling
|
||||
if (sibling && !sibling.matches(isInline)) return sibling
|
||||
throw new Error('Failed to extract footnote')
|
||||
}
|
||||
return el
|
||||
}
|
||||
|
||||
export class FootnoteHandler extends EventTarget {
|
||||
detectFootnotes = true
|
||||
#showFragment(book, { index, anchor }, href) {
|
||||
const view = document.createElement('foliate-view')
|
||||
return new Promise((resolve, reject) => {
|
||||
view.addEventListener('load', e => {
|
||||
try {
|
||||
const { doc } = e.detail
|
||||
const el = anchor(doc)
|
||||
const type = getReferencedType(el)
|
||||
const hidden = el?.matches?.('aside') && type === 'footnote'
|
||||
if (el) {
|
||||
const range = el.startContainer ? el : doc.createRange()
|
||||
if (!el.startContainer) {
|
||||
if (el.matches('li, aside')) range.selectNodeContents(el)
|
||||
else range.selectNode(el)
|
||||
}
|
||||
const frag = range.extractContents()
|
||||
doc.body.replaceChildren()
|
||||
doc.body.appendChild(frag)
|
||||
}
|
||||
const detail = { view, href, type, hidden, target: el }
|
||||
this.dispatchEvent(new CustomEvent('render', { detail }))
|
||||
resolve()
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
view.open(book)
|
||||
.then(() => this.dispatchEvent(new CustomEvent('before-render', { detail: { view } })))
|
||||
.then(() => view.goTo(index))
|
||||
.catch(reject)
|
||||
})
|
||||
}
|
||||
handle(book, e) {
|
||||
const { a, href } = e.detail
|
||||
const { yes, maybe } = isFootnoteReference(a)
|
||||
if (yes) {
|
||||
e.preventDefault()
|
||||
return Promise.resolve(book.resolveHref(href)).then(target =>
|
||||
this.#showFragment(book, target, href))
|
||||
}
|
||||
else if (this.detectFootnotes && maybe()) {
|
||||
e.preventDefault()
|
||||
return Promise.resolve(book.resolveHref(href)).then(({ index, anchor }) => {
|
||||
const target = { index, anchor: doc => extractFootnote(doc, anchor) }
|
||||
return this.#showFragment(book, target, href)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,282 +0,0 @@
|
||||
const NS = {
|
||||
ATOM: 'http://www.w3.org/2005/Atom',
|
||||
OPDS: 'http://opds-spec.org/2010/catalog',
|
||||
THR: 'http://purl.org/syndication/thread/1.0',
|
||||
DC: 'http://purl.org/dc/elements/1.1/',
|
||||
DCTERMS: 'http://purl.org/dc/terms/',
|
||||
}
|
||||
|
||||
const MIME = {
|
||||
ATOM: 'application/atom+xml',
|
||||
OPDS2: 'application/opds+json',
|
||||
}
|
||||
|
||||
export const REL = {
|
||||
ACQ: 'http://opds-spec.org/acquisition',
|
||||
FACET: 'http://opds-spec.org/facet',
|
||||
GROUP: 'http://opds-spec.org/group',
|
||||
COVER: [
|
||||
'http://opds-spec.org/image',
|
||||
'http://opds-spec.org/cover',
|
||||
],
|
||||
THUMBNAIL: [
|
||||
'http://opds-spec.org/image/thumbnail',
|
||||
'http://opds-spec.org/thumbnail',
|
||||
],
|
||||
}
|
||||
|
||||
export const SYMBOL = {
|
||||
SUMMARY: Symbol('summary'),
|
||||
CONTENT: Symbol('content'),
|
||||
}
|
||||
|
||||
const FACET_GROUP = Symbol('facetGroup')
|
||||
|
||||
const groupByArray = (arr, f) => {
|
||||
const map = new Map()
|
||||
if (arr) for (const el of arr) {
|
||||
const keys = f(el)
|
||||
for (const key of [keys].flat()) {
|
||||
const group = map.get(key)
|
||||
if (group) group.push(el)
|
||||
else map.set(key, [el])
|
||||
}
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
// https://www.rfc-editor.org/rfc/rfc7231#section-3.1.1
|
||||
const parseMediaType = str => {
|
||||
if (!str) return null
|
||||
const [mediaType, ...ps] = str.split(/ *; */)
|
||||
return {
|
||||
mediaType: mediaType.toLowerCase(),
|
||||
parameters: Object.fromEntries(ps.map(p => {
|
||||
const [name, val] = p.split('=')
|
||||
return [name.toLowerCase(), val?.replace(/(^"|"$)/g, '')]
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
export const isOPDSCatalog = str => {
|
||||
const parsed = parseMediaType(str)
|
||||
if (!parsed) return false
|
||||
const { mediaType, parameters } = parsed
|
||||
if (mediaType === MIME.OPDS2) return true
|
||||
return mediaType === MIME.ATOM && parameters.profile?.toLowerCase() === 'opds-catalog'
|
||||
}
|
||||
|
||||
// ignore the namespace if it doesn't appear in document at all
|
||||
const useNS = (doc, ns) =>
|
||||
doc.lookupNamespaceURI(null) === ns || doc.lookupPrefix(ns) ? ns : null
|
||||
|
||||
const filterNS = ns => ns
|
||||
? name => el => el.namespaceURI === ns && el.localName === name
|
||||
: name => el => el.localName === name
|
||||
|
||||
const getContent = el => {
|
||||
if (!el) return
|
||||
const type = el.getAttribute('type') ?? 'text'
|
||||
const value = type === 'xhtml' ? el.innerHTML
|
||||
: type === 'html' ? el.textContent
|
||||
.replaceAll('<', '<')
|
||||
.replaceAll('>', '>')
|
||||
.replaceAll('&', '&')
|
||||
: el.textContent
|
||||
return { value, type }
|
||||
}
|
||||
|
||||
const getTextContent = el => {
|
||||
const content = getContent(el)
|
||||
if (content?.type === 'text') return content?.value
|
||||
}
|
||||
|
||||
const getSummary = (a, b) => getTextContent(a) ?? getTextContent(b)
|
||||
|
||||
const getPrice = link => {
|
||||
const price = link.getElementsByTagNameNS(NS.OPDS, 'price')[0]
|
||||
return price ? {
|
||||
currency: price.getAttribute('currencycode'),
|
||||
value: price.textContent,
|
||||
} : null
|
||||
}
|
||||
|
||||
const getIndirectAcquisition = el => {
|
||||
const ia = el.getElementsByTagNameNS(NS.OPDS, 'indirectAcquisition')[0]
|
||||
if (!ia) return []
|
||||
return [{ type: ia.getAttribute('type') }, ...getIndirectAcquisition(ia)]
|
||||
}
|
||||
|
||||
const getLink = link => {
|
||||
const obj = {
|
||||
rel: link.getAttribute('rel')?.split(/ +/),
|
||||
href: link.getAttribute('href'),
|
||||
type: link.getAttribute('type'),
|
||||
title: link.getAttribute('title'),
|
||||
properties: {
|
||||
price: getPrice(link),
|
||||
indirectAcquisition: getIndirectAcquisition(link),
|
||||
numberOfItems: link.getAttributeNS(NS.THR, 'count'),
|
||||
},
|
||||
[FACET_GROUP]: link.getAttributeNS(NS.OPDS, 'facetGroup'),
|
||||
}
|
||||
if (link.getAttributeNS(NS.OPDS, 'activeFacet') === 'true')
|
||||
obj.rel = [obj.rel ?? []].flat().concat('self')
|
||||
return obj
|
||||
}
|
||||
|
||||
export const getPublication = entry => {
|
||||
const filter = filterNS(useNS(entry.ownerDocument, NS.ATOM))
|
||||
const children = Array.from(entry.children)
|
||||
const filterDCEL = filterNS(NS.DC)
|
||||
const filterDCTERMS = filterNS(NS.DCTERMS)
|
||||
const filterDC = x => {
|
||||
const a = filterDCEL(x), b = filterDCTERMS(x)
|
||||
return y => a(y) || b(y)
|
||||
}
|
||||
const links = children.filter(filter('link')).map(getLink)
|
||||
const linksByRel = groupByArray(links, link => link.rel)
|
||||
return {
|
||||
metadata: {
|
||||
title: children.find(filter('title'))?.textContent ?? '',
|
||||
author: children.filter(filter('author')).map(person => {
|
||||
const NS = person.namespaceURI
|
||||
const uri = person.getElementsByTagNameNS(NS, 'uri')[0]?.textContent
|
||||
return {
|
||||
name: person.getElementsByTagNameNS(NS, 'name')[0]?.textContent ?? '',
|
||||
links: uri ? [{ href: uri }] : [],
|
||||
}
|
||||
}),
|
||||
publisher: children.find(filterDC('publisher'))?.textContent,
|
||||
published: (children.find(filterDCTERMS('issued'))
|
||||
?? children.find(filterDC('date')))?.textContent,
|
||||
language: children.find(filterDC('language'))?.textContent,
|
||||
identifier: children.find(filterDC('identifier'))?.textContent,
|
||||
subject: children.filter(filter('category')).map(category => ({
|
||||
name: category.getAttribute('label'),
|
||||
code: category.getAttribute('term'),
|
||||
})),
|
||||
[SYMBOL.CONTENT]: getContent(children.find(filter('content'))
|
||||
?? children.find(filter('summary'))),
|
||||
},
|
||||
links,
|
||||
images: REL.COVER.concat(REL.THUMBNAIL)
|
||||
.map(R => linksByRel.get(R)?.[0]).filter(x => x),
|
||||
}
|
||||
}
|
||||
|
||||
export const getFeed = doc => {
|
||||
const ns = useNS(doc, NS.ATOM)
|
||||
const filter = filterNS(ns)
|
||||
const children = Array.from(doc.documentElement.children)
|
||||
const entries = children.filter(filter('entry'))
|
||||
const links = children.filter(filter('link')).map(getLink)
|
||||
const linksByRel = groupByArray(links, link => link.rel)
|
||||
|
||||
const groupedItems = new Map([[null, []]])
|
||||
const groupLinkMap = new Map()
|
||||
for (const entry of entries) {
|
||||
const children = Array.from(entry.children)
|
||||
const links = children.filter(filter('link')).map(getLink)
|
||||
const linksByRel = groupByArray(links, link => link.rel)
|
||||
const isPub = [...linksByRel.keys()]
|
||||
.some(rel => rel?.startsWith(REL.ACQ) || rel === 'preview')
|
||||
|
||||
const groupLinks = linksByRel.get(REL.GROUP) ?? linksByRel.get('collection')
|
||||
const groupLink = groupLinks?.length
|
||||
? groupLinks.find(link => groupedItems.has(link.href)) ?? groupLinks[0] : null
|
||||
if (groupLink && !groupLinkMap.has(groupLink.href))
|
||||
groupLinkMap.set(groupLink.href, groupLink)
|
||||
|
||||
const item = isPub
|
||||
? getPublication(entry)
|
||||
: Object.assign(links.find(link => isOPDSCatalog(link.type)) ?? links[0] ?? {}, {
|
||||
title: children.find(filter('title'))?.textContent,
|
||||
[SYMBOL.SUMMARY]: getSummary(children.find(filter('summary')),
|
||||
children.find(filter('content'))),
|
||||
})
|
||||
|
||||
const arr = groupedItems.get(groupLink?.href ?? null)
|
||||
if (arr) arr.push(item)
|
||||
else groupedItems.set(groupLink.href, [item])
|
||||
}
|
||||
const [items, ...groups] = Array.from(groupedItems, ([key, items]) => {
|
||||
const itemsKey = items[0]?.metadata ? 'publications' : 'navigation'
|
||||
if (key == null) return { [itemsKey]: items }
|
||||
const link = groupLinkMap.get(key)
|
||||
return {
|
||||
metadata: {
|
||||
title: link.title,
|
||||
numberOfItems: link.properties.numberOfItems,
|
||||
},
|
||||
links: [{ rel: 'self', href: link.href, type: link.type }],
|
||||
[itemsKey]: items,
|
||||
}
|
||||
})
|
||||
return {
|
||||
metadata: {
|
||||
title: children.find(filter('title'))?.textContent,
|
||||
subtitle: children.find(filter('subtitle'))?.textContent,
|
||||
},
|
||||
links,
|
||||
...items,
|
||||
groups,
|
||||
facets: Array.from(
|
||||
groupByArray(linksByRel.get(REL.FACET) ?? [], link => link[FACET_GROUP]),
|
||||
([facet, links]) => ({ metadata: { title: facet }, links })),
|
||||
}
|
||||
}
|
||||
|
||||
export const getSearch = async link => {
|
||||
const { replace, getVariables } = await import('./uri-template.js')
|
||||
return {
|
||||
metadata: {
|
||||
title: link.title,
|
||||
},
|
||||
search: map => replace(link.href, map.get(null)),
|
||||
params: Array.from(getVariables(link.href), name => ({ name })),
|
||||
}
|
||||
}
|
||||
|
||||
export const getOpenSearch = doc => {
|
||||
const defaultNS = doc.documentElement.namespaceURI
|
||||
const filter = filterNS(defaultNS)
|
||||
const children = Array.from(doc.documentElement.children)
|
||||
|
||||
const $$urls = children.filter(filter('Url'))
|
||||
const $url = $$urls.find(url => isOPDSCatalog(url.getAttribute('type'))) ?? $$urls[0]
|
||||
if (!$url) throw new Error('document must contain at least one Url element')
|
||||
|
||||
const regex = /{(?:([^}]+?):)?(.+?)(\?)?}/g
|
||||
const defaultMap = new Map([
|
||||
['count', '100'],
|
||||
['startIndex', $url.getAttribute('indexOffset') ?? '0'],
|
||||
['startPage', $url.getAttribute('pageOffset') ?? '0'],
|
||||
['language', '*'],
|
||||
['inputEncoding', 'UTF-8'],
|
||||
['outputEncoding', 'UTF-8'],
|
||||
])
|
||||
|
||||
const template = $url.getAttribute('template')
|
||||
return {
|
||||
metadata: {
|
||||
title: (children.find(filter('LongName')) ?? children.find(filter('ShortName')))?.textContent,
|
||||
description: children.find(filter('Description'))?.textContent,
|
||||
},
|
||||
search: map => template.replace(regex, (_, prefix, param) => {
|
||||
const namespace = prefix ? $url.lookupNamespaceURI(prefix) : null
|
||||
const ns = namespace === defaultNS ? null : namespace
|
||||
const val = map.get(ns)?.get(param)
|
||||
return encodeURIComponent(val ? val : (!ns ? defaultMap.get(param) ?? '' : ''))
|
||||
}),
|
||||
params: Array.from(template.matchAll(regex), ([, prefix, param, optional]) => {
|
||||
const namespace = prefix ? $url.lookupNamespaceURI(prefix) : null
|
||||
const ns = namespace === defaultNS ? null : namespace
|
||||
return {
|
||||
ns, name: param,
|
||||
required: !optional,
|
||||
value: ns && ns !== defaultNS ? '' : defaultMap.get(param) ?? '',
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
const createSVGElement = tag =>
|
||||
document.createElementNS('http://www.w3.org/2000/svg', tag)
|
||||
|
||||
export class Overlayer {
|
||||
#svg = createSVGElement('svg')
|
||||
#map = new Map()
|
||||
#doc = null
|
||||
constructor(doc) {
|
||||
this.#doc = doc
|
||||
Object.assign(this.#svg.style, {
|
||||
position: 'absolute', top: '0', left: '0',
|
||||
width: '100%', height: '100%',
|
||||
pointerEvents: 'none',
|
||||
})
|
||||
}
|
||||
get element() {
|
||||
return this.#svg
|
||||
}
|
||||
get #zoom() {
|
||||
// Safari does not zoom the client rects, while Chrome, Edge and Firefox does
|
||||
if (/^((?!chrome|android).)*AppleWebKit/i.test(navigator.userAgent) && !window.chrome) {
|
||||
return window.getComputedStyle(this.#doc.body).zoom || 1.0
|
||||
}
|
||||
return 1.0
|
||||
}
|
||||
#splitRangeByParagraph(range) {
|
||||
const ancestor = range.commonAncestorContainer
|
||||
const paragraphs = Array.from(ancestor.querySelectorAll?.('p, h1, h2, h3, h4') || [])
|
||||
|
||||
const splitRanges = []
|
||||
paragraphs.forEach((p) => {
|
||||
const pRange = document.createRange()
|
||||
if (range.intersectsNode(p)) {
|
||||
pRange.selectNodeContents(p)
|
||||
if (pRange.compareBoundaryPoints(Range.START_TO_START, range) < 0) {
|
||||
pRange.setStart(range.startContainer, range.startOffset)
|
||||
}
|
||||
if (pRange.compareBoundaryPoints(Range.END_TO_END, range) > 0) {
|
||||
pRange.setEnd(range.endContainer, range.endOffset)
|
||||
}
|
||||
splitRanges.push(pRange)
|
||||
}
|
||||
})
|
||||
return splitRanges.length === 0 ? [range] : splitRanges
|
||||
}
|
||||
add(key, range, draw, options) {
|
||||
if (this.#map.has(key)) this.remove(key)
|
||||
if (typeof range === 'function') range = range(this.#svg.getRootNode())
|
||||
const zoom = this.#zoom
|
||||
let rects = []
|
||||
this.#splitRangeByParagraph(range).forEach((pRange) => {
|
||||
const pRects = Array.from(pRange.getClientRects()).map(rect => ({
|
||||
left: rect.left * zoom,
|
||||
top: rect.top * zoom,
|
||||
right: rect.right * zoom,
|
||||
bottom: rect.bottom * zoom,
|
||||
width: rect.width * zoom,
|
||||
height: rect.height * zoom,
|
||||
}))
|
||||
rects = rects.concat(pRects)
|
||||
})
|
||||
const element = draw(rects, options)
|
||||
this.#svg.append(element)
|
||||
this.#map.set(key, { range, draw, options, element, rects })
|
||||
}
|
||||
remove(key) {
|
||||
if (!this.#map.has(key)) return
|
||||
this.#svg.removeChild(this.#map.get(key).element)
|
||||
this.#map.delete(key)
|
||||
}
|
||||
redraw() {
|
||||
for (const obj of this.#map.values()) {
|
||||
const { range, draw, options, element } = obj
|
||||
this.#svg.removeChild(element)
|
||||
const zoom = this.#zoom
|
||||
let rects = []
|
||||
this.#splitRangeByParagraph(range).forEach((pRange) => {
|
||||
const pRects = Array.from(pRange.getClientRects()).map(rect => ({
|
||||
left: rect.left * zoom,
|
||||
top: rect.top * zoom,
|
||||
right: rect.right * zoom,
|
||||
bottom: rect.bottom * zoom,
|
||||
width: rect.width * zoom,
|
||||
height: rect.height * zoom,
|
||||
}))
|
||||
rects = rects.concat(pRects)
|
||||
})
|
||||
const el = draw(rects, options)
|
||||
this.#svg.append(el)
|
||||
obj.element = el
|
||||
obj.rects = rects
|
||||
}
|
||||
}
|
||||
hitTest({ x, y }) {
|
||||
const arr = Array.from(this.#map.entries())
|
||||
// loop in reverse to hit more recently added items first
|
||||
for (let i = arr.length - 1; i >= 0; i--) {
|
||||
const [key, obj] = arr[i]
|
||||
for (const { left, top, right, bottom } of obj.rects)
|
||||
if (top <= y && left <= x && bottom > y && right > x)
|
||||
return [key, obj.range]
|
||||
}
|
||||
return []
|
||||
}
|
||||
static underline(rects, options = {}) {
|
||||
const { color = 'red', width: strokeWidth = 2, padding = 0, writingMode } = options
|
||||
const g = createSVGElement('g')
|
||||
g.setAttribute('fill', color)
|
||||
if (writingMode === 'vertical-rl' || writingMode === 'vertical-lr')
|
||||
for (const { right, top, height } of rects) {
|
||||
const el = createSVGElement('rect')
|
||||
el.setAttribute('x', right - strokeWidth / 2 + padding)
|
||||
el.setAttribute('y', top)
|
||||
el.setAttribute('height', height)
|
||||
el.setAttribute('width', strokeWidth)
|
||||
g.append(el)
|
||||
}
|
||||
else for (const { left, bottom, width } of rects) {
|
||||
const el = createSVGElement('rect')
|
||||
el.setAttribute('x', left)
|
||||
el.setAttribute('y', bottom - strokeWidth / 2 + padding)
|
||||
el.setAttribute('height', strokeWidth)
|
||||
el.setAttribute('width', width)
|
||||
g.append(el)
|
||||
}
|
||||
return g
|
||||
}
|
||||
static strikethrough(rects, options = {}) {
|
||||
const { color = 'red', width: strokeWidth = 2, writingMode } = options
|
||||
const g = createSVGElement('g')
|
||||
g.setAttribute('fill', color)
|
||||
if (writingMode === 'vertical-rl' || writingMode === 'vertical-lr')
|
||||
for (const { right, left, top, height } of rects) {
|
||||
const el = createSVGElement('rect')
|
||||
el.setAttribute('x', (right + left) / 2)
|
||||
el.setAttribute('y', top)
|
||||
el.setAttribute('height', height)
|
||||
el.setAttribute('width', strokeWidth)
|
||||
g.append(el)
|
||||
}
|
||||
else for (const { left, top, bottom, width } of rects) {
|
||||
const el = createSVGElement('rect')
|
||||
el.setAttribute('x', left)
|
||||
el.setAttribute('y', (top + bottom) / 2)
|
||||
el.setAttribute('height', strokeWidth)
|
||||
el.setAttribute('width', width)
|
||||
g.append(el)
|
||||
}
|
||||
return g
|
||||
}
|
||||
static squiggly(rects, options = {}) {
|
||||
const { color = 'red', width: strokeWidth = 2, padding = 0, writingMode } = options
|
||||
const g = createSVGElement('g')
|
||||
g.setAttribute('fill', 'none')
|
||||
g.setAttribute('stroke', color)
|
||||
g.setAttribute('stroke-width', strokeWidth)
|
||||
const block = strokeWidth * 1.5
|
||||
if (writingMode === 'vertical-rl' || writingMode === 'vertical-lr')
|
||||
for (const { right, top, height } of rects) {
|
||||
const el = createSVGElement('path')
|
||||
const n = Math.round(height / block / 1.5)
|
||||
const inline = height / n
|
||||
const ls = Array.from({ length: n },
|
||||
(_, i) => `l${i % 2 ? -block : block} ${inline}`).join('')
|
||||
el.setAttribute('d', `M${right - strokeWidth / 2 + padding} ${top}${ls}`)
|
||||
g.append(el)
|
||||
}
|
||||
else for (const { left, bottom, width } of rects) {
|
||||
const el = createSVGElement('path')
|
||||
const n = Math.round(width / block / 1.5)
|
||||
const inline = width / n
|
||||
const ls = Array.from({ length: n },
|
||||
(_, i) => `l${inline} ${i % 2 ? block : -block}`).join('')
|
||||
el.setAttribute('d', `M${left} ${bottom + strokeWidth / 2 + padding}${ls}`)
|
||||
g.append(el)
|
||||
}
|
||||
return g
|
||||
}
|
||||
static highlight(rects, options = {}) {
|
||||
const { color = 'red', padding = 0 } = options
|
||||
const g = createSVGElement('g')
|
||||
g.setAttribute('fill', color)
|
||||
g.style.opacity = 'var(--overlayer-highlight-opacity, .3)'
|
||||
g.style.mixBlendMode = 'var(--overlayer-highlight-blend-mode, normal)'
|
||||
for (const { left, top, height, width } of rects) {
|
||||
const el = createSVGElement('rect')
|
||||
el.setAttribute('x', left - padding)
|
||||
el.setAttribute('y', top - padding)
|
||||
el.setAttribute('height', height + padding * 2)
|
||||
el.setAttribute('width', width + padding * 2)
|
||||
g.append(el)
|
||||
}
|
||||
return g
|
||||
}
|
||||
static outline(rects, options = {}) {
|
||||
const { color = 'red', width: strokeWidth = 3, padding = 0, radius = 3 } = options
|
||||
const g = createSVGElement('g')
|
||||
g.setAttribute('fill', 'none')
|
||||
g.setAttribute('stroke', color)
|
||||
g.setAttribute('stroke-width', strokeWidth)
|
||||
for (const { left, top, height, width } of rects) {
|
||||
const el = createSVGElement('rect')
|
||||
el.setAttribute('x', left - padding)
|
||||
el.setAttribute('y', top - padding)
|
||||
el.setAttribute('height', height + padding * 2)
|
||||
el.setAttribute('width', width + padding * 2)
|
||||
el.setAttribute('rx', radius)
|
||||
g.append(el)
|
||||
}
|
||||
return g
|
||||
}
|
||||
// make an exact copy of an image in the overlay
|
||||
// one can then apply filters to the entire element, without affecting them;
|
||||
// it's a bit silly and probably better to just invert images twice
|
||||
// (though the color will be off in that case if you do heu-rotate)
|
||||
static copyImage([rect], options = {}) {
|
||||
const { src } = options
|
||||
const image = createSVGElement('image')
|
||||
const { left, top, height, width } = rect
|
||||
image.setAttribute('href', src)
|
||||
image.setAttribute('x', left)
|
||||
image.setAttribute('y', top)
|
||||
image.setAttribute('height', height)
|
||||
image.setAttribute('width', width)
|
||||
return image
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,616 +0,0 @@
|
||||
/* global pdfjsLib */
|
||||
|
||||
// https://github.com/mozilla/pdf.js/blob/f04967017f22e46d70d11468dd928b4cdc2f6ea1/web/text_layer_builder.css
|
||||
const textLayerBuilderCSS = `
|
||||
/* Copyright 2014 Mozilla Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
:root {
|
||||
--highlight-bg-color: rgb(180 0 170);
|
||||
--highlight-selected-bg-color: rgb(0 100 0);
|
||||
}
|
||||
|
||||
@media screen and (forced-colors: active) {
|
||||
:root {
|
||||
--highlight-bg-color: Highlight;
|
||||
--highlight-selected-bg-color: ButtonText;
|
||||
}
|
||||
}
|
||||
|
||||
.textLayer {
|
||||
position: absolute;
|
||||
text-align: initial;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
opacity: 0.25;
|
||||
line-height: 1;
|
||||
text-size-adjust: none;
|
||||
forced-color-adjust: none;
|
||||
transform-origin: 0 0;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.textLayer :is(span, br) {
|
||||
color: transparent;
|
||||
position: absolute;
|
||||
white-space: pre;
|
||||
cursor: text;
|
||||
transform-origin: 0% 0%;
|
||||
}
|
||||
|
||||
/* Only necessary in Google Chrome, see issue 14205, and most unfortunately
|
||||
* the problem doesn't show up in "text" reference tests. */
|
||||
/*#if !MOZCENTRAL*/
|
||||
.textLayer span.markedContent {
|
||||
top: 0;
|
||||
height: 0;
|
||||
}
|
||||
/*#endif*/
|
||||
|
||||
.textLayer .highlight {
|
||||
margin: -1px;
|
||||
padding: 1px;
|
||||
background-color: var(--highlight-bg-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.textLayer .highlight.appended {
|
||||
position: initial;
|
||||
}
|
||||
|
||||
.textLayer .highlight.begin {
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
.textLayer .highlight.end {
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
.textLayer .highlight.middle {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.textLayer .highlight.selected {
|
||||
background-color: var(--highlight-selected-bg-color);
|
||||
}
|
||||
|
||||
.textLayer ::selection {
|
||||
/*#if !MOZCENTRAL*/
|
||||
background: blue;
|
||||
/*#endif*/
|
||||
background: AccentColor; /* stylelint-disable-line declaration-block-no-duplicate-properties */
|
||||
}
|
||||
|
||||
/* Avoids https://github.com/mozilla/pdf.js/issues/13840 in Chrome */
|
||||
/*#if !MOZCENTRAL*/
|
||||
.textLayer br::selection {
|
||||
background: transparent;
|
||||
}
|
||||
/*#endif*/
|
||||
|
||||
.textLayer .endOfContent {
|
||||
display: block;
|
||||
position: absolute;
|
||||
inset: 100% 0 0;
|
||||
z-index: -1;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.textLayer .endOfContent.active {
|
||||
top: 0;
|
||||
}
|
||||
`
|
||||
|
||||
//https://github.com/mozilla/pdf.js/blob/d64f223d034ad74fb62571c3acff566d25eca413/web/annotation_layer_builder.css
|
||||
const annotationLayerBuilderCSS = `
|
||||
/* Copyright 2014 Mozilla Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
:root {
|
||||
--annotation-unfocused-field-background: url("data:image/svg+xml;charset=UTF-8,<svg width='1px' height='1px' xmlns='http://www.w3.org/2000/svg'><rect width='100%' height='100%' style='fill:rgba(0, 54, 255, 0.13);'/></svg>");
|
||||
--input-focus-border-color: Highlight;
|
||||
--input-focus-outline: 1px solid Canvas;
|
||||
--input-unfocused-border-color: transparent;
|
||||
--input-disabled-border-color: transparent;
|
||||
--input-hover-border-color: black;
|
||||
--link-outline: none;
|
||||
}
|
||||
|
||||
@media screen and (forced-colors: active) {
|
||||
:root {
|
||||
--input-focus-border-color: CanvasText;
|
||||
--input-unfocused-border-color: ActiveText;
|
||||
--input-disabled-border-color: GrayText;
|
||||
--input-hover-border-color: Highlight;
|
||||
--link-outline: 1.5px solid LinkText;
|
||||
--hcm-highligh-filter: invert(100%);
|
||||
}
|
||||
.annotationLayer .textWidgetAnnotation :is(input, textarea):required,
|
||||
.annotationLayer .choiceWidgetAnnotation select:required,
|
||||
.annotationLayer
|
||||
.buttonWidgetAnnotation:is(.checkBox, .radioButton)
|
||||
input:required {
|
||||
outline: 1.5px solid selectedItem;
|
||||
}
|
||||
|
||||
.annotationLayer .linkAnnotation:hover {
|
||||
backdrop-filter: var(--hcm-highligh-filter);
|
||||
}
|
||||
|
||||
.annotationLayer .linkAnnotation > a:hover {
|
||||
opacity: 0 !important;
|
||||
background: none !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.annotationLayer .popupAnnotation .popup {
|
||||
outline: calc(1.5px * var(--scale-factor)) solid CanvasText !important;
|
||||
background-color: ButtonFace !important;
|
||||
color: ButtonText !important;
|
||||
}
|
||||
|
||||
.annotationLayer .highlightArea:hover::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
backdrop-filter: var(--hcm-highligh-filter);
|
||||
content: "";
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.annotationLayer .popupAnnotation.focused .popup {
|
||||
outline: calc(3px * var(--scale-factor)) solid Highlight !important;
|
||||
}
|
||||
}
|
||||
|
||||
.annotationLayer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
transform-origin: 0 0;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.annotationLayer[data-main-rotation="90"] .norotate {
|
||||
transform: rotate(270deg) translateX(-100%);
|
||||
}
|
||||
.annotationLayer[data-main-rotation="180"] .norotate {
|
||||
transform: rotate(180deg) translate(-100%, -100%);
|
||||
}
|
||||
.annotationLayer[data-main-rotation="270"] .norotate {
|
||||
transform: rotate(90deg) translateY(-100%);
|
||||
}
|
||||
|
||||
.annotationLayer canvas {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.annotationLayer section {
|
||||
position: absolute;
|
||||
text-align: initial;
|
||||
pointer-events: auto;
|
||||
box-sizing: border-box;
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
.annotationLayer .linkAnnotation {
|
||||
outline: var(--link-outline);
|
||||
}
|
||||
|
||||
.annotationLayer :is(.linkAnnotation, .buttonWidgetAnnotation.pushButton) > a {
|
||||
position: absolute;
|
||||
font-size: 1em;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.annotationLayer
|
||||
:is(.linkAnnotation, .buttonWidgetAnnotation.pushButton):not(.hasBorder)
|
||||
> a:hover {
|
||||
opacity: 0.2;
|
||||
background-color: rgb(255 255 0);
|
||||
box-shadow: 0 2px 10px rgb(255 255 0);
|
||||
}
|
||||
|
||||
.annotationLayer .linkAnnotation.hasBorder:hover {
|
||||
background-color: rgb(255 255 0 / 0.2);
|
||||
}
|
||||
|
||||
.annotationLayer .hasBorder {
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.annotationLayer .textAnnotation img {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation :is(input, textarea),
|
||||
.annotationLayer .choiceWidgetAnnotation select,
|
||||
.annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input {
|
||||
background-image: var(--annotation-unfocused-field-background);
|
||||
border: 2px solid var(--input-unfocused-border-color);
|
||||
box-sizing: border-box;
|
||||
font: calc(9px * var(--scale-factor)) sans-serif;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation :is(input, textarea):required,
|
||||
.annotationLayer .choiceWidgetAnnotation select:required,
|
||||
.annotationLayer
|
||||
.buttonWidgetAnnotation:is(.checkBox, .radioButton)
|
||||
input:required {
|
||||
outline: 1.5px solid red;
|
||||
}
|
||||
|
||||
.annotationLayer .choiceWidgetAnnotation select option {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton input {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation textarea {
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation :is(input, textarea)[disabled],
|
||||
.annotationLayer .choiceWidgetAnnotation select[disabled],
|
||||
.annotationLayer
|
||||
.buttonWidgetAnnotation:is(.checkBox, .radioButton)
|
||||
input[disabled] {
|
||||
background: none;
|
||||
border: 2px solid var(--input-disabled-border-color);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation :is(input, textarea):hover,
|
||||
.annotationLayer .choiceWidgetAnnotation select:hover,
|
||||
.annotationLayer
|
||||
.buttonWidgetAnnotation:is(.checkBox, .radioButton)
|
||||
input:hover {
|
||||
border: 2px solid var(--input-hover-border-color);
|
||||
}
|
||||
.annotationLayer .textWidgetAnnotation :is(input, textarea):hover,
|
||||
.annotationLayer .choiceWidgetAnnotation select:hover,
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:hover {
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation :is(input, textarea):focus,
|
||||
.annotationLayer .choiceWidgetAnnotation select:focus {
|
||||
background: none;
|
||||
border: 2px solid var(--input-focus-border-color);
|
||||
border-radius: 2px;
|
||||
outline: var(--input-focus-outline);
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) :focus {
|
||||
background-image: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox :focus {
|
||||
border: 2px solid var(--input-focus-border-color);
|
||||
border-radius: 2px;
|
||||
outline: var(--input-focus-outline);
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton :focus {
|
||||
border: 2px solid var(--input-focus-border-color);
|
||||
outline: var(--input-focus-outline);
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::before,
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::after,
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton input:checked::before {
|
||||
background-color: CanvasText;
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::before,
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::after {
|
||||
height: 80%;
|
||||
left: 45%;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::before {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.checkBox input:checked::after {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.radioButton input:checked::before {
|
||||
border-radius: 50%;
|
||||
height: 50%;
|
||||
left: 30%;
|
||||
top: 20%;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation input.comb {
|
||||
font-family: monospace;
|
||||
padding-left: 2px;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.annotationLayer .textWidgetAnnotation input.comb:focus {
|
||||
/*
|
||||
* Letter spacing is placed on the right side of each character. Hence, the
|
||||
* letter spacing of the last character may be placed outside the visible
|
||||
* area, causing horizontal scrolling. We avoid this by extending the width
|
||||
* when the element has focus and revert this when it loses focus.
|
||||
*/
|
||||
width: 103%;
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation:is(.checkBox, .radioButton) input {
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.annotationLayer .fileAttachmentAnnotation .popupTriggerArea {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.annotationLayer .popupAnnotation {
|
||||
position: absolute;
|
||||
font-size: calc(9px * var(--scale-factor));
|
||||
pointer-events: none;
|
||||
width: max-content;
|
||||
max-width: 45%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.annotationLayer .popup {
|
||||
background-color: rgb(255 255 153);
|
||||
box-shadow: 0 calc(2px * var(--scale-factor)) calc(5px * var(--scale-factor))
|
||||
rgb(136 136 136);
|
||||
border-radius: calc(2px * var(--scale-factor));
|
||||
outline: 1.5px solid rgb(255 255 74);
|
||||
padding: calc(6px * var(--scale-factor));
|
||||
cursor: pointer;
|
||||
font: message-box;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.annotationLayer .popupAnnotation.focused .popup {
|
||||
outline-width: 3px;
|
||||
}
|
||||
|
||||
.annotationLayer .popup * {
|
||||
font-size: calc(9px * var(--scale-factor));
|
||||
}
|
||||
|
||||
.annotationLayer .popup > .header {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.annotationLayer .popup > .header h1 {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.annotationLayer .popup > .header .popupDate {
|
||||
display: inline-block;
|
||||
margin-left: calc(5px * var(--scale-factor));
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.annotationLayer .popupContent {
|
||||
border-top: 1px solid rgb(51 51 51);
|
||||
margin-top: calc(2px * var(--scale-factor));
|
||||
padding-top: calc(2px * var(--scale-factor));
|
||||
}
|
||||
|
||||
.annotationLayer .richText > * {
|
||||
white-space: pre-wrap;
|
||||
font-size: calc(9px * var(--scale-factor));
|
||||
}
|
||||
|
||||
.annotationLayer .popupTriggerArea {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.annotationLayer section svg {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.annotationLayer .annotationTextContent {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
color: transparent;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.annotationLayer .annotationTextContent span {
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.annotationLayer svg.quadrilateralsContainer {
|
||||
contain: strict;
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
`
|
||||
|
||||
const renderPage = async (page, getImageBlob) => {
|
||||
|
||||
const naturalPdfSize = page.getViewport({ scale: 1 })
|
||||
const naturalPdfRatio = naturalPdfSize.width / naturalPdfSize.height
|
||||
const appRatio = innerWidth / innerHeight
|
||||
const pdfToAppResolutionRatio = appRatio / naturalPdfRatio
|
||||
|
||||
const scale = devicePixelRatio * pdfToAppResolutionRatio
|
||||
const viewport = page.getViewport({ scale })
|
||||
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.height = viewport.height
|
||||
canvas.width = viewport.width
|
||||
const canvasContext = canvas.getContext('2d')
|
||||
await page.render({ canvasContext, viewport }).promise
|
||||
const blob = await new Promise(resolve => canvas.toBlob(resolve))
|
||||
if (getImageBlob) return blob
|
||||
|
||||
/*
|
||||
// with the SVG backend
|
||||
const operatorList = await page.getOperatorList()
|
||||
const svgGraphics = new pdfjsLib.SVGGraphics(page.commonObjs, page.objs)
|
||||
const svg = await svgGraphics.getSVG(operatorList, viewport)
|
||||
const str = new XMLSerializer().serializeToString(svg)
|
||||
const blob = new Blob([str], { type: 'image/svg+xml' })
|
||||
*/
|
||||
|
||||
const container = document.createElement('div')
|
||||
container.classList.add('textLayer')
|
||||
await pdfjsLib.renderTextLayer({
|
||||
textContentSource: await page.getTextContent(),
|
||||
container, viewport,
|
||||
}).promise
|
||||
|
||||
const div = document.createElement('div')
|
||||
div.classList.add('annotationLayer')
|
||||
await new pdfjsLib.AnnotationLayer({ page, viewport, div }).render({
|
||||
annotations: await page.getAnnotations(),
|
||||
linkService: {
|
||||
getDestinationHash: dest => JSON.stringify(dest),
|
||||
addLinkAttributes: (link, url) => link.href = url,
|
||||
},
|
||||
})
|
||||
|
||||
const src = URL.createObjectURL(blob)
|
||||
const url = URL.createObjectURL(new Blob([`
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
:root {
|
||||
--scale-factor: ${scale};
|
||||
}
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
${textLayerBuilderCSS}
|
||||
${annotationLayerBuilderCSS}
|
||||
</style>
|
||||
<img src="${src}">
|
||||
${container.outerHTML}
|
||||
${div.outerHTML}
|
||||
`], { type: 'text/html' }))
|
||||
return url
|
||||
}
|
||||
|
||||
const makeTOCItem = item => ({
|
||||
label: item.title,
|
||||
href: JSON.stringify(item.dest),
|
||||
subitems: item.items.length ? item.items.map(makeTOCItem) : null,
|
||||
})
|
||||
|
||||
export const makePDF = async file => {
|
||||
const data = new Uint8Array(await file.arrayBuffer())
|
||||
const pdf = await pdfjsLib.getDocument({ data }).promise
|
||||
|
||||
const book = { rendition: { layout: 'pre-paginated' } }
|
||||
|
||||
const info = (await pdf.getMetadata())?.info
|
||||
book.metadata = {
|
||||
title: info?.Title,
|
||||
author: info?.Author,
|
||||
}
|
||||
|
||||
const outline = await pdf.getOutline()
|
||||
book.toc = outline?.map(makeTOCItem)
|
||||
|
||||
const cache = new Map()
|
||||
book.sections = Array.from({ length: pdf.numPages }).map((_, i) => ({
|
||||
id: i,
|
||||
load: async () => {
|
||||
const cached = cache.get(i)
|
||||
if (cached) return cached
|
||||
const url = await renderPage(await pdf.getPage(i + 1))
|
||||
cache.set(i, url)
|
||||
return url
|
||||
},
|
||||
size: 1000,
|
||||
}))
|
||||
book.sections[0].pageSpread = 'right'
|
||||
book.isExternal = uri => /^\w+:/i.test(uri)
|
||||
book.resolveHref = async href => {
|
||||
const parsed = JSON.parse(href)
|
||||
const dest = typeof parsed === 'string'
|
||||
? await pdf.getDestination(parsed) : parsed
|
||||
if (!dest || !dest[0]) return { index: 0 }
|
||||
const index = await pdf.getPageIndex(dest[0])
|
||||
return { index }
|
||||
}
|
||||
book.splitTOCHref = async href => {
|
||||
const parsed = JSON.parse(href)
|
||||
const dest = typeof parsed === 'string'
|
||||
? await pdf.getDestination(parsed) : parsed
|
||||
if (!dest || !dest[0]) return [0, null]
|
||||
const index = await pdf.getPageIndex(dest[0])
|
||||
return [index, null]
|
||||
}
|
||||
book.getTOCFragment = doc => doc.documentElement
|
||||
book.getCover = async () => renderPage(await pdf.getPage(1), true)
|
||||
return book
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
// assign a unique ID for each TOC item
|
||||
const assignIDs = toc => {
|
||||
let id = 0
|
||||
const assignID = item => {
|
||||
item.id = id++
|
||||
if (item.subitems) for (const subitem of item.subitems) assignID(subitem)
|
||||
}
|
||||
for (const item of toc) assignID(item)
|
||||
return toc
|
||||
}
|
||||
|
||||
const flatten = items => items
|
||||
.map(item => item.subitems?.length
|
||||
? [item, flatten(item.subitems)].flat()
|
||||
: item)
|
||||
.flat()
|
||||
|
||||
export class TOCProgress {
|
||||
async init({ toc, ids, splitHref, getFragment }) {
|
||||
assignIDs(toc)
|
||||
const items = flatten(toc)
|
||||
const grouped = new Map()
|
||||
for (const [i, item] of items.entries()) {
|
||||
const [id, fragment] = await splitHref(item?.href) ?? []
|
||||
const value = { fragment, item }
|
||||
if (grouped.has(id)) grouped.get(id).items.push(value)
|
||||
else grouped.set(id, { prev: items[i - 1], items: [value] })
|
||||
}
|
||||
const map = new Map()
|
||||
for (const [i, id] of ids.entries()) {
|
||||
if (grouped.has(id)) map.set(id, grouped.get(id))
|
||||
else map.set(id, map.get(ids[i - 1]))
|
||||
}
|
||||
this.ids = ids
|
||||
this.map = map
|
||||
this.getFragment = getFragment
|
||||
}
|
||||
getProgress(index, range) {
|
||||
if (!this.ids) return
|
||||
const id = this.ids[index]
|
||||
const obj = this.map.get(id)
|
||||
if (!obj) return null
|
||||
const { prev, items } = obj
|
||||
if (!items) return prev
|
||||
if (!range || items.length === 1 && !items[0].fragment) return items[0].item
|
||||
|
||||
const doc = range.startContainer.getRootNode()
|
||||
for (const [i, { fragment }] of items.entries()) {
|
||||
const el = this.getFragment(doc, fragment)
|
||||
if (!el) continue
|
||||
if (range.comparePoint(el, 0) > 0)
|
||||
return (items[i - 1]?.item ?? prev)
|
||||
}
|
||||
return items[items.length - 1].item
|
||||
}
|
||||
}
|
||||
|
||||
export class SectionProgress {
|
||||
constructor(sections, sizePerLoc, sizePerTimeUnit) {
|
||||
this.sizes = sections.map(s => s.linear != 'no' && s.size > 0 ? s.size : 0)
|
||||
this.sizePerLoc = sizePerLoc
|
||||
this.sizePerTimeUnit = sizePerTimeUnit
|
||||
this.sizeTotal = this.sizes.reduce((a, b) => a + b, 0)
|
||||
this.sectionFractions = this.#getSectionFractions()
|
||||
}
|
||||
#getSectionFractions() {
|
||||
const { sizeTotal } = this
|
||||
const results = [0]
|
||||
let sum = 0
|
||||
for (const size of this.sizes) results.push((sum += size) / sizeTotal)
|
||||
return results
|
||||
}
|
||||
// get progress given index of and fractions within a section
|
||||
getProgress(index, fractionInSection, pageFraction = 0) {
|
||||
const { sizes, sizePerLoc, sizePerTimeUnit, sizeTotal } = this
|
||||
const sizeInSection = sizes[index] ?? 0
|
||||
const sizeBefore = sizes.slice(0, index).reduce((a, b) => a + b, 0)
|
||||
const size = sizeBefore + fractionInSection * sizeInSection
|
||||
const nextSize = size + pageFraction * sizeInSection
|
||||
const remainingTotal = sizeTotal - size
|
||||
const remainingSection = (1 - fractionInSection) * sizeInSection
|
||||
return {
|
||||
fraction: nextSize / sizeTotal,
|
||||
section: {
|
||||
current: index,
|
||||
total: sizes.length,
|
||||
},
|
||||
location: {
|
||||
current: Math.floor(size / sizePerLoc),
|
||||
next: Math.floor(nextSize / sizePerLoc),
|
||||
total: Math.ceil(sizeTotal / sizePerLoc),
|
||||
},
|
||||
time: {
|
||||
section: remainingSection / sizePerTimeUnit,
|
||||
total: remainingTotal / sizePerTimeUnit,
|
||||
},
|
||||
}
|
||||
}
|
||||
// the inverse of `getProgress`
|
||||
// get index of and fraction in section based on total fraction
|
||||
getSection(fraction) {
|
||||
if (fraction <= 0) return [0, 0]
|
||||
if (fraction >= 1) return [this.sizes.length - 1, 1]
|
||||
fraction = fraction + Number.EPSILON
|
||||
const { sizeTotal } = this
|
||||
let index = this.sectionFractions.findIndex(x => x > fraction) - 1
|
||||
if (index < 0) return [0, 0]
|
||||
while (!this.sizes[index]) index++
|
||||
const fractionInSection = (fraction - this.sectionFractions[index])
|
||||
/ (this.sizes[index] / sizeTotal)
|
||||
return [index, fractionInSection]
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
// length for context in excerpts
|
||||
const CONTEXT_LENGTH = 50
|
||||
|
||||
const normalizeWhitespace = str => str.replace(/\s+/g, ' ')
|
||||
|
||||
const makeExcerpt = (strs, { startIndex, startOffset, endIndex, endOffset }) => {
|
||||
const start = strs[startIndex]
|
||||
const end = strs[endIndex]
|
||||
const match = start === end
|
||||
? start.slice(startOffset, endOffset)
|
||||
: start.slice(startOffset)
|
||||
+ strs.slice(start + 1, end).join('')
|
||||
+ end.slice(0, endOffset)
|
||||
const trimmedStart = normalizeWhitespace(start.slice(0, startOffset)).trimStart()
|
||||
const trimmedEnd = normalizeWhitespace(end.slice(endOffset)).trimEnd()
|
||||
const ellipsisPre = trimmedStart.length < CONTEXT_LENGTH ? '' : '…'
|
||||
const ellipsisPost = trimmedEnd.length < CONTEXT_LENGTH ? '' : '…'
|
||||
const pre = `${ellipsisPre}${trimmedStart.slice(-CONTEXT_LENGTH)}`
|
||||
const post = `${trimmedEnd.slice(0, CONTEXT_LENGTH)}${ellipsisPost}`
|
||||
return { pre, match, post }
|
||||
}
|
||||
|
||||
const simpleSearch = function* (strs, query, options = {}) {
|
||||
const { locales = 'en', sensitivity } = options
|
||||
const matchCase = sensitivity === 'variant'
|
||||
const haystack = strs.join('')
|
||||
const lowerHaystack = matchCase ? haystack : haystack.toLocaleLowerCase(locales)
|
||||
const needle = matchCase ? query : query.toLocaleLowerCase(locales)
|
||||
const needleLength = needle.length
|
||||
let index = -1
|
||||
let strIndex = -1
|
||||
let sum = 0
|
||||
do {
|
||||
index = lowerHaystack.indexOf(needle, index + 1)
|
||||
if (index > -1) {
|
||||
while (sum <= index) sum += strs[++strIndex].length
|
||||
const startIndex = strIndex
|
||||
const startOffset = index - (sum - strs[strIndex].length)
|
||||
const end = index + needleLength
|
||||
while (sum <= end) sum += strs[++strIndex].length
|
||||
const endIndex = strIndex
|
||||
const endOffset = end - (sum - strs[strIndex].length)
|
||||
const range = { startIndex, startOffset, endIndex, endOffset }
|
||||
yield { range, excerpt: makeExcerpt(strs, range) }
|
||||
}
|
||||
} while (index > -1)
|
||||
}
|
||||
|
||||
const segmenterSearch = function* (strs, query, options = {}) {
|
||||
const { locales = 'en', granularity = 'word', sensitivity = 'base' } = options
|
||||
let segmenter, collator
|
||||
try {
|
||||
segmenter = new Intl.Segmenter(locales, { usage: 'search', granularity })
|
||||
collator = new Intl.Collator(locales, { sensitivity })
|
||||
} catch (e) {
|
||||
console.warn(e)
|
||||
segmenter = new Intl.Segmenter('en', { usage: 'search', granularity })
|
||||
collator = new Intl.Collator('en', { sensitivity })
|
||||
}
|
||||
const queryLength = Array.from(segmenter.segment(query)).length
|
||||
|
||||
const substrArr = []
|
||||
let strIndex = 0
|
||||
let segments = segmenter.segment(strs[strIndex])[Symbol.iterator]()
|
||||
main: while (strIndex < strs.length) {
|
||||
while (substrArr.length < queryLength) {
|
||||
const { done, value } = segments.next()
|
||||
if (done) {
|
||||
// the current string is exhausted
|
||||
// move on to the next string
|
||||
strIndex++
|
||||
if (strIndex < strs.length) {
|
||||
segments = segmenter.segment(strs[strIndex])[Symbol.iterator]()
|
||||
continue
|
||||
} else break main
|
||||
}
|
||||
const { index, segment } = value
|
||||
// ignore formatting characters
|
||||
if (!/[^\p{Format}]/u.test(segment)) continue
|
||||
// normalize whitespace
|
||||
if (/\s/u.test(segment)) {
|
||||
if (!/\s/u.test(substrArr[substrArr.length - 1]?.segment))
|
||||
substrArr.push({ strIndex, index, segment: ' ' })
|
||||
continue
|
||||
}
|
||||
value.strIndex = strIndex
|
||||
substrArr.push(value)
|
||||
}
|
||||
const substr = substrArr.map(x => x.segment).join('')
|
||||
if (collator.compare(query, substr) === 0) {
|
||||
const endIndex = strIndex
|
||||
const lastSeg = substrArr[substrArr.length - 1]
|
||||
const endOffset = lastSeg.index + lastSeg.segment.length
|
||||
const startIndex = substrArr[0].strIndex
|
||||
const startOffset = substrArr[0].index
|
||||
const range = { startIndex, startOffset, endIndex, endOffset }
|
||||
yield { range, excerpt: makeExcerpt(strs, range) }
|
||||
}
|
||||
substrArr.shift()
|
||||
}
|
||||
}
|
||||
|
||||
export const search = (strs, query, options) => {
|
||||
const { granularity = 'grapheme', sensitivity = 'base' } = options
|
||||
if (!Intl?.Segmenter || granularity === 'grapheme'
|
||||
&& (sensitivity === 'variant' || sensitivity === 'accent'))
|
||||
return simpleSearch(strs, query, options)
|
||||
return segmenterSearch(strs, query, options)
|
||||
}
|
||||
|
||||
export const searchMatcher = (textWalker, opts) => {
|
||||
const { defalutLocale, matchCase, matchDiacritics, matchWholeWords } = opts
|
||||
return function* (doc, query) {
|
||||
const iter = textWalker(doc, function* (strs, makeRange) {
|
||||
for (const result of search(strs, query, {
|
||||
locales: doc.body.lang || doc.documentElement.lang || defalutLocale || 'en',
|
||||
granularity: matchWholeWords ? 'word' : 'grapheme',
|
||||
sensitivity: matchDiacritics && matchCase ? 'variant'
|
||||
: matchDiacritics && !matchCase ? 'accent'
|
||||
: !matchDiacritics && matchCase ? 'case'
|
||||
: 'base',
|
||||
})) {
|
||||
const { startIndex, startOffset, endIndex, endOffset } = result.range
|
||||
result.range = makeRange(startIndex, startOffset, endIndex, endOffset)
|
||||
yield result
|
||||
}
|
||||
})
|
||||
for (const result of iter) yield result
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
const walkRange = (range, walker) => {
|
||||
const nodes = []
|
||||
for (let node = walker.currentNode; node; node = walker.nextNode()) {
|
||||
const compare = range.comparePoint(node, 0)
|
||||
if (compare === 0) nodes.push(node)
|
||||
else if (compare > 0) break
|
||||
}
|
||||
return nodes
|
||||
}
|
||||
|
||||
const walkDocument = (_, walker) => {
|
||||
const nodes = []
|
||||
for (let node = walker.nextNode(); node; node = walker.nextNode())
|
||||
nodes.push(node)
|
||||
return nodes
|
||||
}
|
||||
|
||||
const filter = NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT
|
||||
| NodeFilter.SHOW_CDATA_SECTION
|
||||
|
||||
const acceptNode = node => {
|
||||
if (node.nodeType === 1) {
|
||||
const name = node.tagName.toLowerCase()
|
||||
if (name === 'script' || name === 'style') return NodeFilter.FILTER_REJECT
|
||||
|
||||
// Skip translation elements to preserve CFI calculations
|
||||
if (node.classList && node.classList.contains('translated-text')) {
|
||||
return NodeFilter.FILTER_REJECT
|
||||
}
|
||||
|
||||
return NodeFilter.FILTER_SKIP
|
||||
}
|
||||
return NodeFilter.FILTER_ACCEPT
|
||||
}
|
||||
|
||||
export const textWalker = function* (x, func) {
|
||||
const root = x.commonAncestorContainer ?? x.body ?? x
|
||||
const walker = document.createTreeWalker(root, filter, { acceptNode })
|
||||
const walk = x.commonAncestorContainer ? walkRange : walkDocument
|
||||
const nodes = walk(x, walker)
|
||||
const strs = nodes.map(node => node.nodeValue)
|
||||
const makeRange = (startIndex, startOffset, endIndex, endOffset) => {
|
||||
const range = document.createRange()
|
||||
range.setStart(nodes[startIndex], startOffset)
|
||||
range.setEnd(nodes[endIndex], endOffset)
|
||||
return range
|
||||
}
|
||||
for (const match of func(strs, makeRange)) yield match
|
||||
}
|
||||
@@ -1,359 +0,0 @@
|
||||
// Translation modes
|
||||
export const TranslationMode = {
|
||||
OFF: 'off',
|
||||
TRANSLATION_ONLY: 'translation-only',
|
||||
ORIGINAL_ONLY: 'original-only',
|
||||
BILINGUAL: 'bilingual'
|
||||
}
|
||||
|
||||
// Make TranslationMode globally available for debugging
|
||||
if (typeof window !== 'undefined') {
|
||||
window.TranslationMode = TranslationMode
|
||||
}
|
||||
|
||||
// Translation function that calls Flutter's translation service
|
||||
const translate = async (text) => {
|
||||
try {
|
||||
// Call Flutter's translation handler
|
||||
const result = await window.flutter_inappwebview.callHandler('translateText', text)
|
||||
return result || `Translation failed: ${text}`
|
||||
} catch (error) {
|
||||
console.error('Translation failed:', error)
|
||||
return `Translation error: ${text}`
|
||||
}
|
||||
}
|
||||
|
||||
export class Translator {
|
||||
#translationMode = TranslationMode.OFF
|
||||
observedElements = new Set()
|
||||
#translatedElements = new WeakMap()
|
||||
#observer = null
|
||||
|
||||
constructor() {
|
||||
this.#initializeObserver()
|
||||
}
|
||||
|
||||
#initializeObserver() {
|
||||
this.#observer = new IntersectionObserver(
|
||||
(entries) => {
|
||||
// console.log(`IntersectionObserver triggered with ${entries.length} entries`)
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
// console.log('Element intersecting, translating:', entry.target.tagName, entry.target.textContent?.substring(0, 30))
|
||||
this.#translateElement(entry.target).catch(error =>
|
||||
console.warn('Translation failed in observer:', error)
|
||||
)
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
rootMargin: '1280px',
|
||||
threshold: 0
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
async setTranslationMode(mode) {
|
||||
if (!Object.values(TranslationMode).includes(mode)) {
|
||||
console.warn(`Invalid translation mode: ${mode}`)
|
||||
return
|
||||
}
|
||||
|
||||
const oldMode = this.#translationMode
|
||||
this.#translationMode = mode
|
||||
|
||||
if (oldMode !== mode) {
|
||||
// console.log(`Translation mode changed from ${oldMode} to ${mode}`)
|
||||
|
||||
if (mode === TranslationMode.OFF) {
|
||||
// Turn off translation
|
||||
this.#updateTranslationDisplay()
|
||||
} else if (oldMode === TranslationMode.OFF) {
|
||||
// Turn on translation - force translate visible elements and wait for completion
|
||||
await this.#forceTranslateVisibleElements()
|
||||
} else {
|
||||
// Just update display mode
|
||||
this.#updateTranslationDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
// Re-render annotations after translation mode change (and after translation completion)
|
||||
if (window.reader && window.reader.annotationsByValue) {
|
||||
const existingAnnotations = Array.from(window.reader.annotationsByValue.values())
|
||||
if (existingAnnotations.length > 0) {
|
||||
// console.log('Re-rendering annotations after translation mode change:', existingAnnotations.length)
|
||||
window.renderAnnotations(existingAnnotations)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getTranslationMode() {
|
||||
return this.#translationMode
|
||||
}
|
||||
|
||||
observeDocument(doc) {
|
||||
// console.log('Observing document for translation, doc:', doc)
|
||||
if (!doc) {
|
||||
console.warn('No document provided to observeDocument')
|
||||
return
|
||||
}
|
||||
|
||||
const textElements = this.#walkTextNodes(doc.body || doc.documentElement)
|
||||
// console.log(`Found ${textElements.length} text elements to observe`)
|
||||
|
||||
textElements.forEach(element => {
|
||||
if (!this.observedElements.has(element)) {
|
||||
this.#observer.observe(element)
|
||||
this.observedElements.add(element)
|
||||
// console.log('Added element to observer:', element.tagName, element.textContent?.substring(0, 50))
|
||||
}
|
||||
})
|
||||
|
||||
// console.log(`Total observed elements: ${this.observedElements.size}`)
|
||||
}
|
||||
|
||||
clearTranslations() {
|
||||
// Remove all translation elements and restore original content
|
||||
this.observedElements.forEach(element => {
|
||||
const translationElements = element.querySelectorAll('.translated-text')
|
||||
translationElements.forEach(trans => trans.remove())
|
||||
|
||||
// Restore original text if hidden
|
||||
this.#restoreOriginalText(element)
|
||||
})
|
||||
|
||||
// Clear observer
|
||||
this.#observer.disconnect()
|
||||
this.observedElements.clear()
|
||||
this.#translatedElements = new WeakMap()
|
||||
|
||||
// Reinitialize observer
|
||||
this.#initializeObserver()
|
||||
}
|
||||
|
||||
#walkTextNodes(root, rejectTags = ['pre', 'code', 'math', 'style', 'script']) {
|
||||
const elements = []
|
||||
|
||||
const walk = (node, depth = 0) => {
|
||||
if (depth > 15) return
|
||||
|
||||
const children = Array.from(node.children || [])
|
||||
for (const child of children) {
|
||||
if (rejectTags.includes(child.tagName.toLowerCase())) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip translation elements
|
||||
if (child.classList.contains('translated-text')) {
|
||||
continue
|
||||
}
|
||||
|
||||
const hasDirectText = Array.from(child.childNodes).some(node => {
|
||||
if (node.nodeType === Node.TEXT_NODE && node.textContent?.trim()) {
|
||||
return true
|
||||
}
|
||||
if (node.nodeType === Node.ELEMENT_NODE && node.tagName === 'SPAN') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
if (child.children.length === 0 && child.textContent?.trim()) {
|
||||
elements.push(child)
|
||||
} else if (hasDirectText) {
|
||||
elements.push(child)
|
||||
} else if (child.children.length > 0) {
|
||||
walk(child, depth + 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
walk(root)
|
||||
return elements
|
||||
}
|
||||
|
||||
async #translateElement(element) {
|
||||
if (this.#translationMode === TranslationMode.OFF) return
|
||||
if (this.#translatedElements.has(element)) return
|
||||
|
||||
const text = element.innerText?.trim()
|
||||
if (!text) return
|
||||
|
||||
try {
|
||||
const translatedText = await translate(text)
|
||||
|
||||
// Mark as translated to prevent re-processing
|
||||
this.#translatedElements.set(element, {
|
||||
originalText: text,
|
||||
translatedText: translatedText
|
||||
})
|
||||
|
||||
this.#applyTranslation(element, translatedText)
|
||||
} catch (error) {
|
||||
console.warn('Translation failed:', error)
|
||||
}
|
||||
}
|
||||
|
||||
#applyTranslation(element, translatedText) {
|
||||
// Remove existing translation if any
|
||||
const existingTranslation = element.querySelector('.translated-text')
|
||||
if (existingTranslation) {
|
||||
existingTranslation.remove()
|
||||
}
|
||||
|
||||
// Create translation wrapper
|
||||
const wrapper = document.createElement('span')
|
||||
wrapper.className = 'translated-text'
|
||||
wrapper.setAttribute('data-translation-mark', '1')
|
||||
wrapper.style.display = 'block'
|
||||
// wrapper.style.fontSize = '0.9em'
|
||||
// wrapper.style.color = '#666'
|
||||
// wrapper.style.fontStyle = 'italic'
|
||||
wrapper.style.marginTop = '0.2em'
|
||||
wrapper.textContent = translatedText
|
||||
|
||||
// Apply based on current mode
|
||||
this.#updateElementDisplay(element, wrapper)
|
||||
|
||||
element.appendChild(wrapper)
|
||||
}
|
||||
|
||||
#updateElementDisplay(element, translationWrapper) {
|
||||
const data = this.#translatedElements.get(element)
|
||||
if (!data) return
|
||||
|
||||
switch (this.#translationMode) {
|
||||
case TranslationMode.TRANSLATION_ONLY:
|
||||
this.#hideOriginalText(element)
|
||||
translationWrapper.style.display = 'block'
|
||||
break
|
||||
|
||||
case TranslationMode.ORIGINAL_ONLY:
|
||||
this.#restoreOriginalText(element)
|
||||
translationWrapper.style.display = 'none'
|
||||
break
|
||||
|
||||
case TranslationMode.BILINGUAL:
|
||||
this.#restoreOriginalText(element)
|
||||
translationWrapper.style.display = 'block'
|
||||
break
|
||||
|
||||
case TranslationMode.OFF:
|
||||
default:
|
||||
this.#restoreOriginalText(element)
|
||||
translationWrapper.style.display = 'none'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
#hideOriginalText(element) {
|
||||
// Use CSS to hide original content instead of removing DOM nodes
|
||||
if (!element.hasAttribute('data-original-visibility')) {
|
||||
element.setAttribute('data-original-visibility', 'hidden')
|
||||
|
||||
// Hide all child nodes except translation elements using CSS
|
||||
Array.from(element.childNodes).forEach(node => {
|
||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
const el = node
|
||||
if (!el.classList || !el.classList.contains('translated-text')) {
|
||||
// Store and hide using CSS
|
||||
if (!el.hasAttribute('data-original-display')) {
|
||||
el.setAttribute('data-original-display', el.style.display || 'initial')
|
||||
el.style.display = 'none'
|
||||
}
|
||||
}
|
||||
} else if (node.nodeType === Node.TEXT_NODE) {
|
||||
// For text nodes, store content and make invisible
|
||||
if (!node.__originalContent) {
|
||||
node.__originalContent = node.textContent
|
||||
node.textContent = ''
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Mark element as having hidden text
|
||||
element.classList.add('translation-source-hidden')
|
||||
}
|
||||
|
||||
#restoreOriginalText(element) {
|
||||
// Restore visibility by reversing the hide operations
|
||||
if (element.hasAttribute('data-original-visibility')) {
|
||||
// Restore all child nodes
|
||||
Array.from(element.childNodes).forEach(node => {
|
||||
if (node.nodeType === Node.ELEMENT_NODE) {
|
||||
const el = node
|
||||
if (!el.classList || !el.classList.contains('translated-text')) {
|
||||
// Restore original display
|
||||
if (el.hasAttribute('data-original-display')) {
|
||||
const originalDisplay = el.getAttribute('data-original-display')
|
||||
el.style.display = originalDisplay === 'initial' ? '' : originalDisplay
|
||||
el.removeAttribute('data-original-display')
|
||||
}
|
||||
}
|
||||
} else if (node.nodeType === Node.TEXT_NODE) {
|
||||
// Restore text content
|
||||
if (node.__originalContent !== undefined) {
|
||||
node.textContent = node.__originalContent
|
||||
delete node.__originalContent
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
element.removeAttribute('data-original-visibility')
|
||||
}
|
||||
|
||||
element.classList.remove('translation-source-hidden')
|
||||
}
|
||||
|
||||
async #forceTranslateVisibleElements() {
|
||||
// console.log('Force translating visible elements')
|
||||
|
||||
const translationPromises = []
|
||||
|
||||
// Find elements in viewport and translate them immediately
|
||||
this.observedElements.forEach(element => {
|
||||
const rect = element.getBoundingClientRect()
|
||||
const isVisible = rect.top < window.innerHeight && rect.bottom > 0
|
||||
|
||||
if (isVisible && !this.#translatedElements.has(element)) {
|
||||
// console.log('Force translating visible element:', element)
|
||||
const translationPromise = this.#translateElement(element).catch(error => {
|
||||
console.warn('Force translation failed:', error)
|
||||
})
|
||||
translationPromises.push(translationPromise)
|
||||
} else if (isVisible && this.#translatedElements.has(element)) {
|
||||
// Element already translated, just update display
|
||||
const translationWrapper = element.querySelector('.translated-text')
|
||||
if (translationWrapper) {
|
||||
this.#updateElementDisplay(element, translationWrapper)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Wait for all visible translations to complete
|
||||
if (translationPromises.length > 0) {
|
||||
// console.log(`Waiting for ${translationPromises.length} translations to complete`)
|
||||
await Promise.allSettled(translationPromises)
|
||||
// console.log('All visible translations completed')
|
||||
}
|
||||
}
|
||||
|
||||
#updateTranslationDisplay() {
|
||||
// console.log('Updating translation display for mode:', this.#translationMode, 'Elements:', this.observedElements.size)
|
||||
this.observedElements.forEach(element => {
|
||||
const translationWrapper = element.querySelector('.translated-text')
|
||||
if (translationWrapper) {
|
||||
// console.log('Updating display for element with translation:', element)
|
||||
this.#updateElementDisplay(element, translationWrapper)
|
||||
} else {
|
||||
// console.log('No translation wrapper found for element:', element)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.clearTranslations()
|
||||
this.#observer = null
|
||||
}
|
||||
}
|
||||
@@ -1,368 +0,0 @@
|
||||
const blockTags = new Set([
|
||||
'article', 'aside', 'audio', 'blockquote', 'caption',
|
||||
'details', 'dialog', 'div', 'dl', 'dt', 'dd',
|
||||
'figure', 'footer', 'form', 'figcaption',
|
||||
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr', 'li',
|
||||
'main', 'math', 'nav', 'ol', 'p', 'pre', 'section', 'tr',
|
||||
])
|
||||
|
||||
function rangeIsEmpty(range) {
|
||||
return range.collapsed || range.toString().trim() === ''
|
||||
}
|
||||
|
||||
const quoteChars = new Set(['"', "'", '“', '”', '‘', '’'])
|
||||
|
||||
const isLocalLink = href => {
|
||||
if (!href) return false
|
||||
const trimmed = href.trim()
|
||||
if (!trimmed) return false
|
||||
if (trimmed.startsWith('#')) return true
|
||||
return !/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed)
|
||||
}
|
||||
|
||||
const shouldSkipTextNode = node => {
|
||||
const parent = node.parentElement
|
||||
if (!parent) return false
|
||||
const anchor = parent.closest('a')
|
||||
if (!anchor) return false
|
||||
return isLocalLink(anchor.getAttribute('href'))
|
||||
}
|
||||
|
||||
const getRangeText = range => {
|
||||
const fragment = range.cloneContents()
|
||||
const walker = document.createTreeWalker(fragment, NodeFilter.SHOW_TEXT)
|
||||
let text = ''
|
||||
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
||||
if (shouldSkipTextNode(node)) continue
|
||||
text += node.textContent ?? ''
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
const findBlockAncestor = node => {
|
||||
let el = node.parentElement
|
||||
while (el && !blockTags.has(el.tagName?.toLowerCase?.())) {
|
||||
el = el.parentElement
|
||||
}
|
||||
return el ?? node.ownerDocument?.body ?? null
|
||||
}
|
||||
|
||||
const isSentenceTerminator = (char, nextChar) => {
|
||||
if (char === '.') {
|
||||
if (!nextChar) return true
|
||||
if (quoteChars.has(nextChar)) return true
|
||||
if (/\s/.test(nextChar)) return true
|
||||
return false
|
||||
}
|
||||
return char === '!' || char === '?' || char === '。' || char === '!' || char === '?'
|
||||
}
|
||||
|
||||
const advancePastQuotes = (text, index) => {
|
||||
let end = index
|
||||
while (end < text.length && quoteChars.has(text[end])) end++
|
||||
return end
|
||||
}
|
||||
|
||||
function* getBlocks(doc) {
|
||||
const walker = doc.createTreeWalker(doc.body, NodeFilter.SHOW_TEXT)
|
||||
let startNode = null
|
||||
let startOffset = 0
|
||||
let currentBlock = null
|
||||
let lastNode = null
|
||||
let lastOffset = 0
|
||||
|
||||
const flushRange = () => {
|
||||
if (!startNode || !lastNode) return null
|
||||
const range = doc.createRange()
|
||||
range.setStart(startNode, startOffset)
|
||||
range.setEnd(lastNode, lastOffset)
|
||||
startNode = null
|
||||
startOffset = 0
|
||||
currentBlock = null
|
||||
lastNode = null
|
||||
lastOffset = 0
|
||||
if (rangeIsEmpty(range)) return null
|
||||
return range
|
||||
}
|
||||
|
||||
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
||||
if (!node.textContent) continue
|
||||
if (shouldSkipTextNode(node)) continue
|
||||
|
||||
const block = findBlockAncestor(node)
|
||||
|
||||
if (!startNode) {
|
||||
startNode = node
|
||||
startOffset = 0
|
||||
currentBlock = block
|
||||
} else if (block !== currentBlock) {
|
||||
const range = flushRange()
|
||||
if (range) yield range
|
||||
startNode = node
|
||||
startOffset = 0
|
||||
currentBlock = block
|
||||
}
|
||||
|
||||
const text = node.textContent
|
||||
let index = 0
|
||||
while (index < text.length) {
|
||||
const char = text[index]
|
||||
const nextChar = text[index + 1]
|
||||
if (isSentenceTerminator(char, nextChar)) {
|
||||
const endOffset = advancePastQuotes(text, index + 1)
|
||||
const range = doc.createRange()
|
||||
range.setStart(startNode, startOffset)
|
||||
range.setEnd(node, endOffset)
|
||||
if (!rangeIsEmpty(range)) yield range
|
||||
startNode = node
|
||||
startOffset = endOffset
|
||||
lastNode = node
|
||||
lastOffset = endOffset
|
||||
index = endOffset
|
||||
continue
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
|
||||
lastNode = node
|
||||
lastOffset = text.length
|
||||
|
||||
if (startNode === node && startOffset === text.length) {
|
||||
startNode = null
|
||||
startOffset = 0
|
||||
currentBlock = null
|
||||
}
|
||||
}
|
||||
|
||||
const remaining = flushRange()
|
||||
if (remaining) yield remaining
|
||||
}
|
||||
|
||||
class ListIterator {
|
||||
#arr = []
|
||||
#iter
|
||||
#index = -1
|
||||
#f
|
||||
constructor(iter, f = x => x) {
|
||||
this.#iter = iter
|
||||
this.#f = f
|
||||
}
|
||||
current() {
|
||||
if (this.#arr[this.#index]) return this.#f(this.#arr[this.#index])
|
||||
}
|
||||
first() {
|
||||
const newIndex = 0
|
||||
if (this.#arr[newIndex]) {
|
||||
this.#index = newIndex
|
||||
return this.#f(this.#arr[newIndex])
|
||||
}
|
||||
}
|
||||
last() {
|
||||
for (const value of this.#iter) this.#arr.push(value)
|
||||
const newIndex = this.#arr.length - 1
|
||||
if (this.#arr[newIndex]) {
|
||||
this.#index = newIndex
|
||||
return this.#f(this.#arr[newIndex])
|
||||
}
|
||||
}
|
||||
prev() {
|
||||
const newIndex = this.#index - 1
|
||||
if (this.#arr[newIndex]) {
|
||||
this.#index = newIndex
|
||||
return this.#f(this.#arr[newIndex])
|
||||
}
|
||||
}
|
||||
next() {
|
||||
const newIndex = this.#index + 1
|
||||
if (this.#arr[newIndex]) {
|
||||
this.#index = newIndex
|
||||
return this.#f(this.#arr[newIndex])
|
||||
}
|
||||
while (true) {
|
||||
const { done, value } = this.#iter.next()
|
||||
if (done) break
|
||||
this.#arr.push(value)
|
||||
if (this.#arr[newIndex]) {
|
||||
this.#index = newIndex
|
||||
return this.#f(this.#arr[newIndex])
|
||||
}
|
||||
}
|
||||
}
|
||||
#ensure(index) {
|
||||
while (this.#arr[index] == null) {
|
||||
const { done, value } = this.#iter.next()
|
||||
if (done) break
|
||||
this.#arr.push(value)
|
||||
if (this.#arr.length - 1 >= index) break
|
||||
}
|
||||
return this.#arr[index]
|
||||
}
|
||||
prepare() {
|
||||
const newIndex = this.#index + 1
|
||||
if (this.#arr[newIndex]) return this.#f(this.#arr[newIndex])
|
||||
while (true) {
|
||||
const { done, value } = this.#iter.next()
|
||||
if (done) break
|
||||
this.#arr.push(value)
|
||||
if (this.#arr[newIndex]) return this.#f(this.#arr[newIndex])
|
||||
}
|
||||
}
|
||||
peek(count = 1, offset = 1) {
|
||||
if (count <= 0) return []
|
||||
const startIndex = Math.max(this.#index + offset, 0)
|
||||
const results = []
|
||||
const endIndex = startIndex + count
|
||||
for (let idx = startIndex; idx < endIndex; idx++) {
|
||||
const value = this.#arr[idx] ?? this.#ensure(idx)
|
||||
if (!value) break
|
||||
results.push(this.#f(value))
|
||||
}
|
||||
return results
|
||||
}
|
||||
find(f) {
|
||||
const index = this.#arr.findIndex(x => f(x))
|
||||
if (index > -1) {
|
||||
this.#index = index
|
||||
return this.#f(this.#arr[index])
|
||||
}
|
||||
while (true) {
|
||||
const { done, value } = this.#iter.next()
|
||||
if (done) break
|
||||
this.#arr.push(value)
|
||||
if (f(value)) {
|
||||
this.#index = this.#arr.length - 1
|
||||
return this.#f(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class TTS {
|
||||
#list
|
||||
#lastMark
|
||||
#getCfi
|
||||
constructor(doc, textWalker, highlight, getCfi) {
|
||||
this.doc = doc
|
||||
this.highlight = highlight
|
||||
this.#getCfi = getCfi
|
||||
this.#list = new ListIterator(getBlocks(doc), range => {
|
||||
return [getRangeText(range), range]
|
||||
})
|
||||
}
|
||||
|
||||
#getText(text, getNode) {
|
||||
if (!text) return ''
|
||||
if (!getNode) return text
|
||||
const tempElement = document.createElement('div')
|
||||
tempElement.innerHTML = text
|
||||
let node = getNode(tempElement)?.previousSibling
|
||||
while (node) {
|
||||
const next = node.previousSibling ?? node.parentNode?.previousSibling
|
||||
node.parentNode.removeChild(node)
|
||||
node = next
|
||||
}
|
||||
return tempElement.textContent
|
||||
}
|
||||
|
||||
#ensureCurrentEntry() {
|
||||
const current = this.#list.current()
|
||||
if (current) return current
|
||||
return this.#list.first() ?? this.#list.next()
|
||||
}
|
||||
|
||||
#resultFrom(entry, { highlight = false } = {}) {
|
||||
if (!entry) return null
|
||||
const [text, range] = entry
|
||||
if (!text || !range) return null
|
||||
const plainText = this.#getText(text)
|
||||
let cfi = null
|
||||
if (highlight && this.highlight && range.cloneRange) {
|
||||
cfi = this.highlight(range.cloneRange()) ?? null
|
||||
}
|
||||
if (!cfi && this.#getCfi && range.cloneRange) {
|
||||
cfi = this.#getCfi(range.cloneRange())
|
||||
}
|
||||
return { text: plainText, cfi }
|
||||
}
|
||||
|
||||
start() {
|
||||
this.#lastMark = null
|
||||
const entry = this.#list.first()
|
||||
if (!entry) return this.next()
|
||||
return this.#resultFrom(entry, { highlight: true })?.text
|
||||
}
|
||||
|
||||
end() {
|
||||
this.#lastMark = null
|
||||
const entry = this.#list.last()
|
||||
if (!entry) return this.next()
|
||||
return this.#resultFrom(entry, { highlight: true })?.text
|
||||
}
|
||||
|
||||
resume() {
|
||||
const entry = this.#list.current()
|
||||
if (!entry) return this.next()
|
||||
return this.#resultFrom(entry)?.text
|
||||
}
|
||||
|
||||
prev(paused) {
|
||||
this.#lastMark = null
|
||||
const entry = this.#list.prev()
|
||||
if (paused && entry?.[1]) this.highlight(entry[1].cloneRange())
|
||||
return this.#resultFrom(entry)?.text
|
||||
}
|
||||
|
||||
next(paused) {
|
||||
this.#lastMark = null
|
||||
const entry = this.#list.next()
|
||||
if (paused && entry?.[1]) this.highlight(entry[1].cloneRange())
|
||||
return this.#resultFrom(entry)?.text
|
||||
}
|
||||
|
||||
// get next text without moving the iterator
|
||||
prepare() {
|
||||
const entry = this.#list.prepare()
|
||||
return this.#resultFrom(entry)?.text
|
||||
}
|
||||
|
||||
from(range) {
|
||||
this.#lastMark = null
|
||||
const entry = this.#list.find(range_ =>
|
||||
range.compareBoundaryPoints(Range.END_TO_START, range_) <= 0)
|
||||
if (entry?.[1]) this.highlight(entry[1].cloneRange())
|
||||
return this.#resultFrom(entry)?.text
|
||||
}
|
||||
|
||||
currentDetail() {
|
||||
const entry = this.#ensureCurrentEntry()
|
||||
return this.#resultFrom(entry)
|
||||
}
|
||||
|
||||
collectDetails(count = 1, { includeCurrent = false, offset = 1 } = {}) {
|
||||
if (!Number.isFinite(count) || count <= 0) return []
|
||||
const details = []
|
||||
if (includeCurrent) {
|
||||
const entry = this.#ensureCurrentEntry()
|
||||
const detail = this.#resultFrom(entry)
|
||||
if (detail) details.push(detail)
|
||||
}
|
||||
const needed = count - details.length
|
||||
if (needed <= 0) return details
|
||||
const entries = this.#list.peek(needed, offset)
|
||||
for (const entry of entries) {
|
||||
const detail = this.#resultFrom(entry)
|
||||
if (detail) details.push(detail)
|
||||
}
|
||||
return details
|
||||
}
|
||||
|
||||
highlightCfi(cfi) {
|
||||
if (!cfi) return null
|
||||
const entry = this.#list.find(range => {
|
||||
const candidate = this.#getCfi?.(range.cloneRange?.())
|
||||
return candidate === cfi
|
||||
})
|
||||
if (!entry) return null
|
||||
return this.#resultFrom(entry, { highlight: true })
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// URI Template: https://datatracker.ietf.org/doc/html/rfc6570
|
||||
|
||||
const regex = /{([+#./;?&])?([^}]+?)}/g
|
||||
const varspecRegex = /(.+?)(\*|:[1-9]\d{0,3})?$/
|
||||
|
||||
const table = {
|
||||
undefined: { first: '', sep: ',' },
|
||||
'+': { first: '', sep: ',', allowReserved: true },
|
||||
'.': { first: '.', sep: '.' },
|
||||
'/': { first: '/', sep: '/' },
|
||||
';': { first: ';', sep: ';', named: true, ifemp: '' },
|
||||
'?': { first: '?', sep: '&', named: true, ifemp: '=' },
|
||||
'&': { first: '&', sep: '&', named: true, ifemp: '=' },
|
||||
'#': { first: '&', sep: '&', allowReserved: true },
|
||||
}
|
||||
|
||||
// 2.4.1 Prefix Values, "Note that this numbering is in characters, not octets"
|
||||
const prefix = (maxLength, str) => {
|
||||
let result = ''
|
||||
for (const char of str) {
|
||||
const newResult = char
|
||||
if (newResult.length > maxLength) return result
|
||||
else result = newResult
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const replace = (str, map) => str.replace(regex, (_, operator, variableList) => {
|
||||
const { first, sep, named, ifemp, allowReserved } = table[operator]
|
||||
// TODO: this isn't spec compliant
|
||||
const encode = allowReserved ? encodeURI : encodeURIComponent
|
||||
const values = variableList.split(',').map(varspec => {
|
||||
const match = varspec.match(varspecRegex)
|
||||
if (!match) return
|
||||
const [, name, modifier] = match
|
||||
let value = map.get(name)
|
||||
if (modifier?.startsWith(':')) {
|
||||
const maxLength = parseInt(modifier.slice(1))
|
||||
value = prefix(maxLength, value)
|
||||
}
|
||||
return [name, value ? encode(value) : null]
|
||||
})
|
||||
if (!values.filter(([, value]) => value).length) return ''
|
||||
return first + values
|
||||
.map(([name, value]) => value
|
||||
? (named ? name + (value ? '=' + value : ifemp) : value) : '')
|
||||
.filter(x => x).join(sep)
|
||||
})
|
||||
|
||||
export const getVariables = str => new Set(Array.from(str.matchAll(regex),
|
||||
([,, variableList]) => variableList.split(',')
|
||||
.map(varspec => varspec.match(varspecRegex)?.[1])).flat())
|
||||
1
assets/foliate-js/src/vendor/fflate.js
vendored
1
assets/foliate-js/src/vendor/fflate.js
vendored
@@ -1 +0,0 @@
|
||||
var r=Uint8Array,e=Uint16Array,a=Uint32Array,n=new r([0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0]),t=new r([0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0]),i=new r([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),f=function(r,n){for(var t=new e(31),i=0;i<31;++i)t[i]=n+=1<<r[i-1];var f=new a(t[30]);for(i=1;i<30;++i)for(var o=t[i];o<t[i+1];++o)f[o]=o-t[i]<<5|i;return[t,f]},o=f(n,2),v=o[0],l=o[1];v[28]=258,l[258]=28;for(var u=f(t,0)[0],c=new e(32768),d=0;d<32768;++d){var s=(43690&d)>>>1|(21845&d)<<1;s=(61680&(s=(52428&s)>>>2|(13107&s)<<2))>>>4|(3855&s)<<4,c[d]=((65280&s)>>>8|(255&s)<<8)>>>1}var w=function(r,a,n){for(var t=r.length,i=0,f=new e(a);i<t;++i)r[i]&&++f[r[i]-1];var o,v=new e(a);for(i=0;i<a;++i)v[i]=v[i-1]+f[i-1]<<1;if(n){o=new e(1<<a);var l=15-a;for(i=0;i<t;++i)if(r[i])for(var u=i<<4|r[i],d=a-r[i],s=v[r[i]-1]++<<d,w=s|(1<<d)-1;s<=w;++s)o[c[s]>>>l]=u}else for(o=new e(t),i=0;i<t;++i)r[i]&&(o[i]=c[v[r[i]-1]++]>>>15-r[i]);return o},b=new r(288);for(d=0;d<144;++d)b[d]=8;for(d=144;d<256;++d)b[d]=9;for(d=256;d<280;++d)b[d]=7;for(d=280;d<288;++d)b[d]=8;var h=new r(32);for(d=0;d<32;++d)h[d]=5;var E=w(b,9,1),p=w(h,5,1),g=function(r){for(var e=r[0],a=1;a<r.length;++a)r[a]>e&&(e=r[a]);return e},y=function(r,e,a){var n=e/8|0;return(r[n]|r[n+1]<<8)>>(7&e)&a},k=function(r,e){var a=e/8|0;return(r[a]|r[a+1]<<8|r[a+2]<<16)>>(7&e)},T=["unexpected EOF","invalid block type","invalid length/literal","invalid distance","stream finished","no stream handler",,"no callback","invalid UTF-8 data","extra field too long","date not in range 1980-2099","filename too long","stream finishing","invalid zip data"],m=function(r,e,a){var n=new Error(e||T[r]);if(n.code=r,Error.captureStackTrace&&Error.captureStackTrace(n,m),!a)throw n;return n},x=function(f,o,l){var c=f.length;if(!c||l&&l.f&&!l.l)return o||new r(0);var d=!o||l,s=!l||l.i;l||(l={}),o||(o=new r(3*c));var b=function(e){var a=o.length;if(e>a){var n=new r(Math.max(2*a,e));n.set(o),o=n}},h=l.f||0,T=l.p||0,x=l.b||0,S=l.l,U=l.d,_=l.m,z=l.n,A=8*c;do{if(!S){h=y(f,T,1);var M=y(f,T+1,3);if(T+=3,!M){var B=f[(C=4+((T+7)/8|0))-4]|f[C-3]<<8,D=C+B;if(D>c){s&&m(0);break}d&&b(x+B),o.set(f.subarray(C,D),x),l.b=x+=B,l.p=T=8*D,l.f=h;continue}if(1==M)S=E,U=p,_=9,z=5;else if(2==M){var F=y(f,T,31)+257,L=y(f,T+10,15)+4,N=F+y(f,T+5,31)+1;T+=14;for(var P=new r(N),R=new r(19),Y=0;Y<L;++Y)R[i[Y]]=y(f,T+3*Y,7);T+=3*L;var O=g(R),j=(1<<O)-1,q=w(R,O,1);for(Y=0;Y<N;){var C,G=q[y(f,T,j)];if(T+=15&G,(C=G>>>4)<16)P[Y++]=C;else{var H=0,I=0;for(16==C?(I=3+y(f,T,3),T+=2,H=P[Y-1]):17==C?(I=3+y(f,T,7),T+=3):18==C&&(I=11+y(f,T,127),T+=7);I--;)P[Y++]=H}}var J=P.subarray(0,F),K=P.subarray(F);_=g(J),z=g(K),S=w(J,_,1),U=w(K,z,1)}else m(1);if(T>A){s&&m(0);break}}d&&b(x+131072);for(var Q=(1<<_)-1,V=(1<<z)-1,W=T;;W=T){var X=(H=S[k(f,T)&Q])>>>4;if((T+=15&H)>A){s&&m(0);break}if(H||m(2),X<256)o[x++]=X;else{if(256==X){W=T,S=null;break}var Z=X-254;if(X>264){var $=n[Y=X-257];Z=y(f,T,(1<<$)-1)+v[Y],T+=$}var rr=U[k(f,T)&V],er=rr>>>4;rr||m(3),T+=15&rr;K=u[er];if(er>3){$=t[er];K+=k(f,T)&(1<<$)-1,T+=$}if(T>A){s&&m(0);break}d&&b(x+131072);for(var ar=x+Z;x<ar;x+=4)o[x]=o[x-K],o[x+1]=o[x+1-K],o[x+2]=o[x+2-K],o[x+3]=o[x+3-K];x=ar}}l.l=S,l.p=W,l.b=x,l.f=h,S&&(h=1,l.m=_,l.d=U,l.n=z)}while(!h);return x==o.length?o:function(n,t,i){(null==t||t<0)&&(t=0),(null==i||i>n.length)&&(i=n.length);var f=new(2==n.BYTES_PER_ELEMENT?e:4==n.BYTES_PER_ELEMENT?a:r)(i-t);return f.set(n.subarray(t,i)),f}(o,0,x)},S=new r(0);function U(r,e){return x(((8!=(15&(a=r)[0])||a[0]>>>4>7||(a[0]<<8|a[1])%31)&&m(6,"invalid zlib data"),32&a[1]&&m(6,"invalid zlib data: preset dictionaries not supported"),r.subarray(2,-4)),e);var a}var _="undefined"!=typeof TextDecoder&&new TextDecoder;try{_.decode(S,{stream:!0}),1}catch(r){}export{U as unzlibSync};
|
||||
18146
assets/foliate-js/src/vendor/pdfjs/pdf.js
vendored
18146
assets/foliate-js/src/vendor/pdfjs/pdf.js
vendored
File diff suppressed because it is too large
Load Diff
58353
assets/foliate-js/src/vendor/pdfjs/pdf.worker.js
vendored
58353
assets/foliate-js/src/vendor/pdfjs/pdf.worker.js
vendored
File diff suppressed because one or more lines are too long
116
assets/foliate-js/src/vendor/prism/README.md
vendored
116
assets/foliate-js/src/vendor/prism/README.md
vendored
@@ -1,116 +0,0 @@
|
||||
# Prism.js Code Syntax Highlighting
|
||||
|
||||
This directory contains the Prism.js library for code syntax highlighting in Anx Reader.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
prism/
|
||||
├── prism-core.min.js # Core Prism.js library
|
||||
├── prism-autoloader.min.js # Automatic language loading plugin
|
||||
├── components/ # Language definition files (62 languages)
|
||||
│ ├── prism-javascript.min.js
|
||||
│ ├── prism-python.min.js
|
||||
│ ├── prism-java.min.js
|
||||
│ └── ... (62 files total)
|
||||
├── themes/ # CSS themes (12 themes)
|
||||
│ ├── prism-default.min.css
|
||||
│ ├── prism-vs-dark.min.css
|
||||
│ ├── prism-one-dark.min.css
|
||||
│ └── ... (12 files total)
|
||||
└── download_components.sh # Script to download additional languages
|
||||
```
|
||||
|
||||
## Supported Languages (62)
|
||||
|
||||
The following languages are included for offline use:
|
||||
|
||||
### Web Development
|
||||
- JavaScript, TypeScript, JSX, TSX
|
||||
- HTML/XML (markup), CSS, Sass, SCSS, Less
|
||||
- PHP, PHP-Extras
|
||||
- JSON, YAML, TOML
|
||||
- Markdown, LaTeX
|
||||
|
||||
### System & Scripting
|
||||
- Bash, Shell Session, PowerShell, Batch
|
||||
- Python, Ruby, Perl, Lua, R
|
||||
|
||||
### Compiled Languages
|
||||
- C, C++, C#, Objective-C
|
||||
- Java, Kotlin, Scala, Groovy
|
||||
- Go, Rust, Swift, Dart
|
||||
|
||||
### Functional Languages
|
||||
- Haskell, Elixir, Erlang, Julia
|
||||
|
||||
### Database
|
||||
- SQL, PL/SQL, MongoDB
|
||||
|
||||
### Configuration & DevOps
|
||||
- Docker, Git, Diff
|
||||
- Nginx, Makefile
|
||||
- INI, Properties
|
||||
|
||||
### Other
|
||||
- GraphQL, Protobuf
|
||||
- Regex, HTTP
|
||||
- Visual Basic, VB.NET
|
||||
|
||||
## Themes (12)
|
||||
|
||||
### Light Themes (4)
|
||||
1. **Default** - Classic Prism theme
|
||||
2. **GitHub** - GitHub-style highlighting
|
||||
3. **One Light** - Atom One Light theme
|
||||
4. **Material Light** - Material Design light theme
|
||||
|
||||
### Dark Themes (8)
|
||||
1. **VS Dark** - Visual Studio Code dark theme
|
||||
2. **One Dark** - Atom One Dark theme
|
||||
3. **Dracula** - Popular Dracula theme
|
||||
4. **Material Dark** - Material Design dark theme
|
||||
5. **Nord** - Nord color palette
|
||||
6. **Night Owl** - Night Owl theme
|
||||
7. **Solarized Dark** - Solarized dark variant
|
||||
8. **Atom Dark** - Atom editor dark theme
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Automatic Detection**: When a code block is detected, Prism.js automatically identifies the language
|
||||
2. **Local Loading**: The autoloader loads the required language file from `components/` folder
|
||||
3. **Offline Support**: All 62 language files are pre-downloaded for offline use
|
||||
4. **No Network Required**: Everything works without internet connection
|
||||
|
||||
## Adding More Languages
|
||||
|
||||
If you need additional languages not included in the default set:
|
||||
|
||||
1. Visit: https://github.com/PrismJS/prism/tree/master/components
|
||||
2. Download the required `prism-{language}.min.js` file
|
||||
3. Place it in the `components/` folder
|
||||
|
||||
Or use the included download script:
|
||||
|
||||
```bash
|
||||
cd assets/foliate-js/src/vendor/prism
|
||||
./download_components.sh
|
||||
```
|
||||
|
||||
## Version
|
||||
|
||||
Current version: **Prism.js 1.29.0**
|
||||
|
||||
## Total Size
|
||||
|
||||
- Core + Autoloader: ~13 KB
|
||||
- Themes (12 files): ~30 KB
|
||||
- Languages (62 files): ~272 KB
|
||||
- **Total: ~315 KB**
|
||||
|
||||
## References
|
||||
|
||||
- Official Website: https://prismjs.com/
|
||||
- GitHub: https://github.com/PrismJS/prism
|
||||
- Documentation: https://prismjs.com/docs/
|
||||
- Language List: https://prismjs.com/#supported-languages
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
Prism.languages.basic={comment:{pattern:/(?:!|REM\b).+/i,inside:{keyword:/^REM/i}},string:{pattern:/"(?:""|[!#$%&'()*,\/:;<=>?^\w +\-.])*"/,greedy:!0},number:/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:E[+-]?\d+)?/i,keyword:/\b(?:AS|BEEP|BLOAD|BSAVE|CALL(?: ABSOLUTE)?|CASE|CHAIN|CHDIR|CLEAR|CLOSE|CLS|COM|COMMON|CONST|DATA|DECLARE|DEF(?: FN| SEG|DBL|INT|LNG|SNG|STR)|DIM|DO|DOUBLE|ELSE|ELSEIF|END|ENVIRON|ERASE|ERROR|EXIT|FIELD|FILES|FOR|FUNCTION|GET|GOSUB|GOTO|IF|INPUT|INTEGER|IOCTL|KEY|KILL|LINE INPUT|LOCATE|LOCK|LONG|LOOP|LSET|MKDIR|NAME|NEXT|OFF|ON(?: COM| ERROR| KEY| TIMER)?|OPEN|OPTION BASE|OUT|POKE|PUT|READ|REDIM|REM|RESTORE|RESUME|RETURN|RMDIR|RSET|RUN|SELECT CASE|SHARED|SHELL|SINGLE|SLEEP|STATIC|STEP|STOP|STRING|SUB|SWAP|SYSTEM|THEN|TIMER|TO|TROFF|TRON|TYPE|UNLOCK|UNTIL|USING|VIEW PRINT|WAIT|WEND|WHILE|WRITE)(?:\$|\b)/i,function:/\b(?:ABS|ACCESS|ACOS|ANGLE|AREA|ARITHMETIC|ARRAY|ASIN|ASK|AT|ATN|BASE|BEGIN|BREAK|CAUSE|CEIL|CHR|CLIP|COLLATE|COLOR|CON|COS|COSH|COT|CSC|DATE|DATUM|DEBUG|DECIMAL|DEF|DEG|DEGREES|DELETE|DET|DEVICE|DISPLAY|DOT|ELAPSED|EPS|ERASABLE|EXLINE|EXP|EXTERNAL|EXTYPE|FILETYPE|FIXED|FP|GO|GRAPH|HANDLER|IDN|IMAGE|IN|INT|INTERNAL|IP|IS|KEYED|LBOUND|LCASE|LEFT|LEN|LENGTH|LET|LINE|LINES|LOG|LOG10|LOG2|LTRIM|MARGIN|MAT|MAX|MAXNUM|MID|MIN|MISSING|MOD|NATIVE|NUL|NUMERIC|OF|OPTION|ORD|ORGANIZATION|OUTIN|OUTPUT|PI|POINT|POINTER|POINTS|POS|PRINT|PROGRAM|PROMPT|RAD|RADIANS|RANDOMIZE|RECORD|RECSIZE|RECTYPE|RELATIVE|REMAINDER|REPEAT|REST|RETRY|REWRITE|RIGHT|RND|ROUND|RTRIM|SAME|SEC|SELECT|SEQUENTIAL|SET|SETTER|SGN|SIN|SINH|SIZE|SKIP|SQR|STANDARD|STATUS|STR|STREAM|STYLE|TAB|TAN|TANH|TEMPLATE|TEXT|THERE|TIME|TIMEOUT|TRACE|TRANSFORM|TRUNCATE|UBOUND|UCASE|USE|VAL|VARIABLE|VIEWPORT|WHEN|WINDOW|WITH|ZER|ZONEWIDTH)(?:\$|\b)/i,operator:/<[=>]?|>=?|[+\-*\/^=&]|\b(?:AND|EQV|IMP|NOT|OR|XOR)\b/i,punctuation:/[,;:()]/};
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){var r=/%%?[~:\w]+%?|!\S+!/,t={pattern:/\/[a-z?]+(?=[ :]|$):?|-[a-z]\b|--[a-z-]+\b/im,alias:"attr-name",inside:{punctuation:/:/}},n=/"(?:[\\"]"|[^"])*"(?!")/,i=/(?:\b|-)\d+\b/;e.languages.batch={comment:[/^::.*/m,{pattern:/((?:^|[&(])[ \t]*)rem\b(?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0}],label:{pattern:/^:.*/m,alias:"property"},command:[{pattern:/((?:^|[&(])[ \t]*)for(?: \/[a-z?](?:[ :](?:"[^"]*"|[^\s"/]\S*))?)* \S+ in \([^)]+\) do/im,lookbehind:!0,inside:{keyword:/\b(?:do|in)\b|^for\b/i,string:n,parameter:t,variable:r,number:i,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*)if(?: \/[a-z?](?:[ :](?:"[^"]*"|[^\s"/]\S*))?)* (?:not )?(?:cmdextversion \d+|defined \w+|errorlevel \d+|exist \S+|(?:"[^"]*"|(?!")(?:(?!==)\S)+)?(?:==| (?:equ|geq|gtr|leq|lss|neq) )(?:"[^"]*"|[^\s"]\S*))/im,lookbehind:!0,inside:{keyword:/\b(?:cmdextversion|defined|errorlevel|exist|not)\b|^if\b/i,string:n,parameter:t,variable:r,number:i,operator:/\^|==|\b(?:equ|geq|gtr|leq|lss|neq)\b/i}},{pattern:/((?:^|[&()])[ \t]*)else\b/im,lookbehind:!0,inside:{keyword:/^else\b/i}},{pattern:/((?:^|[&(])[ \t]*)set(?: \/[a-z](?:[ :](?:"[^"]*"|[^\s"/]\S*))?)* (?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0,inside:{keyword:/^set\b/i,string:n,parameter:t,variable:[r,/\w+(?=(?:[*\/%+\-&^|]|<<|>>)?=)/],number:i,operator:/[*\/%+\-&^|]=?|<<=?|>>=?|[!~_=]/,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*@?)\w+\b(?:"(?:[\\"]"|[^"])*"(?!")|[^"^&)\r\n]|\^(?:\r\n|[\s\S]))*/m,lookbehind:!0,inside:{keyword:/^\w+\b/,string:n,parameter:t,label:{pattern:/(^\s*):\S+/m,lookbehind:!0,alias:"property"},variable:r,number:i,operator:/\^/}}],operator:/[&@]/,punctuation:/[()']/}}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.c=Prism.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),Prism.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],char:Prism.languages.c.char,comment:Prism.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:Prism.languages.c}}}}),Prism.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete Prism.languages.c.boolean;
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/};
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
!function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n="\\b(?!<keyword>)\\w+(?:\\s*\\.\\s*\\w+)*\\b".replace(/<keyword>/g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp("(\\b(?:class|concept|enum|struct|typename)\\s+)(?!<keyword>)\\w+".replace(/<keyword>/g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp('(\\b(?:import|module)\\s+)(?:"(?:\\\\(?:\r\n|[^])|[^"\\\\\r\n])*"|<[^<>\r\n]*>|'+"<mod-name>(?:\\s*:\\s*<mod-name>)?|:\\s*<mod-name>".replace(/<mod-name>/g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(Prism);
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
!function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){var a=[/\b(?:async|sync|yield)\*/,/\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|covariant|default|deferred|do|dynamic|else|enum|export|extends|extension|external|factory|final|finally|for|get|hide|if|implements|import|in|interface|library|mixin|new|null|on|operator|part|rethrow|return|set|show|static|super|switch|sync|this|throw|try|typedef|var|void|while|with|yield)\b/],n="(^|[^\\w.])(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp(n+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}}}};e.languages.dart=e.languages.extend("clike",{"class-name":[s,{pattern:RegExp(n+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()])"),lookbehind:!0,inside:s.inside}],keyword:a,operator:/\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/}),e.languages.insertBefore("dart","string",{"string-literal":{pattern:/r?(?:("""|''')[\s\S]*?\1|(["'])(?:\\.|(?!\2)[^\\\r\n])*\2(?!\2))/,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:\w+|\{(?:[^{}]|\{[^{}]*\})*\})/,lookbehind:!0,inside:{punctuation:/^\$\{?|\}$/,expression:{pattern:/[\s\S]+/,inside:e.languages.dart}}},string:/[\s\S]+/}},string:void 0}),e.languages.insertBefore("dart","class-name",{metadata:{pattern:/@\w+/,alias:"function"}}),e.languages.insertBefore("dart","class-name",{generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":s,keyword:a,punctuation:/[<>(),.:]/,operator:/[?&|]/}}})}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var n={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(n).forEach((function(a){var i=n[a],r=[];/^\w+$/.test(a)||r.push(/\w+/.exec(a)[0]),"diff"===a&&r.push("bold"),e.languages.diff[a]={pattern:RegExp("^(?:["+i+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:r,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(a)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:n})}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){var n="(?:[ \t]+(?![ \t])(?:<SP_BS>)?|<SP_BS>)".replace(/<SP_BS>/g,(function(){return"\\\\[\r\n](?:\\s|\\\\[\r\n]|#.*(?!.))*(?![\\s#]|\\\\[\r\n])"})),r="\"(?:[^\"\\\\\r\n]|\\\\(?:\r\n|[^]))*\"|'(?:[^'\\\\\r\n]|\\\\(?:\r\n|[^]))*'",t="--[\\w-]+=(?:<STR>|(?![\"'])(?:[^\\s\\\\]|\\\\.)+)".replace(/<STR>/g,(function(){return r})),o={pattern:RegExp(r),greedy:!0},i={pattern:/(^[ \t]*)#.*/m,lookbehind:!0,greedy:!0};function a(e,r){return e=e.replace(/<OPT>/g,(function(){return t})).replace(/<SP>/g,(function(){return n})),RegExp(e,r)}e.languages.docker={instruction:{pattern:/(^[ \t]*)(?:ADD|ARG|CMD|COPY|ENTRYPOINT|ENV|EXPOSE|FROM|HEALTHCHECK|LABEL|MAINTAINER|ONBUILD|RUN|SHELL|STOPSIGNAL|USER|VOLUME|WORKDIR)(?=\s)(?:\\.|[^\r\n\\])*(?:\\$(?:\s|#.*$)*(?![\s#])(?:\\.|[^\r\n\\])*)*/im,lookbehind:!0,greedy:!0,inside:{options:{pattern:a("(^(?:ONBUILD<SP>)?\\w+<SP>)<OPT>(?:<SP><OPT>)*","i"),lookbehind:!0,greedy:!0,inside:{property:{pattern:/(^|\s)--[\w-]+/,lookbehind:!0},string:[o,{pattern:/(=)(?!["'])(?:[^\s\\]|\\.)+/,lookbehind:!0}],operator:/\\$/m,punctuation:/=/}},keyword:[{pattern:a("(^(?:ONBUILD<SP>)?HEALTHCHECK<SP>(?:<OPT><SP>)*)(?:CMD|NONE)\\b","i"),lookbehind:!0,greedy:!0},{pattern:a("(^(?:ONBUILD<SP>)?FROM<SP>(?:<OPT><SP>)*(?!--)[^ \t\\\\]+<SP>)AS","i"),lookbehind:!0,greedy:!0},{pattern:a("(^ONBUILD<SP>)\\w+","i"),lookbehind:!0,greedy:!0},{pattern:/^\w+/,greedy:!0}],comment:i,string:o,variable:/\$(?:\w+|\{[^{}"'\\]*\})/,operator:/\\$/m}},comment:i},e.languages.dockerfile=e.languages.docker}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.elixir={doc:{pattern:/@(?:doc|moduledoc)\s+(?:("""|''')[\s\S]*?\1|("|')(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2)/,inside:{attribute:/^@\w+/,string:/['"][\s\S]+/}},comment:{pattern:/#.*/,greedy:!0},regex:{pattern:/~[rR](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|[^\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[uismxfr]*/,greedy:!0},string:[{pattern:/~[cCsSwW](?:("""|''')(?:\\[\s\S]|(?!\1)[^\\])+\1|([\/|"'])(?:\\.|(?!\2)[^\\\r\n])+\2|\((?:\\.|[^\\)\r\n])+\)|\[(?:\\.|[^\\\]\r\n])+\]|\{(?:\\.|#\{[^}]+\}|#(?!\{)|[^#\\}\r\n])+\}|<(?:\\.|[^\\>\r\n])+>)[csa]?/,greedy:!0,inside:{}},{pattern:/("""|''')[\s\S]*?\1/,greedy:!0,inside:{}},{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{}}],atom:{pattern:/(^|[^:]):\w+/,lookbehind:!0,alias:"symbol"},module:{pattern:/\b[A-Z]\w*\b/,alias:"class-name"},"attr-name":/\b\w+\??:(?!:)/,argument:{pattern:/(^|[^&])&\d+/,lookbehind:!0,alias:"variable"},attribute:{pattern:/@\w+/,alias:"variable"},function:/\b[_a-zA-Z]\w*[?!]?(?:(?=\s*(?:\.\s*)?\()|(?=\/\d))/,number:/\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i,keyword:/\b(?:after|alias|and|case|catch|cond|def(?:callback|delegate|exception|impl|macro|module|n|np|p|protocol|struct)?|do|else|end|fn|for|if|import|not|or|quote|raise|require|rescue|try|unless|unquote|use|when)\b/,boolean:/\b(?:false|nil|true)\b/,operator:[/\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/,{pattern:/([^<])<(?!<)/,lookbehind:!0},{pattern:/([^>])>(?!>)/,lookbehind:!0}],punctuation:/<<|>>|[.,%\[\]{}()]/},Prism.languages.elixir.string.forEach((function(e){e.inside={interpolation:{pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"},rest:Prism.languages.elixir}}}}));
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.erlang={comment:/%.+/,string:{pattern:/"(?:\\.|[^\\"\r\n])*"/,greedy:!0},"quoted-function":{pattern:/'(?:\\.|[^\\'\r\n])+'(?=\()/,alias:"function"},"quoted-atom":{pattern:/'(?:\\.|[^\\'\r\n])+'/,alias:"atom"},boolean:/\b(?:false|true)\b/,keyword:/\b(?:after|begin|case|catch|end|fun|if|of|receive|try|when)\b/,number:[/\$\\?./,/\b\d+#[a-z0-9]+/i,/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i],function:/\b[a-z][\w@]*(?=\()/,variable:{pattern:/(^|[^@])(?:\b|\?)[A-Z_][\w@]*/,lookbehind:!0},operator:[/[=\/<>:]=|=[:\/]=|\+\+?|--?|[=*\/!]|\b(?:and|andalso|band|bnot|bor|bsl|bsr|bxor|div|not|or|orelse|rem|xor)\b/,{pattern:/(^|[^<])<(?!<)/,lookbehind:!0},{pattern:/(^|[^>])>(?!>)/,lookbehind:!0}],atom:/\b[a-z][\w@]*/,punctuation:/[()[\]{}:;,.#|]|<<|>>/};
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.git={comment:/^#.*/m,deleted:/^[-–].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m};
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.go=Prism.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),Prism.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete Prism.languages.go["class-name"];
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:Prism.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},Prism.hooks.add("after-tokenize",(function(n){if("graphql"===n.language)for(var t=n.tokens.filter((function(n){return"string"!=typeof n&&"comment"!==n.type&&"scalar"!==n.type})),e=0;e<t.length;){var a=t[e++];if("keyword"===a.type&&"mutation"===a.content){var r=[];if(c(["definition-mutation","punctuation"])&&"("===l(1).content){e+=2;var i=f(/^\($/,/^\)$/);if(-1===i)continue;for(;e<i;e++){var o=l(0);"variable"===o.type&&(b(o,"variable-input"),r.push(o.content))}e=i+1}if(c(["punctuation","property-query"])&&"{"===l(0).content&&(e++,b(l(0),"property-mutation"),r.length>0)){var s=f(/^\{$/,/^\}$/);if(-1===s)continue;for(var u=e;u<s;u++){var p=t[u];"variable"===p.type&&r.indexOf(p.content)>=0&&b(p,"variable-input")}}}}function l(n){return t[e+n]}function c(n,t){t=t||0;for(var e=0;e<n.length;e++){var a=l(e+t);if(!a||a.type!==n[e])return!1}return!0}function f(n,a){for(var r=1,i=e;i<t.length;i++){var o=t[i],s=o.content;if("punctuation"===o.type&&"string"==typeof s)if(n.test(s))r++;else if(a.test(s)&&0==--r)return i}return-1}function b(n,t){var e=n.alias;e?Array.isArray(e)||(n.alias=e=[e]):n.alias=e=[],e.push(t)}}));
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){var n={pattern:/((?:^|[^\\$])(?:\\{2})*)\$(?:\w+|\{[^{}]*\})/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:null}}};e.languages.groovy=e.languages.extend("clike",{string:{pattern:/'''(?:[^\\]|\\[\s\S])*?'''|'(?:\\.|[^\\'\r\n])*'/,greedy:!0},keyword:/\b(?:abstract|as|assert|boolean|break|byte|case|catch|char|class|const|continue|def|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|in|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|trait|transient|try|void|volatile|while)\b/,number:/\b(?:0b[01_]+|0x[\da-f_]+(?:\.[\da-f_p\-]+)?|[\d_]+(?:\.[\d_]+)?(?:e[+-]?\d+)?)[glidf]?\b/i,operator:{pattern:/(^|[^.])(?:~|==?~?|\?[.:]?|\*(?:[.=]|\*=?)?|\.[@&]|\.\.<|\.\.(?!\.)|-[-=>]?|\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\|[|=]?|\/=?|\^=?|%=?)/,lookbehind:!0},punctuation:/\.+|[{}[\];(),:$]/}),e.languages.insertBefore("groovy","string",{shebang:{pattern:/#!.+/,alias:"comment",greedy:!0},"interpolation-string":{pattern:/"""(?:[^\\]|\\[\s\S])*?"""|(["/])(?:\\.|(?!\1)[^\\\r\n])*\1|\$\/(?:[^/$]|\$(?:[/$]|(?![/$]))|\/(?!\$))*\/\$/,greedy:!0,inside:{interpolation:n,string:/[\s\S]+/}}}),e.languages.insertBefore("groovy","punctuation",{"spock-block":/\b(?:and|cleanup|expect|given|setup|then|when|where):/}),e.languages.insertBefore("groovy","function",{annotation:{pattern:/(^|[^.])@\w+/,lookbehind:!0,alias:"punctuation"}}),n.inside.expression.inside=e.languages.groovy}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.haskell={comment:{pattern:/(^|[^-!#$%*+=?&@|~.:<>^\\\/])(?:--(?:(?=.)[^-!#$%*+=?&@|~.:<>^\\\/].*|$)|\{-[\s\S]*?-\})/m,lookbehind:!0},char:{pattern:/'(?:[^\\']|\\(?:[abfnrtv\\"'&]|\^[A-Z@[\]^_]|ACK|BEL|BS|CAN|CR|DC1|DC2|DC3|DC4|DEL|DLE|EM|ENQ|EOT|ESC|ETB|ETX|FF|FS|GS|HT|LF|NAK|NUL|RS|SI|SO|SOH|SP|STX|SUB|SYN|US|VT|\d+|o[0-7]+|x[0-9a-fA-F]+))'/,alias:"string"},string:{pattern:/"(?:[^\\"]|\\(?:\S|\s+\\))*"/,greedy:!0},keyword:/\b(?:case|class|data|deriving|do|else|if|in|infixl|infixr|instance|let|module|newtype|of|primitive|then|type|where)\b/,"import-statement":{pattern:/(^[\t ]*)import\s+(?:qualified\s+)?(?:[A-Z][\w']*)(?:\.[A-Z][\w']*)*(?:\s+as\s+(?:[A-Z][\w']*)(?:\.[A-Z][\w']*)*)?(?:\s+hiding\b)?/m,lookbehind:!0,inside:{keyword:/\b(?:as|hiding|import|qualified)\b/,punctuation:/\./}},builtin:/\b(?:abs|acos|acosh|all|and|any|appendFile|approxRational|asTypeOf|asin|asinh|atan|atan2|atanh|basicIORun|break|catch|ceiling|chr|compare|concat|concatMap|const|cos|cosh|curry|cycle|decodeFloat|denominator|digitToInt|div|divMod|drop|dropWhile|either|elem|encodeFloat|enumFrom|enumFromThen|enumFromThenTo|enumFromTo|error|even|exp|exponent|fail|filter|flip|floatDigits|floatRadix|floatRange|floor|fmap|foldl|foldl1|foldr|foldr1|fromDouble|fromEnum|fromInt|fromInteger|fromIntegral|fromRational|fst|gcd|getChar|getContents|getLine|group|head|id|inRange|index|init|intToDigit|interact|ioError|isAlpha|isAlphaNum|isAscii|isControl|isDenormalized|isDigit|isHexDigit|isIEEE|isInfinite|isLower|isNaN|isNegativeZero|isOctDigit|isPrint|isSpace|isUpper|iterate|last|lcm|length|lex|lexDigits|lexLitChar|lines|log|logBase|lookup|map|mapM|mapM_|max|maxBound|maximum|maybe|min|minBound|minimum|mod|negate|not|notElem|null|numerator|odd|or|ord|otherwise|pack|pi|pred|primExitWith|print|product|properFraction|putChar|putStr|putStrLn|quot|quotRem|range|rangeSize|read|readDec|readFile|readFloat|readHex|readIO|readInt|readList|readLitChar|readLn|readOct|readParen|readSigned|reads|readsPrec|realToFrac|recip|rem|repeat|replicate|return|reverse|round|scaleFloat|scanl|scanl1|scanr|scanr1|seq|sequence|sequence_|show|showChar|showInt|showList|showLitChar|showParen|showSigned|showString|shows|showsPrec|significand|signum|sin|sinh|snd|sort|span|splitAt|sqrt|subtract|succ|sum|tail|take|takeWhile|tan|tanh|threadToIOResult|toEnum|toInt|toInteger|toLower|toRational|toUpper|truncate|uncurry|undefined|unlines|until|unwords|unzip|unzip3|userError|words|writeFile|zip|zip3|zipWith|zipWith3)\b/,number:/\b(?:\d+(?:\.\d+)?(?:e[+-]?\d+)?|0o[0-7]+|0x[0-9a-f]+)\b/i,operator:[{pattern:/`(?:[A-Z][\w']*\.)*[_a-z][\w']*`/,greedy:!0},{pattern:/(\s)\.(?=\s)/,lookbehind:!0},/[-!#$%*+=?&@|~:<>^\\\/][-!#$%*+=?&@|~.:<>^\\\/]*|\.[-!#$%*+=?&@|~.:<>^\\\/]+/],hvariable:{pattern:/\b(?:[A-Z][\w']*\.)*[_a-z][\w']*/,inside:{punctuation:/\./}},constant:{pattern:/\b(?:[A-Z][\w']*\.)*[A-Z][\w']*/,inside:{punctuation:/\./}},punctuation:/[{}[\];(),.:]/},Prism.languages.hs=Prism.languages.haskell;
|
||||
@@ -1 +0,0 @@
|
||||
!function(t){function a(t){return RegExp("(^(?:"+t+"):[ \t]*(?![ \t]))[^]+","i")}t.languages.http={"request-line":{pattern:/^(?:CONNECT|DELETE|GET|HEAD|OPTIONS|PATCH|POST|PRI|PUT|SEARCH|TRACE)\s(?:https?:\/\/|\/)\S*\sHTTP\/[\d.]+/m,inside:{method:{pattern:/^[A-Z]+\b/,alias:"property"},"request-target":{pattern:/^(\s)(?:https?:\/\/|\/)\S*(?=\s)/,lookbehind:!0,alias:"url",inside:t.languages.uri},"http-version":{pattern:/^(\s)HTTP\/[\d.]+/,lookbehind:!0,alias:"property"}}},"response-status":{pattern:/^HTTP\/[\d.]+ \d+ .+/m,inside:{"http-version":{pattern:/^HTTP\/[\d.]+/,alias:"property"},"status-code":{pattern:/^(\s)\d+(?=\s)/,lookbehind:!0,alias:"number"},"reason-phrase":{pattern:/^(\s).+/,lookbehind:!0,alias:"string"}}},header:{pattern:/^[\w-]+:.+(?:(?:\r\n?|\n)[ \t].+)*/m,inside:{"header-value":[{pattern:a("Content-Security-Policy"),lookbehind:!0,alias:["csp","languages-csp"],inside:t.languages.csp},{pattern:a("Public-Key-Pins(?:-Report-Only)?"),lookbehind:!0,alias:["hpkp","languages-hpkp"],inside:t.languages.hpkp},{pattern:a("Strict-Transport-Security"),lookbehind:!0,alias:["hsts","languages-hsts"],inside:t.languages.hsts},{pattern:a("[^:]+"),lookbehind:!0}],"header-name":{pattern:/^[^:]+/,alias:"keyword"},punctuation:/^:/}}};var e,n=t.languages,s={"application/javascript":n.javascript,"application/json":n.json||n.javascript,"application/xml":n.xml,"text/xml":n.xml,"text/html":n.html,"text/css":n.css,"text/plain":n.plain},i={"application/json":!0,"application/xml":!0};function r(t){var a=t.replace(/^[a-z]+\//,"");return"(?:"+t+"|\\w+/(?:[\\w.-]+\\+)+"+a+"(?![+\\w.-]))"}for(var p in s)if(s[p]){e=e||{};var l=i[p]?r(p):p;e[p.replace(/\//g,"-")]={pattern:RegExp("(content-type:\\s*"+l+"(?:(?:\r\n?|\n)[\\w-].*)*(?:\r(?:\n|(?!\n))|\n))[^ \t\\w-][^]*","i"),lookbehind:!0,inside:s[p]}}e&&t.languages.insertBefore("http","header",e)}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.ini={comment:{pattern:/(^[ \f\t\v]*)[#;][^\n\r]*/m,lookbehind:!0},section:{pattern:/(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m,lookbehind:!0,inside:{"section-name":{pattern:/(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/,lookbehind:!0,alias:"selector"},punctuation:/\[|\]/}},key:{pattern:/(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m,lookbehind:!0,alias:"attr-name"},value:{pattern:/(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/,lookbehind:!0,alias:"attr-value",inside:{"inner-value":{pattern:/^("|').+(?=\1$)/,lookbehind:!0}}},punctuation:/=/};
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){var n=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,t="(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",s={pattern:RegExp("(^|[^\\w.])"+t+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[s,{pattern:RegExp("(^|[^\\w.])"+t+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=()]|\\s*(?:\\[[\\s,]*\\]\\s*)?::\\s*new\\b)"),lookbehind:!0,inside:s.inside},{pattern:RegExp("(\\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\\s+)"+t+"[A-Z]\\w*\\b"),lookbehind:!0,inside:s.inside}],keyword:n,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":s,keyword:n,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp("(\\bimport\\s+)"+t+"(?:[A-Z]\\w*|\\*)(?=\\s*;)"),lookbehind:!0,inside:{namespace:s.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp("(\\bimport\\s+static\\s+)"+t+"(?:\\w+|\\*)(?=\\s*;)"),lookbehind:!0,alias:"static",inside:{namespace:s.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!<keyword>)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(/<keyword>/g,(function(){return n.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript;
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},Prism.languages.webmanifest=Prism.languages.json;
|
||||
@@ -1 +0,0 @@
|
||||
!function(t){var n=t.util.clone(t.languages.javascript),e="(?:\\{<S>*\\.{3}(?:[^{}]|<BRACES>)*\\})";function a(t,n){return t=t.replace(/<S>/g,(function(){return"(?:\\s|//.*(?!.)|/\\*(?:[^*]|\\*(?!/))\\*/)"})).replace(/<BRACES>/g,(function(){return"(?:\\{(?:\\{(?:\\{[^{}]*\\}|[^{}])*\\}|[^{}])*\\})"})).replace(/<SPREAD>/g,(function(){return e})),RegExp(t,n)}e=a(e).source,t.languages.jsx=t.languages.extend("markup",n),t.languages.jsx.tag.pattern=a("</?(?:[\\w.:-]+(?:<S>+(?:[\\w.:$-]+(?:=(?:\"(?:\\\\[^]|[^\\\\\"])*\"|'(?:\\\\[^]|[^\\\\'])*'|[^\\s{'\"/>=]+|<BRACES>))?|<SPREAD>))*<S>*/?)?>"),t.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,t.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,t.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,t.languages.jsx.tag.inside.comment=n.comment,t.languages.insertBefore("inside","attr-name",{spread:{pattern:a("<SPREAD>"),inside:t.languages.jsx}},t.languages.jsx.tag),t.languages.insertBefore("inside","special-attr",{script:{pattern:a("=<BRACES>"),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:t.languages.jsx}}},t.languages.jsx.tag);var s=function(t){return t?"string"==typeof t?t:"string"==typeof t.content?t.content:t.content.map(s).join(""):""},g=function(n){for(var e=[],a=0;a<n.length;a++){var o=n[a],i=!1;if("string"!=typeof o&&("tag"===o.type&&o.content[0]&&"tag"===o.content[0].type?"</"===o.content[0].content[0].content?e.length>0&&e[e.length-1].tagName===s(o.content[0].content[1])&&e.pop():"/>"===o.content[o.content.length-1].content||e.push({tagName:s(o.content[0].content[1]),openedBraces:0}):e.length>0&&"punctuation"===o.type&&"{"===o.content?e[e.length-1].openedBraces++:e.length>0&&e[e.length-1].openedBraces>0&&"punctuation"===o.type&&"}"===o.content?e[e.length-1].openedBraces--:i=!0),(i||"string"==typeof o)&&e.length>0&&0===e[e.length-1].openedBraces){var r=s(o);a<n.length-1&&("string"==typeof n[a+1]||"plain-text"===n[a+1].type)&&(r+=s(n[a+1]),n.splice(a+1,1)),a>0&&("string"==typeof n[a-1]||"plain-text"===n[a-1].type)&&(r=s(n[a-1])+r,n.splice(a-1,1),a--),n[a]=new t.Token("plain-text",r,null,r)}o.content&&"string"!=typeof o.content&&g(o.content)}};t.hooks.add("after-tokenize",(function(t){"jsx"!==t.language&&"tsx"!==t.language||g(t.tokens)}))}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.julia={comment:{pattern:/(^|[^\\])(?:#=(?:[^#=]|=(?!#)|#(?!=)|#=(?:[^#=]|=(?!#)|#(?!=))*=#)*=#|#.*)/,lookbehind:!0},regex:{pattern:/r"(?:\\.|[^"\\\r\n])*"[imsx]{0,4}/,greedy:!0},string:{pattern:/"""[\s\S]+?"""|(?:\b\w+)?"(?:\\.|[^"\\\r\n])*"|`(?:[^\\`\r\n]|\\.)*`/,greedy:!0},char:{pattern:/(^|[^\w'])'(?:\\[^\r\n][^'\r\n]*|[^\\\r\n])'/,lookbehind:!0,greedy:!0},keyword:/\b(?:abstract|baremodule|begin|bitstype|break|catch|ccall|const|continue|do|else|elseif|end|export|finally|for|function|global|if|immutable|import|importall|in|let|local|macro|module|print|println|quote|return|struct|try|type|typealias|using|while)\b/,boolean:/\b(?:false|true)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[box])?(?:[\da-f]+(?:_[\da-f]+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[efp][+-]?\d+(?:_\d+)*)?j?/i,operator:/&&|\|\||[-+*^%÷⊻&$\\]=?|\/[\/=]?|!=?=?|\|[=>]?|<(?:<=?|[=:|])?|>(?:=|>>?=?)?|==?=?|[~≠≤≥'√∛]/,punctuation:/::?|[{}[\]();,.?]/,constant:/\b(?:(?:Inf|NaN)(?:16|32|64)?|im|pi)\b|[πℯ]/};
|
||||
@@ -1 +0,0 @@
|
||||
!function(n){n.languages.kotlin=n.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete n.languages.kotlin["class-name"];var e={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:n.languages.kotlin}};n.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:e},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:e},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete n.languages.kotlin.string,n.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),n.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),n.languages.kt=n.languages.kotlin,n.languages.kts=n.languages.kotlin}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
!function(a){var e=/\\(?:[^a-z()[\]]|[a-z*]+)/i,n={"equation-command":{pattern:e,alias:"regex"}};a.languages.latex={comment:/%.*/,cdata:{pattern:/(\\begin\{((?:lstlisting|verbatim)\*?)\})[\s\S]*?(?=\\end\{\2\})/,lookbehind:!0},equation:[{pattern:/\$\$(?:\\[\s\S]|[^\\$])+\$\$|\$(?:\\[\s\S]|[^\\$])+\$|\\\([\s\S]*?\\\)|\\\[[\s\S]*?\\\]/,inside:n,alias:"string"},{pattern:/(\\begin\{((?:align|eqnarray|equation|gather|math|multline)\*?)\})[\s\S]*?(?=\\end\{\2\})/,lookbehind:!0,inside:n,alias:"string"}],keyword:{pattern:/(\\(?:begin|cite|documentclass|end|label|ref|usepackage)(?:\[[^\]]+\])?\{)[^}]+(?=\})/,lookbehind:!0},url:{pattern:/(\\url\{)[^}]+(?=\})/,lookbehind:!0},headline:{pattern:/(\\(?:chapter|frametitle|paragraph|part|section|subparagraph|subsection|subsubparagraph|subsubsection|subsubsubparagraph)\*?(?:\[[^\]]+\])?\{)[^}]+(?=\})/,lookbehind:!0,alias:"class-name"},function:{pattern:e,alias:"selector"},punctuation:/[[\]{}&]/},a.languages.tex=a.languages.latex,a.languages.context=a.languages.latex}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.less=Prism.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/,operator:/[+\-*\/]/}),Prism.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}});
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[^z]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+(?:\.[a-f\d]*)?(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|(?:\.\d*)?(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,function:/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/};
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/};
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
!function(e){function n(e,n){return"___"+e.toUpperCase()+n+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(t,a,r,o){if(t.language===a){var c=t.tokenStack=[];t.code=t.code.replace(r,(function(e){if("function"==typeof o&&!o(e))return e;for(var r,i=c.length;-1!==t.code.indexOf(r=n(a,i));)++i;return c[i]=e,r})),t.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(t,a){if(t.language===a&&t.tokenStack){t.grammar=e.languages[a];var r=0,o=Object.keys(t.tokenStack);!function c(i){for(var u=0;u<i.length&&!(r>=o.length);u++){var g=i[u];if("string"==typeof g||g.content&&"string"==typeof g.content){var l=o[r],s=t.tokenStack[l],f="string"==typeof g?g:g.content,p=n(a,l),k=f.indexOf(p);if(k>-1){++r;var m=f.substring(0,k),d=new e.Token(a,e.tokenize(s,t.grammar),"language-"+a,s),h=f.substring(k+p.length),v=[];m&&v.push.apply(v,c([m])),v.push(d),h&&v.push.apply(v,c([h])),"string"==typeof g?i.splice.apply(i,[u,1].concat(v)):g.content=v}}else g.content&&c(g.content)}return i}(t.tokens)}}}})}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.markup={comment:{pattern:/<!--(?:(?!<!--)[\s\S])*?-->/,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^<!\[CDATA\[|\]\]>$/i;var t={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:<!\\[CDATA\\[(?:[^\\]]|\\](?!\\]>))*\\]\\]>|(?!<!\\[CDATA\\[)[^])*?(?=</__>)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml;
|
||||
@@ -1 +0,0 @@
|
||||
!function($){var e=["$eq","$gt","$gte","$in","$lt","$lte","$ne","$nin","$and","$not","$nor","$or","$exists","$type","$expr","$jsonSchema","$mod","$regex","$text","$where","$geoIntersects","$geoWithin","$near","$nearSphere","$all","$elemMatch","$size","$bitsAllClear","$bitsAllSet","$bitsAnyClear","$bitsAnySet","$comment","$elemMatch","$meta","$slice","$currentDate","$inc","$min","$max","$mul","$rename","$set","$setOnInsert","$unset","$addToSet","$pop","$pull","$push","$pullAll","$each","$position","$slice","$sort","$bit","$addFields","$bucket","$bucketAuto","$collStats","$count","$currentOp","$facet","$geoNear","$graphLookup","$group","$indexStats","$limit","$listLocalSessions","$listSessions","$lookup","$match","$merge","$out","$planCacheStats","$project","$redact","$replaceRoot","$replaceWith","$sample","$set","$skip","$sort","$sortByCount","$unionWith","$unset","$unwind","$setWindowFields","$abs","$accumulator","$acos","$acosh","$add","$addToSet","$allElementsTrue","$and","$anyElementTrue","$arrayElemAt","$arrayToObject","$asin","$asinh","$atan","$atan2","$atanh","$avg","$binarySize","$bsonSize","$ceil","$cmp","$concat","$concatArrays","$cond","$convert","$cos","$dateFromParts","$dateToParts","$dateFromString","$dateToString","$dayOfMonth","$dayOfWeek","$dayOfYear","$degreesToRadians","$divide","$eq","$exp","$filter","$first","$floor","$function","$gt","$gte","$hour","$ifNull","$in","$indexOfArray","$indexOfBytes","$indexOfCP","$isArray","$isNumber","$isoDayOfWeek","$isoWeek","$isoWeekYear","$last","$last","$let","$literal","$ln","$log","$log10","$lt","$lte","$ltrim","$map","$max","$mergeObjects","$meta","$min","$millisecond","$minute","$mod","$month","$multiply","$ne","$not","$objectToArray","$or","$pow","$push","$radiansToDegrees","$range","$reduce","$regexFind","$regexFindAll","$regexMatch","$replaceOne","$replaceAll","$reverseArray","$round","$rtrim","$second","$setDifference","$setEquals","$setIntersection","$setIsSubset","$setUnion","$size","$sin","$slice","$split","$sqrt","$stdDevPop","$stdDevSamp","$strcasecmp","$strLenBytes","$strLenCP","$substr","$substrBytes","$substrCP","$subtract","$sum","$switch","$tan","$toBool","$toDate","$toDecimal","$toDouble","$toInt","$toLong","$toObjectId","$toString","$toLower","$toUpper","$trim","$trunc","$type","$week","$year","$zip","$count","$dateAdd","$dateDiff","$dateSubtract","$dateTrunc","$getField","$rand","$sampleRate","$setField","$unsetField","$comment","$explain","$hint","$max","$maxTimeMS","$min","$orderby","$query","$returnKey","$showDiskLoc","$natural"],t="(?:"+(e=e.map((function($){return $.replace("$","\\$")}))).join("|")+")\\b";$.languages.mongodb=$.languages.extend("javascript",{}),$.languages.insertBefore("mongodb","string",{property:{pattern:/(?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)(?=\s*:)/,greedy:!0,inside:{keyword:RegExp("^(['\"])?"+t+"(?:\\1)?$")}}}),$.languages.mongodb.string.inside={url:{pattern:/https?:\/\/[-\w@:%.+~#=]{1,256}\.[a-z0-9()]{1,6}\b[-\w()@:%+.~#?&/=]*/i,greedy:!0},entity:{pattern:/\b(?:(?:[01]?\d\d?|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d\d?|2[0-4]\d|25[0-5])\b/,greedy:!0}},$.languages.insertBefore("mongodb","constant",{builtin:{pattern:RegExp("\\b(?:"+["ObjectId","Code","BinData","DBRef","Timestamp","NumberLong","NumberDecimal","MaxKey","MinKey","RegExp","ISODate","UUID"].join("|")+")\\b"),alias:"keyword"}})}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){var n=/\$(?:\w[a-z\d]*(?:_[^\x00-\x1F\s"'\\()$]*)?|\{[^}\s"'\\]+\})/i;e.languages.nginx={comment:{pattern:/(^|[\s{};])#.*/,lookbehind:!0,greedy:!0},directive:{pattern:/(^|\s)\w(?:[^;{}"'\\\s]|\\.|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\s+(?:#.*(?!.)|(?![#\s])))*?(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:{string:{pattern:/((?:^|[^\\])(?:\\\\)*)(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,lookbehind:!0,greedy:!0,inside:{escape:{pattern:/\\["'\\nrt]/,alias:"entity"},variable:n}},comment:{pattern:/(\s)#.*/,lookbehind:!0,greedy:!0},keyword:{pattern:/^\S+/,greedy:!0},boolean:{pattern:/(\s)(?:off|on)(?!\S)/,lookbehind:!0},number:{pattern:/(\s)\d+[a-z]*(?!\S)/i,lookbehind:!0},variable:n}},punctuation:/[{};]/}}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.objectivec=Prism.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete Prism.languages.objectivec["class-name"],Prism.languages.objc=Prism.languages.objectivec;
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){var n="(?:\\((?:[^()\\\\]|\\\\[^])*\\)|\\{(?:[^{}\\\\]|\\\\[^])*\\}|\\[(?:[^[\\]\\\\]|\\\\[^])*\\]|<(?:[^<>\\\\]|\\\\[^])*>)";e.languages.perl={comment:[{pattern:/(^\s*)=\w[\s\S]*?=cut.*/m,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0,greedy:!0}],string:[{pattern:RegExp("\\b(?:q|qq|qw|qx)(?![a-zA-Z0-9])\\s*(?:"+["([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\1)[^\\\\]|\\\\[^])*\\1","([a-zA-Z0-9])(?:(?!\\2)[^\\\\]|\\\\[^])*\\2",n].join("|")+")"),greedy:!0},{pattern:/("|`)(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:RegExp("\\b(?:m|qr)(?![a-zA-Z0-9])\\s*(?:"+["([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\1)[^\\\\]|\\\\[^])*\\1","([a-zA-Z0-9])(?:(?!\\2)[^\\\\]|\\\\[^])*\\2",n].join("|")+")[msixpodualngc]*"),greedy:!0},{pattern:RegExp("(^|[^-])\\b(?:s|tr|y)(?![a-zA-Z0-9])\\s*(?:"+["([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\2)[^\\\\]|\\\\[^])*\\2(?:(?!\\2)[^\\\\]|\\\\[^])*\\2","([a-zA-Z0-9])(?:(?!\\3)[^\\\\]|\\\\[^])*\\3(?:(?!\\3)[^\\\\]|\\\\[^])*\\3",n+"\\s*"+n].join("|")+")[msixpodualngcer]*"),lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|x|xor)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+(?![\w$]))+(?:::)*/,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*?>|\b_\b/,alias:"symbol"},"v-string":{pattern:/v\d+(?:\.\d+)*|\d+(?:\.\d+){2,}/,alias:"string"},function:{pattern:/(\bsub[ \t]+)\w+/,lookbehind:!0},keyword:/\b(?:any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|return|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(?:and|cmp|eq|ge|gt|le|lt|ne|not|or|xor)\b/,punctuation:/[{}[\];(),:]/}}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.insertBefore("php","variable",{this:{pattern:/\$this\b/,alias:"keyword"},global:/\$(?:GLOBALS|HTTP_RAW_POST_DATA|_(?:COOKIE|ENV|FILES|GET|POST|REQUEST|SERVER|SESSION)|argc|argv|http_response_header|php_errormsg)\b/,scope:{pattern:/\b[\w\\]+::/,inside:{keyword:/\b(?:parent|self|static)\b/,punctuation:/::|\\/}}});
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
||||
Prism.languages.plsql=Prism.languages.extend("sql",{comment:{pattern:/\/\*[\s\S]*?\*\/|--.*/,greedy:!0},keyword:/\b(?:A|ACCESSIBLE|ADD|AGENT|AGGREGATE|ALL|ALTER|AND|ANY|ARRAY|AS|ASC|AT|ATTRIBUTE|AUTHID|AVG|BEGIN|BETWEEN|BFILE_BASE|BINARY|BLOB_BASE|BLOCK|BODY|BOTH|BOUND|BULK|BY|BYTE|C|CALL|CALLING|CASCADE|CASE|CHAR|CHARACTER|CHARSET|CHARSETFORM|CHARSETID|CHAR_BASE|CHECK|CLOB_BASE|CLONE|CLOSE|CLUSTER|CLUSTERS|COLAUTH|COLLECT|COLUMNS|COMMENT|COMMIT|COMMITTED|COMPILED|COMPRESS|CONNECT|CONSTANT|CONSTRUCTOR|CONTEXT|CONTINUE|CONVERT|COUNT|CRASH|CREATE|CREDENTIAL|CURRENT|CURSOR|CUSTOMDATUM|DANGLING|DATA|DATE|DATE_BASE|DAY|DECLARE|DEFAULT|DEFINE|DELETE|DESC|DETERMINISTIC|DIRECTORY|DISTINCT|DOUBLE|DROP|DURATION|ELEMENT|ELSE|ELSIF|EMPTY|END|ESCAPE|EXCEPT|EXCEPTION|EXCEPTIONS|EXCLUSIVE|EXECUTE|EXISTS|EXIT|EXTERNAL|FETCH|FINAL|FIRST|FIXED|FLOAT|FOR|FORALL|FORCE|FROM|FUNCTION|GENERAL|GOTO|GRANT|GROUP|HASH|HAVING|HEAP|HIDDEN|HOUR|IDENTIFIED|IF|IMMEDIATE|IMMUTABLE|IN|INCLUDING|INDEX|INDEXES|INDICATOR|INDICES|INFINITE|INSERT|INSTANTIABLE|INT|INTERFACE|INTERSECT|INTERVAL|INTO|INVALIDATE|IS|ISOLATION|JAVA|LANGUAGE|LARGE|LEADING|LENGTH|LEVEL|LIBRARY|LIKE|LIKE2|LIKE4|LIKEC|LIMIT|LIMITED|LOCAL|LOCK|LONG|LOOP|MAP|MAX|MAXLEN|MEMBER|MERGE|MIN|MINUS|MINUTE|MOD|MODE|MODIFY|MONTH|MULTISET|MUTABLE|NAME|NAN|NATIONAL|NATIVE|NCHAR|NEW|NOCOMPRESS|NOCOPY|NOT|NOWAIT|NULL|NUMBER_BASE|OBJECT|OCICOLL|OCIDATE|OCIDATETIME|OCIDURATION|OCIINTERVAL|OCILOBLOCATOR|OCINUMBER|OCIRAW|OCIREF|OCIREFCURSOR|OCIROWID|OCISTRING|OCITYPE|OF|OLD|ON|ONLY|OPAQUE|OPEN|OPERATOR|OPTION|OR|ORACLE|ORADATA|ORDER|ORGANIZATION|ORLANY|ORLVARY|OTHERS|OUT|OVERLAPS|OVERRIDING|PACKAGE|PARALLEL_ENABLE|PARAMETER|PARAMETERS|PARENT|PARTITION|PASCAL|PERSISTABLE|PIPE|PIPELINED|PLUGGABLE|POLYMORPHIC|PRAGMA|PRECISION|PRIOR|PRIVATE|PROCEDURE|PUBLIC|RAISE|RANGE|RAW|READ|RECORD|REF|REFERENCE|RELIES_ON|REM|REMAINDER|RENAME|RESOURCE|RESULT|RESULT_CACHE|RETURN|RETURNING|REVERSE|REVOKE|ROLLBACK|ROW|SAMPLE|SAVE|SAVEPOINT|SB1|SB2|SB4|SECOND|SEGMENT|SELECT|SELF|SEPARATE|SEQUENCE|SERIALIZABLE|SET|SHARE|SHORT|SIZE|SIZE_T|SOME|SPARSE|SQL|SQLCODE|SQLDATA|SQLNAME|SQLSTATE|STANDARD|START|STATIC|STDDEV|STORED|STRING|STRUCT|STYLE|SUBMULTISET|SUBPARTITION|SUBSTITUTABLE|SUBTYPE|SUM|SYNONYM|TABAUTH|TABLE|TDO|THE|THEN|TIME|TIMESTAMP|TIMEZONE_ABBR|TIMEZONE_HOUR|TIMEZONE_MINUTE|TIMEZONE_REGION|TO|TRAILING|TRANSACTION|TRANSACTIONAL|TRUSTED|TYPE|UB1|UB2|UB4|UNDER|UNION|UNIQUE|UNPLUG|UNSIGNED|UNTRUSTED|UPDATE|USE|USING|VALIST|VALUE|VALUES|VARIABLE|VARIANCE|VARRAY|VARYING|VIEW|VIEWS|VOID|WHEN|WHERE|WHILE|WITH|WORK|WRAPPED|WRITE|YEAR|ZONE)\b/i,operator:/:=?|=>|[<>^~!]=|\.\.|\|\||\*\*|[-+*/%<>=@]/}),Prism.languages.insertBefore("plsql","operator",{label:{pattern:/<<\s*\w+\s*>>/,alias:"symbol"}});
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){var i=e.languages.powershell={comment:[{pattern:/(^|[^`])<#[\s\S]*?#>/,lookbehind:!0},{pattern:/(^|[^`])#.*/,lookbehind:!0}],string:[{pattern:/"(?:`[\s\S]|[^`"])*"/,greedy:!0,inside:null},{pattern:/'(?:[^']|'')*'/,greedy:!0}],namespace:/\[[a-z](?:\[(?:\[[^\]]*\]|[^\[\]])*\]|[^\[\]])*\]/i,boolean:/\$(?:false|true)\b/i,variable:/\$\w+\b/,function:[/\b(?:Add|Approve|Assert|Backup|Block|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|ForEach|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Sort|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Tee|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Where|Write)-[a-z]+\b/i,/\b(?:ac|cat|chdir|clc|cli|clp|clv|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|ebp|echo|epal|epcsv|epsn|erase|fc|fl|ft|fw|gal|gbp|gc|gci|gcs|gdr|gi|gl|gm|gp|gps|group|gsv|gu|gv|gwmi|iex|ii|ipal|ipcsv|ipsn|irm|iwmi|iwr|kill|lp|ls|measure|mi|mount|move|mp|mv|nal|ndr|ni|nv|ogv|popd|ps|pushd|pwd|rbp|rd|rdr|ren|ri|rm|rmdir|rni|rnp|rp|rv|rvpa|rwmi|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls|sort|sp|spps|spsv|start|sv|swmi|tee|trcm|type|write)\b/i],keyword:/\b(?:Begin|Break|Catch|Class|Continue|Data|Define|Do|DynamicParam|Else|ElseIf|End|Exit|Filter|Finally|For|ForEach|From|Function|If|InlineScript|Parallel|Param|Process|Return|Sequence|Switch|Throw|Trap|Try|Until|Using|Var|While|Workflow)\b/i,operator:{pattern:/(^|\W)(?:!|-(?:b?(?:and|x?or)|as|(?:Not)?(?:Contains|In|Like|Match)|eq|ge|gt|is(?:Not)?|Join|le|lt|ne|not|Replace|sh[lr])\b|-[-=]?|\+[+=]?|[*\/%]=?)/i,lookbehind:!0},punctuation:/[|{}[\];(),.]/};i.string[0].inside={function:{pattern:/(^|[^`])\$\((?:\$\([^\r\n()]*\)|(?!\$\()[^\r\n)])*\)/,lookbehind:!0,inside:i},boolean:i.boolean,variable:i.variable}}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.properties={comment:/^[ \t]*[#!].*$/m,value:{pattern:/(^[ \t]*(?:\\(?:\r\n|[\s\S])|[^\\\s:=])+(?: *[=:] *(?! )| ))(?:\\(?:\r\n|[\s\S])|[^\\\r\n])+/m,lookbehind:!0,alias:"attr-value"},key:{pattern:/^[ \t]*(?:\\(?:\r\n|[\s\S])|[^\\\s:=])+(?= *[=:]| )/m,alias:"attr-name"},punctuation:/[=:]/};
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){var s=/\b(?:bool|bytes|double|s?fixed(?:32|64)|float|[su]?int(?:32|64)|string)\b/;e.languages.protobuf=e.languages.extend("clike",{"class-name":[{pattern:/(\b(?:enum|extend|message|service)\s+)[A-Za-z_]\w*(?=\s*\{)/,lookbehind:!0},{pattern:/(\b(?:rpc\s+\w+|returns)\s*\(\s*(?:stream\s+)?)\.?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*(?=\s*\))/,lookbehind:!0}],keyword:/\b(?:enum|extend|extensions|import|message|oneof|option|optional|package|public|repeated|required|reserved|returns|rpc(?=\s+\w)|service|stream|syntax|to)\b(?!\s*=\s*\d)/,function:/\b[a-z_]\w*(?=\s*\()/i}),e.languages.insertBefore("protobuf","operator",{map:{pattern:/\bmap<\s*[\w.]+\s*,\s*[\w.]+\s*>(?=\s+[a-z_]\w*\s*[=;])/i,alias:"class-name",inside:{punctuation:/[<>.,]/,builtin:s}},builtin:s,"positional-class-name":{pattern:/(?:\b|\B\.)[a-z_]\w*(?:\.[a-z_]\w*)*(?=\s+[a-z_]\w*\s*[=;])/i,alias:"class-name",inside:{punctuation:/\./}},annotation:{pattern:/(\[\s*)[a-z_]\w*(?=\s*=)/i,lookbehind:!0}})}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern://,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python;
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.r={comment:/#.*/,string:{pattern:/(['"])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},"percent-operator":{pattern:/%[^%\s]*%/,alias:"operator"},boolean:/\b(?:FALSE|TRUE)\b/,ellipsis:/\.\.(?:\.|\d+)/,number:[/\b(?:Inf|NaN)\b/,/(?:\b0x[\dA-Fa-f]+(?:\.\d*)?|\b\d+(?:\.\d*)?|\B\.\d+)(?:[EePp][+-]?\d+)?[iL]?/],keyword:/\b(?:NA|NA_character_|NA_complex_|NA_integer_|NA_real_|NULL|break|else|for|function|if|in|next|repeat|while)\b/,operator:/->?>?|<(?:=|<?-)?|[>=!]=?|::?|&&?|\|\|?|[+*\/^$@~]/,punctuation:/[(){}\[\],;]/};
|
||||
@@ -1 +0,0 @@
|
||||
!function(a){var e={pattern:/\\[\\(){}[\]^$+*?|.]/,alias:"escape"},n=/\\(?:x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]+\}|0[0-7]{0,2}|[123][0-7]{2}|c[a-zA-Z]|.)/,t="(?:[^\\\\-]|"+n.source+")",s=RegExp(t+"-"+t),i={pattern:/(<|')[^<>']+(?=[>']$)/,lookbehind:!0,alias:"variable"};a.languages.regex={"char-class":{pattern:/((?:^|[^\\])(?:\\\\)*)\[(?:[^\\\]]|\\[\s\S])*\]/,lookbehind:!0,inside:{"char-class-negation":{pattern:/(^\[)\^/,lookbehind:!0,alias:"operator"},"char-class-punctuation":{pattern:/^\[|\]$/,alias:"punctuation"},range:{pattern:s,inside:{escape:n,"range-punctuation":{pattern:/-/,alias:"operator"}}},"special-escape":e,"char-set":{pattern:/\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},escape:n}},"special-escape":e,"char-set":{pattern:/\.|\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},backreference:[{pattern:/\\(?![123][0-7]{2})[1-9]/,alias:"keyword"},{pattern:/\\k<[^<>']+>/,alias:"keyword",inside:{"group-name":i}}],anchor:{pattern:/[$^]|\\[ABbGZz]/,alias:"function"},escape:n,group:[{pattern:/\((?:\?(?:<[^<>']+>|'[^<>']+'|[>:]|<?[=!]|[idmnsuxU]+(?:-[idmnsuxU]+)?:?))?/,alias:"punctuation",inside:{"group-name":i}},{pattern:/\)/,alias:"punctuation"}],quantifier:{pattern:/(?:[+*?]|\{\d+(?:,\d*)?\})[?+]?/,alias:"number"},alternation:{pattern:/\|/,alias:"keyword"}}}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){e.languages.ruby=e.languages.extend("clike",{comment:{pattern:/#.*|^=begin\s[\s\S]*?^=end/m,greedy:!0},"class-name":{pattern:/(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:BEGIN|END|alias|and|begin|break|case|class|def|define_method|defined|do|each|else|elsif|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|private|protected|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/,operator:/\.{2,3}|&\.|===|<?=>|[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,punctuation:/[(){}[\].,;]/}),e.languages.insertBefore("ruby","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}});var n={pattern:/((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,lookbehind:!0,inside:{content:{pattern:/^(#\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:e.languages.ruby},delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"}}};delete e.languages.ruby.function;var t="(?:"+["([^a-zA-Z0-9\\s{(\\[<=])(?:(?!\\1)[^\\\\]|\\\\[^])*\\1","\\((?:[^()\\\\]|\\\\[^]|\\((?:[^()\\\\]|\\\\[^])*\\))*\\)","\\{(?:[^{}\\\\]|\\\\[^]|\\{(?:[^{}\\\\]|\\\\[^])*\\})*\\}","\\[(?:[^\\[\\]\\\\]|\\\\[^]|\\[(?:[^\\[\\]\\\\]|\\\\[^])*\\])*\\]","<(?:[^<>\\\\]|\\\\[^]|<(?:[^<>\\\\]|\\\\[^])*>)*>"].join("|")+")",i='(?:"(?:\\\\.|[^"\\\\\r\n])*"|(?:\\b[a-zA-Z_]\\w*|[^\\s\0-\\x7F]+)[?!]?|\\$.)';e.languages.insertBefore("ruby","keyword",{"regex-literal":[{pattern:RegExp("%r"+t+"[egimnosux]{0,6}"),greedy:!0,inside:{interpolation:n,regex:/[\s\S]+/}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:n,regex:/[\s\S]+/}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:[{pattern:RegExp("(^|[^:]):"+i),lookbehind:!0,greedy:!0},{pattern:RegExp("([\r\n{(,][ \t]*)"+i+"(?=:(?!:))"),lookbehind:!0,greedy:!0}],"method-definition":{pattern:/(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,lookbehind:!0,inside:{function:/\b\w+$/,keyword:/^self\b/,"class-name":/^\w+/,punctuation:/\./}}}),e.languages.insertBefore("ruby","string",{"string-literal":[{pattern:RegExp("%[qQiIwWs]?"+t),greedy:!0,inside:{interpolation:n,string:/[\s\S]+/}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:n,string:/[\s\S]+/}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?/}},interpolation:n,string:/[\s\S]+/}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?'|'$/}},string:/[\s\S]+/}}],"command-literal":[{pattern:RegExp("%x"+t),greedy:!0,inside:{interpolation:n,command:{pattern:/[\s\S]+/,alias:"string"}}},{pattern:/`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,greedy:!0,inside:{interpolation:n,command:{pattern:/[\s\S]+/,alias:"string"}}}]}),delete e.languages.ruby.string,e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,constant:/\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/}),e.languages.rb=e.languages.ruby}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){for(var a="/\\*(?:[^*/]|\\*(?!/)|/(?!\\*)|<self>)*\\*/",t=0;t<2;t++)a=a.replace(/<self>/g,(function(){return a}));a=a.replace(/<self>/g,(function(){return"[^\\s\\S]"})),e.languages.rust={comment:[{pattern:RegExp("(^|[^\\\\])"+a),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<<?=?|>>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/}}}),delete e.languages.sass.atrule;var r=/\$[-\w]+|#\{\$[-\w]+\}/,t=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|not|or)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:r,operator:t}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:r,operator:t,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.scala=Prism.languages.extend("java",{"triple-quoted-string":{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},keyword:/<-|=>|\b(?:abstract|case|catch|class|def|derives|do|else|enum|extends|extension|final|finally|for|forSome|given|if|implicit|import|infix|inline|lazy|match|new|null|object|opaque|open|override|package|private|protected|return|sealed|self|super|this|throw|trait|transparent|try|type|using|val|var|while|with|yield)\b/,number:/\b0x(?:[\da-f]*\.)?[\da-f]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e\d+)?[dfl]?/i,builtin:/\b(?:Any|AnyRef|AnyVal|Boolean|Byte|Char|Double|Float|Int|Long|Nothing|Short|String|Unit)\b/,symbol:/'[^\d\s\\]\w*/}),Prism.languages.insertBefore("scala","triple-quoted-string",{"string-interpolation":{pattern:/\b[a-z]\w*(?:"""(?:[^$]|\$(?:[^{]|\{(?:[^{}]|\{[^{}]*\})*\}))*?"""|"(?:[^$"\r\n]|\$(?:[^{]|\{(?:[^{}]|\{[^{}]*\})*\}))*")/i,greedy:!0,inside:{id:{pattern:/^\w+/,greedy:!0,alias:"function"},escape:{pattern:/\\\$"|\$[$"]/,greedy:!0,alias:"symbol"},interpolation:{pattern:/\$(?:\w+|\{(?:[^{}]|\{[^{}]*\})*\})/,greedy:!0,inside:{punctuation:/^\$\{?|\}$/,expression:{pattern:/[\s\S]+/,inside:Prism.languages.scala}}},string:/[\s\S]+/}}}),delete Prism.languages.scala["class-name"],delete Prism.languages.scala.function,delete Prism.languages.scala.constant;
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.scss=Prism.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),Prism.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),Prism.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),Prism.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),Prism.languages.scss.atrule.inside.rest=Prism.languages.scss;
|
||||
@@ -1 +0,0 @@
|
||||
!function(s){var n=['"(?:\\\\[^]|\\$\\([^)]+\\)|\\$(?!\\()|`[^`]+`|[^"\\\\`$])*"',"'[^']*'","\\$'(?:[^'\\\\]|\\\\[^])*'","<<-?\\s*([\"']?)(\\w+)\\1\\s[^]*?[\r\n]\\2"].join("|");s.languages["shell-session"]={command:{pattern:RegExp('^(?:[^\\s@:$#%*!/\\\\]+@[^\r\n@:$#%*!/\\\\]+(?::[^\0-\\x1F$#%*?"<>:;|]+)?|[/~.][^\0-\\x1F$#%*?"<>@:;|]*)?[$#%](?=\\s)'+"(?:[^\\\\\r\n \t'\"<$]|[ \t](?:(?!#)|#.*$)|\\\\(?:[^\r]|\r\n?)|\\$(?!')|<(?!<)|<<str>>)+".replace(/<<str>>/g,(function(){return n})),"m"),greedy:!0,inside:{info:{pattern:/^[^#$%]+/,alias:"punctuation",inside:{user:/^[^\s@:$#%*!/\\]+@[^\r\n@:$#%*!/\\]+/,punctuation:/:/,path:/[\s\S]+/}},bash:{pattern:/(^[$#%]\s*)\S[\s\S]*/,lookbehind:!0,alias:"language-bash",inside:s.languages.bash},"shell-symbol":{pattern:/^[$#%]/,alias:"important"}}},output:/.(?:.*(?:[\r\n]|.$))*/},s.languages["sh-session"]=s.languages.shellsession=s.languages["shell-session"]}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\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,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/};
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp('(^|[^"#])(?:"(?:\\\\(?:\\((?:[^()]|\\([^()]*\\))*\\)|\r\n|[^(])|[^\\\\\r\n"])*"|"""(?:\\\\(?:\\((?:[^()]|\\([^()]*\\))*\\)|[^(])|[^\\\\"]|"(?!""))*""")(?!["#])'),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp('(^|[^"#])(#+)(?:"(?:\\\\(?:#+\\((?:[^()]|\\([^()]*\\))*\\)|\r\n|[^#])|[^\\\\\r\n])*?"|"""(?:\\\\(?:#+\\((?:[^()]|\\([^()]*\\))*\\)|[^#])|[^\\\\])*?""")\\2'),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp("#(?:(?:elseif|if)\\b(?:[ \t]*(?:![ \t]*)?(?:\\b\\w+\\b(?:[ \t]*\\((?:[^()]|\\([^()]*\\))*\\))?|\\((?:[^()]|\\([^()]*\\))*\\))(?:[ \t]*(?:&&|\\|\\|))?)+|(?:else|endif)\\b)"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},Prism.languages.swift["string-literal"].forEach((function(e){e.inside.interpolation.inside=Prism.languages.swift}));
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){function n(e){return e.replace(/__/g,(function(){return"(?:[\\w-]+|'[^'\n\r]*'|\"(?:\\\\.|[^\\\\\"\r\n])*\")"}))}e.languages.toml={comment:{pattern:/#.*/,greedy:!0},table:{pattern:RegExp(n("(^[\t ]*\\[\\s*(?:\\[\\s*)?)__(?:\\s*\\.\\s*__)*(?=\\s*\\])"),"m"),lookbehind:!0,greedy:!0,alias:"class-name"},key:{pattern:RegExp(n("(^[\t ]*|[{,]\\s*)__(?:\\s*\\.\\s*__)*(?=\\s*=)"),"m"),lookbehind:!0,greedy:!0,alias:"property"},string:{pattern:/"""(?:\\[\s\S]|[^\\])*?"""|'''[\s\S]*?'''|'[^'\n\r]*'|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},date:[{pattern:/\b\d{4}-\d{2}-\d{2}(?:[T\s]\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})?)?\b/i,alias:"number"},{pattern:/\b\d{2}:\d{2}:\d{2}(?:\.\d+)?\b/,alias:"number"}],number:/(?:\b0(?:x[\da-zA-Z]+(?:_[\da-zA-Z]+)*|o[0-7]+(?:_[0-7]+)*|b[10]+(?:_[10]+)*))\b|[-+]?\b\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?\b|[-+]?\b(?:inf|nan)\b/,boolean:/\b(?:false|true)\b/,punctuation:/[.,=[\]{}]/}}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){var a=e.util.clone(e.languages.typescript);e.languages.tsx=e.languages.extend("jsx",a),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"];var t=e.languages.tsx.tag;t.pattern=RegExp("(^|[^\\w$]|(?=</))(?:"+t.pattern.source+")",t.pattern.flags),t.lookbehind=!0}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var s=e.languages.extend("typescript",{});delete s["class-name"],e.languages.typescript["class-name"].inside=s,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:s}}}}),e.languages.ts=e.languages.typescript}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages.vbnet=Prism.languages.extend("basic",{comment:[{pattern:/(?:!|REM\b).+/i,inside:{keyword:/^REM/i}},{pattern:/(^|[^\\:])'.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(^|[^"])"(?:""|[^"])*"(?!")/,lookbehind:!0,greedy:!0},keyword:/(?:\b(?:ADDHANDLER|ADDRESSOF|ALIAS|AND|ANDALSO|AS|BEEP|BLOAD|BOOLEAN|BSAVE|BYREF|BYTE|BYVAL|CALL(?: ABSOLUTE)?|CASE|CATCH|CBOOL|CBYTE|CCHAR|CDATE|CDBL|CDEC|CHAIN|CHAR|CHDIR|CINT|CLASS|CLEAR|CLNG|CLOSE|CLS|COBJ|COM|COMMON|CONST|CONTINUE|CSBYTE|CSHORT|CSNG|CSTR|CTYPE|CUINT|CULNG|CUSHORT|DATA|DATE|DECIMAL|DECLARE|DEF(?: FN| SEG|DBL|INT|LNG|SNG|STR)|DEFAULT|DELEGATE|DIM|DIRECTCAST|DO|DOUBLE|ELSE|ELSEIF|END|ENUM|ENVIRON|ERASE|ERROR|EVENT|EXIT|FALSE|FIELD|FILES|FINALLY|FOR(?: EACH)?|FRIEND|FUNCTION|GET|GETTYPE|GETXMLNAMESPACE|GLOBAL|GOSUB|GOTO|HANDLES|IF|IMPLEMENTS|IMPORTS|IN|INHERITS|INPUT|INTEGER|INTERFACE|IOCTL|IS|ISNOT|KEY|KILL|LET|LIB|LIKE|LINE INPUT|LOCATE|LOCK|LONG|LOOP|LSET|ME|MKDIR|MOD|MODULE|MUSTINHERIT|MUSTOVERRIDE|MYBASE|MYCLASS|NAME|NAMESPACE|NARROWING|NEW|NEXT|NOT|NOTHING|NOTINHERITABLE|NOTOVERRIDABLE|OBJECT|OF|OFF|ON(?: COM| ERROR| KEY| TIMER)?|OPEN|OPERATOR|OPTION(?: BASE)?|OPTIONAL|OR|ORELSE|OUT|OVERLOADS|OVERRIDABLE|OVERRIDES|PARAMARRAY|PARTIAL|POKE|PRIVATE|PROPERTY|PROTECTED|PUBLIC|PUT|RAISEEVENT|READ|READONLY|REDIM|REM|REMOVEHANDLER|RESTORE|RESUME|RETURN|RMDIR|RSET|RUN|SBYTE|SELECT(?: CASE)?|SET|SHADOWS|SHARED|SHELL|SHORT|SINGLE|SLEEP|STATIC|STEP|STOP|STRING|STRUCTURE|SUB|SWAP|SYNCLOCK|SYSTEM|THEN|THROW|TIMER|TO|TROFF|TRON|TRUE|TRY|TRYCAST|TYPE|TYPEOF|UINTEGER|ULONG|UNLOCK|UNTIL|USHORT|USING|VIEW PRINT|WAIT|WEND|WHEN|WHILE|WIDENING|WITH|WITHEVENTS|WRITE|WRITEONLY|XOR)|\B(?:#CONST|#ELSE|#ELSEIF|#END|#IF))(?:\$|\b)/i,punctuation:/[,;:(){}]/});
|
||||
@@ -1 +0,0 @@
|
||||
Prism.languages["visual-basic"]={comment:{pattern:/(?:['‘’]|REM\b)(?:[^\r\n_]|_(?:\r\n?|\n)?)*/i,inside:{keyword:/^REM/i}},directive:{pattern:/#(?:Const|Else|ElseIf|End|ExternalChecksum|ExternalSource|If|Region)(?:\b_[ \t]*(?:\r\n?|\n)|.)+/i,alias:"property",greedy:!0},string:{pattern:/\$?["“”](?:["“”]{2}|[^"“”])*["“”]C?/i,greedy:!0},date:{pattern:/#[ \t]*(?:\d+([/-])\d+\1\d+(?:[ \t]+(?:\d+[ \t]*(?:AM|PM)|\d+:\d+(?::\d+)?(?:[ \t]*(?:AM|PM))?))?|\d+[ \t]*(?:AM|PM)|\d+:\d+(?::\d+)?(?:[ \t]*(?:AM|PM))?)[ \t]*#/i,alias:"number"},number:/(?:(?:\b\d+(?:\.\d+)?|\.\d+)(?:E[+-]?\d+)?|&[HO][\dA-F]+)(?:[FRD]|U?[ILS])?/i,boolean:/\b(?:False|Nothing|True)\b/i,keyword:/\b(?:AddHandler|AddressOf|Alias|And(?:Also)?|As|Boolean|ByRef|Byte|ByVal|Call|Case|Catch|C(?:Bool|Byte|Char|Date|Dbl|Dec|Int|Lng|Obj|SByte|Short|Sng|Str|Type|UInt|ULng|UShort)|Char|Class|Const|Continue|Currency|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double|Each|Else(?:If)?|End(?:If)?|Enum|Erase|Error|Event|Exit|Finally|For|Friend|Function|Get(?:Type|XMLNamespace)?|Global|GoSub|GoTo|Handles|If|Implements|Imports|In|Inherits|Integer|Interface|Is|IsNot|Let|Lib|Like|Long|Loop|Me|Mod|Module|Must(?:Inherit|Override)|My(?:Base|Class)|Namespace|Narrowing|New|Next|Not(?:Inheritable|Overridable)?|Object|Of|On|Operator|Option(?:al)?|Or(?:Else)?|Out|Overloads|Overridable|Overrides|ParamArray|Partial|Private|Property|Protected|Public|RaiseEvent|ReadOnly|ReDim|RemoveHandler|Resume|Return|SByte|Select|Set|Shadows|Shared|short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock|Then|Throw|To|Try|TryCast|Type|TypeOf|U(?:Integer|Long|Short)|Until|Using|Variant|Wend|When|While|Widening|With(?:Events)?|WriteOnly|Xor)\b/i,operator:/[+\-*/\\^<=>&#@$%!]|\b_(?=[ \t]*[\r\n])/,punctuation:/[{}().,:?]/},Prism.languages.vb=Prism.languages["visual-basic"],Prism.languages.vba=Prism.languages["visual-basic"];
|
||||
@@ -1 +0,0 @@
|
||||
!function(a){function e(e,n){a.languages[e]&&a.languages.insertBefore(e,"comment",{"doc-comment":n})}var n=a.languages.markup.tag,t={pattern:/\/\/\/.*/,greedy:!0,alias:"comment",inside:{tag:n}},g={pattern:/'''.*/,greedy:!0,alias:"comment",inside:{tag:n}};e("csharp",t),e("fsharp",t),e("vbnet",g)}(Prism);
|
||||
@@ -1 +0,0 @@
|
||||
!function(e){var n=/[*&][^\s[\]{},]+/,r=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,t="(?:"+r.source+"(?:[ \t]+"+n.source+")?|"+n.source+"(?:[ \t]+"+r.source+")?)",a="(?:[^\\s\\x00-\\x08\\x0e-\\x1f!\"#%&'*,\\-:>?@[\\]`{|}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]|[?:-]<PLAIN>)(?:[ \t]*(?:(?![#:])<PLAIN>|:<PLAIN>))*".replace(/<PLAIN>/g,(function(){return"[^\\s\\x00-\\x08\\x0e-\\x1f,[\\]{}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]"})),d="\"(?:[^\"\\\\\r\n]|\\\\.)*\"|'(?:[^'\\\\\r\n]|\\\\.)*'";function o(e,n){n=(n||"").replace(/m/g,"")+"m";var r="([:\\-,[{]\\s*(?:\\s<<prop>>[ \t]+)?)(?:<<value>>)(?=[ \t]*(?:$|,|\\]|\\}|(?:[\r\n]\\s*)?#))".replace(/<<prop>>/g,(function(){return t})).replace(/<<value>>/g,(function(){return e}));return RegExp(r,n)}e.languages.yaml={scalar:{pattern:RegExp("([\\-:]\\s*(?:\\s<<prop>>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\\S[^\r\n]*(?:\\2[^\r\n]+)*)".replace(/<<prop>>/g,(function(){return t}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp("((?:^|[:\\-,[{\r\n?])[ \t]*(?:<<prop>>[ \t]+)?)<<key>>(?=\\s*:\\s)".replace(/<<prop>>/g,(function(){return t})).replace(/<<key>>/g,(function(){return"(?:"+a+"|"+d+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:o("\\d{4}-\\d\\d?-\\d\\d?(?:[tT]|[ \t]+)\\d\\d?:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[ \t]*(?:Z|[-+]\\d\\d?(?::\\d{2})?))?|\\d{4}-\\d{2}-\\d{2}|\\d\\d?:\\d{2}(?::\\d{2}(?:\\.\\d*)?)?"),lookbehind:!0,alias:"number"},boolean:{pattern:o("false|true","i"),lookbehind:!0,alias:"important"},null:{pattern:o("null|~","i"),lookbehind:!0,alias:"important"},string:{pattern:o(d),lookbehind:!0,greedy:!0},number:{pattern:o("[+-]?(?:0x[\\da-f]+|0o[0-7]+|(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?|\\.inf|\\.nan)","i"),lookbehind:!0},tag:r,important:n,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user