mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-28 04:23:32 +01:00
move workbench/themes to browser namespace
This commit is contained in:
@@ -28,7 +28,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"applicationinsights": "1.0.8",
|
||||
"fast-plist": "0.1.2",
|
||||
"gc-signals": "^0.0.1",
|
||||
"getmac": "1.4.1",
|
||||
"graceful-fs": "4.1.11",
|
||||
@@ -82,6 +81,7 @@
|
||||
"event-stream": "3.3.4",
|
||||
"express": "^4.13.1",
|
||||
"fancy-log": "^1.3.3",
|
||||
"fast-plist": "0.1.2",
|
||||
"glob": "^5.0.13",
|
||||
"gulp": "^4.0.0",
|
||||
"gulp-atom-electron": "^1.20.0",
|
||||
|
||||
7
src/typings/fast-plist.d.ts
vendored
7
src/typings/fast-plist.d.ts
vendored
@@ -1,7 +0,0 @@
|
||||
|
||||
declare module "fast-plist" {
|
||||
/**
|
||||
* A very fast plist parser
|
||||
*/
|
||||
export function parse(content: string): any;
|
||||
}
|
||||
@@ -175,7 +175,7 @@ import { LifecycleService } from 'vs/platform/lifecycle/electron-browser/lifecyc
|
||||
import { ToggleDevToolsAction } from 'vs/workbench/electron-browser/actions/developerActions';
|
||||
import { registerWindowDriver } from 'vs/platform/driver/electron-browser/driver';
|
||||
import { IExtensionUrlHandler, ExtensionUrlHandler } from 'vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler';
|
||||
import { WorkbenchThemeService } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
|
||||
import { WorkbenchThemeService } from 'vs/workbench/services/themes/browser/workbenchThemeService';
|
||||
import { DialogService, FileDialogService } from 'vs/workbench/services/dialogs/electron-browser/dialogService';
|
||||
import { ShowPreviousWindowTab, MoveWindowTabToNewWindow, MergeAllWindowTabs, ShowNextWindowTab, ToggleWindowTabsBar, NewWindowTab, OpenRecentAction, ReloadWindowAction, ReloadWindowWithExtensionsDisabledAction } from 'vs/workbench/electron-browser/actions/windowActions';
|
||||
import { IBroadcastService, BroadcastService } from 'vs/workbench/services/broadcast/electron-browser/broadcastService';
|
||||
|
||||
@@ -8,7 +8,7 @@ import { basename } from 'vs/base/common/path';
|
||||
import * as Json from 'vs/base/common/json';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { ExtensionData, ITokenColorCustomizations, ITokenColorizationRule, IColorTheme, IColorMap, IThemeExtensionPoint, VS_LIGHT_THEME, VS_HC_THEME } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import { convertSettings } from 'vs/workbench/services/themes/electron-browser/themeCompatibility';
|
||||
import { convertSettings } from 'vs/workbench/services/themes/browser/themeCompatibility';
|
||||
import * as nls from 'vs/nls';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
@@ -16,10 +16,11 @@ import * as resources from 'vs/base/common/resources';
|
||||
import { Extensions, IColorRegistry, ColorIdentifier, editorBackground, editorForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { ThemeType } from 'vs/platform/theme/common/themeService';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IColorCustomizations } from 'vs/workbench/services/themes/electron-browser/workbenchThemeService';
|
||||
import { IColorCustomizations } from 'vs/workbench/services/themes/browser/workbenchThemeService';
|
||||
import { getParseErrorMessage } from 'vs/base/common/jsonErrorMessages';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { parse as parsePList } from 'vs/workbench/services/themes/common/plistParser';
|
||||
|
||||
let colorRegistry = Registry.as<IColorRegistry>(Extensions.ColorContribution);
|
||||
|
||||
@@ -330,29 +331,19 @@ function _loadColorTheme(fileService: IFileService, themeLocation: URI, resultRu
|
||||
}
|
||||
}
|
||||
|
||||
let pListParser: Promise<{ parse(content: string) }>;
|
||||
function getPListParser() {
|
||||
if (!pListParser) {
|
||||
pListParser = import('fast-plist');
|
||||
}
|
||||
return pListParser;
|
||||
}
|
||||
|
||||
function _loadSyntaxTokens(fileService: IFileService, themeLocation: URI, resultRules: ITokenColorizationRule[], resultColors: IColorMap): Promise<any> {
|
||||
return fileService.resolveContent(themeLocation, { encoding: 'utf8' }).then(content => {
|
||||
return getPListParser().then(parser => {
|
||||
try {
|
||||
let contentValue = parser.parse(content.value.toString());
|
||||
let settings: ITokenColorizationRule[] = contentValue.settings;
|
||||
if (!Array.isArray(settings)) {
|
||||
return Promise.reject(new Error(nls.localize('error.plist.invalidformat', "Problem parsing tmTheme file: {0}. 'settings' is not array.")));
|
||||
}
|
||||
convertSettings(settings, resultRules, resultColors);
|
||||
return Promise.resolve(null);
|
||||
} catch (e) {
|
||||
return Promise.reject(new Error(nls.localize('error.cannotparse', "Problems parsing tmTheme file: {0}", e.message)));
|
||||
try {
|
||||
let contentValue = parsePList(content.value.toString());
|
||||
let settings: ITokenColorizationRule[] = contentValue.settings;
|
||||
if (!Array.isArray(settings)) {
|
||||
return Promise.reject(new Error(nls.localize('error.plist.invalidformat', "Problem parsing tmTheme file: {0}. 'settings' is not array.")));
|
||||
}
|
||||
});
|
||||
convertSettings(settings, resultRules, resultColors);
|
||||
return Promise.resolve(null);
|
||||
} catch (e) {
|
||||
return Promise.reject(new Error(nls.localize('error.cannotparse', "Problems parsing tmTheme file: {0}", e.message)));
|
||||
}
|
||||
}, error => {
|
||||
return Promise.reject(new Error(nls.localize('error.cannotload', "Problems loading tmTheme file {0}: {1}", themeLocation.toString(), error.message)));
|
||||
});
|
||||
@@ -9,7 +9,7 @@ import * as types from 'vs/base/common/types';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import { ExtensionsRegistry, ExtensionMessageCollector } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { ExtensionData, IThemeExtensionPoint, VS_LIGHT_THEME, VS_DARK_THEME, VS_HC_THEME } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||
import { ColorThemeData } from 'vs/workbench/services/themes/electron-browser/colorThemeData';
|
||||
import { ColorThemeData } from 'vs/workbench/services/themes/browser/colorThemeData';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
@@ -8,8 +8,6 @@ import { Color } from 'vs/base/common/color';
|
||||
import * as colorRegistry from 'vs/platform/theme/common/colorRegistry';
|
||||
|
||||
import * as editorColorRegistry from 'vs/editor/common/view/editorColorRegistry';
|
||||
import * as wordHighlighter from 'vs/editor/contrib/wordHighlighter/wordHighlighter';
|
||||
import { peekViewEditorMatchHighlight, peekViewResultsMatchHighlight } from 'vs/editor/contrib/referenceSearch/referencesWidget';
|
||||
|
||||
const settingToColorIdMapping: { [settingId: string]: string[] } = {};
|
||||
function addSettingMapping(settingId: string, colorId: string) {
|
||||
@@ -56,11 +54,11 @@ addSettingMapping('selectionHighlightColor', colorRegistry.editorSelectionHighli
|
||||
addSettingMapping('findMatchHighlight', colorRegistry.editorFindMatchHighlight);
|
||||
addSettingMapping('currentFindMatchHighlight', colorRegistry.editorFindMatch);
|
||||
addSettingMapping('hoverHighlight', colorRegistry.editorHoverHighlight);
|
||||
addSettingMapping('wordHighlight', wordHighlighter.editorWordHighlight);
|
||||
addSettingMapping('wordHighlightStrong', wordHighlighter.editorWordHighlightStrong);
|
||||
addSettingMapping('wordHighlight', 'editor.wordHighlightBackground'); // inlined to avoid editor/contrib dependenies
|
||||
addSettingMapping('wordHighlightStrong', 'editor.wordHighlightStrongBackground');
|
||||
addSettingMapping('findRangeHighlight', colorRegistry.editorFindRangeHighlight);
|
||||
addSettingMapping('findMatchHighlight', peekViewResultsMatchHighlight);
|
||||
addSettingMapping('referenceHighlight', peekViewEditorMatchHighlight);
|
||||
addSettingMapping('findMatchHighlight', 'peekViewResult.matchHighlightBackground');
|
||||
addSettingMapping('referenceHighlight', 'peekViewEditor.matchHighlightBackground');
|
||||
addSettingMapping('lineHighlight', editorColorRegistry.editorLineHighlight);
|
||||
addSettingMapping('rangeHighlight', editorColorRegistry.editorRangeHighlight);
|
||||
addSettingMapping('caret', editorColorRegistry.editorCursorForeground);
|
||||
@@ -19,7 +19,7 @@ import { ITheme, Extensions as ThemingExtensions, IThemingRegistry } from 'vs/pl
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { registerFileIconThemeSchemas } from 'vs/workbench/services/themes/common/fileIconThemeSchema';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { ColorThemeStore } from 'vs/workbench/services/themes/electron-browser/colorThemeStore';
|
||||
import { ColorThemeStore } from 'vs/workbench/services/themes/browser/colorThemeStore';
|
||||
import { FileIconThemeStore } from 'vs/workbench/services/themes/common/fileIconThemeStore';
|
||||
import { FileIconThemeData } from 'vs/workbench/services/themes/common/fileIconThemeData';
|
||||
import { IWindowService } from 'vs/platform/windows/common/windows';
|
||||
497
src/vs/workbench/services/themes/common/plistParser.ts
Normal file
497
src/vs/workbench/services/themes/common/plistParser.ts
Normal file
@@ -0,0 +1,497 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
const enum ChCode {
|
||||
BOM = 65279,
|
||||
|
||||
SPACE = 32,
|
||||
TAB = 9,
|
||||
CARRIAGE_RETURN = 13,
|
||||
LINE_FEED = 10,
|
||||
|
||||
SLASH = 47,
|
||||
|
||||
LESS_THAN = 60,
|
||||
QUESTION_MARK = 63,
|
||||
EXCLAMATION_MARK = 33,
|
||||
}
|
||||
|
||||
const enum State {
|
||||
ROOT_STATE = 0,
|
||||
DICT_STATE = 1,
|
||||
ARR_STATE = 2
|
||||
}
|
||||
|
||||
export function parseWithLocation(content: string, filename: string, locationKeyName: string): any {
|
||||
return _parse(content, filename, locationKeyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* A very fast plist parser
|
||||
*/
|
||||
export function parse(content: string): any {
|
||||
return _parse(content, null, null);
|
||||
}
|
||||
|
||||
function _parse(content: string, filename: string | null, locationKeyName: string | null): any {
|
||||
const len = content.length;
|
||||
|
||||
let pos = 0;
|
||||
let line = 1;
|
||||
let char = 0;
|
||||
|
||||
// Skip UTF8 BOM
|
||||
if (len > 0 && content.charCodeAt(0) === ChCode.BOM) {
|
||||
pos = 1;
|
||||
}
|
||||
|
||||
function advancePosBy(by: number): void {
|
||||
if (locationKeyName === null) {
|
||||
pos = pos + by;
|
||||
} else {
|
||||
while (by > 0) {
|
||||
let chCode = content.charCodeAt(pos);
|
||||
if (chCode === ChCode.LINE_FEED) {
|
||||
pos++; line++; char = 0;
|
||||
} else {
|
||||
pos++; char++;
|
||||
}
|
||||
by--;
|
||||
}
|
||||
}
|
||||
}
|
||||
function advancePosTo(to: number): void {
|
||||
if (locationKeyName === null) {
|
||||
pos = to;
|
||||
} else {
|
||||
advancePosBy(to - pos);
|
||||
}
|
||||
}
|
||||
|
||||
function skipWhitespace(): void {
|
||||
while (pos < len) {
|
||||
let chCode = content.charCodeAt(pos);
|
||||
if (chCode !== ChCode.SPACE && chCode !== ChCode.TAB && chCode !== ChCode.CARRIAGE_RETURN && chCode !== ChCode.LINE_FEED) {
|
||||
break;
|
||||
}
|
||||
advancePosBy(1);
|
||||
}
|
||||
}
|
||||
|
||||
function advanceIfStartsWith(str: string): boolean {
|
||||
if (content.substr(pos, str.length) === str) {
|
||||
advancePosBy(str.length);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function advanceUntil(str: string): void {
|
||||
let nextOccurence = content.indexOf(str, pos);
|
||||
if (nextOccurence !== -1) {
|
||||
advancePosTo(nextOccurence + str.length);
|
||||
} else {
|
||||
// EOF
|
||||
advancePosTo(len);
|
||||
}
|
||||
}
|
||||
|
||||
function captureUntil(str: string): string {
|
||||
let nextOccurence = content.indexOf(str, pos);
|
||||
if (nextOccurence !== -1) {
|
||||
let r = content.substring(pos, nextOccurence);
|
||||
advancePosTo(nextOccurence + str.length);
|
||||
return r;
|
||||
} else {
|
||||
// EOF
|
||||
let r = content.substr(pos);
|
||||
advancePosTo(len);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
let state = State.ROOT_STATE;
|
||||
|
||||
let cur: any = null;
|
||||
let stateStack: State[] = [];
|
||||
let objStack: any[] = [];
|
||||
let curKey: string | null = null;
|
||||
|
||||
function pushState(newState: State, newCur: any): void {
|
||||
stateStack.push(state);
|
||||
objStack.push(cur);
|
||||
state = newState;
|
||||
cur = newCur;
|
||||
}
|
||||
|
||||
function popState(): void {
|
||||
if (stateStack.length === 0) {
|
||||
return fail('illegal state stack');
|
||||
}
|
||||
state = stateStack.pop()!;
|
||||
cur = objStack.pop();
|
||||
}
|
||||
|
||||
function fail(msg: string): void {
|
||||
throw new Error('Near offset ' + pos + ': ' + msg + ' ~~~' + content.substr(pos, 50) + '~~~');
|
||||
}
|
||||
|
||||
const dictState = {
|
||||
enterDict: function () {
|
||||
if (curKey === null) {
|
||||
return fail('missing <key>');
|
||||
}
|
||||
let newDict = {};
|
||||
if (locationKeyName !== null) {
|
||||
newDict[locationKeyName] = {
|
||||
filename: filename,
|
||||
line: line,
|
||||
char: char
|
||||
};
|
||||
}
|
||||
cur[curKey] = newDict;
|
||||
curKey = null;
|
||||
pushState(State.DICT_STATE, newDict);
|
||||
},
|
||||
enterArray: function () {
|
||||
if (curKey === null) {
|
||||
return fail('missing <key>');
|
||||
}
|
||||
let newArr: any[] = [];
|
||||
cur[curKey] = newArr;
|
||||
curKey = null;
|
||||
pushState(State.ARR_STATE, newArr);
|
||||
}
|
||||
};
|
||||
|
||||
const arrState = {
|
||||
enterDict: function () {
|
||||
let newDict = {};
|
||||
if (locationKeyName !== null) {
|
||||
newDict[locationKeyName] = {
|
||||
filename: filename,
|
||||
line: line,
|
||||
char: char
|
||||
};
|
||||
}
|
||||
cur.push(newDict);
|
||||
pushState(State.DICT_STATE, newDict);
|
||||
},
|
||||
enterArray: function () {
|
||||
let newArr: any[] = [];
|
||||
cur.push(newArr);
|
||||
pushState(State.ARR_STATE, newArr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function enterDict() {
|
||||
if (state === State.DICT_STATE) {
|
||||
dictState.enterDict();
|
||||
} else if (state === State.ARR_STATE) {
|
||||
arrState.enterDict();
|
||||
} else { // ROOT_STATE
|
||||
cur = {};
|
||||
if (locationKeyName !== null) {
|
||||
cur[locationKeyName] = {
|
||||
filename: filename,
|
||||
line: line,
|
||||
char: char
|
||||
};
|
||||
}
|
||||
pushState(State.DICT_STATE, cur);
|
||||
}
|
||||
}
|
||||
function leaveDict() {
|
||||
if (state === State.DICT_STATE) {
|
||||
popState();
|
||||
} else if (state === State.ARR_STATE) {
|
||||
return fail('unexpected </dict>');
|
||||
} else { // ROOT_STATE
|
||||
return fail('unexpected </dict>');
|
||||
}
|
||||
}
|
||||
function enterArray() {
|
||||
if (state === State.DICT_STATE) {
|
||||
dictState.enterArray();
|
||||
} else if (state === State.ARR_STATE) {
|
||||
arrState.enterArray();
|
||||
} else { // ROOT_STATE
|
||||
cur = [];
|
||||
pushState(State.ARR_STATE, cur);
|
||||
}
|
||||
}
|
||||
function leaveArray() {
|
||||
if (state === State.DICT_STATE) {
|
||||
return fail('unexpected </array>');
|
||||
} else if (state === State.ARR_STATE) {
|
||||
popState();
|
||||
} else { // ROOT_STATE
|
||||
return fail('unexpected </array>');
|
||||
}
|
||||
}
|
||||
function acceptKey(val: string) {
|
||||
if (state === State.DICT_STATE) {
|
||||
if (curKey !== null) {
|
||||
return fail('too many <key>');
|
||||
}
|
||||
curKey = val;
|
||||
} else if (state === State.ARR_STATE) {
|
||||
return fail('unexpected <key>');
|
||||
} else { // ROOT_STATE
|
||||
return fail('unexpected <key>');
|
||||
}
|
||||
}
|
||||
function acceptString(val: string) {
|
||||
if (state === State.DICT_STATE) {
|
||||
if (curKey === null) {
|
||||
return fail('missing <key>');
|
||||
}
|
||||
cur[curKey] = val;
|
||||
curKey = null;
|
||||
} else if (state === State.ARR_STATE) {
|
||||
cur.push(val);
|
||||
} else { // ROOT_STATE
|
||||
cur = val;
|
||||
}
|
||||
}
|
||||
function acceptReal(val: number) {
|
||||
if (isNaN(val)) {
|
||||
return fail('cannot parse float');
|
||||
}
|
||||
if (state === State.DICT_STATE) {
|
||||
if (curKey === null) {
|
||||
return fail('missing <key>');
|
||||
}
|
||||
cur[curKey] = val;
|
||||
curKey = null;
|
||||
} else if (state === State.ARR_STATE) {
|
||||
cur.push(val);
|
||||
} else { // ROOT_STATE
|
||||
cur = val;
|
||||
}
|
||||
}
|
||||
function acceptInteger(val: number) {
|
||||
if (isNaN(val)) {
|
||||
return fail('cannot parse integer');
|
||||
}
|
||||
if (state === State.DICT_STATE) {
|
||||
if (curKey === null) {
|
||||
return fail('missing <key>');
|
||||
}
|
||||
cur[curKey] = val;
|
||||
curKey = null;
|
||||
} else if (state === State.ARR_STATE) {
|
||||
cur.push(val);
|
||||
} else { // ROOT_STATE
|
||||
cur = val;
|
||||
}
|
||||
}
|
||||
function acceptDate(val: Date) {
|
||||
if (state === State.DICT_STATE) {
|
||||
if (curKey === null) {
|
||||
return fail('missing <key>');
|
||||
}
|
||||
cur[curKey] = val;
|
||||
curKey = null;
|
||||
} else if (state === State.ARR_STATE) {
|
||||
cur.push(val);
|
||||
} else { // ROOT_STATE
|
||||
cur = val;
|
||||
}
|
||||
}
|
||||
function acceptData(val: string) {
|
||||
if (state === State.DICT_STATE) {
|
||||
if (curKey === null) {
|
||||
return fail('missing <key>');
|
||||
}
|
||||
cur[curKey] = val;
|
||||
curKey = null;
|
||||
} else if (state === State.ARR_STATE) {
|
||||
cur.push(val);
|
||||
} else { // ROOT_STATE
|
||||
cur = val;
|
||||
}
|
||||
}
|
||||
function acceptBool(val: boolean) {
|
||||
if (state === State.DICT_STATE) {
|
||||
if (curKey === null) {
|
||||
return fail('missing <key>');
|
||||
}
|
||||
cur[curKey] = val;
|
||||
curKey = null;
|
||||
} else if (state === State.ARR_STATE) {
|
||||
cur.push(val);
|
||||
} else { // ROOT_STATE
|
||||
cur = val;
|
||||
}
|
||||
}
|
||||
|
||||
function escapeVal(str: string): string {
|
||||
return str.replace(/&#([0-9]+);/g, function (_: string, m0: string) {
|
||||
return (<any>String).fromCodePoint(parseInt(m0, 10));
|
||||
}).replace(/&#x([0-9a-f]+);/g, function (_: string, m0: string) {
|
||||
return (<any>String).fromCodePoint(parseInt(m0, 16));
|
||||
}).replace(/&|<|>|"|'/g, function (_: string) {
|
||||
switch (_) {
|
||||
case '&': return '&';
|
||||
case '<': return '<';
|
||||
case '>': return '>';
|
||||
case '"': return '"';
|
||||
case ''': return '\'';
|
||||
}
|
||||
return _;
|
||||
});
|
||||
}
|
||||
|
||||
interface IParsedTag {
|
||||
name: string;
|
||||
isClosed: boolean;
|
||||
}
|
||||
|
||||
function parseOpenTag(): IParsedTag {
|
||||
let r = captureUntil('>');
|
||||
let isClosed = false;
|
||||
if (r.charCodeAt(r.length - 1) === ChCode.SLASH) {
|
||||
isClosed = true;
|
||||
r = r.substring(0, r.length - 1);
|
||||
}
|
||||
|
||||
return {
|
||||
name: r.trim(),
|
||||
isClosed: isClosed
|
||||
};
|
||||
}
|
||||
|
||||
function parseTagValue(tag: IParsedTag): string {
|
||||
if (tag.isClosed) {
|
||||
return '';
|
||||
}
|
||||
let val = captureUntil('</');
|
||||
advanceUntil('>');
|
||||
return escapeVal(val);
|
||||
}
|
||||
|
||||
while (pos < len) {
|
||||
skipWhitespace();
|
||||
if (pos >= len) {
|
||||
break;
|
||||
}
|
||||
|
||||
const chCode = content.charCodeAt(pos);
|
||||
advancePosBy(1);
|
||||
if (chCode !== ChCode.LESS_THAN) {
|
||||
return fail('expected <');
|
||||
}
|
||||
|
||||
if (pos >= len) {
|
||||
return fail('unexpected end of input');
|
||||
}
|
||||
|
||||
const peekChCode = content.charCodeAt(pos);
|
||||
|
||||
if (peekChCode === ChCode.QUESTION_MARK) {
|
||||
advancePosBy(1);
|
||||
advanceUntil('?>');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (peekChCode === ChCode.EXCLAMATION_MARK) {
|
||||
advancePosBy(1);
|
||||
|
||||
if (advanceIfStartsWith('--')) {
|
||||
advanceUntil('-->');
|
||||
continue;
|
||||
}
|
||||
|
||||
advanceUntil('>');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (peekChCode === ChCode.SLASH) {
|
||||
advancePosBy(1);
|
||||
skipWhitespace();
|
||||
|
||||
if (advanceIfStartsWith('plist')) {
|
||||
advanceUntil('>');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (advanceIfStartsWith('dict')) {
|
||||
advanceUntil('>');
|
||||
leaveDict();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (advanceIfStartsWith('array')) {
|
||||
advanceUntil('>');
|
||||
leaveArray();
|
||||
continue;
|
||||
}
|
||||
|
||||
return fail('unexpected closed tag');
|
||||
}
|
||||
|
||||
let tag = parseOpenTag();
|
||||
|
||||
switch (tag.name) {
|
||||
case 'dict':
|
||||
enterDict();
|
||||
if (tag.isClosed) {
|
||||
leaveDict();
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'array':
|
||||
enterArray();
|
||||
if (tag.isClosed) {
|
||||
leaveArray();
|
||||
}
|
||||
continue;
|
||||
|
||||
case 'key':
|
||||
acceptKey(parseTagValue(tag));
|
||||
continue;
|
||||
|
||||
case 'string':
|
||||
acceptString(parseTagValue(tag));
|
||||
continue;
|
||||
|
||||
case 'real':
|
||||
acceptReal(parseFloat(parseTagValue(tag)));
|
||||
continue;
|
||||
|
||||
case 'integer':
|
||||
acceptInteger(parseInt(parseTagValue(tag), 10));
|
||||
continue;
|
||||
|
||||
case 'date':
|
||||
acceptDate(new Date(parseTagValue(tag)));
|
||||
continue;
|
||||
|
||||
case 'data':
|
||||
acceptData(parseTagValue(tag));
|
||||
continue;
|
||||
|
||||
case 'true':
|
||||
parseTagValue(tag);
|
||||
acceptBool(true);
|
||||
continue;
|
||||
|
||||
case 'false':
|
||||
parseTagValue(tag);
|
||||
acceptBool(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (/^plist/.test(tag.name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return fail('unexpected opened tag ' + tag.name);
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
Reference in New Issue
Block a user