1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-27 21:05:53 +00:00
FrankerFaceZ/src/utilities/path-parser.js
SirStendec ab4f72c345 4.20.70
* Fixed: Popout Chat from the dashboard and mod view not working correctly. Please note there is still a race condition on the dashboard popout chat. It may require several refreshes or not work at all depending on your Internet connection.
* Fixed: Only load the chat types from Twitch once. Ignore any future module loads.
* Fixed: Hide the empty bar at the bottom of Twitch pages due to incorrect styles being applied to the new snackbar container element.
* Fixed: Apollo should only clear the query cache if it makes changes to a query. Likewise, Apollo should only fetch the `gql-printer` module upon demand.
* Fixed: Remove debug logging from `utilities/dom::createElement`
* Changed: Slightly delay tool-tip repositioning when rich content is loaded, hopefully reducing flicker events.
* Changed: Refactor WebMunch, adding compatibility for a future webpack update and reducing the number of modules checked when scanning for modules.
* Changed: Allow Switchboard to keep trying to load routes if the one it tries fails to actually populate `require()`.
* API Added: `EventEmitter::hasListeners(event)` method for determining if there are any listeners for a specific event.
* API Added: `localStorage.ffzLogLevel` can be set to override the global log level.
* API Added: `log.verbose(...)` as an even weaker logging level than `debug(...)`
* API Changed: Allow Tooltip instances to add tool-tips to the DOM under a different element than the parent element used for events.
2021-02-24 14:38:25 -05:00

130 lines
No EOL
2.1 KiB
JavaScript

'use strict';
export function parse(path) {
return parseAST({
path,
i: 0
});
}
function parseAST(ctx) {
const path = ctx.path,
length = path.length,
out = [];
let token, raw;
let old_tab = false,
old_page = false;
while ( ctx.i < length ) {
const start = ctx.i,
char = path[start],
next = path[start + 1];
if ( ! token ) {
raw = [];
token = {};
}
// JSON
if ( char === '@' && next === '{') {
ctx.i++;
const tag = parseJSON(ctx);
if ( tag )
Object.assign(token, tag);
continue;
}
// Segment End?
const tab = char === `~` && next === '>',
page = char === '>' && next === '>',
segment = ! page && char === '>';
if ( ! segment && ! page && ! tab ) {
raw.push(char);
ctx.i++;
continue;
}
// We're at the end of a segment, so push
// the token out.
if ( tab || page )
ctx.i++;
token.title = raw.join('').trim();
token.key = token.title.toSnakeCase();
token.page = old_page;
token.tab = old_tab;
old_page = page;
old_tab = tab;
out.push(token);
token = raw = null;
ctx.i++;
}
if ( token ) {
token.title = raw.join('').trim();
token.key = token.title.toSnakeCase();
token.page = old_page;
token.tab = old_tab;
out.push(token);
}
return out;
}
function parseJSON(ctx) {
const path = ctx.path,
length = path.length,
start = ctx.i;
ctx.i++;
const stack = ['{'];
let string = false;
while ( ctx.i < length && stack.length ) {
const start = ctx.i,
char = path[start];
if ( string ) {
if ( char === '\\' ) {
ctx.i++;
continue;
}
if ( (char === '"' || char === "'") && char === string ) {
stack.pop();
string = false;
}
} else {
if ( char === '"' || char === "'" ) {
string = char;
stack.push(char);
}
if ( char === '{' || char === '[' )
stack.push(char);
if ( char === ']' ) {
if ( stack.pop() !== '[' )
throw new SyntaxError('Invalid JSON');
}
if ( char === '}' ) {
if ( stack.pop() !== '{' )
throw new SyntaxError('Invalid JSON');
}
}
ctx.i++;
}
return JSON.parse(path.slice(start, ctx.i));
}