chore: prepare for offline test

这个提交包含在:
bhsd 2023-01-22 02:19:54 -08:00
父节点 6053133f0e
当前提交 18be436276
共有 7 个文件被更改,包括 519 次插入4 次删除

查看文件

@ -1,6 +1,6 @@
{
"env": {
"browser": true,
"node": true,
"es6": true
},
"plugins": [
@ -19,6 +19,9 @@
"mw": "readonly",
"CodeMirror": "readonly"
},
"ignorePatterns": [
"codemirror.js"
],
"rules": {
"array-callback-return": 2,
"no-cond-assign": 0,
@ -410,5 +413,16 @@
"es-x": {
"aggressive": true
}
}
},
"overrides": [
{
"files": [
"mediawiki.js"
],
"env": {
"browser": true,
"node": false
}
}
]
}

1
.gitignore vendored
查看文件

@ -3,3 +3,4 @@
.DS_Store
.vscode/
test.txt
processed.txt

248
codemirror.js 普通文件
查看文件

@ -0,0 +1,248 @@
/*
* CodeMirror, copyright (c) by Marijn Haverbeke and others
* Distributed under an MIT license: https://codemirror.net/LICENSE
*/
'use strict';
// STRING STREAM
/*
* Fed to the mode parsers, provides helper functions to make
* parsers more succinct.
*/
class StringStream {
constructor( string, lineOracle ) {
this.pos = 0;
this.start = 0;
this.string = string;
this.lineStart = 0;
this.lineOracle = lineOracle;
}
eol() {
return this.pos >= this.string.length;
}
sol() {
return this.pos === this.lineStart;
}
peek() {
return this.string.charAt( this.pos ) || undefined;
}
next() {
if ( !this.eol() ) {
return this.string.charAt( this.pos++ );
}
}
eat( match ) {
const ch = this.string.charAt( this.pos );
let ok;
if ( typeof match === 'string' ) {
ok = ch === match;
} else {
ok = ch && ( match.test ? match.test( ch ) : match( ch ) );
}
if ( ok ) {
++this.pos;
return ch;
}
}
eatWhile( match ) {
const start = this.pos;
while ( this.eat( match ) ) {
// pass
}
return this.pos > start;
}
eatSpace() {
const start = this.pos;
while ( /[\s\xa0]/.test( this.string.charAt( this.pos ) ) ) {
++this.pos;
}
return this.pos > start;
}
skipToEnd() {
this.pos = this.string.length;
}
skipTo( ch ) {
const found = this.string.indexOf( ch, this.pos );
if ( found > -1 ) {
this.pos = found;
return true;
}
}
backUp( n ) {
this.pos -= n;
}
match( pattern, consume, caseInsensitive ) {
if ( typeof pattern === 'string' ) {
const cased = function ( str ) {
return caseInsensitive ? str.toLowerCase() : str;
};
const substr = this.string.substr( this.pos, pattern.length );
if ( cased( substr ) === cased( pattern ) ) {
if ( consume !== false ) {
this.pos += pattern.length;
}
return true;
}
} else {
const match = this.string.slice( this.pos ).match( pattern );
if ( match && match.index > 0 ) {
return null;
} else if ( match && consume !== false ) {
this.pos += match[ 0 ].length;
}
return match;
}
}
current() {
return this.string.slice( this.start, this.pos );
}
lookAhead( n ) {
const oracle = this.lineOracle;
return oracle && oracle.lookAhead( n );
}
}
/**
* @typedef {object} mime
* @property {string} name
* @property {any}
*/
/**
* @typedef {object} mode
* @property {function} startState
* @property {function} copyState
* @property {function} token
* @property {function} blankLine
*/
/**
* @typedef {function} factory
* @returns {mode}
*/
// Known modes, by name and by MIME
const modes = {}, /** @type {Object.<string, factory>} */
mimeModes = {}, /** @type {Object.<string, string>} */
defaults = {};
/**
* @param {string} name
* @param {factory} mode
*/
function defineMode( name, mode ) {
modes[ name ] = mode;
}
/**
* @param {string} mime
* @param {string} spec
*/
function defineMIME( mime, spec ) {
mimeModes[ mime ] = spec;
}
/**
* Given a MIME type, a {name, ...options} config object, or a name
* string, return a copy of the mode config object.
* @param {?(string|mime)} spec
* @returns {mime}
*/
function resolveMode( spec ) {
let found = spec;
if ( typeof spec === 'string' && spec in mimeModes ) {
found = mimeModes[ spec ];
} else if ( spec && typeof spec.name === 'string' && spec.name in mimeModes ) {
found.name = mimeModes[ spec.name ];
}
if ( typeof found === 'string' ) {
return { name: found };
}
return found || { name: 'null' };
}
/**
* Given a mode spec (anything that resolveMode accepts), find and
* initialize an actual mode object.
* @param {?object} options
* @param {?(string|mime)} spec
* @returns {mode}
*/
function getMode( options, spec ) {
const found = resolveMode( spec ), /** @type {mime} */
mfactory = modes[ found.name ]; /** @type {factory} */
if ( !mfactory ) {
return getMode( options, 'text/plain' );
}
const modeObj = mfactory( options, found ); /** @type {mode} */
modeObj.name = spec.name;
return modeObj;
}
function copyState( mode, state ) {
if ( state === true ) {
return true;
}
if ( mode.copyState ) {
return mode.copyState( state );
}
return structuredClone( state );
}
function startState( mode, a1, a2 ) {
return mode.startState ? mode.startState( a1, a2 ) : true;
}
function runMode( string, modespec, callback, options ) {
let i = 0;
const mode = getMode( defaults, modespec ),
lines = string.split( '\n' ),
state = options && options.state || startState( mode ),
lineOracle = {
lookAhead( n ) {
return lines[ i + n ];
},
};
for ( const e = lines.length; i < e; ++i ) {
if ( i ) {
callback( '\n' );
}
const stream = new StringStream( lines[ i ], lineOracle );
if ( !stream.string && mode.blankLine ) {
mode.blankLine( state );
}
while ( !stream.eol() ) {
const style = mode.token( stream, state );
callback( stream.current(), style, i, stream.start, state, mode );
stream.start = stream.pos;
}
}
}
// Copy StringStream and mode methods into exports (CodeMirror) object.
const CodeMirror = {
defaults,
modes,
mimeModes,
defineMode,
defineMIME,
getMode,
copyState,
startState,
runMode,
};
// Minimal default mode.
CodeMirror.defineMode( 'null', function () {
return {
token( stream ) {
return stream.skipToEnd();
},
};
} );
CodeMirror.defineMIME( 'text/plain', 'null' );
module.exports = CodeMirror;

228
config.json 普通文件
查看文件

@ -0,0 +1,228 @@
{
"tagModes": {
"ref": "text/mediawiki",
"pre": "mw-tag-pre",
"nowiki": "mw-tag-nowiki"
},
"tags": {
"pre": true,
"nowiki": true,
"gallery": true,
"indicator": true,
"poem": true,
"ref": true,
"references": true,
"categorytree": true
},
"doubleUnderscore": [
{
"__notoc__": "notoc",
"__nogallery__": "nogallery",
"__forcetoc__": "forcetoc",
"__toc__": "toc",
"__noeditsection__": "noeditsection",
"__notitleconvert__": "notitleconvert",
"__notc__": "notitleconvert",
"__nocontentconvert__": "nocontentconvert",
"__nocc__": "nocontentconvert"
},
{
"__NEWSECTIONLINK__": "newsectionlink",
"__NONEWSECTIONLINK__": "nonewsectionlink",
"__HIDDENCAT__": "hiddencat",
"__EXPECTUNUSEDCATEGORY__": "expectunusedcategory",
"__INDEX__": "index",
"__NOINDEX__": "noindex",
"__STATICREDIRECT__": "staticredirect",
"__NOGLOBAL__": "noglobal",
"__EXPECTED_UNCONNECTED_PAGE__": "expectedUnconnectedPage"
}
],
"functionSynonyms": [
{
"ns": "ns",
"nse": "nse",
"urlencode": "urlencode",
"lcfirst": "lcfirst",
"ucfirst": "ucfirst",
"lc": "lc",
"uc": "uc",
"localurl": "localurl",
"localurle": "localurle",
"fullurl": "fullurl",
"fullurle": "fullurle",
"canonicalurl": "canonicalurl",
"canonicalurle": "canonicalurle",
"formatnum": "formatnum",
"grammar": "grammar",
"gender": "gender",
"plural": "plural",
"bidi": "bidi",
"#language": "language",
"padleft": "padleft",
"padright": "padright",
"anchorencode": "anchorencode",
"filepath": "filepath",
"pageid": "pageid",
"int": "int",
"#special": "special",
"#speciale": "speciale",
"#tag": "tag",
"#formatdate": "formatdate",
"#dateformat": "formatdate",
"#invoke": "invoke",
"#if": "if",
"#ifeq": "ifeq",
"#switch": "switch",
"#ifexist": "ifexist",
"#ifexpr": "ifexpr",
"#iferror": "iferror",
"#time": "time",
"#timel": "timel",
"#expr": "expr",
"#rel2abs": "rel2abs",
"#titleparts": "titleparts",
"#categorytree": "categorytree",
"articlepath": "articlepath",
"server": "server",
"servername": "servername",
"scriptpath": "scriptpath",
"stylepath": "stylepath",
"msg": "msg",
"raw": "raw",
"msgnw": "msgnw",
"subst": "subst",
"safesubst": "safesubst"
},
{
"NUMBEROFPAGES": "numberofpages",
"NUMBEROFUSERS": "numberofusers",
"NUMBEROFACTIVEUSERS": "numberofactiveusers",
"NUMBEROFARTICLES": "numberofarticles",
"NUMBEROFFILES": "numberoffiles",
"NUMBEROFADMINS": "numberofadmins",
"NUMBERINGROUP": "numberingroup",
"NUMINGROUP": "numberingroup",
"NUMBEROFEDITS": "numberofedits",
"DEFAULTSORT": "defaultsort",
"DEFAULTSORTKEY": "defaultsort",
"DEFAULTCATEGORYSORT": "defaultsort",
"PAGESINCATEGORY": "pagesincategory",
"PAGESINCAT": "pagesincategory",
"PAGESIZE": "pagesize",
"PROTECTIONLEVEL": "protectionlevel",
"PROTECTIONEXPIRY": "protectionexpiry",
"NAMESPACEE": "namespacee",
"NAMESPACENUMBER": "namespacenumber",
"TALKSPACE": "talkspace",
"TALKSPACEE": "talkspacee",
"SUBJECTSPACE": "subjectspace",
"ARTICLESPACE": "subjectspace",
"SUBJECTSPACEE": "subjectspacee",
"ARTICLESPACEE": "subjectspacee",
"PAGENAME": "pagename",
"PAGENAMEE": "pagenamee",
"FULLPAGENAME": "fullpagename",
"FULLPAGENAMEE": "fullpagenamee",
"ROOTPAGENAME": "rootpagename",
"ROOTPAGENAMEE": "rootpagenamee",
"BASEPAGENAME": "basepagename",
"BASEPAGENAMEE": "basepagenamee",
"SUBPAGENAME": "subpagename",
"SUBPAGENAMEE": "subpagenamee",
"TALKPAGENAME": "talkpagename",
"TALKPAGENAMEE": "talkpagenamee",
"SUBJECTPAGENAME": "subjectpagename",
"ARTICLEPAGENAME": "subjectpagename",
"SUBJECTPAGENAMEE": "subjectpagenamee",
"ARTICLEPAGENAMEE": "subjectpagenamee",
"REVISIONID": "revisionid",
"REVISIONDAY": "revisionday",
"REVISIONDAY2": "revisionday2",
"REVISIONMONTH": "revisionmonth",
"REVISIONMONTH1": "revisionmonth1",
"REVISIONYEAR": "revisionyear",
"REVISIONTIMESTAMP": "revisiontimestamp",
"REVISIONUSER": "revisionuser",
"CASCADINGSOURCES": "cascadingsources",
"NAMESPACE": "namespace",
"DISPLAYTITLE": "displaytitle",
"!": "!",
"CURRENTMONTH": "currentmonth",
"CURRENTMONTH2": "currentmonth",
"CURRENTMONTH1": "currentmonth1",
"CURRENTMONTHNAME": "currentmonthname",
"CURRENTMONTHNAMEGEN": "currentmonthnamegen",
"CURRENTMONTHABBREV": "currentmonthabbrev",
"CURRENTDAY": "currentday",
"CURRENTDAY2": "currentday2",
"CURRENTDAYNAME": "currentdayname",
"CURRENTYEAR": "currentyear",
"CURRENTTIME": "currenttime",
"CURRENTHOUR": "currenthour",
"LOCALMONTH": "localmonth",
"LOCALMONTH2": "localmonth",
"LOCALMONTH1": "localmonth1",
"LOCALMONTHNAME": "localmonthname",
"LOCALMONTHNAMEGEN": "localmonthnamegen",
"LOCALMONTHABBREV": "localmonthabbrev",
"LOCALDAY": "localday",
"LOCALDAY2": "localday2",
"LOCALDAYNAME": "localdayname",
"LOCALYEAR": "localyear",
"LOCALTIME": "localtime",
"LOCALHOUR": "localhour",
"SITENAME": "sitename",
"CURRENTWEEK": "currentweek",
"CURRENTDOW": "currentdow",
"LOCALWEEK": "localweek",
"LOCALDOW": "localdow",
"REVISIONSIZE": "revisionsize",
"CURRENTVERSION": "currentversion",
"CURRENTTIMESTAMP": "currenttimestamp",
"LOCALTIMESTAMP": "localtimestamp",
"CONTENTLANGUAGE": "contentlanguage",
"CONTENTLANG": "contentlanguage",
"PAGELANGUAGE": "pagelanguage"
}
],
"urlProtocols": "bitcoin\\:|ftp\\:\\/\\/|ftps\\:\\/\\/|geo\\:|git\\:\\/\\/|gopher\\:\\/\\/|http\\:\\/\\/|https\\:\\/\\/|irc\\:\\/\\/|ircs\\:\\/\\/|magnet\\:|mailto\\:|mms\\:\\/\\/|news\\:|nntp\\:\\/\\/|redis\\:\\/\\/|sftp\\:\\/\\/|sip\\:|sips\\:|sms\\:|ssh\\:\\/\\/|svn\\:\\/\\/|tel\\:|telnet\\:\\/\\/|urn\\:|worldwind\\:\\/\\/|xmpp\\:|\\/\\/",
"redirect": [
"#REDIRECT"
],
"img": {
"thumbnail": "img_thumbnail",
"thumb": "img_thumbnail",
"thumbnail=$1": "img_manualthumb",
"thumb=$1": "img_manualthumb",
"right": "img_right",
"left": "img_left",
"none": "img_none",
"$1px": "img_width",
"center": "img_center",
"centre": "img_center",
"framed": "img_framed",
"enframed": "img_framed",
"frame": "img_framed",
"frameless": "img_frameless",
"lang=$1": "img_lang",
"page=$1": "img_page",
"page $1": "img_page",
"upright": "img_upright",
"upright=$1": "img_upright",
"upright $1": "img_upright",
"border": "img_border",
"baseline": "img_baseline",
"sub": "img_sub",
"super": "img_super",
"sup": "img_super",
"top": "img_top",
"text-top": "img_text_top",
"middle": "img_middle",
"bottom": "img_bottom",
"text-bottom": "img_text_bottom",
"link=$1": "img_link",
"alt=$1": "img_alt",
"class=$1": "img_class"
}
}

查看文件

@ -16,7 +16,7 @@
voidHtmlTags = {
br: true, hr: true, wbr: true, img: true
},
span = document.createElement( 'span' ); // used for isEntity()
span = typeof document === 'object' && document.createElement( 'span' ); // used for isEntity()
let mwConfig, urlProtocols;
/**
@ -62,6 +62,9 @@
}
function isEntity( str ) {
if ( !span ) {
return true;
}
span.innerHTML = str;
return span.textContent.length === 1;
}
@ -215,7 +218,7 @@
if ( /[^\]|[]/.test( stream.peek() ) ) {
state.nLink++;
state.stack.push( state.tokenize );
const nsIds = mw.config.get( 'wgNamespaceIds' ),
const nsIds = typeof mw === 'object' ? mw.config.get( 'wgNamespaceIds' ) : { File: 6 },
nsFile = Object.keys( nsIds ).filter( function ( ns ) {
return nsIds[ ns ] === 6;
} ).join( '|' ),

18
runmode.js 普通文件
查看文件

@ -0,0 +1,18 @@
'use strict';
const fs = require( 'fs' ),
text = fs.readFileSync( 'test.txt', 'utf8' );
global.CodeMirror = require( './codemirror' );
require( './mediawiki.js' );
CodeMirror.defaults.mwConfig = require( './config.json' );
let output = '';
function print( string ) {
output += string;
}
console.time( 'CodeMirror' );
CodeMirror.runMode( text, 'text/mediawiki', print );
console.timeEnd( 'CodeMirror' );
console.log( output );

3
runmode.sh 可执行文件
查看文件

@ -0,0 +1,3 @@
node --prof runmode.js
node --prof-process isolate-0x*-v8.log > processed.txt
rm isolate-0x*-v8.log