mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-03-02 10:57:45 +01:00
Merge pull request #2996 from SillyTavern/webpack
Add Webpack to eliminate frontend vendoring
This commit is contained in:
commit
45a0d63e6a
@ -5,7 +5,7 @@ end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{js, conf, json, css, less, html}]
|
||||
[*.{js,conf,json,css,less,html}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
@ -19,6 +19,10 @@ module.exports = {
|
||||
parserOptions: {
|
||||
sourceType: 'module',
|
||||
},
|
||||
globals: {
|
||||
globalThis: 'readonly',
|
||||
Deno: 'readonly',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.cjs'],
|
||||
@ -50,23 +54,9 @@ module.exports = {
|
||||
},
|
||||
// These scripts are loaded in HTML; tell ESLint not to complain about them being undefined
|
||||
globals: {
|
||||
DOMPurify: 'readonly',
|
||||
droll: 'readonly',
|
||||
Fuse: 'readonly',
|
||||
Handlebars: 'readonly',
|
||||
hljs: 'readonly',
|
||||
localforage: 'readonly',
|
||||
moment: 'readonly',
|
||||
pdfjsLib: 'readonly',
|
||||
Popper: 'readonly',
|
||||
showdown: 'readonly',
|
||||
showdownKatex: 'readonly',
|
||||
SVGInject: 'readonly',
|
||||
toastr: 'readonly',
|
||||
Readability: 'readonly',
|
||||
isProbablyReaderable: 'readonly',
|
||||
ePub: 'readonly',
|
||||
diff_match_patch: 'readonly',
|
||||
pdfjsLib: 'readonly',
|
||||
toastr: 'readonly',
|
||||
SillyTavern: 'readonly',
|
||||
},
|
||||
},
|
||||
|
@ -133,7 +133,6 @@
|
||||
"auto_fix_generated_markdown": false,
|
||||
"send_on_enter": 0,
|
||||
"console_log_prompts": false,
|
||||
"render_formulas": false,
|
||||
"allow_name1_display": false,
|
||||
"allow_name2_display": false,
|
||||
"hotswap_enabled": true,
|
||||
|
1152
package-lock.json
generated
1152
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
@ -1,28 +1,42 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"@adobe/css-tools": "^4.4.0",
|
||||
"@agnai/sentencepiece-js": "^1.1.1",
|
||||
"@agnai/web-tokenizers": "^0.1.3",
|
||||
"@iconfu/svg-inject": "^1.2.3",
|
||||
"@mozilla/readability": "^0.5.0",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@zeldafan0225/ai_horde": "^5.1.0",
|
||||
"archiver": "^7.0.1",
|
||||
"bing-translate-api": "^2.9.1",
|
||||
"body-parser": "^1.20.2",
|
||||
"bowser": "^2.11.0",
|
||||
"command-exists": "^1.2.9",
|
||||
"compression": "^1",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"cookie-session": "^2.1.0",
|
||||
"cors": "^2.8.5",
|
||||
"csrf-csrf": "^2.2.3",
|
||||
"diff-match-patch": "^1.0.5",
|
||||
"dompurify": "^3.1.7",
|
||||
"droll": "^0.2.1",
|
||||
"express": "^4.21.0",
|
||||
"form-data": "^4.0.0",
|
||||
"fuse.js": "^7.0.0",
|
||||
"google-translate-api-x": "^10.7.1",
|
||||
"handlebars": "^4.7.8",
|
||||
"helmet": "^7.1.0",
|
||||
"highlight.js": "^11.10.0",
|
||||
"html-entities": "^2.5.2",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"ip-matching": "^2.1.2",
|
||||
"ipaddr.js": "^2.0.1",
|
||||
"jimp": "^0.22.10",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mime-types": "^2.1.35",
|
||||
"moment": "^2.30.1",
|
||||
"morphdom": "^2.7.4",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"node-fetch": "^3.3.2",
|
||||
"node-persist": "^4.0.1",
|
||||
@ -34,11 +48,15 @@
|
||||
"rate-limiter-flexible": "^5.0.0",
|
||||
"response-time": "^2.3.2",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"seedrandom": "^3.0.5",
|
||||
"showdown": "^2.1.0",
|
||||
"sillytavern-transformers": "2.14.6",
|
||||
"simple-git": "^3.19.1",
|
||||
"tiktoken": "^1.0.16",
|
||||
"vectra": "^0.2.2",
|
||||
"wavefile": "^11.0.0",
|
||||
"webpack": "^5.95.0",
|
||||
"webpack-dev-middleware": "^7.4.2",
|
||||
"write-file-atomic": "^5.0.1",
|
||||
"ws": "^8.17.1",
|
||||
"yaml": "^2.3.4",
|
||||
@ -69,6 +87,8 @@
|
||||
"version": "1.12.7",
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"start:deno": "deno run --allow-run --allow-net --allow-read --allow-write --allow-sys --allow-env server.js",
|
||||
"start:bun": "bun server.js",
|
||||
"start:no-csrf": "node server.js --disableCsrf",
|
||||
"postinstall": "node post-install.js",
|
||||
"lint": "eslint \"src/**/*.js\" \"public/**/*.js\" ./*.js",
|
||||
@ -91,7 +111,7 @@
|
||||
"@types/cookie-parser": "^1.4.7",
|
||||
"@types/cookie-session": "^2.0.49",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/dompurify": "^3.0.5",
|
||||
"@types/deno": "^2.0.0",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/jquery": "^3.5.29",
|
||||
"@types/lodash": "^4.17.10",
|
||||
|
@ -479,11 +479,6 @@
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.custom-katex-html,
|
||||
.katex-html {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hoverglow {
|
||||
transition: opacity 200ms;
|
||||
}
|
||||
|
960
public/global.d.ts
vendored
960
public/global.d.ts
vendored
@ -1,21 +1,14 @@
|
||||
import libs from './lib';
|
||||
|
||||
// Global namespace modules
|
||||
declare var droll;
|
||||
declare var Handlebars;
|
||||
declare var hljs;
|
||||
declare var localforage;
|
||||
declare var pdfjsLib;
|
||||
declare var Popper;
|
||||
declare var showdown;
|
||||
declare var showdownKatex;
|
||||
declare var SVGInject;
|
||||
declare var Readability;
|
||||
declare var isProbablyReaderable;
|
||||
declare var ePub;
|
||||
declare var ai;
|
||||
declare var pdfjsLib;
|
||||
declare var ePub;
|
||||
|
||||
declare var SillyTavern: {
|
||||
getContext(): any;
|
||||
llm: any;
|
||||
libs: typeof libs;
|
||||
};
|
||||
|
||||
// Jquery plugins
|
||||
@ -117,160 +110,6 @@ interface JQuery {
|
||||
//#endregion
|
||||
}
|
||||
|
||||
//#region Fuse
|
||||
|
||||
/**
|
||||
* Fuse.js provides fast and flexible fuzzy searching
|
||||
* @constructor
|
||||
* @param list - The list of items to search through
|
||||
* @param options - Configuration options for the search algorithm
|
||||
*/
|
||||
declare var Fuse: {
|
||||
new(list: any[], options?: FuseOptions): FuseInstance;
|
||||
};
|
||||
|
||||
/** Instead of providing a (nested) key as a string, an object can be defined that can specify weight and a custom get function */
|
||||
interface FuseKey {
|
||||
/**
|
||||
* The name of they key. Supports nested paths.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* You can allocate a weight to keys to give them higher (or lower) values in search results. The weight value has to be greater than 0. When a weight isn't provided, it will default to 1.
|
||||
* @default 1
|
||||
*/
|
||||
weight?: number;
|
||||
/**
|
||||
* Function to retrieve an object's value at the specified path. The default searches nested paths.
|
||||
* @default (obj: T, path: string | string[]) => string | string[]
|
||||
*/
|
||||
getFn?: (any) => string;
|
||||
}
|
||||
|
||||
/** Configuration options for the Fuse search algorithm */
|
||||
interface FuseOptions {
|
||||
/**
|
||||
* List of keys that will be searched. Supports nested paths, weighted search, and searching in arrays of strings and objects.
|
||||
* @default []
|
||||
*/
|
||||
keys?: string[] | FuseKey[];
|
||||
|
||||
/**
|
||||
* How much distance one character can be from another to be considered a match.
|
||||
* @default 100
|
||||
*/
|
||||
distance?: number;
|
||||
|
||||
/**
|
||||
* At what point the match algorithm gives up. A threshold of 0.0 requires a perfect match, while 1.0 matches everything.
|
||||
* @default 0.6
|
||||
*/
|
||||
threshold?: number;
|
||||
|
||||
/**
|
||||
* Whether the score should be included in the result set. A score of 0 indicates a perfect match, while a score of 1 indicates a complete mismatch.
|
||||
* @default false
|
||||
*/
|
||||
includeScore?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates whether comparisons should be case-sensitive.
|
||||
* @default false
|
||||
*/
|
||||
isCaseSensitive?: boolean;
|
||||
|
||||
/**
|
||||
* Whether the matches should be included in the result set. When true, each record in the result set will include the indices of matched characters.
|
||||
* @default false
|
||||
*/
|
||||
includeMatches?: boolean;
|
||||
|
||||
/**
|
||||
* Only matches whose length exceeds this value will be returned.
|
||||
* @default 1
|
||||
*/
|
||||
minMatchCharLength?: number;
|
||||
|
||||
/**
|
||||
* Whether to sort the result list by score.
|
||||
* @default true
|
||||
*/
|
||||
shouldSort?: boolean;
|
||||
|
||||
/**
|
||||
* When true, the matching function will continue to the end of a search pattern even if a perfect match has already been found.
|
||||
* @default false
|
||||
*/
|
||||
findAllMatches?: boolean;
|
||||
|
||||
/**
|
||||
* Determines approximately where in the text the pattern is expected to be found.
|
||||
* @default 0
|
||||
*/
|
||||
location?: number;
|
||||
|
||||
/**
|
||||
* When true, search will ignore location and distance, so it won't matter where in the string the pattern appears.
|
||||
* @default false
|
||||
*/
|
||||
ignoreLocation?: boolean;
|
||||
|
||||
/**
|
||||
* When true, it enables the use of Unix-like search commands.
|
||||
* @default false
|
||||
*/
|
||||
useExtendedSearch?: boolean;
|
||||
|
||||
/**
|
||||
* Function to retrieve an object's value at the specified path. The default searches nested paths.
|
||||
* @default (obj: T, path: string | string[]) => string | string[]
|
||||
*/
|
||||
getFn?: (obj: any, path: string | string[]) => string | string[];
|
||||
|
||||
/**
|
||||
* Function to sort the results. The default sorts by ascending relevance score.
|
||||
* @default (a, b) => number
|
||||
*/
|
||||
sortFn?: (a: any, b: any) => number;
|
||||
|
||||
/**
|
||||
* When true, the calculation for the relevance score will ignore the field-length norm.
|
||||
* @default false
|
||||
*/
|
||||
ignoreFieldNorm?: boolean;
|
||||
|
||||
/**
|
||||
* Determines how much the field-length norm affects scoring. 0 is equivalent to ignoring the field-length norm, while higher values increase the effect.
|
||||
* @default 1
|
||||
*/
|
||||
fieldNormWeight?: number;
|
||||
}
|
||||
|
||||
|
||||
/** Represents an individual Fuse search result */
|
||||
interface FuseResult {
|
||||
/** The original item that was matched */
|
||||
item: any;
|
||||
/** The index of the item from the original input collection that was searched */
|
||||
refIndex: number;
|
||||
/** The search score, where 0 is a perfect match and 1 is the worst */
|
||||
score?: number;
|
||||
/** Optional list of matched search keys */
|
||||
matches?: Array<{ key: string; indices: [number, number][] }>;
|
||||
}
|
||||
|
||||
/** Represents a Fuse instance, used for performing searches */
|
||||
interface FuseInstance {
|
||||
/**
|
||||
* Searches through the list using the specified query.
|
||||
* @param query - The search term or phrase to use
|
||||
* @returns An array of search results matching the query
|
||||
*/
|
||||
search(query: string): FuseResult[];
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region select2
|
||||
|
||||
/** Options for configuring a select2 instance */
|
||||
@ -575,792 +414,3 @@ interface SortableUI {
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
// MIT Licence. Copied from:
|
||||
// https://github.com/moment/moment/blob/develop/ts3.1-typings/moment.d.ts
|
||||
/**
|
||||
* @param strict Strict parsing disables the deprecated fallback to the native Date constructor when
|
||||
* parsing a string.
|
||||
*/
|
||||
declare function moment(inp?: moment.MomentInput, strict?: boolean): moment.Moment;
|
||||
/**
|
||||
* @param strict Strict parsing requires that the format and input match exactly, including delimiters.
|
||||
* Strict parsing is frequently the best parsing option. For more information about choosing strict vs
|
||||
* forgiving parsing, see the [parsing guide](https://momentjs.com/guides/#/parsing/).
|
||||
*/
|
||||
declare function moment(inp?: moment.MomentInput, format?: moment.MomentFormatSpecification, strict?: boolean): moment.Moment;
|
||||
/**
|
||||
* @param strict Strict parsing requires that the format and input match exactly, including delimiters.
|
||||
* Strict parsing is frequently the best parsing option. For more information about choosing strict vs
|
||||
* forgiving parsing, see the [parsing guide](https://momentjs.com/guides/#/parsing/).
|
||||
*/
|
||||
declare function moment(inp?: moment.MomentInput, format?: moment.MomentFormatSpecification, language?: string, strict?: boolean): moment.Moment;
|
||||
|
||||
declare namespace moment {
|
||||
type RelativeTimeKey = 's' | 'ss' | 'm' | 'mm' | 'h' | 'hh' | 'd' | 'dd' | 'w' | 'ww' | 'M' | 'MM' | 'y' | 'yy';
|
||||
type CalendarKey = 'sameDay' | 'nextDay' | 'lastDay' | 'nextWeek' | 'lastWeek' | 'sameElse' | string;
|
||||
type LongDateFormatKey = 'LTS' | 'LT' | 'L' | 'LL' | 'LLL' | 'LLLL' | 'lts' | 'lt' | 'l' | 'll' | 'lll' | 'llll';
|
||||
|
||||
interface Locale {
|
||||
calendar(key?: CalendarKey, m?: Moment, now?: Moment): string;
|
||||
|
||||
longDateFormat(key: LongDateFormatKey): string;
|
||||
invalidDate(): string;
|
||||
ordinal(n: number): string;
|
||||
|
||||
preparse(inp: string): string;
|
||||
postformat(inp: string): string;
|
||||
relativeTime(n: number, withoutSuffix: boolean,
|
||||
key: RelativeTimeKey, isFuture: boolean): string;
|
||||
pastFuture(diff: number, absRelTime: string): string;
|
||||
set(config: Object): void;
|
||||
|
||||
months(): string[];
|
||||
months(m: Moment, format?: string): string;
|
||||
monthsShort(): string[];
|
||||
monthsShort(m: Moment, format?: string): string;
|
||||
monthsParse(monthName: string, format: string, strict: boolean): number;
|
||||
monthsRegex(strict: boolean): RegExp;
|
||||
monthsShortRegex(strict: boolean): RegExp;
|
||||
|
||||
week(m: Moment): number;
|
||||
firstDayOfYear(): number;
|
||||
firstDayOfWeek(): number;
|
||||
|
||||
weekdays(): string[];
|
||||
weekdays(m: Moment, format?: string): string;
|
||||
weekdaysMin(): string[];
|
||||
weekdaysMin(m: Moment): string;
|
||||
weekdaysShort(): string[];
|
||||
weekdaysShort(m: Moment): string;
|
||||
weekdaysParse(weekdayName: string, format: string, strict: boolean): number;
|
||||
weekdaysRegex(strict: boolean): RegExp;
|
||||
weekdaysShortRegex(strict: boolean): RegExp;
|
||||
weekdaysMinRegex(strict: boolean): RegExp;
|
||||
|
||||
isPM(input: string): boolean;
|
||||
meridiem(hour: number, minute: number, isLower: boolean): string;
|
||||
}
|
||||
|
||||
interface StandaloneFormatSpec {
|
||||
format: string[];
|
||||
standalone: string[];
|
||||
isFormat?: RegExp;
|
||||
}
|
||||
|
||||
interface WeekSpec {
|
||||
dow: number;
|
||||
doy?: number;
|
||||
}
|
||||
|
||||
type CalendarSpecVal = string | ((m?: MomentInput, now?: Moment) => string);
|
||||
interface CalendarSpec {
|
||||
sameDay?: CalendarSpecVal;
|
||||
nextDay?: CalendarSpecVal;
|
||||
lastDay?: CalendarSpecVal;
|
||||
nextWeek?: CalendarSpecVal;
|
||||
lastWeek?: CalendarSpecVal;
|
||||
sameElse?: CalendarSpecVal;
|
||||
|
||||
// any additional properties might be used with moment.calendarFormat
|
||||
[x: string]: CalendarSpecVal | undefined;
|
||||
}
|
||||
|
||||
type RelativeTimeSpecVal = (
|
||||
string |
|
||||
((n: number, withoutSuffix: boolean,
|
||||
key: RelativeTimeKey, isFuture: boolean) => string)
|
||||
);
|
||||
type RelativeTimeFuturePastVal = string | ((relTime: string) => string);
|
||||
|
||||
interface RelativeTimeSpec {
|
||||
future?: RelativeTimeFuturePastVal;
|
||||
past?: RelativeTimeFuturePastVal;
|
||||
s?: RelativeTimeSpecVal;
|
||||
ss?: RelativeTimeSpecVal;
|
||||
m?: RelativeTimeSpecVal;
|
||||
mm?: RelativeTimeSpecVal;
|
||||
h?: RelativeTimeSpecVal;
|
||||
hh?: RelativeTimeSpecVal;
|
||||
d?: RelativeTimeSpecVal;
|
||||
dd?: RelativeTimeSpecVal;
|
||||
w?: RelativeTimeSpecVal;
|
||||
ww?: RelativeTimeSpecVal;
|
||||
M?: RelativeTimeSpecVal;
|
||||
MM?: RelativeTimeSpecVal;
|
||||
y?: RelativeTimeSpecVal;
|
||||
yy?: RelativeTimeSpecVal;
|
||||
}
|
||||
|
||||
interface LongDateFormatSpec {
|
||||
LTS: string;
|
||||
LT: string;
|
||||
L: string;
|
||||
LL: string;
|
||||
LLL: string;
|
||||
LLLL: string;
|
||||
|
||||
// lets forget for a sec that any upper/lower permutation will also work
|
||||
lts?: string;
|
||||
lt?: string;
|
||||
l?: string;
|
||||
ll?: string;
|
||||
lll?: string;
|
||||
llll?: string;
|
||||
}
|
||||
|
||||
type MonthWeekdayFn = (momentToFormat: Moment, format?: string) => string;
|
||||
type WeekdaySimpleFn = (momentToFormat: Moment) => string;
|
||||
|
||||
interface LocaleSpecification {
|
||||
months?: string[] | StandaloneFormatSpec | MonthWeekdayFn;
|
||||
monthsShort?: string[] | StandaloneFormatSpec | MonthWeekdayFn;
|
||||
|
||||
weekdays?: string[] | StandaloneFormatSpec | MonthWeekdayFn;
|
||||
weekdaysShort?: string[] | StandaloneFormatSpec | WeekdaySimpleFn;
|
||||
weekdaysMin?: string[] | StandaloneFormatSpec | WeekdaySimpleFn;
|
||||
|
||||
meridiemParse?: RegExp;
|
||||
meridiem?: (hour: number, minute:number, isLower: boolean) => string;
|
||||
|
||||
isPM?: (input: string) => boolean;
|
||||
|
||||
longDateFormat?: LongDateFormatSpec;
|
||||
calendar?: CalendarSpec;
|
||||
relativeTime?: RelativeTimeSpec;
|
||||
invalidDate?: string;
|
||||
ordinal?: (n: number) => string;
|
||||
ordinalParse?: RegExp;
|
||||
|
||||
week?: WeekSpec;
|
||||
|
||||
// Allow anything: in general any property that is passed as locale spec is
|
||||
// put in the locale object so it can be used by locale functions
|
||||
[x: string]: any;
|
||||
}
|
||||
|
||||
interface MomentObjectOutput {
|
||||
years: number;
|
||||
/* One digit */
|
||||
months: number;
|
||||
/* Day of the month */
|
||||
date: number;
|
||||
hours: number;
|
||||
minutes: number;
|
||||
seconds: number;
|
||||
milliseconds: number;
|
||||
}
|
||||
interface argThresholdOpts {
|
||||
ss?: number;
|
||||
s?: number;
|
||||
m?: number;
|
||||
h?: number;
|
||||
d?: number;
|
||||
w?: number | null;
|
||||
M?: number;
|
||||
}
|
||||
|
||||
interface Duration {
|
||||
clone(): Duration;
|
||||
|
||||
humanize(argWithSuffix?: boolean, argThresholds?: argThresholdOpts): string;
|
||||
|
||||
humanize(argThresholds?: argThresholdOpts): string;
|
||||
|
||||
abs(): Duration;
|
||||
|
||||
as(units: unitOfTime.Base): number;
|
||||
get(units: unitOfTime.Base): number;
|
||||
|
||||
milliseconds(): number;
|
||||
asMilliseconds(): number;
|
||||
|
||||
seconds(): number;
|
||||
asSeconds(): number;
|
||||
|
||||
minutes(): number;
|
||||
asMinutes(): number;
|
||||
|
||||
hours(): number;
|
||||
asHours(): number;
|
||||
|
||||
days(): number;
|
||||
asDays(): number;
|
||||
|
||||
weeks(): number;
|
||||
asWeeks(): number;
|
||||
|
||||
months(): number;
|
||||
asMonths(): number;
|
||||
|
||||
years(): number;
|
||||
asYears(): number;
|
||||
|
||||
add(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration;
|
||||
subtract(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration;
|
||||
|
||||
locale(): string;
|
||||
locale(locale: LocaleSpecifier): Duration;
|
||||
localeData(): Locale;
|
||||
|
||||
toISOString(): string;
|
||||
toJSON(): string;
|
||||
|
||||
isValid(): boolean;
|
||||
|
||||
/**
|
||||
* @deprecated since version 2.8.0
|
||||
*/
|
||||
lang(locale: LocaleSpecifier): Moment;
|
||||
/**
|
||||
* @deprecated since version 2.8.0
|
||||
*/
|
||||
lang(): Locale;
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
toIsoString(): string;
|
||||
}
|
||||
|
||||
interface MomentRelativeTime {
|
||||
future: any;
|
||||
past: any;
|
||||
s: any;
|
||||
ss: any;
|
||||
m: any;
|
||||
mm: any;
|
||||
h: any;
|
||||
hh: any;
|
||||
d: any;
|
||||
dd: any;
|
||||
M: any;
|
||||
MM: any;
|
||||
y: any;
|
||||
yy: any;
|
||||
}
|
||||
|
||||
interface MomentLongDateFormat {
|
||||
L: string;
|
||||
LL: string;
|
||||
LLL: string;
|
||||
LLLL: string;
|
||||
LT: string;
|
||||
LTS: string;
|
||||
|
||||
l?: string;
|
||||
ll?: string;
|
||||
lll?: string;
|
||||
llll?: string;
|
||||
lt?: string;
|
||||
lts?: string;
|
||||
}
|
||||
|
||||
interface MomentParsingFlags {
|
||||
empty: boolean;
|
||||
unusedTokens: string[];
|
||||
unusedInput: string[];
|
||||
overflow: number;
|
||||
charsLeftOver: number;
|
||||
nullInput: boolean;
|
||||
invalidMonth: string | null;
|
||||
invalidFormat: boolean;
|
||||
userInvalidated: boolean;
|
||||
iso: boolean;
|
||||
parsedDateParts: any[];
|
||||
meridiem: string | null;
|
||||
}
|
||||
|
||||
interface MomentParsingFlagsOpt {
|
||||
empty?: boolean;
|
||||
unusedTokens?: string[];
|
||||
unusedInput?: string[];
|
||||
overflow?: number;
|
||||
charsLeftOver?: number;
|
||||
nullInput?: boolean;
|
||||
invalidMonth?: string;
|
||||
invalidFormat?: boolean;
|
||||
userInvalidated?: boolean;
|
||||
iso?: boolean;
|
||||
parsedDateParts?: any[];
|
||||
meridiem?: string | null;
|
||||
}
|
||||
|
||||
interface MomentBuiltinFormat {
|
||||
__momentBuiltinFormatBrand: any;
|
||||
}
|
||||
|
||||
type MomentFormatSpecification = string | MomentBuiltinFormat | (string | MomentBuiltinFormat)[];
|
||||
|
||||
namespace unitOfTime {
|
||||
type Base = (
|
||||
"year" | "years" | "y" |
|
||||
"month" | "months" | "M" |
|
||||
"week" | "weeks" | "w" |
|
||||
"day" | "days" | "d" |
|
||||
"hour" | "hours" | "h" |
|
||||
"minute" | "minutes" | "m" |
|
||||
"second" | "seconds" | "s" |
|
||||
"millisecond" | "milliseconds" | "ms"
|
||||
);
|
||||
|
||||
type _quarter = "quarter" | "quarters" | "Q";
|
||||
type _isoWeek = "isoWeek" | "isoWeeks" | "W";
|
||||
type _date = "date" | "dates" | "D";
|
||||
type DurationConstructor = Base | _quarter;
|
||||
|
||||
type DurationAs = Base;
|
||||
|
||||
type StartOf = Base | _quarter | _isoWeek | _date | null;
|
||||
|
||||
type Diff = Base | _quarter;
|
||||
|
||||
type MomentConstructor = Base | _date;
|
||||
|
||||
type All = Base | _quarter | _isoWeek | _date |
|
||||
"weekYear" | "weekYears" | "gg" |
|
||||
"isoWeekYear" | "isoWeekYears" | "GG" |
|
||||
"dayOfYear" | "dayOfYears" | "DDD" |
|
||||
"weekday" | "weekdays" | "e" |
|
||||
"isoWeekday" | "isoWeekdays" | "E";
|
||||
}
|
||||
|
||||
interface MomentInputObject {
|
||||
years?: number;
|
||||
year?: number;
|
||||
y?: number;
|
||||
|
||||
months?: number;
|
||||
month?: number;
|
||||
M?: number;
|
||||
|
||||
days?: number;
|
||||
day?: number;
|
||||
d?: number;
|
||||
|
||||
dates?: number;
|
||||
date?: number;
|
||||
D?: number;
|
||||
|
||||
hours?: number;
|
||||
hour?: number;
|
||||
h?: number;
|
||||
|
||||
minutes?: number;
|
||||
minute?: number;
|
||||
m?: number;
|
||||
|
||||
seconds?: number;
|
||||
second?: number;
|
||||
s?: number;
|
||||
|
||||
milliseconds?: number;
|
||||
millisecond?: number;
|
||||
ms?: number;
|
||||
}
|
||||
|
||||
interface DurationInputObject extends MomentInputObject {
|
||||
quarters?: number;
|
||||
quarter?: number;
|
||||
Q?: number;
|
||||
|
||||
weeks?: number;
|
||||
week?: number;
|
||||
w?: number;
|
||||
}
|
||||
|
||||
interface MomentSetObject extends MomentInputObject {
|
||||
weekYears?: number;
|
||||
weekYear?: number;
|
||||
gg?: number;
|
||||
|
||||
isoWeekYears?: number;
|
||||
isoWeekYear?: number;
|
||||
GG?: number;
|
||||
|
||||
quarters?: number;
|
||||
quarter?: number;
|
||||
Q?: number;
|
||||
|
||||
weeks?: number;
|
||||
week?: number;
|
||||
w?: number;
|
||||
|
||||
isoWeeks?: number;
|
||||
isoWeek?: number;
|
||||
W?: number;
|
||||
|
||||
dayOfYears?: number;
|
||||
dayOfYear?: number;
|
||||
DDD?: number;
|
||||
|
||||
weekdays?: number;
|
||||
weekday?: number;
|
||||
e?: number;
|
||||
|
||||
isoWeekdays?: number;
|
||||
isoWeekday?: number;
|
||||
E?: number;
|
||||
}
|
||||
|
||||
interface FromTo {
|
||||
from: MomentInput;
|
||||
to: MomentInput;
|
||||
}
|
||||
|
||||
type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | null | undefined;
|
||||
type DurationInputArg1 = Duration | number | string | FromTo | DurationInputObject | null | undefined;
|
||||
type DurationInputArg2 = unitOfTime.DurationConstructor;
|
||||
type LocaleSpecifier = string | Moment | Duration | string[] | boolean;
|
||||
|
||||
interface MomentCreationData {
|
||||
input: MomentInput;
|
||||
format?: MomentFormatSpecification;
|
||||
locale: Locale;
|
||||
isUTC: boolean;
|
||||
strict?: boolean;
|
||||
}
|
||||
|
||||
interface Moment extends Object {
|
||||
format(format?: string): string;
|
||||
|
||||
startOf(unitOfTime: unitOfTime.StartOf): Moment;
|
||||
endOf(unitOfTime: unitOfTime.StartOf): Moment;
|
||||
|
||||
add(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
|
||||
/**
|
||||
* @deprecated reverse syntax
|
||||
*/
|
||||
add(unit: unitOfTime.DurationConstructor, amount: number|string): Moment;
|
||||
|
||||
subtract(amount?: DurationInputArg1, unit?: DurationInputArg2): Moment;
|
||||
/**
|
||||
* @deprecated reverse syntax
|
||||
*/
|
||||
subtract(unit: unitOfTime.DurationConstructor, amount: number|string): Moment;
|
||||
|
||||
calendar(): string;
|
||||
calendar(formats: CalendarSpec): string;
|
||||
calendar(time?: MomentInput, formats?: CalendarSpec): string;
|
||||
|
||||
clone(): Moment;
|
||||
|
||||
/**
|
||||
* @return Unix timestamp in milliseconds
|
||||
*/
|
||||
valueOf(): number;
|
||||
|
||||
// current date/time in local mode
|
||||
local(keepLocalTime?: boolean): Moment;
|
||||
isLocal(): boolean;
|
||||
|
||||
// current date/time in UTC mode
|
||||
utc(keepLocalTime?: boolean): Moment;
|
||||
isUTC(): boolean;
|
||||
/**
|
||||
* @deprecated use isUTC
|
||||
*/
|
||||
isUtc(): boolean;
|
||||
|
||||
parseZone(): Moment;
|
||||
isValid(): boolean;
|
||||
invalidAt(): number;
|
||||
|
||||
hasAlignedHourOffset(other?: MomentInput): boolean;
|
||||
|
||||
creationData(): MomentCreationData;
|
||||
parsingFlags(): MomentParsingFlags;
|
||||
|
||||
year(y: number): Moment;
|
||||
year(): number;
|
||||
/**
|
||||
* @deprecated use year(y)
|
||||
*/
|
||||
years(y: number): Moment;
|
||||
/**
|
||||
* @deprecated use year()
|
||||
*/
|
||||
years(): number;
|
||||
quarter(): number;
|
||||
quarter(q: number): Moment;
|
||||
quarters(): number;
|
||||
quarters(q: number): Moment;
|
||||
month(M: number|string): Moment;
|
||||
month(): number;
|
||||
/**
|
||||
* @deprecated use month(M)
|
||||
*/
|
||||
months(M: number|string): Moment;
|
||||
/**
|
||||
* @deprecated use month()
|
||||
*/
|
||||
months(): number;
|
||||
day(d: number|string): Moment;
|
||||
day(): number;
|
||||
days(d: number|string): Moment;
|
||||
days(): number;
|
||||
date(d: number): Moment;
|
||||
date(): number;
|
||||
/**
|
||||
* @deprecated use date(d)
|
||||
*/
|
||||
dates(d: number): Moment;
|
||||
/**
|
||||
* @deprecated use date()
|
||||
*/
|
||||
dates(): number;
|
||||
hour(h: number): Moment;
|
||||
hour(): number;
|
||||
hours(h: number): Moment;
|
||||
hours(): number;
|
||||
minute(m: number): Moment;
|
||||
minute(): number;
|
||||
minutes(m: number): Moment;
|
||||
minutes(): number;
|
||||
second(s: number): Moment;
|
||||
second(): number;
|
||||
seconds(s: number): Moment;
|
||||
seconds(): number;
|
||||
millisecond(ms: number): Moment;
|
||||
millisecond(): number;
|
||||
milliseconds(ms: number): Moment;
|
||||
milliseconds(): number;
|
||||
weekday(): number;
|
||||
weekday(d: number): Moment;
|
||||
isoWeekday(): number;
|
||||
isoWeekday(d: number|string): Moment;
|
||||
weekYear(): number;
|
||||
weekYear(d: number): Moment;
|
||||
isoWeekYear(): number;
|
||||
isoWeekYear(d: number): Moment;
|
||||
week(): number;
|
||||
week(d: number): Moment;
|
||||
weeks(): number;
|
||||
weeks(d: number): Moment;
|
||||
isoWeek(): number;
|
||||
isoWeek(d: number): Moment;
|
||||
isoWeeks(): number;
|
||||
isoWeeks(d: number): Moment;
|
||||
weeksInYear(): number;
|
||||
isoWeeksInYear(): number;
|
||||
isoWeeksInISOWeekYear(): number;
|
||||
dayOfYear(): number;
|
||||
dayOfYear(d: number): Moment;
|
||||
|
||||
from(inp: MomentInput, suffix?: boolean): string;
|
||||
to(inp: MomentInput, suffix?: boolean): string;
|
||||
fromNow(withoutSuffix?: boolean): string;
|
||||
toNow(withoutPrefix?: boolean): string;
|
||||
|
||||
diff(b: MomentInput, unitOfTime?: unitOfTime.Diff, precise?: boolean): number;
|
||||
|
||||
toArray(): [number, number, number, number, number, number, number];
|
||||
toDate(): Date;
|
||||
toISOString(keepOffset?: boolean): string;
|
||||
inspect(): string;
|
||||
toJSON(): string;
|
||||
unix(): number;
|
||||
|
||||
isLeapYear(): boolean;
|
||||
/**
|
||||
* @deprecated in favor of utcOffset
|
||||
*/
|
||||
zone(): number;
|
||||
zone(b: number|string): Moment;
|
||||
utcOffset(): number;
|
||||
utcOffset(b: number|string, keepLocalTime?: boolean): Moment;
|
||||
isUtcOffset(): boolean;
|
||||
daysInMonth(): number;
|
||||
isDST(): boolean;
|
||||
|
||||
zoneAbbr(): string;
|
||||
zoneName(): string;
|
||||
|
||||
isBefore(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
|
||||
isAfter(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
|
||||
isSame(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
|
||||
isSameOrAfter(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
|
||||
isSameOrBefore(inp?: MomentInput, granularity?: unitOfTime.StartOf): boolean;
|
||||
isBetween(a: MomentInput, b: MomentInput, granularity?: unitOfTime.StartOf, inclusivity?: "()" | "[)" | "(]" | "[]"): boolean;
|
||||
|
||||
/**
|
||||
* @deprecated as of 2.8.0, use locale
|
||||
*/
|
||||
lang(language: LocaleSpecifier): Moment;
|
||||
/**
|
||||
* @deprecated as of 2.8.0, use locale
|
||||
*/
|
||||
lang(): Locale;
|
||||
|
||||
locale(): string;
|
||||
locale(locale: LocaleSpecifier): Moment;
|
||||
|
||||
localeData(): Locale;
|
||||
|
||||
/**
|
||||
* @deprecated no reliable implementation
|
||||
*/
|
||||
isDSTShifted(): boolean;
|
||||
|
||||
// NOTE(constructor): Same as moment constructor
|
||||
/**
|
||||
* @deprecated as of 2.7.0, use moment.min/max
|
||||
*/
|
||||
max(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;
|
||||
/**
|
||||
* @deprecated as of 2.7.0, use moment.min/max
|
||||
*/
|
||||
max(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;
|
||||
|
||||
// NOTE(constructor): Same as moment constructor
|
||||
/**
|
||||
* @deprecated as of 2.7.0, use moment.min/max
|
||||
*/
|
||||
min(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;
|
||||
/**
|
||||
* @deprecated as of 2.7.0, use moment.min/max
|
||||
*/
|
||||
min(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;
|
||||
|
||||
get(unit: unitOfTime.All): number;
|
||||
set(unit: unitOfTime.All, value: number): Moment;
|
||||
set(objectLiteral: MomentSetObject): Moment;
|
||||
|
||||
toObject(): MomentObjectOutput;
|
||||
}
|
||||
|
||||
export var version: string;
|
||||
export var fn: Moment;
|
||||
|
||||
// NOTE(constructor): Same as moment constructor
|
||||
/**
|
||||
* @param strict Strict parsing disables the deprecated fallback to the native Date constructor when
|
||||
* parsing a string.
|
||||
*/
|
||||
export function utc(inp?: MomentInput, strict?: boolean): Moment;
|
||||
/**
|
||||
* @param strict Strict parsing requires that the format and input match exactly, including delimiters.
|
||||
* Strict parsing is frequently the best parsing option. For more information about choosing strict vs
|
||||
* forgiving parsing, see the [parsing guide](https://momentjs.com/guides/#/parsing/).
|
||||
*/
|
||||
export function utc(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;
|
||||
/**
|
||||
* @param strict Strict parsing requires that the format and input match exactly, including delimiters.
|
||||
* Strict parsing is frequently the best parsing option. For more information about choosing strict vs
|
||||
* forgiving parsing, see the [parsing guide](https://momentjs.com/guides/#/parsing/).
|
||||
*/
|
||||
export function utc(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;
|
||||
|
||||
export function unix(timestamp: number): Moment;
|
||||
|
||||
export function invalid(flags?: MomentParsingFlagsOpt): Moment;
|
||||
export function isMoment(m: any): m is Moment;
|
||||
export function isDate(m: any): m is Date;
|
||||
export function isDuration(d: any): d is Duration;
|
||||
|
||||
/**
|
||||
* @deprecated in 2.8.0
|
||||
*/
|
||||
export function lang(language?: string): string;
|
||||
/**
|
||||
* @deprecated in 2.8.0
|
||||
*/
|
||||
export function lang(language?: string, definition?: Locale): string;
|
||||
|
||||
export function locale(language?: string): string;
|
||||
export function locale(language?: string[]): string;
|
||||
export function locale(language?: string, definition?: LocaleSpecification | null | undefined): string;
|
||||
|
||||
export function localeData(key?: string | string[]): Locale;
|
||||
|
||||
export function duration(inp?: DurationInputArg1, unit?: DurationInputArg2): Duration;
|
||||
|
||||
// NOTE(constructor): Same as moment constructor
|
||||
export function parseZone(inp?: MomentInput, format?: MomentFormatSpecification, strict?: boolean): Moment;
|
||||
export function parseZone(inp?: MomentInput, format?: MomentFormatSpecification, language?: string, strict?: boolean): Moment;
|
||||
|
||||
export function months(): string[];
|
||||
export function months(index: number): string;
|
||||
export function months(format: string): string[];
|
||||
export function months(format: string, index: number): string;
|
||||
export function monthsShort(): string[];
|
||||
export function monthsShort(index: number): string;
|
||||
export function monthsShort(format: string): string[];
|
||||
export function monthsShort(format: string, index: number): string;
|
||||
|
||||
export function weekdays(): string[];
|
||||
export function weekdays(index: number): string;
|
||||
export function weekdays(format: string): string[];
|
||||
export function weekdays(format: string, index: number): string;
|
||||
export function weekdays(localeSorted: boolean): string[];
|
||||
export function weekdays(localeSorted: boolean, index: number): string;
|
||||
export function weekdays(localeSorted: boolean, format: string): string[];
|
||||
export function weekdays(localeSorted: boolean, format: string, index: number): string;
|
||||
export function weekdaysShort(): string[];
|
||||
export function weekdaysShort(index: number): string;
|
||||
export function weekdaysShort(format: string): string[];
|
||||
export function weekdaysShort(format: string, index: number): string;
|
||||
export function weekdaysShort(localeSorted: boolean): string[];
|
||||
export function weekdaysShort(localeSorted: boolean, index: number): string;
|
||||
export function weekdaysShort(localeSorted: boolean, format: string): string[];
|
||||
export function weekdaysShort(localeSorted: boolean, format: string, index: number): string;
|
||||
export function weekdaysMin(): string[];
|
||||
export function weekdaysMin(index: number): string;
|
||||
export function weekdaysMin(format: string): string[];
|
||||
export function weekdaysMin(format: string, index: number): string;
|
||||
export function weekdaysMin(localeSorted: boolean): string[];
|
||||
export function weekdaysMin(localeSorted: boolean, index: number): string;
|
||||
export function weekdaysMin(localeSorted: boolean, format: string): string[];
|
||||
export function weekdaysMin(localeSorted: boolean, format: string, index: number): string;
|
||||
|
||||
export function min(moments: Moment[]): Moment;
|
||||
export function min(...moments: Moment[]): Moment;
|
||||
export function max(moments: Moment[]): Moment;
|
||||
export function max(...moments: Moment[]): Moment;
|
||||
|
||||
/**
|
||||
* Returns unix time in milliseconds. Overwrite for profit.
|
||||
*/
|
||||
export function now(): number;
|
||||
|
||||
export function defineLocale(language: string, localeSpec: LocaleSpecification | null): Locale;
|
||||
export function updateLocale(language: string, localeSpec: LocaleSpecification | null): Locale;
|
||||
|
||||
export function locales(): string[];
|
||||
|
||||
export function normalizeUnits(unit: unitOfTime.All): string;
|
||||
export function relativeTimeThreshold(threshold: string): number | boolean;
|
||||
export function relativeTimeThreshold(threshold: string, limit: number): boolean;
|
||||
export function relativeTimeRounding(fn: (num: number) => number): boolean;
|
||||
export function relativeTimeRounding(): (num: number) => number;
|
||||
export function calendarFormat(m: Moment, now: Moment): string;
|
||||
|
||||
export function parseTwoDigitYear(input: string): number;
|
||||
/**
|
||||
* Constant used to enable explicit ISO_8601 format parsing.
|
||||
*/
|
||||
export var ISO_8601: MomentBuiltinFormat;
|
||||
export var RFC_2822: MomentBuiltinFormat;
|
||||
|
||||
export var defaultFormat: string;
|
||||
export var defaultFormatUtc: string;
|
||||
|
||||
export var suppressDeprecationWarnings: boolean;
|
||||
export var deprecationHandler: ((name: string | null, msg: string) => void) | null | undefined;
|
||||
|
||||
export var HTML5_FMT: {
|
||||
DATETIME_LOCAL: string,
|
||||
DATETIME_LOCAL_SECONDS: string,
|
||||
DATETIME_LOCAL_MS: string,
|
||||
DATE: string,
|
||||
TIME: string,
|
||||
TIME_SECONDS: string,
|
||||
TIME_MS: string,
|
||||
WEEK: string,
|
||||
MONTH: string
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
declare global {
|
||||
const moment: typeof moment;
|
||||
}
|
||||
|
@ -4400,13 +4400,6 @@
|
||||
<input id="auto_fix_generated_markdown" type="checkbox" />
|
||||
<small data-i18n="Auto-fix Markdown">Auto-fix Markdown</small>
|
||||
</label>
|
||||
<label class="checkbox_label" for="render_formulas" title="Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX." data-i18n="[title]Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX">
|
||||
<input id="render_formulas" type="checkbox" />
|
||||
<small data-i18n="Render Formulas">Render Formulas</small>
|
||||
<a href="https://docs.sillytavern.app/usage/core-concepts/uicustomization/#formulas-rendering" class="notes-link" target="_blank">
|
||||
<small class="fa-solid fa-circle-question note-link-small"></small>
|
||||
</a>
|
||||
</label>
|
||||
<label class="checkbox_label" for="forbid_external_media" title="Disallow embedded media from other domains in chat messages." data-i18n="[title]Disallow embedded media from other domains in chat messages">
|
||||
<input id="forbid_external_media" type="checkbox" />
|
||||
<small data-i18n="Forbid External Media">Forbid External Media</small>
|
||||
@ -6750,42 +6743,23 @@
|
||||
|
||||
<!-- Script includes -->
|
||||
<script src="lib/polyfill.js"></script>
|
||||
<script src="lib/diff_match_patch.js"></script>
|
||||
<script src="lib/jquery-3.5.1.min.js"></script>
|
||||
<script src="lib/jquery-ui.min.js"></script>
|
||||
<script src="lib/jquery.transit.min.js"></script>
|
||||
<script src="lib/jquery-cookie-1.4.1.min.js"></script>
|
||||
<script src="lib/jquery.ui.touch-punch.min.js"></script>
|
||||
<script src="lib/showdown.min.js"></script>
|
||||
<script src="lib/showdown-patch.js"></script>
|
||||
<script src="lib/showdown-katex.min.js"></script>
|
||||
<script src="lib/popper.js"></script>
|
||||
<script src="lib/purify.min.js"></script>
|
||||
<script src="lib/highlight.min.js"></script>
|
||||
<script src="lib/moment-with-locales.min.js"></script>
|
||||
<script src="lib/cropper.min.js"></script>
|
||||
<script src="lib/jquery-cropper.min.js"></script>
|
||||
<script src="lib/toastr.min.js"></script>
|
||||
<script src="lib/fuse.js"></script>
|
||||
<script src="lib/select2.min.js"></script>
|
||||
<script src="lib/select2-search-placeholder.js"></script>
|
||||
<script src="lib/seedrandom.min.js"></script>
|
||||
<script src="lib/droll.js"></script>
|
||||
<script src="lib/localforage.min.js"></script>
|
||||
<script src="lib/handlebars.js"></script>
|
||||
<script src="lib/pagination.js"></script>
|
||||
<script src="lib/toolcool-color-picker.js"></script>
|
||||
<script src="lib/svg-inject.js"></script>
|
||||
<script src="lib/Readability.js"></script>
|
||||
<script src="lib/Readability-readerable.js"></script>
|
||||
<script src="lib/jquery.izoomify.js"></script>
|
||||
<script type="module" src="lib/structured-clone/monkey-patch.js"></script>
|
||||
<script type="module" src="lib/swiped-events.js"></script>
|
||||
<script type="module" src="lib/eventemitter.js"></script>
|
||||
<script type="module" src="scripts/i18n.js"></script>
|
||||
<script type="module" src="scripts/bulk-edit.js"></script>
|
||||
<script type="module" src="scripts/setting-search.js"></script>
|
||||
<script type="module" src="scripts/server-history.js"></script>
|
||||
<script type="module" src="script.js"></script>
|
||||
<script>
|
||||
window.addEventListener('load', (event) => {
|
||||
|
@ -16,17 +16,6 @@
|
||||
"scripts/extensions/quick-reply/lib/**"
|
||||
],
|
||||
"typeAcquisition": {
|
||||
"include": [
|
||||
"@popperjs/core",
|
||||
"showdown",
|
||||
"seedrandom",
|
||||
"showdown-katex",
|
||||
"droll",
|
||||
"handlebars",
|
||||
"highlight.js",
|
||||
"localforage",
|
||||
"pdfjs-dist",
|
||||
"@mozilla/readability"
|
||||
]
|
||||
"include": []
|
||||
}
|
||||
}
|
||||
|
118
public/lib.js
Normal file
118
public/lib.js
Normal file
@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Add all the libraries that you want to expose to the client here.
|
||||
* They are bundled and exposed by Webpack in the /lib.js file.
|
||||
*/
|
||||
import lodash from 'lodash';
|
||||
import Fuse from 'fuse.js';
|
||||
import DOMPurify from 'dompurify';
|
||||
import hljs from 'highlight.js';
|
||||
import localforage from 'localforage';
|
||||
import Handlebars from 'handlebars';
|
||||
import css from '@adobe/css-tools';
|
||||
import Bowser from 'bowser';
|
||||
import DiffMatchPatch from 'diff-match-patch';
|
||||
import { isProbablyReaderable, Readability } from '@mozilla/readability';
|
||||
import SVGInject from '@iconfu/svg-inject';
|
||||
import showdown from 'showdown';
|
||||
import moment from 'moment';
|
||||
import seedrandom from 'seedrandom';
|
||||
import * as Popper from '@popperjs/core';
|
||||
import droll from 'droll';
|
||||
import morphdom from 'morphdom';
|
||||
|
||||
/**
|
||||
* Expose the libraries to the 'window' object.
|
||||
* Needed for compatibility with old extensions.
|
||||
* Note: New extensions are encouraged to import the libraries directly from lib.js.
|
||||
*/
|
||||
export function initLibraryShims() {
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
if (!('Fuse' in window)) {
|
||||
// @ts-ignore
|
||||
window.Fuse = Fuse;
|
||||
}
|
||||
if (!('DOMPurify' in window)) {
|
||||
// @ts-ignore
|
||||
window.DOMPurify = DOMPurify;
|
||||
}
|
||||
if (!('hljs' in window)) {
|
||||
// @ts-ignore
|
||||
window.hljs = hljs;
|
||||
}
|
||||
if (!('localforage' in window)) {
|
||||
// @ts-ignore
|
||||
window.localforage = localforage;
|
||||
}
|
||||
if (!('Handlebars' in window)) {
|
||||
// @ts-ignore
|
||||
window.Handlebars = Handlebars;
|
||||
}
|
||||
if (!('diff_match_patch' in window)) {
|
||||
// @ts-ignore
|
||||
window.diff_match_patch = DiffMatchPatch;
|
||||
}
|
||||
if (!('SVGInject' in window)) {
|
||||
// @ts-ignore
|
||||
window.SVGInject = SVGInject;
|
||||
}
|
||||
if (!('showdown' in window)) {
|
||||
// @ts-ignore
|
||||
window.showdown = showdown;
|
||||
}
|
||||
if (!('moment' in window)) {
|
||||
// @ts-ignore
|
||||
window.moment = moment;
|
||||
}
|
||||
if (!('Popper' in window)) {
|
||||
// @ts-ignore
|
||||
window.Popper = Popper;
|
||||
}
|
||||
if (!('droll' in window)) {
|
||||
// @ts-ignore
|
||||
window.droll = droll;
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
lodash,
|
||||
Fuse,
|
||||
DOMPurify,
|
||||
hljs,
|
||||
localforage,
|
||||
Handlebars,
|
||||
css,
|
||||
Bowser,
|
||||
DiffMatchPatch,
|
||||
Readability,
|
||||
isProbablyReaderable,
|
||||
SVGInject,
|
||||
showdown,
|
||||
moment,
|
||||
seedrandom,
|
||||
Popper,
|
||||
droll,
|
||||
morphdom,
|
||||
};
|
||||
|
||||
export {
|
||||
lodash,
|
||||
Fuse,
|
||||
DOMPurify,
|
||||
hljs,
|
||||
localforage,
|
||||
Handlebars,
|
||||
css,
|
||||
Bowser,
|
||||
DiffMatchPatch,
|
||||
Readability,
|
||||
isProbablyReaderable,
|
||||
SVGInject,
|
||||
showdown,
|
||||
moment,
|
||||
seedrandom,
|
||||
Popper,
|
||||
droll,
|
||||
morphdom,
|
||||
};
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Arc90 Inc
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code is heavily based on Arc90's readability.js (1.7.1) script
|
||||
* available at: http://code.google.com/p/arc90labs-readability
|
||||
*/
|
||||
|
||||
var REGEXPS = {
|
||||
// NOTE: These two regular expressions are duplicated in
|
||||
// Readability.js. Please keep both copies in sync.
|
||||
unlikelyCandidates: /-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
|
||||
okMaybeItsACandidate: /and|article|body|column|content|main|shadow/i,
|
||||
};
|
||||
|
||||
function isNodeVisible(node) {
|
||||
// Have to null-check node.style and node.className.indexOf to deal with SVG and MathML nodes.
|
||||
return (!node.style || node.style.display != "none")
|
||||
&& !node.hasAttribute("hidden")
|
||||
//check for "fallback-image" so that wikimedia math images are displayed
|
||||
&& (!node.hasAttribute("aria-hidden") || node.getAttribute("aria-hidden") != "true" || (node.className && node.className.indexOf && node.className.indexOf("fallback-image") !== -1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decides whether or not the document is reader-able without parsing the whole thing.
|
||||
* @param {Object} options Configuration object.
|
||||
* @param {number} [options.minContentLength=140] The minimum node content length used to decide if the document is readerable.
|
||||
* @param {number} [options.minScore=20] The minumum cumulated 'score' used to determine if the document is readerable.
|
||||
* @param {Function} [options.visibilityChecker=isNodeVisible] The function used to determine if a node is visible.
|
||||
* @return {boolean} Whether or not we suspect Readability.parse() will suceeed at returning an article object.
|
||||
*/
|
||||
function isProbablyReaderable(doc, options = {}) {
|
||||
// For backward compatibility reasons 'options' can either be a configuration object or the function used
|
||||
// to determine if a node is visible.
|
||||
if (typeof options == "function") {
|
||||
options = { visibilityChecker: options };
|
||||
}
|
||||
|
||||
var defaultOptions = { minScore: 20, minContentLength: 140, visibilityChecker: isNodeVisible };
|
||||
options = Object.assign(defaultOptions, options);
|
||||
|
||||
var nodes = doc.querySelectorAll("p, pre, article");
|
||||
|
||||
// Get <div> nodes which have <br> node(s) and append them into the `nodes` variable.
|
||||
// Some articles' DOM structures might look like
|
||||
// <div>
|
||||
// Sentences<br>
|
||||
// <br>
|
||||
// Sentences<br>
|
||||
// </div>
|
||||
var brNodes = doc.querySelectorAll("div > br");
|
||||
if (brNodes.length) {
|
||||
var set = new Set(nodes);
|
||||
[].forEach.call(brNodes, function (node) {
|
||||
set.add(node.parentNode);
|
||||
});
|
||||
nodes = Array.from(set);
|
||||
}
|
||||
|
||||
var score = 0;
|
||||
// This is a little cheeky, we use the accumulator 'score' to decide what to return from
|
||||
// this callback:
|
||||
return [].some.call(nodes, function (node) {
|
||||
if (!options.visibilityChecker(node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var matchString = node.className + " " + node.id;
|
||||
if (REGEXPS.unlikelyCandidates.test(matchString) &&
|
||||
!REGEXPS.okMaybeItsACandidate.test(matchString)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node.matches("li p")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var textContentLength = node.textContent.trim().length;
|
||||
if (textContentLength < options.minContentLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
score += Math.sqrt(textContentLength - options.minContentLength);
|
||||
|
||||
if (score > options.minScore) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof module === "object") {
|
||||
/* global module */
|
||||
module.exports = isProbablyReaderable;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
14
public/lib/bowser.min.js
vendored
14
public/lib/bowser.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,765 +0,0 @@
|
||||
|
||||
function $parcel$defineInteropFlag(a) {
|
||||
Object.defineProperty(a, '__esModule', {value: true, configurable: true});
|
||||
}
|
||||
|
||||
function $parcel$export(e, n, v, s) {
|
||||
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
|
||||
}
|
||||
var $009ddb00d3ec72b8$exports = {};
|
||||
|
||||
$parcel$defineInteropFlag($009ddb00d3ec72b8$exports);
|
||||
|
||||
$parcel$export($009ddb00d3ec72b8$exports, "default", () => $009ddb00d3ec72b8$export$2e2bcd8739ae039);
|
||||
class $009ddb00d3ec72b8$export$2e2bcd8739ae039 extends Error {
|
||||
constructor(filename, msg, lineno, column, css){
|
||||
super(filename + ":" + lineno + ":" + column + ": " + msg);
|
||||
this.reason = msg;
|
||||
this.filename = filename;
|
||||
this.line = lineno;
|
||||
this.column = column;
|
||||
this.source = css;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var $0865a9fb4cc365fe$exports = {};
|
||||
|
||||
$parcel$defineInteropFlag($0865a9fb4cc365fe$exports);
|
||||
|
||||
$parcel$export($0865a9fb4cc365fe$exports, "default", () => $0865a9fb4cc365fe$export$2e2bcd8739ae039);
|
||||
/**
|
||||
* Store position information for a node
|
||||
*/ class $0865a9fb4cc365fe$export$2e2bcd8739ae039 {
|
||||
constructor(start, end, source){
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.source = source;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var $b2e137848b48cf4f$exports = {};
|
||||
|
||||
$parcel$export($b2e137848b48cf4f$exports, "CssTypes", () => $b2e137848b48cf4f$export$9be5dd6e61d5d73a);
|
||||
var $b2e137848b48cf4f$export$9be5dd6e61d5d73a;
|
||||
(function(CssTypes) {
|
||||
CssTypes["stylesheet"] = "stylesheet";
|
||||
CssTypes["rule"] = "rule";
|
||||
CssTypes["declaration"] = "declaration";
|
||||
CssTypes["comment"] = "comment";
|
||||
CssTypes["container"] = "container";
|
||||
CssTypes["charset"] = "charset";
|
||||
CssTypes["document"] = "document";
|
||||
CssTypes["customMedia"] = "custom-media";
|
||||
CssTypes["fontFace"] = "font-face";
|
||||
CssTypes["host"] = "host";
|
||||
CssTypes["import"] = "import";
|
||||
CssTypes["keyframes"] = "keyframes";
|
||||
CssTypes["keyframe"] = "keyframe";
|
||||
CssTypes["layer"] = "layer";
|
||||
CssTypes["media"] = "media";
|
||||
CssTypes["namespace"] = "namespace";
|
||||
CssTypes["page"] = "page";
|
||||
CssTypes["supports"] = "supports";
|
||||
})($b2e137848b48cf4f$export$9be5dd6e61d5d73a || ($b2e137848b48cf4f$export$9be5dd6e61d5d73a = {}));
|
||||
|
||||
|
||||
// http://www.w3.org/TR/CSS21/grammar.html
|
||||
// https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027
|
||||
// New rule => https://www.w3.org/TR/CSS22/syndata.html#comments
|
||||
// [^] is equivalent to [.\n\r]
|
||||
const $d708735ed1303b43$var$commentre = /\/\*[^]*?(?:\*\/|$)/g;
|
||||
const $d708735ed1303b43$export$98e6a39c04603d36 = (css, options)=>{
|
||||
options = options || {};
|
||||
/**
|
||||
* Positional.
|
||||
*/ let lineno = 1;
|
||||
let column = 1;
|
||||
/**
|
||||
* Update lineno and column based on `str`.
|
||||
*/ function updatePosition(str) {
|
||||
const lines = str.match(/\n/g);
|
||||
if (lines) lineno += lines.length;
|
||||
const i = str.lastIndexOf("\n");
|
||||
column = ~i ? str.length - i : column + str.length;
|
||||
}
|
||||
/**
|
||||
* Mark position and patch `node.position`.
|
||||
*/ function position() {
|
||||
const start = {
|
||||
line: lineno,
|
||||
column: column
|
||||
};
|
||||
return function(node) {
|
||||
node.position = new (0, $0865a9fb4cc365fe$export$2e2bcd8739ae039)(start, {
|
||||
line: lineno,
|
||||
column: column
|
||||
}, options?.source || "");
|
||||
whitespace();
|
||||
return node;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Error `msg`.
|
||||
*/ const errorsList = [];
|
||||
function error(msg) {
|
||||
const err = new (0, $009ddb00d3ec72b8$export$2e2bcd8739ae039)(options?.source || "", msg, lineno, column, css);
|
||||
if (options?.silent) errorsList.push(err);
|
||||
else throw err;
|
||||
}
|
||||
/**
|
||||
* Parse stylesheet.
|
||||
*/ function stylesheet() {
|
||||
const rulesList = rules();
|
||||
const result = {
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).stylesheet,
|
||||
stylesheet: {
|
||||
source: options?.source,
|
||||
rules: rulesList,
|
||||
parsingErrors: errorsList
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Opening brace.
|
||||
*/ function open() {
|
||||
return match(/^{\s*/);
|
||||
}
|
||||
/**
|
||||
* Closing brace.
|
||||
*/ function close() {
|
||||
return match(/^}/);
|
||||
}
|
||||
/**
|
||||
* Parse ruleset.
|
||||
*/ function rules() {
|
||||
let node;
|
||||
const rules = [];
|
||||
whitespace();
|
||||
comments(rules);
|
||||
while(css.length && css.charAt(0) !== "}" && (node = atrule() || rule()))if (node) {
|
||||
rules.push(node);
|
||||
comments(rules);
|
||||
}
|
||||
return rules;
|
||||
}
|
||||
/**
|
||||
* Match `re` and return captures.
|
||||
*/ function match(re) {
|
||||
const m = re.exec(css);
|
||||
if (!m) return;
|
||||
const str = m[0];
|
||||
updatePosition(str);
|
||||
css = css.slice(str.length);
|
||||
return m;
|
||||
}
|
||||
/**
|
||||
* Parse whitespace.
|
||||
*/ function whitespace() {
|
||||
match(/^\s*/);
|
||||
}
|
||||
/**
|
||||
* Parse comments;
|
||||
*/ function comments(rules) {
|
||||
let c;
|
||||
rules = rules || [];
|
||||
while(c = comment())if (c) rules.push(c);
|
||||
return rules;
|
||||
}
|
||||
/**
|
||||
* Parse comment.
|
||||
*/ function comment() {
|
||||
const pos = position();
|
||||
if ("/" !== css.charAt(0) || "*" !== css.charAt(1)) return;
|
||||
const m = match(/^\/\*[^]*?\*\//);
|
||||
if (!m) return error("End of comment missing");
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).comment,
|
||||
comment: m[0].slice(2, -2)
|
||||
});
|
||||
}
|
||||
function findClosingParenthese(str, start, depth) {
|
||||
let ptr = start + 1;
|
||||
let found = false;
|
||||
let closeParentheses = str.indexOf(")", ptr);
|
||||
while(!found && closeParentheses !== -1){
|
||||
const nextParentheses = str.indexOf("(", ptr);
|
||||
if (nextParentheses !== -1 && nextParentheses < closeParentheses) {
|
||||
const nextSearch = findClosingParenthese(str, nextParentheses + 1, depth + 1);
|
||||
ptr = nextSearch + 1;
|
||||
closeParentheses = str.indexOf(")", ptr);
|
||||
} else found = true;
|
||||
}
|
||||
if (found && closeParentheses !== -1) return closeParentheses;
|
||||
else return -1;
|
||||
}
|
||||
/**
|
||||
* Parse selector.
|
||||
*/ function selector() {
|
||||
const m = match(/^([^{]+)/);
|
||||
if (!m) return;
|
||||
// remove comment in selector;
|
||||
let res = $d708735ed1303b43$var$trim(m[0]).replace($d708735ed1303b43$var$commentre, "");
|
||||
// Optimisation: If there is no ',' no need to split or post-process (this is less costly)
|
||||
if (res.indexOf(",") === -1) return [
|
||||
res
|
||||
];
|
||||
// Replace all the , in the parentheses by \u200C
|
||||
let ptr = 0;
|
||||
let startParentheses = res.indexOf("(", ptr);
|
||||
while(startParentheses !== -1){
|
||||
const closeParentheses = findClosingParenthese(res, startParentheses, 0);
|
||||
if (closeParentheses === -1) break;
|
||||
ptr = closeParentheses + 1;
|
||||
res = res.substring(0, startParentheses) + res.substring(startParentheses, closeParentheses).replace(/,/g, "\u200C") + res.substring(closeParentheses);
|
||||
startParentheses = res.indexOf("(", ptr);
|
||||
}
|
||||
// Replace all the , in ' and " by \u200C
|
||||
res = res/**
|
||||
* replace ',' by \u200C for data selector (div[data-lang="fr,de,us"])
|
||||
*
|
||||
* Examples:
|
||||
* div[data-lang="fr,\"de,us"]
|
||||
* div[data-lang='fr,\'de,us']
|
||||
*
|
||||
* Regex logic:
|
||||
* ("|')(?:\\\1|.)*?\1 => Handle the " and '
|
||||
*
|
||||
* Optimization 1:
|
||||
* No greedy capture (see docs about the difference between .* and .*?)
|
||||
*
|
||||
* Optimization 2:
|
||||
* ("|')(?:\\\1|.)*?\1 this use reference to capture group, it work faster.
|
||||
*/ .replace(/("|')(?:\\\1|.)*?\1/g, (m)=>m.replace(/,/g, "\u200C"));
|
||||
// Split all the left , and replace all the \u200C by ,
|
||||
return res// Split the selector by ','
|
||||
.split(",")// Replace back \u200C by ','
|
||||
.map((s)=>{
|
||||
return $d708735ed1303b43$var$trim(s.replace(/\u200C/g, ","));
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse declaration.
|
||||
*/ function declaration() {
|
||||
const pos = position();
|
||||
// prop
|
||||
const propMatch = match(/^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/);
|
||||
if (!propMatch) return;
|
||||
const propValue = $d708735ed1303b43$var$trim(propMatch[0]);
|
||||
// :
|
||||
if (!match(/^:\s*/)) return error("property missing ':'");
|
||||
// val
|
||||
const val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/);
|
||||
const ret = pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).declaration,
|
||||
property: propValue.replace($d708735ed1303b43$var$commentre, ""),
|
||||
value: val ? $d708735ed1303b43$var$trim(val[0]).replace($d708735ed1303b43$var$commentre, "") : ""
|
||||
});
|
||||
// ;
|
||||
match(/^[;\s]*/);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* Parse declarations.
|
||||
*/ function declarations() {
|
||||
const decls = [];
|
||||
if (!open()) return error("missing '{'");
|
||||
comments(decls);
|
||||
// declarations
|
||||
let decl;
|
||||
while(decl = declaration())if (decl) {
|
||||
decls.push(decl);
|
||||
comments(decls);
|
||||
}
|
||||
if (!close()) return error("missing '}'");
|
||||
return decls;
|
||||
}
|
||||
/**
|
||||
* Parse keyframe.
|
||||
*/ function keyframe() {
|
||||
let m;
|
||||
const vals = [];
|
||||
const pos = position();
|
||||
while(m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)){
|
||||
vals.push(m[1]);
|
||||
match(/^,\s*/);
|
||||
}
|
||||
if (!vals.length) return;
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframe,
|
||||
values: vals,
|
||||
declarations: declarations() || []
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse keyframes.
|
||||
*/ function atkeyframes() {
|
||||
const pos = position();
|
||||
const m1 = match(/^@([-\w]+)?keyframes\s*/);
|
||||
if (!m1) return;
|
||||
const vendor = m1[1];
|
||||
// identifier
|
||||
const m2 = match(/^([-\w]+)\s*/);
|
||||
if (!m2) return error("@keyframes missing name");
|
||||
const name = m2[1];
|
||||
if (!open()) return error("@keyframes missing '{'");
|
||||
let frame;
|
||||
let frames = comments();
|
||||
while(frame = keyframe()){
|
||||
frames.push(frame);
|
||||
frames = frames.concat(comments());
|
||||
}
|
||||
if (!close()) return error("@keyframes missing '}'");
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframes,
|
||||
name: name,
|
||||
vendor: vendor,
|
||||
keyframes: frames
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse supports.
|
||||
*/ function atsupports() {
|
||||
const pos = position();
|
||||
const m = match(/^@supports *([^{]+)/);
|
||||
if (!m) return;
|
||||
const supports = $d708735ed1303b43$var$trim(m[1]);
|
||||
if (!open()) return error("@supports missing '{'");
|
||||
const style = comments().concat(rules());
|
||||
if (!close()) return error("@supports missing '}'");
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).supports,
|
||||
supports: supports,
|
||||
rules: style
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse host.
|
||||
*/ function athost() {
|
||||
const pos = position();
|
||||
const m = match(/^@host\s*/);
|
||||
if (!m) return;
|
||||
if (!open()) return error("@host missing '{'");
|
||||
const style = comments().concat(rules());
|
||||
if (!close()) return error("@host missing '}'");
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).host,
|
||||
rules: style
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse container.
|
||||
*/ function atcontainer() {
|
||||
const pos = position();
|
||||
const m = match(/^@container *([^{]+)/);
|
||||
if (!m) return;
|
||||
const container = $d708735ed1303b43$var$trim(m[1]);
|
||||
if (!open()) return error("@container missing '{'");
|
||||
const style = comments().concat(rules());
|
||||
if (!close()) return error("@container missing '}'");
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).container,
|
||||
container: container,
|
||||
rules: style
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse container.
|
||||
*/ function atlayer() {
|
||||
const pos = position();
|
||||
const m = match(/^@layer *([^{;@]+)/);
|
||||
if (!m) return;
|
||||
const layer = $d708735ed1303b43$var$trim(m[1]);
|
||||
if (!open()) {
|
||||
match(/^[;\s]*/);
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).layer,
|
||||
layer: layer
|
||||
});
|
||||
}
|
||||
const style = comments().concat(rules());
|
||||
if (!close()) return error("@layer missing '}'");
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).layer,
|
||||
layer: layer,
|
||||
rules: style
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse media.
|
||||
*/ function atmedia() {
|
||||
const pos = position();
|
||||
const m = match(/^@media *([^{]+)/);
|
||||
if (!m) return;
|
||||
const media = $d708735ed1303b43$var$trim(m[1]);
|
||||
if (!open()) return error("@media missing '{'");
|
||||
const style = comments().concat(rules());
|
||||
if (!close()) return error("@media missing '}'");
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).media,
|
||||
media: media,
|
||||
rules: style
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse custom-media.
|
||||
*/ function atcustommedia() {
|
||||
const pos = position();
|
||||
const m = match(/^@custom-media\s+(--\S+)\s*([^{;\s][^{;]*);/);
|
||||
if (!m) return;
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).customMedia,
|
||||
name: $d708735ed1303b43$var$trim(m[1]),
|
||||
media: $d708735ed1303b43$var$trim(m[2])
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse paged media.
|
||||
*/ function atpage() {
|
||||
const pos = position();
|
||||
const m = match(/^@page */);
|
||||
if (!m) return;
|
||||
const sel = selector() || [];
|
||||
if (!open()) return error("@page missing '{'");
|
||||
let decls = comments();
|
||||
// declarations
|
||||
let decl;
|
||||
while(decl = declaration()){
|
||||
decls.push(decl);
|
||||
decls = decls.concat(comments());
|
||||
}
|
||||
if (!close()) return error("@page missing '}'");
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).page,
|
||||
selectors: sel,
|
||||
declarations: decls
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse document.
|
||||
*/ function atdocument() {
|
||||
const pos = position();
|
||||
const m = match(/^@([-\w]+)?document *([^{]+)/);
|
||||
if (!m) return;
|
||||
const vendor = $d708735ed1303b43$var$trim(m[1]);
|
||||
const doc = $d708735ed1303b43$var$trim(m[2]);
|
||||
if (!open()) return error("@document missing '{'");
|
||||
const style = comments().concat(rules());
|
||||
if (!close()) return error("@document missing '}'");
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).document,
|
||||
document: doc,
|
||||
vendor: vendor,
|
||||
rules: style
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse font-face.
|
||||
*/ function atfontface() {
|
||||
const pos = position();
|
||||
const m = match(/^@font-face\s*/);
|
||||
if (!m) return;
|
||||
if (!open()) return error("@font-face missing '{'");
|
||||
let decls = comments();
|
||||
// declarations
|
||||
let decl;
|
||||
while(decl = declaration()){
|
||||
decls.push(decl);
|
||||
decls = decls.concat(comments());
|
||||
}
|
||||
if (!close()) return error("@font-face missing '}'");
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).fontFace,
|
||||
declarations: decls
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Parse import
|
||||
*/ const atimport = _compileAtrule("import");
|
||||
/**
|
||||
* Parse charset
|
||||
*/ const atcharset = _compileAtrule("charset");
|
||||
/**
|
||||
* Parse namespace
|
||||
*/ const atnamespace = _compileAtrule("namespace");
|
||||
/**
|
||||
* Parse non-block at-rules
|
||||
*/ function _compileAtrule(name) {
|
||||
const re = new RegExp("^@" + name + "\\s*((?::?[^;'\"]|\"(?:\\\\\"|[^\"])*?\"|'(?:\\\\'|[^'])*?')+)(?:;|$)");
|
||||
// ^@import\s*([^;"']|("|')(?:\\\2|.)*?\2)+(;|$)
|
||||
return function() {
|
||||
const pos = position();
|
||||
const m = match(re);
|
||||
if (!m) return;
|
||||
const ret = {
|
||||
type: name
|
||||
};
|
||||
ret[name] = m[1].trim();
|
||||
return pos(ret);
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Parse at rule.
|
||||
*/ function atrule() {
|
||||
if (css[0] !== "@") return;
|
||||
return atkeyframes() || atmedia() || atcustommedia() || atsupports() || atimport() || atcharset() || atnamespace() || atdocument() || atpage() || athost() || atfontface() || atcontainer() || atlayer();
|
||||
}
|
||||
/**
|
||||
* Parse rule.
|
||||
*/ function rule() {
|
||||
const pos = position();
|
||||
const sel = selector();
|
||||
if (!sel) return error("selector missing");
|
||||
comments();
|
||||
return pos({
|
||||
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).rule,
|
||||
selectors: sel,
|
||||
declarations: declarations() || []
|
||||
});
|
||||
}
|
||||
return $d708735ed1303b43$var$addParent(stylesheet());
|
||||
};
|
||||
/**
|
||||
* Trim `str`.
|
||||
*/ function $d708735ed1303b43$var$trim(str) {
|
||||
return str ? str.trim() : "";
|
||||
}
|
||||
/**
|
||||
* Adds non-enumerable parent node reference to each node.
|
||||
*/ function $d708735ed1303b43$var$addParent(obj, parent) {
|
||||
const isNode = obj && typeof obj.type === "string";
|
||||
const childParent = isNode ? obj : parent;
|
||||
for(const k in obj){
|
||||
const value = obj[k];
|
||||
if (Array.isArray(value)) value.forEach((v)=>{
|
||||
$d708735ed1303b43$var$addParent(v, childParent);
|
||||
});
|
||||
else if (value && typeof value === "object") $d708735ed1303b43$var$addParent(value, childParent);
|
||||
}
|
||||
if (isNode) Object.defineProperty(obj, "parent", {
|
||||
configurable: true,
|
||||
writable: true,
|
||||
enumerable: false,
|
||||
value: parent || null
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
var $d708735ed1303b43$export$2e2bcd8739ae039 = $d708735ed1303b43$export$98e6a39c04603d36;
|
||||
|
||||
|
||||
|
||||
class $de9540138ed1fd01$var$Compiler {
|
||||
constructor(options){
|
||||
this.level = 0;
|
||||
this.indentation = " ";
|
||||
this.compress = false;
|
||||
if (typeof options?.indent === "string") this.indentation = options?.indent;
|
||||
if (options?.compress) this.compress = true;
|
||||
}
|
||||
// We disable no-unused-vars for _position. We keep position for potential reintroduction of source-map
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
emit(str, _position) {
|
||||
return str;
|
||||
}
|
||||
/**
|
||||
* Increase, decrease or return current indentation.
|
||||
*/ indent(level) {
|
||||
this.level = this.level || 1;
|
||||
if (level) {
|
||||
this.level += level;
|
||||
return "";
|
||||
}
|
||||
return Array(this.level).join(this.indentation);
|
||||
}
|
||||
visit(node) {
|
||||
switch(node.type){
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).stylesheet:
|
||||
return this.stylesheet(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).rule:
|
||||
return this.rule(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).declaration:
|
||||
return this.declaration(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).comment:
|
||||
return this.comment(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).container:
|
||||
return this.container(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).charset:
|
||||
return this.charset(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).document:
|
||||
return this.document(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).customMedia:
|
||||
return this.customMedia(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).fontFace:
|
||||
return this.fontFace(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).host:
|
||||
return this.host(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).import:
|
||||
return this.import(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframes:
|
||||
return this.keyframes(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframe:
|
||||
return this.keyframe(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).layer:
|
||||
return this.layer(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).media:
|
||||
return this.media(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).namespace:
|
||||
return this.namespace(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).page:
|
||||
return this.page(node);
|
||||
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).supports:
|
||||
return this.supports(node);
|
||||
}
|
||||
}
|
||||
mapVisit(nodes, delim) {
|
||||
let buf = "";
|
||||
delim = delim || "";
|
||||
for(let i = 0, length = nodes.length; i < length; i++){
|
||||
buf += this.visit(nodes[i]);
|
||||
if (delim && i < length - 1) buf += this.emit(delim);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
compile(node) {
|
||||
if (this.compress) return node.stylesheet.rules.map(this.visit, this).join("");
|
||||
return this.stylesheet(node);
|
||||
}
|
||||
/**
|
||||
* Visit stylesheet node.
|
||||
*/ stylesheet(node) {
|
||||
return this.mapVisit(node.stylesheet.rules, "\n\n");
|
||||
}
|
||||
/**
|
||||
* Visit comment node.
|
||||
*/ comment(node) {
|
||||
if (this.compress) return this.emit("", node.position);
|
||||
return this.emit(this.indent() + "/*" + node.comment + "*/", node.position);
|
||||
}
|
||||
/**
|
||||
* Visit container node.
|
||||
*/ container(node) {
|
||||
if (this.compress) return this.emit("@container " + node.container, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
||||
return this.emit(this.indent() + "@container " + node.container, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
||||
}
|
||||
/**
|
||||
* Visit container node.
|
||||
*/ layer(node) {
|
||||
if (this.compress) return this.emit("@layer " + node.layer, node.position) + (node.rules ? this.emit("{") + this.mapVisit(node.rules) + this.emit("}") : ";");
|
||||
return this.emit(this.indent() + "@layer " + node.layer, node.position) + (node.rules ? this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}") : ";");
|
||||
}
|
||||
/**
|
||||
* Visit import node.
|
||||
*/ import(node) {
|
||||
return this.emit("@import " + node.import + ";", node.position);
|
||||
}
|
||||
/**
|
||||
* Visit media node.
|
||||
*/ media(node) {
|
||||
if (this.compress) return this.emit("@media " + node.media, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
||||
return this.emit(this.indent() + "@media " + node.media, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
||||
}
|
||||
/**
|
||||
* Visit document node.
|
||||
*/ document(node) {
|
||||
const doc = "@" + (node.vendor || "") + "document " + node.document;
|
||||
if (this.compress) return this.emit(doc, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
||||
return this.emit(doc, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit(this.indent(-1) + "\n}");
|
||||
}
|
||||
/**
|
||||
* Visit charset node.
|
||||
*/ charset(node) {
|
||||
return this.emit("@charset " + node.charset + ";", node.position);
|
||||
}
|
||||
/**
|
||||
* Visit namespace node.
|
||||
*/ namespace(node) {
|
||||
return this.emit("@namespace " + node.namespace + ";", node.position);
|
||||
}
|
||||
/**
|
||||
* Visit supports node.
|
||||
*/ supports(node) {
|
||||
if (this.compress) return this.emit("@supports " + node.supports, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
||||
return this.emit(this.indent() + "@supports " + node.supports, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
||||
}
|
||||
/**
|
||||
* Visit keyframes node.
|
||||
*/ keyframes(node) {
|
||||
if (this.compress) return this.emit("@" + (node.vendor || "") + "keyframes " + node.name, node.position) + this.emit("{") + this.mapVisit(node.keyframes) + this.emit("}");
|
||||
return this.emit("@" + (node.vendor || "") + "keyframes " + node.name, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.keyframes, "\n") + this.emit(this.indent(-1) + "}");
|
||||
}
|
||||
/**
|
||||
* Visit keyframe node.
|
||||
*/ keyframe(node) {
|
||||
const decls = node.declarations;
|
||||
if (this.compress) return this.emit(node.values.join(","), node.position) + this.emit("{") + this.mapVisit(decls) + this.emit("}");
|
||||
return this.emit(this.indent()) + this.emit(node.values.join(", "), node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(decls, "\n") + this.emit(this.indent(-1) + "\n" + this.indent() + "}\n");
|
||||
}
|
||||
/**
|
||||
* Visit page node.
|
||||
*/ page(node) {
|
||||
if (this.compress) {
|
||||
const sel = node.selectors.length ? node.selectors.join(", ") : "";
|
||||
return this.emit("@page " + sel, node.position) + this.emit("{") + this.mapVisit(node.declarations) + this.emit("}");
|
||||
}
|
||||
const sel = node.selectors.length ? node.selectors.join(", ") + " " : "";
|
||||
return this.emit("@page " + sel, node.position) + this.emit("{\n") + this.emit(this.indent(1)) + this.mapVisit(node.declarations, "\n") + this.emit(this.indent(-1)) + this.emit("\n}");
|
||||
}
|
||||
/**
|
||||
* Visit font-face node.
|
||||
*/ fontFace(node) {
|
||||
if (this.compress) return this.emit("@font-face", node.position) + this.emit("{") + this.mapVisit(node.declarations) + this.emit("}");
|
||||
return this.emit("@font-face ", node.position) + this.emit("{\n") + this.emit(this.indent(1)) + this.mapVisit(node.declarations, "\n") + this.emit(this.indent(-1)) + this.emit("\n}");
|
||||
}
|
||||
/**
|
||||
* Visit host node.
|
||||
*/ host(node) {
|
||||
if (this.compress) return this.emit("@host", node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
||||
return this.emit("@host", node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit(this.indent(-1) + "\n}");
|
||||
}
|
||||
/**
|
||||
* Visit custom-media node.
|
||||
*/ customMedia(node) {
|
||||
return this.emit("@custom-media " + node.name + " " + node.media + ";", node.position);
|
||||
}
|
||||
/**
|
||||
* Visit rule node.
|
||||
*/ rule(node) {
|
||||
const decls = node.declarations;
|
||||
if (!decls.length) return "";
|
||||
if (this.compress) return this.emit(node.selectors.join(","), node.position) + this.emit("{") + this.mapVisit(decls) + this.emit("}");
|
||||
const indent = this.indent();
|
||||
return this.emit(node.selectors.map((s)=>{
|
||||
return indent + s;
|
||||
}).join(",\n"), node.position) + this.emit(" {\n") + this.emit(this.indent(1)) + this.mapVisit(decls, "\n") + this.emit(this.indent(-1)) + this.emit("\n" + this.indent() + "}");
|
||||
}
|
||||
/**
|
||||
* Visit declaration node.
|
||||
*/ declaration(node) {
|
||||
if (this.compress) return this.emit(node.property + ":" + node.value, node.position) + this.emit(";");
|
||||
return this.emit(this.indent()) + this.emit(node.property + ": " + node.value, node.position) + this.emit(";");
|
||||
}
|
||||
}
|
||||
var $de9540138ed1fd01$export$2e2bcd8739ae039 = $de9540138ed1fd01$var$Compiler;
|
||||
|
||||
|
||||
var $fdf773ab87e20450$export$2e2bcd8739ae039 = (node, options)=>{
|
||||
const compiler = new (0, $de9540138ed1fd01$export$2e2bcd8739ae039)(options || {});
|
||||
return compiler.compile(node);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const $149c1bd638913645$export$98e6a39c04603d36 = (0, $d708735ed1303b43$export$2e2bcd8739ae039);
|
||||
const $149c1bd638913645$export$fac44ee5b035f737 = (0, $fdf773ab87e20450$export$2e2bcd8739ae039);
|
||||
var $149c1bd638913645$export$2e2bcd8739ae039 = {
|
||||
parse: $149c1bd638913645$export$98e6a39c04603d36,
|
||||
stringify: $149c1bd638913645$export$fac44ee5b035f737
|
||||
};
|
||||
|
||||
|
||||
export {$149c1bd638913645$export$98e6a39c04603d36 as parse, $149c1bd638913645$export$fac44ee5b035f737 as stringify, $149c1bd638913645$export$2e2bcd8739ae039 as default, $b2e137848b48cf4f$export$9be5dd6e61d5d73a as CssTypes};
|
||||
//# sourceMappingURL=index.mjs.map
|
@ -1,55 +0,0 @@
|
||||
var diff_match_patch=function(){this.Diff_Timeout=1;this.Diff_EditCost=4;this.Match_Threshold=.5;this.Match_Distance=1E3;this.Patch_DeleteThreshold=.5;this.Patch_Margin=4;this.Match_MaxBits=32},DIFF_DELETE=-1,DIFF_INSERT=1,DIFF_EQUAL=0;diff_match_patch.Diff=function(a,b){this[0]=a;this[1]=b};diff_match_patch.Diff.prototype.length=2;diff_match_patch.Diff.prototype.toString=function(){return this[0]+","+this[1]};
|
||||
diff_match_patch.prototype.diff_main=function(a,b,c,d){"undefined"==typeof d&&(d=0>=this.Diff_Timeout?Number.MAX_VALUE:(new Date).getTime()+1E3*this.Diff_Timeout);if(null==a||null==b)throw Error("Null input. (diff_main)");if(a==b)return a?[new diff_match_patch.Diff(DIFF_EQUAL,a)]:[];"undefined"==typeof c&&(c=!0);var e=c,f=this.diff_commonPrefix(a,b);c=a.substring(0,f);a=a.substring(f);b=b.substring(f);f=this.diff_commonSuffix(a,b);var g=a.substring(a.length-f);a=a.substring(0,a.length-f);b=b.substring(0,
|
||||
b.length-f);a=this.diff_compute_(a,b,e,d);c&&a.unshift(new diff_match_patch.Diff(DIFF_EQUAL,c));g&&a.push(new diff_match_patch.Diff(DIFF_EQUAL,g));this.diff_cleanupMerge(a);return a};
|
||||
diff_match_patch.prototype.diff_compute_=function(a,b,c,d){if(!a)return[new diff_match_patch.Diff(DIFF_INSERT,b)];if(!b)return[new diff_match_patch.Diff(DIFF_DELETE,a)];var e=a.length>b.length?a:b,f=a.length>b.length?b:a,g=e.indexOf(f);return-1!=g?(c=[new diff_match_patch.Diff(DIFF_INSERT,e.substring(0,g)),new diff_match_patch.Diff(DIFF_EQUAL,f),new diff_match_patch.Diff(DIFF_INSERT,e.substring(g+f.length))],a.length>b.length&&(c[0][0]=c[2][0]=DIFF_DELETE),c):1==f.length?[new diff_match_patch.Diff(DIFF_DELETE,
|
||||
a),new diff_match_patch.Diff(DIFF_INSERT,b)]:(e=this.diff_halfMatch_(a,b))?(b=e[1],f=e[3],a=e[4],e=this.diff_main(e[0],e[2],c,d),c=this.diff_main(b,f,c,d),e.concat([new diff_match_patch.Diff(DIFF_EQUAL,a)],c)):c&&100<a.length&&100<b.length?this.diff_lineMode_(a,b,d):this.diff_bisect_(a,b,d)};
|
||||
diff_match_patch.prototype.diff_lineMode_=function(a,b,c){var d=this.diff_linesToChars_(a,b);a=d.chars1;b=d.chars2;d=d.lineArray;a=this.diff_main(a,b,!1,c);this.diff_charsToLines_(a,d);this.diff_cleanupSemantic(a);a.push(new diff_match_patch.Diff(DIFF_EQUAL,""));for(var e=d=b=0,f="",g="";b<a.length;){switch(a[b][0]){case DIFF_INSERT:e++;g+=a[b][1];break;case DIFF_DELETE:d++;f+=a[b][1];break;case DIFF_EQUAL:if(1<=d&&1<=e){a.splice(b-d-e,d+e);b=b-d-e;d=this.diff_main(f,g,!1,c);for(e=d.length-1;0<=e;e--)a.splice(b,
|
||||
0,d[e]);b+=d.length}d=e=0;g=f=""}b++}a.pop();return a};
|
||||
diff_match_patch.prototype.diff_bisect_=function(a,b,c){for(var d=a.length,e=b.length,f=Math.ceil((d+e)/2),g=2*f,h=Array(g),l=Array(g),k=0;k<g;k++)h[k]=-1,l[k]=-1;h[f+1]=0;l[f+1]=0;k=d-e;for(var m=0!=k%2,p=0,x=0,w=0,q=0,t=0;t<f&&!((new Date).getTime()>c);t++){for(var v=-t+p;v<=t-x;v+=2){var n=f+v;var r=v==-t||v!=t&&h[n-1]<h[n+1]?h[n+1]:h[n-1]+1;for(var y=r-v;r<d&&y<e&&a.charAt(r)==b.charAt(y);)r++,y++;h[n]=r;if(r>d)x+=2;else if(y>e)p+=2;else if(m&&(n=f+k-v,0<=n&&n<g&&-1!=l[n])){var u=d-l[n];if(r>=
|
||||
u)return this.diff_bisectSplit_(a,b,r,y,c)}}for(v=-t+w;v<=t-q;v+=2){n=f+v;u=v==-t||v!=t&&l[n-1]<l[n+1]?l[n+1]:l[n-1]+1;for(r=u-v;u<d&&r<e&&a.charAt(d-u-1)==b.charAt(e-r-1);)u++,r++;l[n]=u;if(u>d)q+=2;else if(r>e)w+=2;else if(!m&&(n=f+k-v,0<=n&&n<g&&-1!=h[n]&&(r=h[n],y=f+r-n,u=d-u,r>=u)))return this.diff_bisectSplit_(a,b,r,y,c)}}return[new diff_match_patch.Diff(DIFF_DELETE,a),new diff_match_patch.Diff(DIFF_INSERT,b)]};
|
||||
diff_match_patch.prototype.diff_bisectSplit_=function(a,b,c,d,e){var f=a.substring(0,c),g=b.substring(0,d);a=a.substring(c);b=b.substring(d);f=this.diff_main(f,g,!1,e);e=this.diff_main(a,b,!1,e);return f.concat(e)};
|
||||
diff_match_patch.prototype.diff_linesToChars_=function(a,b){function c(a){for(var b="",c=0,g=-1,h=d.length;g<a.length-1;){g=a.indexOf("\n",c);-1==g&&(g=a.length-1);var l=a.substring(c,g+1);(e.hasOwnProperty?e.hasOwnProperty(l):void 0!==e[l])?b+=String.fromCharCode(e[l]):(h==f&&(l=a.substring(c),g=a.length),b+=String.fromCharCode(h),e[l]=h,d[h++]=l);c=g+1}return b}var d=[],e={};d[0]="";var f=4E4,g=c(a);f=65535;var h=c(b);return{chars1:g,chars2:h,lineArray:d}};
|
||||
diff_match_patch.prototype.diff_charsToLines_=function(a,b){for(var c=0;c<a.length;c++){for(var d=a[c][1],e=[],f=0;f<d.length;f++)e[f]=b[d.charCodeAt(f)];a[c][1]=e.join("")}};diff_match_patch.prototype.diff_commonPrefix=function(a,b){if(!a||!b||a.charAt(0)!=b.charAt(0))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(f,e)==b.substring(f,e)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
|
||||
diff_match_patch.prototype.diff_commonSuffix=function(a,b){if(!a||!b||a.charAt(a.length-1)!=b.charAt(b.length-1))return 0;for(var c=0,d=Math.min(a.length,b.length),e=d,f=0;c<e;)a.substring(a.length-e,a.length-f)==b.substring(b.length-e,b.length-f)?f=c=e:d=e,e=Math.floor((d-c)/2+c);return e};
|
||||
diff_match_patch.prototype.diff_commonOverlap_=function(a,b){var c=a.length,d=b.length;if(0==c||0==d)return 0;c>d?a=a.substring(c-d):c<d&&(b=b.substring(0,c));c=Math.min(c,d);if(a==b)return c;d=0;for(var e=1;;){var f=a.substring(c-e);f=b.indexOf(f);if(-1==f)return d;e+=f;if(0==f||a.substring(c-e)==b.substring(0,e))d=e,e++}};
|
||||
diff_match_patch.prototype.diff_halfMatch_=function(a,b){function c(a,b,c){for(var d=a.substring(c,c+Math.floor(a.length/4)),e=-1,g="",h,k,l,m;-1!=(e=b.indexOf(d,e+1));){var p=f.diff_commonPrefix(a.substring(c),b.substring(e)),u=f.diff_commonSuffix(a.substring(0,c),b.substring(0,e));g.length<u+p&&(g=b.substring(e-u,e)+b.substring(e,e+p),h=a.substring(0,c-u),k=a.substring(c+p),l=b.substring(0,e-u),m=b.substring(e+p))}return 2*g.length>=a.length?[h,k,l,m,g]:null}if(0>=this.Diff_Timeout)return null;
|
||||
var d=a.length>b.length?a:b,e=a.length>b.length?b:a;if(4>d.length||2*e.length<d.length)return null;var f=this,g=c(d,e,Math.ceil(d.length/4));d=c(d,e,Math.ceil(d.length/2));if(g||d)g=d?g?g[4].length>d[4].length?g:d:d:g;else return null;if(a.length>b.length){d=g[0];e=g[1];var h=g[2];var l=g[3]}else h=g[0],l=g[1],d=g[2],e=g[3];return[d,e,h,l,g[4]]};
|
||||
diff_match_patch.prototype.diff_cleanupSemantic=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=0,h=0,l=0,k=0;f<a.length;)a[f][0]==DIFF_EQUAL?(c[d++]=f,g=l,h=k,k=l=0,e=a[f][1]):(a[f][0]==DIFF_INSERT?l+=a[f][1].length:k+=a[f][1].length,e&&e.length<=Math.max(g,h)&&e.length<=Math.max(l,k)&&(a.splice(c[d-1],0,new diff_match_patch.Diff(DIFF_DELETE,e)),a[c[d-1]+1][0]=DIFF_INSERT,d--,d--,f=0<d?c[d-1]:-1,k=l=h=g=0,e=null,b=!0)),f++;b&&this.diff_cleanupMerge(a);this.diff_cleanupSemanticLossless(a);for(f=1;f<
|
||||
a.length;){if(a[f-1][0]==DIFF_DELETE&&a[f][0]==DIFF_INSERT){b=a[f-1][1];c=a[f][1];d=this.diff_commonOverlap_(b,c);e=this.diff_commonOverlap_(c,b);if(d>=e){if(d>=b.length/2||d>=c.length/2)a.splice(f,0,new diff_match_patch.Diff(DIFF_EQUAL,c.substring(0,d))),a[f-1][1]=b.substring(0,b.length-d),a[f+1][1]=c.substring(d),f++}else if(e>=b.length/2||e>=c.length/2)a.splice(f,0,new diff_match_patch.Diff(DIFF_EQUAL,b.substring(0,e))),a[f-1][0]=DIFF_INSERT,a[f-1][1]=c.substring(0,c.length-e),a[f+1][0]=DIFF_DELETE,
|
||||
a[f+1][1]=b.substring(e),f++;f++}f++}};
|
||||
diff_match_patch.prototype.diff_cleanupSemanticLossless=function(a){function b(a,b){if(!a||!b)return 6;var c=a.charAt(a.length-1),d=b.charAt(0),e=c.match(diff_match_patch.nonAlphaNumericRegex_),f=d.match(diff_match_patch.nonAlphaNumericRegex_),g=e&&c.match(diff_match_patch.whitespaceRegex_),h=f&&d.match(diff_match_patch.whitespaceRegex_);c=g&&c.match(diff_match_patch.linebreakRegex_);d=h&&d.match(diff_match_patch.linebreakRegex_);var k=c&&a.match(diff_match_patch.blanklineEndRegex_),l=d&&b.match(diff_match_patch.blanklineStartRegex_);
|
||||
return k||l?5:c||d?4:e&&!g&&h?3:g||h?2:e||f?1:0}for(var c=1;c<a.length-1;){if(a[c-1][0]==DIFF_EQUAL&&a[c+1][0]==DIFF_EQUAL){var d=a[c-1][1],e=a[c][1],f=a[c+1][1],g=this.diff_commonSuffix(d,e);if(g){var h=e.substring(e.length-g);d=d.substring(0,d.length-g);e=h+e.substring(0,e.length-g);f=h+f}g=d;h=e;for(var l=f,k=b(d,e)+b(e,f);e.charAt(0)===f.charAt(0);){d+=e.charAt(0);e=e.substring(1)+f.charAt(0);f=f.substring(1);var m=b(d,e)+b(e,f);m>=k&&(k=m,g=d,h=e,l=f)}a[c-1][1]!=g&&(g?a[c-1][1]=g:(a.splice(c-
|
||||
1,1),c--),a[c][1]=h,l?a[c+1][1]=l:(a.splice(c+1,1),c--))}c++}};diff_match_patch.nonAlphaNumericRegex_=/[^a-zA-Z0-9]/;diff_match_patch.whitespaceRegex_=/\s/;diff_match_patch.linebreakRegex_=/[\r\n]/;diff_match_patch.blanklineEndRegex_=/\n\r?\n$/;diff_match_patch.blanklineStartRegex_=/^\r?\n\r?\n/;
|
||||
diff_match_patch.prototype.diff_cleanupEfficiency=function(a){for(var b=!1,c=[],d=0,e=null,f=0,g=!1,h=!1,l=!1,k=!1;f<a.length;)a[f][0]==DIFF_EQUAL?(a[f][1].length<this.Diff_EditCost&&(l||k)?(c[d++]=f,g=l,h=k,e=a[f][1]):(d=0,e=null),l=k=!1):(a[f][0]==DIFF_DELETE?k=!0:l=!0,e&&(g&&h&&l&&k||e.length<this.Diff_EditCost/2&&3==g+h+l+k)&&(a.splice(c[d-1],0,new diff_match_patch.Diff(DIFF_DELETE,e)),a[c[d-1]+1][0]=DIFF_INSERT,d--,e=null,g&&h?(l=k=!0,d=0):(d--,f=0<d?c[d-1]:-1,l=k=!1),b=!0)),f++;b&&this.diff_cleanupMerge(a)};
|
||||
diff_match_patch.prototype.diff_cleanupMerge=function(a){a.push(new diff_match_patch.Diff(DIFF_EQUAL,""));for(var b=0,c=0,d=0,e="",f="",g;b<a.length;)switch(a[b][0]){case DIFF_INSERT:d++;f+=a[b][1];b++;break;case DIFF_DELETE:c++;e+=a[b][1];b++;break;case DIFF_EQUAL:1<c+d?(0!==c&&0!==d&&(g=this.diff_commonPrefix(f,e),0!==g&&(0<b-c-d&&a[b-c-d-1][0]==DIFF_EQUAL?a[b-c-d-1][1]+=f.substring(0,g):(a.splice(0,0,new diff_match_patch.Diff(DIFF_EQUAL,f.substring(0,g))),b++),f=f.substring(g),e=e.substring(g)),
|
||||
g=this.diff_commonSuffix(f,e),0!==g&&(a[b][1]=f.substring(f.length-g)+a[b][1],f=f.substring(0,f.length-g),e=e.substring(0,e.length-g))),b-=c+d,a.splice(b,c+d),e.length&&(a.splice(b,0,new diff_match_patch.Diff(DIFF_DELETE,e)),b++),f.length&&(a.splice(b,0,new diff_match_patch.Diff(DIFF_INSERT,f)),b++),b++):0!==b&&a[b-1][0]==DIFF_EQUAL?(a[b-1][1]+=a[b][1],a.splice(b,1)):b++,c=d=0,f=e=""}""===a[a.length-1][1]&&a.pop();c=!1;for(b=1;b<a.length-1;)a[b-1][0]==DIFF_EQUAL&&a[b+1][0]==DIFF_EQUAL&&(a[b][1].substring(a[b][1].length-
|
||||
a[b-1][1].length)==a[b-1][1]?(a[b][1]=a[b-1][1]+a[b][1].substring(0,a[b][1].length-a[b-1][1].length),a[b+1][1]=a[b-1][1]+a[b+1][1],a.splice(b-1,1),c=!0):a[b][1].substring(0,a[b+1][1].length)==a[b+1][1]&&(a[b-1][1]+=a[b+1][1],a[b][1]=a[b][1].substring(a[b+1][1].length)+a[b+1][1],a.splice(b+1,1),c=!0)),b++;c&&this.diff_cleanupMerge(a)};
|
||||
diff_match_patch.prototype.diff_xIndex=function(a,b){var c=0,d=0,e=0,f=0,g;for(g=0;g<a.length;g++){a[g][0]!==DIFF_INSERT&&(c+=a[g][1].length);a[g][0]!==DIFF_DELETE&&(d+=a[g][1].length);if(c>b)break;e=c;f=d}return a.length!=g&&a[g][0]===DIFF_DELETE?f:f+(b-e)};
|
||||
diff_match_patch.prototype.diff_prettyHtml=function(a){for(var b=[],c=/&/g,d=/</g,e=/>/g,f=/\n/g,g=0;g<a.length;g++){var h=a[g][0],l=a[g][1].replace(c,"&").replace(d,"<").replace(e,">").replace(f,"¶<br>");switch(h){case DIFF_INSERT:b[g]='<ins style="background:#e6ffe6;">'+l+"</ins>";break;case DIFF_DELETE:b[g]='<del style="background:#ffe6e6;">'+l+"</del>";break;case DIFF_EQUAL:b[g]="<span>"+l+"</span>"}}return b.join("")};
|
||||
diff_match_patch.prototype.diff_text1=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==DIFF_INSERT&&(b[c]=a[c][1]);return b.join("")};diff_match_patch.prototype.diff_text2=function(a){for(var b=[],c=0;c<a.length;c++)a[c][0]!==DIFF_DELETE&&(b[c]=a[c][1]);return b.join("")};
|
||||
diff_match_patch.prototype.diff_levenshtein=function(a){for(var b=0,c=0,d=0,e=0;e<a.length;e++){var f=a[e][1];switch(a[e][0]){case DIFF_INSERT:c+=f.length;break;case DIFF_DELETE:d+=f.length;break;case DIFF_EQUAL:b+=Math.max(c,d),d=c=0}}return b+=Math.max(c,d)};
|
||||
diff_match_patch.prototype.diff_toDelta=function(a){for(var b=[],c=0;c<a.length;c++)switch(a[c][0]){case DIFF_INSERT:b[c]="+"+encodeURI(a[c][1]);break;case DIFF_DELETE:b[c]="-"+a[c][1].length;break;case DIFF_EQUAL:b[c]="="+a[c][1].length}return b.join("\t").replace(/%20/g," ")};
|
||||
diff_match_patch.prototype.diff_fromDelta=function(a,b){for(var c=[],d=0,e=0,f=b.split(/\t/g),g=0;g<f.length;g++){var h=f[g].substring(1);switch(f[g].charAt(0)){case "+":try{c[d++]=new diff_match_patch.Diff(DIFF_INSERT,decodeURI(h))}catch(k){throw Error("Illegal escape in diff_fromDelta: "+h);}break;case "-":case "=":var l=parseInt(h,10);if(isNaN(l)||0>l)throw Error("Invalid number in diff_fromDelta: "+h);h=a.substring(e,e+=l);"="==f[g].charAt(0)?c[d++]=new diff_match_patch.Diff(DIFF_EQUAL,h):c[d++]=
|
||||
new diff_match_patch.Diff(DIFF_DELETE,h);break;default:if(f[g])throw Error("Invalid diff operation in diff_fromDelta: "+f[g]);}}if(e!=a.length)throw Error("Delta length ("+e+") does not equal source text length ("+a.length+").");return c};diff_match_patch.prototype.match_main=function(a,b,c){if(null==a||null==b||null==c)throw Error("Null input. (match_main)");c=Math.max(0,Math.min(c,a.length));return a==b?0:a.length?a.substring(c,c+b.length)==b?c:this.match_bitap_(a,b,c):-1};
|
||||
diff_match_patch.prototype.match_bitap_=function(a,b,c){function d(a,d){var e=a/b.length,g=Math.abs(c-d);return f.Match_Distance?e+g/f.Match_Distance:g?1:e}if(b.length>this.Match_MaxBits)throw Error("Pattern too long for this browser.");var e=this.match_alphabet_(b),f=this,g=this.Match_Threshold,h=a.indexOf(b,c);-1!=h&&(g=Math.min(d(0,h),g),h=a.lastIndexOf(b,c+b.length),-1!=h&&(g=Math.min(d(0,h),g)));var l=1<<b.length-1;h=-1;for(var k,m,p=b.length+a.length,x,w=0;w<b.length;w++){k=0;for(m=p;k<m;)d(w,
|
||||
c+m)<=g?k=m:p=m,m=Math.floor((p-k)/2+k);p=m;k=Math.max(1,c-m+1);var q=Math.min(c+m,a.length)+b.length;m=Array(q+2);for(m[q+1]=(1<<w)-1;q>=k;q--){var t=e[a.charAt(q-1)];m[q]=0===w?(m[q+1]<<1|1)&t:(m[q+1]<<1|1)&t|(x[q+1]|x[q])<<1|1|x[q+1];if(m[q]&l&&(t=d(w,q-1),t<=g))if(g=t,h=q-1,h>c)k=Math.max(1,2*c-h);else break}if(d(w+1,c)>g)break;x=m}return h};
|
||||
diff_match_patch.prototype.match_alphabet_=function(a){for(var b={},c=0;c<a.length;c++)b[a.charAt(c)]=0;for(c=0;c<a.length;c++)b[a.charAt(c)]|=1<<a.length-c-1;return b};
|
||||
diff_match_patch.prototype.patch_addContext_=function(a,b){if(0!=b.length){if(null===a.start2)throw Error("patch not initialized");for(var c=b.substring(a.start2,a.start2+a.length1),d=0;b.indexOf(c)!=b.lastIndexOf(c)&&c.length<this.Match_MaxBits-this.Patch_Margin-this.Patch_Margin;)d+=this.Patch_Margin,c=b.substring(a.start2-d,a.start2+a.length1+d);d+=this.Patch_Margin;(c=b.substring(a.start2-d,a.start2))&&a.diffs.unshift(new diff_match_patch.Diff(DIFF_EQUAL,c));(d=b.substring(a.start2+a.length1,
|
||||
a.start2+a.length1+d))&&a.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,d));a.start1-=c.length;a.start2-=c.length;a.length1+=c.length+d.length;a.length2+=c.length+d.length}};
|
||||
diff_match_patch.prototype.patch_make=function(a,b,c){if("string"==typeof a&&"string"==typeof b&&"undefined"==typeof c){var d=a;b=this.diff_main(d,b,!0);2<b.length&&(this.diff_cleanupSemantic(b),this.diff_cleanupEfficiency(b))}else if(a&&"object"==typeof a&&"undefined"==typeof b&&"undefined"==typeof c)b=a,d=this.diff_text1(b);else if("string"==typeof a&&b&&"object"==typeof b&&"undefined"==typeof c)d=a;else if("string"==typeof a&&"string"==typeof b&&c&&"object"==typeof c)d=a,b=c;else throw Error("Unknown call format to patch_make.");
|
||||
if(0===b.length)return[];c=[];a=new diff_match_patch.patch_obj;for(var e=0,f=0,g=0,h=d,l=0;l<b.length;l++){var k=b[l][0],m=b[l][1];e||k===DIFF_EQUAL||(a.start1=f,a.start2=g);switch(k){case DIFF_INSERT:a.diffs[e++]=b[l];a.length2+=m.length;d=d.substring(0,g)+m+d.substring(g);break;case DIFF_DELETE:a.length1+=m.length;a.diffs[e++]=b[l];d=d.substring(0,g)+d.substring(g+m.length);break;case DIFF_EQUAL:m.length<=2*this.Patch_Margin&&e&&b.length!=l+1?(a.diffs[e++]=b[l],a.length1+=m.length,a.length2+=m.length):
|
||||
m.length>=2*this.Patch_Margin&&e&&(this.patch_addContext_(a,h),c.push(a),a=new diff_match_patch.patch_obj,e=0,h=d,f=g)}k!==DIFF_INSERT&&(f+=m.length);k!==DIFF_DELETE&&(g+=m.length)}e&&(this.patch_addContext_(a,h),c.push(a));return c};
|
||||
diff_match_patch.prototype.patch_deepCopy=function(a){for(var b=[],c=0;c<a.length;c++){var d=a[c],e=new diff_match_patch.patch_obj;e.diffs=[];for(var f=0;f<d.diffs.length;f++)e.diffs[f]=new diff_match_patch.Diff(d.diffs[f][0],d.diffs[f][1]);e.start1=d.start1;e.start2=d.start2;e.length1=d.length1;e.length2=d.length2;b[c]=e}return b};
|
||||
diff_match_patch.prototype.patch_apply=function(a,b){if(0==a.length)return[b,[]];a=this.patch_deepCopy(a);var c=this.patch_addPadding(a);b=c+b+c;this.patch_splitMax(a);for(var d=0,e=[],f=0;f<a.length;f++){var g=a[f].start2+d,h=this.diff_text1(a[f].diffs),l=-1;if(h.length>this.Match_MaxBits){var k=this.match_main(b,h.substring(0,this.Match_MaxBits),g);-1!=k&&(l=this.match_main(b,h.substring(h.length-this.Match_MaxBits),g+h.length-this.Match_MaxBits),-1==l||k>=l)&&(k=-1)}else k=this.match_main(b,h,
|
||||
g);if(-1==k)e[f]=!1,d-=a[f].length2-a[f].length1;else if(e[f]=!0,d=k-g,g=-1==l?b.substring(k,k+h.length):b.substring(k,l+this.Match_MaxBits),h==g)b=b.substring(0,k)+this.diff_text2(a[f].diffs)+b.substring(k+h.length);else if(g=this.diff_main(h,g,!1),h.length>this.Match_MaxBits&&this.diff_levenshtein(g)/h.length>this.Patch_DeleteThreshold)e[f]=!1;else{this.diff_cleanupSemanticLossless(g);h=0;var m;for(l=0;l<a[f].diffs.length;l++){var p=a[f].diffs[l];p[0]!==DIFF_EQUAL&&(m=this.diff_xIndex(g,h));p[0]===
|
||||
DIFF_INSERT?b=b.substring(0,k+m)+p[1]+b.substring(k+m):p[0]===DIFF_DELETE&&(b=b.substring(0,k+m)+b.substring(k+this.diff_xIndex(g,h+p[1].length)));p[0]!==DIFF_DELETE&&(h+=p[1].length)}}}b=b.substring(c.length,b.length-c.length);return[b,e]};
|
||||
diff_match_patch.prototype.patch_addPadding=function(a){for(var b=this.Patch_Margin,c="",d=1;d<=b;d++)c+=String.fromCharCode(d);for(d=0;d<a.length;d++)a[d].start1+=b,a[d].start2+=b;d=a[0];var e=d.diffs;if(0==e.length||e[0][0]!=DIFF_EQUAL)e.unshift(new diff_match_patch.Diff(DIFF_EQUAL,c)),d.start1-=b,d.start2-=b,d.length1+=b,d.length2+=b;else if(b>e[0][1].length){var f=b-e[0][1].length;e[0][1]=c.substring(e[0][1].length)+e[0][1];d.start1-=f;d.start2-=f;d.length1+=f;d.length2+=f}d=a[a.length-1];e=d.diffs;
|
||||
0==e.length||e[e.length-1][0]!=DIFF_EQUAL?(e.push(new diff_match_patch.Diff(DIFF_EQUAL,c)),d.length1+=b,d.length2+=b):b>e[e.length-1][1].length&&(f=b-e[e.length-1][1].length,e[e.length-1][1]+=c.substring(0,f),d.length1+=f,d.length2+=f);return c};
|
||||
diff_match_patch.prototype.patch_splitMax=function(a){for(var b=this.Match_MaxBits,c=0;c<a.length;c++)if(!(a[c].length1<=b)){var d=a[c];a.splice(c--,1);for(var e=d.start1,f=d.start2,g="";0!==d.diffs.length;){var h=new diff_match_patch.patch_obj,l=!0;h.start1=e-g.length;h.start2=f-g.length;""!==g&&(h.length1=h.length2=g.length,h.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,g)));for(;0!==d.diffs.length&&h.length1<b-this.Patch_Margin;){g=d.diffs[0][0];var k=d.diffs[0][1];g===DIFF_INSERT?(h.length2+=
|
||||
k.length,f+=k.length,h.diffs.push(d.diffs.shift()),l=!1):g===DIFF_DELETE&&1==h.diffs.length&&h.diffs[0][0]==DIFF_EQUAL&&k.length>2*b?(h.length1+=k.length,e+=k.length,l=!1,h.diffs.push(new diff_match_patch.Diff(g,k)),d.diffs.shift()):(k=k.substring(0,b-h.length1-this.Patch_Margin),h.length1+=k.length,e+=k.length,g===DIFF_EQUAL?(h.length2+=k.length,f+=k.length):l=!1,h.diffs.push(new diff_match_patch.Diff(g,k)),k==d.diffs[0][1]?d.diffs.shift():d.diffs[0][1]=d.diffs[0][1].substring(k.length))}g=this.diff_text2(h.diffs);
|
||||
g=g.substring(g.length-this.Patch_Margin);k=this.diff_text1(d.diffs).substring(0,this.Patch_Margin);""!==k&&(h.length1+=k.length,h.length2+=k.length,0!==h.diffs.length&&h.diffs[h.diffs.length-1][0]===DIFF_EQUAL?h.diffs[h.diffs.length-1][1]+=k:h.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,k)));l||a.splice(++c,0,h)}}};diff_match_patch.prototype.patch_toText=function(a){for(var b=[],c=0;c<a.length;c++)b[c]=a[c];return b.join("")};
|
||||
diff_match_patch.prototype.patch_fromText=function(a){var b=[];if(!a)return b;a=a.split("\n");for(var c=0,d=/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;c<a.length;){var e=a[c].match(d);if(!e)throw Error("Invalid patch string: "+a[c]);var f=new diff_match_patch.patch_obj;b.push(f);f.start1=parseInt(e[1],10);""===e[2]?(f.start1--,f.length1=1):"0"==e[2]?f.length1=0:(f.start1--,f.length1=parseInt(e[2],10));f.start2=parseInt(e[3],10);""===e[4]?(f.start2--,f.length2=1):"0"==e[4]?f.length2=0:(f.start2--,f.length2=
|
||||
parseInt(e[4],10));for(c++;c<a.length;){e=a[c].charAt(0);try{var g=decodeURI(a[c].substring(1))}catch(h){throw Error("Illegal escape in patch_fromText: "+g);}if("-"==e)f.diffs.push(new diff_match_patch.Diff(DIFF_DELETE,g));else if("+"==e)f.diffs.push(new diff_match_patch.Diff(DIFF_INSERT,g));else if(" "==e)f.diffs.push(new diff_match_patch.Diff(DIFF_EQUAL,g));else if("@"==e)break;else if(""!==e)throw Error('Invalid patch mode "'+e+'" in: '+g);c++}}return b};
|
||||
diff_match_patch.patch_obj=function(){this.diffs=[];this.start2=this.start1=null;this.length2=this.length1=0};
|
||||
diff_match_patch.patch_obj.prototype.toString=function(){for(var a=["@@ -"+(0===this.length1?this.start1+",0":1==this.length1?this.start1+1:this.start1+1+","+this.length1)+" +"+(0===this.length2?this.start2+",0":1==this.length2?this.start2+1:this.start2+1+","+this.length2)+" @@\n"],b,c=0;c<this.diffs.length;c++){switch(this.diffs[c][0]){case DIFF_INSERT:b="+";break;case DIFF_DELETE:b="-";break;case DIFF_EQUAL:b=" "}a[c+1]=b+encodeURI(this.diffs[c][1])+"\n"}return a.join("").replace(/%20/g," ")};
|
||||
this.diff_match_patch=diff_match_patch;this.DIFF_DELETE=DIFF_DELETE;this.DIFF_INSERT=DIFF_INSERT;this.DIFF_EQUAL=DIFF_EQUAL;
|
@ -1,108 +0,0 @@
|
||||
// Borrowed from the Droll library by thebinarypenguin
|
||||
// https://github.com/thebinarypenguin/droll
|
||||
// Licensed under MIT license
|
||||
var droll = {};
|
||||
|
||||
// Define a "class" to represent a formula
|
||||
function DrollFormula() {
|
||||
this.numDice = 0;
|
||||
this.numSides = 0;
|
||||
this.modifier = 0;
|
||||
|
||||
this.minResult = 0;
|
||||
this.maxResult = 0;
|
||||
this.avgResult = 0;
|
||||
}
|
||||
|
||||
// Define a "class" to represent the results of the roll
|
||||
function DrollResult() {
|
||||
this.rolls = [];
|
||||
this.modifier = 0;
|
||||
this.total = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the roll result
|
||||
*/
|
||||
DrollResult.prototype.toString = function () {
|
||||
if (this.rolls.length === 1 && this.modifier === 0) {
|
||||
return this.rolls[0] + '';
|
||||
}
|
||||
|
||||
if (this.rolls.length > 1 && this.modifier === 0) {
|
||||
return this.rolls.join(' + ') + ' = ' + this.total;
|
||||
}
|
||||
|
||||
if (this.rolls.length === 1 && this.modifier > 0) {
|
||||
return this.rolls[0] + ' + ' + this.modifier + ' = ' + this.total;
|
||||
}
|
||||
|
||||
if (this.rolls.length > 1 && this.modifier > 0) {
|
||||
return this.rolls.join(' + ') + ' + ' + this.modifier + ' = ' + this.total;
|
||||
}
|
||||
|
||||
if (this.rolls.length === 1 && this.modifier < 0) {
|
||||
return this.rolls[0] + ' - ' + Math.abs(this.modifier) + ' = ' + this.total;
|
||||
}
|
||||
|
||||
if (this.rolls.length > 1 && this.modifier < 0) {
|
||||
return this.rolls.join(' + ') + ' - ' + Math.abs(this.modifier) + ' = ' + this.total;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the formula into its component pieces.
|
||||
* Returns a DrollFormula object on success or false on failure.
|
||||
*/
|
||||
droll.parse = function (formula) {
|
||||
var pieces = null;
|
||||
var result = new DrollFormula();
|
||||
|
||||
pieces = formula.match(/^([1-9]\d*)?d([1-9]\d*)([+-]\d+)?$/i);
|
||||
if (!pieces) { return false; }
|
||||
|
||||
result.numDice = (pieces[1] - 0) || 1;
|
||||
result.numSides = (pieces[2] - 0);
|
||||
result.modifier = (pieces[3] - 0) || 0;
|
||||
|
||||
result.minResult = (result.numDice * 1) + result.modifier;
|
||||
result.maxResult = (result.numDice * result.numSides) + result.modifier;
|
||||
result.avgResult = (result.maxResult + result.minResult) / 2;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test the validity of the formula.
|
||||
* Returns true on success or false on failure.
|
||||
*/
|
||||
droll.validate = function (formula) {
|
||||
return (droll.parse(formula)) ? true : false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Roll the dice defined by the formula.
|
||||
* Returns a DrollResult object on success or false on failure.
|
||||
*/
|
||||
droll.roll = function (formula) {
|
||||
var pieces = null;
|
||||
var result = new DrollResult();
|
||||
|
||||
pieces = droll.parse(formula);
|
||||
if (!pieces) { return false; }
|
||||
|
||||
for (var a = 0; a < pieces.numDice; a++) {
|
||||
result.rolls[a] = (1 + Math.floor(Math.random() * pieces.numSides));
|
||||
}
|
||||
|
||||
result.modifier = pieces.modifier;
|
||||
|
||||
for (var b = 0; b < result.rolls.length; b++) {
|
||||
result.total += result.rolls[b];
|
||||
}
|
||||
result.total += result.modifier;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// END OF DROLL CODE
|
2
public/lib/epub.min.js
vendored
2
public/lib/epub.min.js
vendored
File diff suppressed because one or more lines are too long
2240
public/lib/fuse.js
2240
public/lib/fuse.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
1361
public/lib/highlight.min.js
vendored
1361
public/lib/highlight.min.js
vendored
File diff suppressed because one or more lines are too long
7
public/lib/localforage.min.js
vendored
7
public/lib/localforage.min.js
vendored
File diff suppressed because one or more lines are too long
2
public/lib/moment-with-locales.min.js
vendored
2
public/lib/moment-with-locales.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
21
public/lib/pdf.min.mjs
Normal file
21
public/lib/pdf.min.mjs
Normal file
File diff suppressed because one or more lines are too long
17398
public/lib/pdf.mjs
17398
public/lib/pdf.mjs
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
21
public/lib/pdf.worker.min.mjs
Normal file
21
public/lib/pdf.worker.min.mjs
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2008
public/lib/popper.js
2008
public/lib/popper.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
3
public/lib/purify.min.js
vendored
3
public/lib/purify.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
public/lib/seedrandom.min.js
vendored
1
public/lib/seedrandom.min.js
vendored
@ -1 +0,0 @@
|
||||
!function(f,a,c){var s,l=256,p="random",d=c.pow(l,6),g=c.pow(2,52),y=2*g,h=l-1;function n(n,t,r){function e(){for(var n=u.g(6),t=d,r=0;n<g;)n=(n+r)*l,t*=l,r=u.g(1);for(;y<=n;)n/=2,t/=2,r>>>=1;return(n+r)/t}var o=[],i=j(function n(t,r){var e,o=[],i=typeof t;if(r&&"object"==i)for(e in t)try{o.push(n(t[e],r-1))}catch(n){}return o.length?o:"string"==i?t:t+"\0"}((t=1==t?{entropy:!0}:t||{}).entropy?[n,S(a)]:null==n?function(){try{var n;return s&&(n=s.randomBytes)?n=n(l):(n=new Uint8Array(l),(f.crypto||f.msCrypto).getRandomValues(n)),S(n)}catch(n){var t=f.navigator,r=t&&t.plugins;return[+new Date,f,r,f.screen,S(a)]}}():n,3),o),u=new m(o);return e.int32=function(){return 0|u.g(4)},e.quick=function(){return u.g(4)/4294967296},e.double=e,j(S(u.S),a),(t.pass||r||function(n,t,r,e){return e&&(e.S&&v(e,u),n.state=function(){return v(u,{})}),r?(c[p]=n,t):n})(e,i,"global"in t?t.global:this==c,t.state)}function m(n){var t,r=n.length,u=this,e=0,o=u.i=u.j=0,i=u.S=[];for(r||(n=[r++]);e<l;)i[e]=e++;for(e=0;e<l;e++)i[e]=i[o=h&o+n[e%r]+(t=i[e])],i[o]=t;(u.g=function(n){for(var t,r=0,e=u.i,o=u.j,i=u.S;n--;)t=i[e=h&e+1],r=r*l+i[h&(i[e]=i[o=h&o+t])+(i[o]=t)];return u.i=e,u.j=o,r})(l)}function v(n,t){return t.i=n.i,t.j=n.j,t.S=n.S.slice(),t}function j(n,t){for(var r,e=n+"",o=0;o<e.length;)t[h&o]=h&(r^=19*t[h&o])+e.charCodeAt(o++);return S(t)}function S(n){return String.fromCharCode.apply(0,n)}if(j(c.random(),a),"object"==typeof module&&module.exports){module.exports=n;try{s=require("crypto")}catch(n){}}else"function"==typeof define&&define.amd?define(function(){return n}):c["seed"+p]=n}("undefined"!=typeof self?self:this,[],Math);
|
36
public/lib/showdown-katex.min.js
vendored
36
public/lib/showdown-katex.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,24 +0,0 @@
|
||||
showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
|
||||
'use strict';
|
||||
text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);
|
||||
|
||||
for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
|
||||
var repText = globals.gHtmlSpans[i],
|
||||
// limiter to prevent infinite loop (assume 10 as limit for recurse)
|
||||
limit = 0;
|
||||
|
||||
while (/¨C(\d+)C/.test(repText)) {
|
||||
var num = RegExp.$1;
|
||||
repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
|
||||
if (limit === 10000) {
|
||||
console.error('maximum nesting of 10000 spans reached!!!');
|
||||
break;
|
||||
}
|
||||
++limit;
|
||||
}
|
||||
text = text.replace('¨C' + i + 'C', repText);
|
||||
}
|
||||
|
||||
text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
|
||||
return text;
|
||||
});
|
1
public/lib/showdown-toc.min.js
vendored
1
public/lib/showdown-toc.min.js
vendored
@ -1 +0,0 @@
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).showdownToc=t()}(this,(function(){"use strict";function e(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function t(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}return function(){var r=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}).toc;return function(){return[{type:"output",filter:function(n){var o=[];n.replace(/(<h([1-6]).*?id="([^"]*?)".*?>(.+?)<\/h[1-6]>)|(<p>\[toc\]<\/p>)/g,(function(n,c,u,i,p){if("<p>[toc]</p>"===n)o.push({type:"toc"});else{p=p.replace(/<[^>]+>/g,"");var f={anchor:i,level:Number(u),text:p};r&&r.push(f),o.push(function(r){for(var n=1;arguments.length>n;n++){var o=null!=arguments[n]?arguments[n]:{};n%2?t(o,!0).forEach((function(t){e(r,t,o[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(r,Object.getOwnPropertyDescriptors(o)):t(o).forEach((function(e){Object.defineProperty(r,e,Object.getOwnPropertyDescriptor(o,e))}))}return r}({type:"header"},f))}return""}));var c=[];return o.forEach((function(e,t){if("toc"===e.type)if(o[t+1]&&"header"===o[t+1].type){for(var r=[],n=o[t+1].level,u=t+1;o.length>u&&"toc"!==o[u].type;u++){o[u].level===n&&r.push(o[u])}c.push(r)}else c.push([])})),n=n.replace(/<p>\[toc\]<\/p>[\n]*/g,(function(){var e=c.shift();return e&&e.length?"<ol>".concat(e.map((function(e){var t=e.text;return'<li><a href="#'.concat(e.anchor,'">').concat(t,"</a></li>")})).join(""),"</ol>\n"):""}))}}]}}}));
|
3
public/lib/showdown.min.js
vendored
3
public/lib/showdown.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,697 +0,0 @@
|
||||
/**
|
||||
* SVGInject - Version 1.2.3
|
||||
* A tiny, intuitive, robust, caching solution for injecting SVG files inline into the DOM.
|
||||
*
|
||||
* https://github.com/iconfu/svg-inject
|
||||
*
|
||||
* Copyright (c) 2018 INCORS, the creators of iconfu.com
|
||||
* @license MIT License - https://github.com/iconfu/svg-inject/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
(function(window, document) {
|
||||
// constants for better minification
|
||||
var _CREATE_ELEMENT_ = 'createElement';
|
||||
var _GET_ELEMENTS_BY_TAG_NAME_ = 'getElementsByTagName';
|
||||
var _LENGTH_ = 'length';
|
||||
var _STYLE_ = 'style';
|
||||
var _TITLE_ = 'title';
|
||||
var _UNDEFINED_ = 'undefined';
|
||||
var _SET_ATTRIBUTE_ = 'setAttribute';
|
||||
var _GET_ATTRIBUTE_ = 'getAttribute';
|
||||
|
||||
var NULL = null;
|
||||
|
||||
// constants
|
||||
var __SVGINJECT = '__svgInject';
|
||||
var ID_SUFFIX = '--inject-';
|
||||
var ID_SUFFIX_REGEX = new RegExp(ID_SUFFIX + '\\d+', "g");
|
||||
var LOAD_FAIL = 'LOAD_FAIL';
|
||||
var SVG_NOT_SUPPORTED = 'SVG_NOT_SUPPORTED';
|
||||
var SVG_INVALID = 'SVG_INVALID';
|
||||
var ATTRIBUTE_EXCLUSION_NAMES = ['src', 'alt', 'onload', 'onerror'];
|
||||
var A_ELEMENT = document[_CREATE_ELEMENT_]('a');
|
||||
var IS_SVG_SUPPORTED = typeof SVGRect != _UNDEFINED_;
|
||||
var DEFAULT_OPTIONS = {
|
||||
useCache: true,
|
||||
copyAttributes: true,
|
||||
makeIdsUnique: true
|
||||
};
|
||||
// Map of IRI referenceable tag names to properties that can reference them. This is defined in
|
||||
// https://www.w3.org/TR/SVG11/linking.html#processingIRI
|
||||
var IRI_TAG_PROPERTIES_MAP = {
|
||||
clipPath: ['clip-path'],
|
||||
'color-profile': NULL,
|
||||
cursor: NULL,
|
||||
filter: NULL,
|
||||
linearGradient: ['fill', 'stroke'],
|
||||
marker: ['marker', 'marker-end', 'marker-mid', 'marker-start'],
|
||||
mask: NULL,
|
||||
pattern: ['fill', 'stroke'],
|
||||
radialGradient: ['fill', 'stroke']
|
||||
};
|
||||
var INJECTED = 1;
|
||||
var FAIL = 2;
|
||||
|
||||
var uniqueIdCounter = 1;
|
||||
var xmlSerializer;
|
||||
var domParser;
|
||||
|
||||
|
||||
// creates an SVG document from an SVG string
|
||||
function svgStringToSvgDoc(svgStr) {
|
||||
domParser = domParser || new DOMParser();
|
||||
return domParser.parseFromString(svgStr, 'text/xml');
|
||||
}
|
||||
|
||||
|
||||
// searializes an SVG element to an SVG string
|
||||
function svgElemToSvgString(svgElement) {
|
||||
xmlSerializer = xmlSerializer || new XMLSerializer();
|
||||
return xmlSerializer.serializeToString(svgElement);
|
||||
}
|
||||
|
||||
|
||||
// Returns the absolute url for the specified url
|
||||
function getAbsoluteUrl(url) {
|
||||
A_ELEMENT.href = url;
|
||||
return A_ELEMENT.href;
|
||||
}
|
||||
|
||||
|
||||
// Load svg with an XHR request
|
||||
function loadSvg(url, callback, errorCallback) {
|
||||
if (url) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.onreadystatechange = function() {
|
||||
if (req.readyState == 4) {
|
||||
// readyState is DONE
|
||||
var status = req.status;
|
||||
if (status == 200) {
|
||||
// request status is OK
|
||||
callback(req.responseXML, req.responseText.trim());
|
||||
} else if (status >= 400) {
|
||||
// request status is error (4xx or 5xx)
|
||||
errorCallback();
|
||||
} else if (status == 0) {
|
||||
// request status 0 can indicate a failed cross-domain call
|
||||
errorCallback();
|
||||
}
|
||||
}
|
||||
};
|
||||
req.open('GET', url, true);
|
||||
req.send();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Copy attributes from img element to svg element
|
||||
function copyAttributes(imgElem, svgElem) {
|
||||
var attribute;
|
||||
var attributeName;
|
||||
var attributeValue;
|
||||
var attributes = imgElem.attributes;
|
||||
for (var i = 0; i < attributes[_LENGTH_]; i++) {
|
||||
attribute = attributes[i];
|
||||
attributeName = attribute.name;
|
||||
// Only copy attributes not explicitly excluded from copying
|
||||
if (ATTRIBUTE_EXCLUSION_NAMES.indexOf(attributeName) == -1) {
|
||||
attributeValue = attribute.value;
|
||||
// If img attribute is "title", insert a title element into SVG element
|
||||
if (attributeName == _TITLE_) {
|
||||
var titleElem;
|
||||
var firstElementChild = svgElem.firstElementChild;
|
||||
if (firstElementChild && firstElementChild.localName.toLowerCase() == _TITLE_) {
|
||||
// If the SVG element's first child is a title element, keep it as the title element
|
||||
titleElem = firstElementChild;
|
||||
} else {
|
||||
// If the SVG element's first child element is not a title element, create a new title
|
||||
// ele,emt and set it as the first child
|
||||
titleElem = document[_CREATE_ELEMENT_ + 'NS']('http://www.w3.org/2000/svg', _TITLE_);
|
||||
svgElem.insertBefore(titleElem, firstElementChild);
|
||||
}
|
||||
// Set new title content
|
||||
titleElem.textContent = attributeValue;
|
||||
} else {
|
||||
// Set img attribute to svg element
|
||||
svgElem[_SET_ATTRIBUTE_](attributeName, attributeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function appends a suffix to IDs of referenced elements in the <defs> in order to to avoid ID collision
|
||||
// between multiple injected SVGs. The suffix has the form "--inject-X", where X is a running number which is
|
||||
// incremented with each injection. References to the IDs are adjusted accordingly.
|
||||
// We assume tha all IDs within the injected SVG are unique, therefore the same suffix can be used for all IDs of one
|
||||
// injected SVG.
|
||||
// If the onlyReferenced argument is set to true, only those IDs will be made unique that are referenced from within the SVG
|
||||
function makeIdsUnique(svgElem, onlyReferenced) {
|
||||
var idSuffix = ID_SUFFIX + uniqueIdCounter++;
|
||||
// Regular expression for functional notations of an IRI references. This will find occurences in the form
|
||||
// url(#anyId) or url("#anyId") (for Internet Explorer) and capture the referenced ID
|
||||
var funcIriRegex = /url\("?#([a-zA-Z][\w:.-]*)"?\)/g;
|
||||
// Get all elements with an ID. The SVG spec recommends to put referenced elements inside <defs> elements, but
|
||||
// this is not a requirement, therefore we have to search for IDs in the whole SVG.
|
||||
var idElements = svgElem.querySelectorAll('[id]');
|
||||
var idElem;
|
||||
// An object containing referenced IDs as keys is used if only referenced IDs should be uniquified.
|
||||
// If this object does not exist, all IDs will be uniquified.
|
||||
var referencedIds = onlyReferenced ? [] : NULL;
|
||||
var tagName;
|
||||
var iriTagNames = {};
|
||||
var iriProperties = [];
|
||||
var changed = false;
|
||||
var i, j;
|
||||
|
||||
if (idElements[_LENGTH_]) {
|
||||
// Make all IDs unique by adding the ID suffix and collect all encountered tag names
|
||||
// that are IRI referenceable from properities.
|
||||
for (i = 0; i < idElements[_LENGTH_]; i++) {
|
||||
tagName = idElements[i].localName; // Use non-namespaced tag name
|
||||
// Make ID unique if tag name is IRI referenceable
|
||||
if (tagName in IRI_TAG_PROPERTIES_MAP) {
|
||||
iriTagNames[tagName] = 1;
|
||||
}
|
||||
}
|
||||
// Get all properties that are mapped to the found IRI referenceable tags
|
||||
for (tagName in iriTagNames) {
|
||||
(IRI_TAG_PROPERTIES_MAP[tagName] || [tagName]).forEach(function (mappedProperty) {
|
||||
// Add mapped properties to array of iri referencing properties.
|
||||
// Use linear search here because the number of possible entries is very small (maximum 11)
|
||||
if (iriProperties.indexOf(mappedProperty) < 0) {
|
||||
iriProperties.push(mappedProperty);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (iriProperties[_LENGTH_]) {
|
||||
// Add "style" to properties, because it may contain references in the form 'style="fill:url(#myFill)"'
|
||||
iriProperties.push(_STYLE_);
|
||||
}
|
||||
// Run through all elements of the SVG and replace IDs in references.
|
||||
// To get all descending elements, getElementsByTagName('*') seems to perform faster than querySelectorAll('*').
|
||||
// Since svgElem.getElementsByTagName('*') does not return the svg element itself, we have to handle it separately.
|
||||
var descElements = svgElem[_GET_ELEMENTS_BY_TAG_NAME_]('*');
|
||||
var element = svgElem;
|
||||
var propertyName;
|
||||
var value;
|
||||
var newValue;
|
||||
for (i = -1; element != NULL;) {
|
||||
if (element.localName == _STYLE_) {
|
||||
// If element is a style element, replace IDs in all occurences of "url(#anyId)" in text content
|
||||
value = element.textContent;
|
||||
newValue = value && value.replace(funcIriRegex, function(match, id) {
|
||||
if (referencedIds) {
|
||||
referencedIds[id] = 1;
|
||||
}
|
||||
return 'url(#' + id + idSuffix + ')';
|
||||
});
|
||||
if (newValue !== value) {
|
||||
element.textContent = newValue;
|
||||
}
|
||||
} else if (element.hasAttributes()) {
|
||||
// Run through all property names for which IDs were found
|
||||
for (j = 0; j < iriProperties[_LENGTH_]; j++) {
|
||||
propertyName = iriProperties[j];
|
||||
value = element[_GET_ATTRIBUTE_](propertyName);
|
||||
newValue = value && value.replace(funcIriRegex, function(match, id) {
|
||||
if (referencedIds) {
|
||||
referencedIds[id] = 1;
|
||||
}
|
||||
return 'url(#' + id + idSuffix + ')';
|
||||
});
|
||||
if (newValue !== value) {
|
||||
element[_SET_ATTRIBUTE_](propertyName, newValue);
|
||||
}
|
||||
}
|
||||
// Replace IDs in xlink:ref and href attributes
|
||||
['xlink:href', 'href'].forEach(function(refAttrName) {
|
||||
var iri = element[_GET_ATTRIBUTE_](refAttrName);
|
||||
if (/^\s*#/.test(iri)) { // Check if iri is non-null and internal reference
|
||||
iri = iri.trim();
|
||||
element[_SET_ATTRIBUTE_](refAttrName, iri + idSuffix);
|
||||
if (referencedIds) {
|
||||
// Add ID to referenced IDs
|
||||
referencedIds[iri.substring(1)] = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
element = descElements[++i];
|
||||
}
|
||||
for (i = 0; i < idElements[_LENGTH_]; i++) {
|
||||
idElem = idElements[i];
|
||||
// If set of referenced IDs exists, make only referenced IDs unique,
|
||||
// otherwise make all IDs unique.
|
||||
if (!referencedIds || referencedIds[idElem.id]) {
|
||||
// Add suffix to element's ID
|
||||
idElem.id += idSuffix;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// return true if SVG element has changed
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
// For cached SVGs the IDs are made unique by simply replacing the already inserted unique IDs with a
|
||||
// higher ID counter. This is much more performant than a call to makeIdsUnique().
|
||||
function makeIdsUniqueCached(svgString) {
|
||||
return svgString.replace(ID_SUFFIX_REGEX, ID_SUFFIX + uniqueIdCounter++);
|
||||
}
|
||||
|
||||
|
||||
// Inject SVG by replacing the img element with the SVG element in the DOM
|
||||
function inject(imgElem, svgElem, absUrl, options) {
|
||||
if (svgElem) {
|
||||
svgElem[_SET_ATTRIBUTE_]('data-inject-url', absUrl);
|
||||
var parentNode = imgElem.parentNode;
|
||||
if (parentNode) {
|
||||
if (options.copyAttributes) {
|
||||
copyAttributes(imgElem, svgElem);
|
||||
}
|
||||
// Invoke beforeInject hook if set
|
||||
var beforeInject = options.beforeInject;
|
||||
var injectElem = (beforeInject && beforeInject(imgElem, svgElem)) || svgElem;
|
||||
// Replace img element with new element. This is the actual injection.
|
||||
parentNode.replaceChild(injectElem, imgElem);
|
||||
// Mark img element as injected
|
||||
imgElem[__SVGINJECT] = INJECTED;
|
||||
removeOnLoadAttribute(imgElem);
|
||||
// Invoke afterInject hook if set
|
||||
var afterInject = options.afterInject;
|
||||
if (afterInject) {
|
||||
afterInject(imgElem, injectElem);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
svgInvalid(imgElem, options);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Merges any number of options objects into a new object
|
||||
function mergeOptions() {
|
||||
var mergedOptions = {};
|
||||
var args = arguments;
|
||||
// Iterate over all specified options objects and add all properties to the new options object
|
||||
for (var i = 0; i < args[_LENGTH_]; i++) {
|
||||
var argument = args[i];
|
||||
for (var key in argument) {
|
||||
if (argument.hasOwnProperty(key)) {
|
||||
mergedOptions[key] = argument[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return mergedOptions;
|
||||
}
|
||||
|
||||
|
||||
// Adds the specified CSS to the document's <head> element
|
||||
function addStyleToHead(css) {
|
||||
var head = document[_GET_ELEMENTS_BY_TAG_NAME_]('head')[0];
|
||||
if (head) {
|
||||
var style = document[_CREATE_ELEMENT_](_STYLE_);
|
||||
style.type = 'text/css';
|
||||
style.appendChild(document.createTextNode(css));
|
||||
head.appendChild(style);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Builds an SVG element from the specified SVG string
|
||||
function buildSvgElement(svgStr, verify) {
|
||||
if (verify) {
|
||||
var svgDoc;
|
||||
try {
|
||||
// Parse the SVG string with DOMParser
|
||||
svgDoc = svgStringToSvgDoc(svgStr);
|
||||
} catch(e) {
|
||||
return NULL;
|
||||
}
|
||||
if (svgDoc[_GET_ELEMENTS_BY_TAG_NAME_]('parsererror')[_LENGTH_]) {
|
||||
// DOMParser does not throw an exception, but instead puts parsererror tags in the document
|
||||
return NULL;
|
||||
}
|
||||
return svgDoc.documentElement;
|
||||
} else {
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = svgStr;
|
||||
return div.firstElementChild;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function removeOnLoadAttribute(imgElem) {
|
||||
// Remove the onload attribute. Should only be used to remove the unstyled image flash protection and
|
||||
// make the element visible, not for removing the event listener.
|
||||
imgElem.removeAttribute('onload');
|
||||
}
|
||||
|
||||
|
||||
function errorMessage(msg) {
|
||||
console.error('SVGInject: ' + msg);
|
||||
}
|
||||
|
||||
|
||||
function fail(imgElem, status, options) {
|
||||
imgElem[__SVGINJECT] = FAIL;
|
||||
if (options.onFail) {
|
||||
options.onFail(imgElem, status);
|
||||
} else {
|
||||
errorMessage(status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function svgInvalid(imgElem, options) {
|
||||
removeOnLoadAttribute(imgElem);
|
||||
fail(imgElem, SVG_INVALID, options);
|
||||
}
|
||||
|
||||
|
||||
function svgNotSupported(imgElem, options) {
|
||||
removeOnLoadAttribute(imgElem);
|
||||
fail(imgElem, SVG_NOT_SUPPORTED, options);
|
||||
}
|
||||
|
||||
|
||||
function loadFail(imgElem, options) {
|
||||
fail(imgElem, LOAD_FAIL, options);
|
||||
}
|
||||
|
||||
|
||||
function removeEventListeners(imgElem) {
|
||||
imgElem.onload = NULL;
|
||||
imgElem.onerror = NULL;
|
||||
}
|
||||
|
||||
|
||||
function imgNotSet(msg) {
|
||||
errorMessage('no img element');
|
||||
}
|
||||
|
||||
|
||||
function createSVGInject(globalName, options) {
|
||||
var defaultOptions = mergeOptions(DEFAULT_OPTIONS, options);
|
||||
var svgLoadCache = {};
|
||||
|
||||
if (IS_SVG_SUPPORTED) {
|
||||
// If the browser supports SVG, add a small stylesheet that hides the <img> elements until
|
||||
// injection is finished. This avoids showing the unstyled SVGs before style is applied.
|
||||
addStyleToHead('img[onload^="' + globalName + '("]{visibility:hidden;}');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* SVGInject
|
||||
*
|
||||
* Injects the SVG specified in the `src` attribute of the specified `img` element or array of `img`
|
||||
* elements. Returns a Promise object which resolves if all passed in `img` elements have either been
|
||||
* injected or failed to inject (Only if a global Promise object is available like in all modern browsers
|
||||
* or through a polyfill).
|
||||
*
|
||||
* Options:
|
||||
* useCache: If set to `true` the SVG will be cached using the absolute URL. Default value is `true`.
|
||||
* copyAttributes: If set to `true` the attributes will be copied from `img` to `svg`. Dfault value
|
||||
* is `true`.
|
||||
* makeIdsUnique: If set to `true` the ID of elements in the `<defs>` element that can be references by
|
||||
* property values (for example 'clipPath') are made unique by appending "--inject-X", where X is a
|
||||
* running number which increases with each injection. This is done to avoid duplicate IDs in the DOM.
|
||||
* beforeLoad: Hook before SVG is loaded. The `img` element is passed as a parameter. If the hook returns
|
||||
* a string it is used as the URL instead of the `img` element's `src` attribute.
|
||||
* afterLoad: Hook after SVG is loaded. The loaded `svg` element and `svg` string are passed as a
|
||||
* parameters. If caching is active this hook will only get called once for injected SVGs with the
|
||||
* same absolute path. Changes to the `svg` element in this hook will be applied to all injected SVGs
|
||||
* with the same absolute path. It's also possible to return an `svg` string or `svg` element which
|
||||
* will then be used for the injection.
|
||||
* beforeInject: Hook before SVG is injected. The `img` and `svg` elements are passed as parameters. If
|
||||
* any html element is returned it gets injected instead of applying the default SVG injection.
|
||||
* afterInject: Hook after SVG is injected. The `img` and `svg` elements are passed as parameters.
|
||||
* onAllFinish: Hook after all `img` elements passed to an SVGInject() call have either been injected or
|
||||
* failed to inject.
|
||||
* onFail: Hook after injection fails. The `img` element and a `status` string are passed as an parameter.
|
||||
* The `status` can be either `'SVG_NOT_SUPPORTED'` (the browser does not support SVG),
|
||||
* `'SVG_INVALID'` (the SVG is not in a valid format) or `'LOAD_FAILED'` (loading of the SVG failed).
|
||||
*
|
||||
* @param {HTMLImageElement} img - an img element or an array of img elements
|
||||
* @param {Object} [options] - optional parameter with [options](#options) for this injection.
|
||||
*/
|
||||
function SVGInject(img, options) {
|
||||
options = mergeOptions(defaultOptions, options);
|
||||
|
||||
var run = function(resolve) {
|
||||
var allFinish = function() {
|
||||
var onAllFinish = options.onAllFinish;
|
||||
if (onAllFinish) {
|
||||
onAllFinish();
|
||||
}
|
||||
resolve && resolve();
|
||||
};
|
||||
|
||||
if (img && typeof img[_LENGTH_] != _UNDEFINED_) {
|
||||
// an array like structure of img elements
|
||||
var injectIndex = 0;
|
||||
var injectCount = img[_LENGTH_];
|
||||
|
||||
if (injectCount == 0) {
|
||||
allFinish();
|
||||
} else {
|
||||
var finish = function() {
|
||||
if (++injectIndex == injectCount) {
|
||||
allFinish();
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < injectCount; i++) {
|
||||
SVGInjectElement(img[i], options, finish);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// only one img element
|
||||
SVGInjectElement(img, options, allFinish);
|
||||
}
|
||||
};
|
||||
|
||||
// return a Promise object if globally available
|
||||
return typeof Promise == _UNDEFINED_ ? run() : new Promise(run);
|
||||
}
|
||||
|
||||
|
||||
// Injects a single svg element. Options must be already merged with the default options.
|
||||
function SVGInjectElement(imgElem, options, callback) {
|
||||
if (imgElem) {
|
||||
var svgInjectAttributeValue = imgElem[__SVGINJECT];
|
||||
if (!svgInjectAttributeValue) {
|
||||
removeEventListeners(imgElem);
|
||||
|
||||
if (!IS_SVG_SUPPORTED) {
|
||||
svgNotSupported(imgElem, options);
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
// Invoke beforeLoad hook if set. If the beforeLoad returns a value use it as the src for the load
|
||||
// URL path. Else use the imgElem's src attribute value.
|
||||
var beforeLoad = options.beforeLoad;
|
||||
var src = (beforeLoad && beforeLoad(imgElem)) || imgElem[_GET_ATTRIBUTE_]('src');
|
||||
|
||||
if (!src) {
|
||||
// If no image src attribute is set do no injection. This can only be reached by using javascript
|
||||
// because if no src attribute is set the onload and onerror events do not get called
|
||||
if (src === '') {
|
||||
loadFail(imgElem, options);
|
||||
}
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
// set array so later calls can register callbacks
|
||||
var onFinishCallbacks = [];
|
||||
imgElem[__SVGINJECT] = onFinishCallbacks;
|
||||
|
||||
var onFinish = function() {
|
||||
callback();
|
||||
onFinishCallbacks.forEach(function(onFinishCallback) {
|
||||
onFinishCallback();
|
||||
});
|
||||
};
|
||||
|
||||
var absUrl = getAbsoluteUrl(src);
|
||||
var useCacheOption = options.useCache;
|
||||
var makeIdsUniqueOption = options.makeIdsUnique;
|
||||
|
||||
var setSvgLoadCacheValue = function(val) {
|
||||
if (useCacheOption) {
|
||||
svgLoadCache[absUrl].forEach(function(svgLoad) {
|
||||
svgLoad(val);
|
||||
});
|
||||
svgLoadCache[absUrl] = val;
|
||||
}
|
||||
};
|
||||
|
||||
if (useCacheOption) {
|
||||
var svgLoad = svgLoadCache[absUrl];
|
||||
|
||||
var handleLoadValue = function(loadValue) {
|
||||
if (loadValue === LOAD_FAIL) {
|
||||
loadFail(imgElem, options);
|
||||
} else if (loadValue === SVG_INVALID) {
|
||||
svgInvalid(imgElem, options);
|
||||
} else {
|
||||
var hasUniqueIds = loadValue[0];
|
||||
var svgString = loadValue[1];
|
||||
var uniqueIdsSvgString = loadValue[2];
|
||||
var svgElem;
|
||||
|
||||
if (makeIdsUniqueOption) {
|
||||
if (hasUniqueIds === NULL) {
|
||||
// IDs for the SVG string have not been made unique before. This may happen if previous
|
||||
// injection of a cached SVG have been run with the option makedIdsUnique set to false
|
||||
svgElem = buildSvgElement(svgString, false);
|
||||
hasUniqueIds = makeIdsUnique(svgElem, false);
|
||||
|
||||
loadValue[0] = hasUniqueIds;
|
||||
loadValue[2] = hasUniqueIds && svgElemToSvgString(svgElem);
|
||||
} else if (hasUniqueIds) {
|
||||
// Make IDs unique for already cached SVGs with better performance
|
||||
svgString = makeIdsUniqueCached(uniqueIdsSvgString);
|
||||
}
|
||||
}
|
||||
|
||||
svgElem = svgElem || buildSvgElement(svgString, false);
|
||||
|
||||
inject(imgElem, svgElem, absUrl, options);
|
||||
}
|
||||
onFinish();
|
||||
};
|
||||
|
||||
if (typeof svgLoad != _UNDEFINED_) {
|
||||
// Value for url exists in cache
|
||||
if (svgLoad.isCallbackQueue) {
|
||||
// Same url has been cached, but value has not been loaded yet, so add to callbacks
|
||||
svgLoad.push(handleLoadValue);
|
||||
} else {
|
||||
handleLoadValue(svgLoad);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
var svgLoad = [];
|
||||
// set property isCallbackQueue to Array to differentiate from array with cached loaded values
|
||||
svgLoad.isCallbackQueue = true;
|
||||
svgLoadCache[absUrl] = svgLoad;
|
||||
}
|
||||
}
|
||||
|
||||
// Load the SVG because it is not cached or caching is disabled
|
||||
loadSvg(absUrl, function(svgXml, svgString) {
|
||||
// Use the XML from the XHR request if it is an instance of Document. Otherwise
|
||||
// (for example of IE9), create the svg document from the svg string.
|
||||
var svgElem = svgXml instanceof Document ? svgXml.documentElement : buildSvgElement(svgString, true);
|
||||
|
||||
var afterLoad = options.afterLoad;
|
||||
if (afterLoad) {
|
||||
// Invoke afterLoad hook which may modify the SVG element. After load may also return a new
|
||||
// svg element or svg string
|
||||
var svgElemOrSvgString = afterLoad(svgElem, svgString) || svgElem;
|
||||
if (svgElemOrSvgString) {
|
||||
// Update svgElem and svgString because of modifications to the SVG element or SVG string in
|
||||
// the afterLoad hook, so the modified SVG is also used for all later cached injections
|
||||
var isString = typeof svgElemOrSvgString == 'string';
|
||||
svgString = isString ? svgElemOrSvgString : svgElemToSvgString(svgElem);
|
||||
svgElem = isString ? buildSvgElement(svgElemOrSvgString, true) : svgElemOrSvgString;
|
||||
}
|
||||
}
|
||||
|
||||
if (svgElem instanceof SVGElement) {
|
||||
var hasUniqueIds = NULL;
|
||||
if (makeIdsUniqueOption) {
|
||||
hasUniqueIds = makeIdsUnique(svgElem, false);
|
||||
}
|
||||
|
||||
if (useCacheOption) {
|
||||
var uniqueIdsSvgString = hasUniqueIds && svgElemToSvgString(svgElem);
|
||||
// set an array with three entries to the load cache
|
||||
setSvgLoadCacheValue([hasUniqueIds, svgString, uniqueIdsSvgString]);
|
||||
}
|
||||
|
||||
inject(imgElem, svgElem, absUrl, options);
|
||||
} else {
|
||||
svgInvalid(imgElem, options);
|
||||
setSvgLoadCacheValue(SVG_INVALID);
|
||||
}
|
||||
onFinish();
|
||||
}, function() {
|
||||
loadFail(imgElem, options);
|
||||
setSvgLoadCacheValue(LOAD_FAIL);
|
||||
onFinish();
|
||||
});
|
||||
} else {
|
||||
if (Array.isArray(svgInjectAttributeValue)) {
|
||||
// svgInjectAttributeValue is an array. Injection is not complete so register callback
|
||||
svgInjectAttributeValue.push(callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
imgNotSet();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the default [options](#options) for SVGInject.
|
||||
*
|
||||
* @param {Object} [options] - default [options](#options) for an injection.
|
||||
*/
|
||||
SVGInject.setOptions = function(options) {
|
||||
defaultOptions = mergeOptions(defaultOptions, options);
|
||||
};
|
||||
|
||||
|
||||
// Create a new instance of SVGInject
|
||||
SVGInject.create = createSVGInject;
|
||||
|
||||
|
||||
/**
|
||||
* Used in onerror Event of an `<img>` element to handle cases when the loading the original src fails
|
||||
* (for example if file is not found or if the browser does not support SVG). This triggers a call to the
|
||||
* options onFail hook if available. The optional second parameter will be set as the new src attribute
|
||||
* for the img element.
|
||||
*
|
||||
* @param {HTMLImageElement} img - an img element
|
||||
* @param {String} [fallbackSrc] - optional parameter fallback src
|
||||
*/
|
||||
SVGInject.err = function(img, fallbackSrc) {
|
||||
if (img) {
|
||||
if (img[__SVGINJECT] != FAIL) {
|
||||
removeEventListeners(img);
|
||||
|
||||
if (!IS_SVG_SUPPORTED) {
|
||||
svgNotSupported(img, defaultOptions);
|
||||
} else {
|
||||
removeOnLoadAttribute(img);
|
||||
loadFail(img, defaultOptions);
|
||||
}
|
||||
if (fallbackSrc) {
|
||||
removeOnLoadAttribute(img);
|
||||
img.src = fallbackSrc;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
imgNotSet();
|
||||
}
|
||||
};
|
||||
|
||||
window[globalName] = SVGInject;
|
||||
|
||||
return SVGInject;
|
||||
}
|
||||
|
||||
var SVGInjectInstance = createSVGInject('SVGInject');
|
||||
|
||||
if (typeof module == 'object' && typeof module.exports == 'object') {
|
||||
module.exports = SVGInjectInstance;
|
||||
}
|
||||
})(window, document);
|
@ -1,303 +0,0 @@
|
||||
const SATURATION_BOUND = [0, 100];
|
||||
const LIGHTNESS_BOUND = [0, 100];
|
||||
|
||||
const pad2 = str => `${str.length === 1 ? '0' : ''}${str}`;
|
||||
|
||||
const clamp = (num, min, max) => Math.max(Math.min(num, max), min);
|
||||
|
||||
const random = (min, max) => Math.floor(Math.random() * ((max - min) + 1)) + min;
|
||||
|
||||
const randomExclude = (min, max, exclude) => {
|
||||
const r = random(min, max);
|
||||
|
||||
for (let i = 0; i < exclude?.length; i++) {
|
||||
const value = exclude[i];
|
||||
|
||||
if (value?.length === 2 && r >= value[0] && r <= value[1]) {
|
||||
return randomExclude(min, max, exclude);
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate hashCode
|
||||
* @param {string} str
|
||||
* @return {number}
|
||||
*/
|
||||
const hashCode = str => {
|
||||
const len = str.length;
|
||||
let hash = 0;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
hash = ((hash << 5) - hash) + str.charCodeAt(i);
|
||||
hash &= hash; // Convert to 32bit integer
|
||||
}
|
||||
|
||||
return hash;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clamps `num` within the inclusive `range` bounds
|
||||
* @param {number} num
|
||||
* @param {number|Array} range
|
||||
* @return {number}
|
||||
*/
|
||||
const boundHashCode = (num, range) => {
|
||||
if (typeof range === 'number') {
|
||||
return range;
|
||||
}
|
||||
|
||||
return (num % Math.abs(range[1] - range[0])) + range[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Sanitizing the `range`
|
||||
* @param {number|Array} range
|
||||
* @param {Array} bound
|
||||
* @return {number|Array}
|
||||
*/
|
||||
const sanitizeRange = (range, bound) => {
|
||||
if (typeof range === 'number') {
|
||||
return clamp(Math.abs(range), ...bound);
|
||||
}
|
||||
|
||||
if (range.length === 1 || range[0] === range[1]) {
|
||||
return clamp(Math.abs(range[0]), ...bound);
|
||||
}
|
||||
|
||||
return [
|
||||
Math.abs(clamp(range[0], ...bound)),
|
||||
clamp(Math.abs(range[1]), ...bound),
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} p
|
||||
* @param {number} q
|
||||
* @param {number} t
|
||||
* @return {number}
|
||||
*/
|
||||
const hueToRgb = (p, q, t) => {
|
||||
if (t < 0) {
|
||||
t += 1;
|
||||
} else if (t > 1) {
|
||||
t -= 1;
|
||||
}
|
||||
|
||||
if (t < 1 / 6) {
|
||||
return p + ((q - p) * 6 * t);
|
||||
}
|
||||
|
||||
if (t < 1 / 2) {
|
||||
return q;
|
||||
}
|
||||
|
||||
if (t < 2 / 3) {
|
||||
return p + ((q - p) * ((2 / 3) - t) * 6);
|
||||
}
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts an HSL color to RGB
|
||||
* @param {number} h Hue
|
||||
* @param {number} s Saturation
|
||||
* @param {number} l Lightness
|
||||
* @return {Array}
|
||||
*/
|
||||
const hslToRgb = (h, s, l) => {
|
||||
let r;
|
||||
let g;
|
||||
let b;
|
||||
|
||||
h /= 360;
|
||||
s /= 100;
|
||||
l /= 100;
|
||||
|
||||
if (s === 0) {
|
||||
// achromatic
|
||||
r = g = b = l;
|
||||
} else {
|
||||
const q = l < 0.5
|
||||
? l * (1 + s)
|
||||
: (l + s) - (l * s);
|
||||
const p = (2 * l) - q;
|
||||
|
||||
r = hueToRgb(p, q, h + (1 / 3));
|
||||
g = hueToRgb(p, q, h);
|
||||
b = hueToRgb(p, q, h - (1 / 3));
|
||||
}
|
||||
|
||||
return [
|
||||
Math.round(r * 255),
|
||||
Math.round(g * 255),
|
||||
Math.round(b * 255),
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines whether the RGB color is light or not
|
||||
* http://www.w3.org/TR/AERT#color-contrast
|
||||
* @param {number} r Red
|
||||
* @param {number} g Green
|
||||
* @param {number} b Blue
|
||||
* @param {number} differencePoint
|
||||
* @return {boolean}
|
||||
*/
|
||||
const rgbIsLight = (r, g, b, differencePoint) => ((r * 299) + (g * 587) + (b * 114)) / 1000 >= differencePoint; // eslint-disable-line max-len
|
||||
|
||||
/**
|
||||
* Converts an HSL color to string format
|
||||
* @param {number} h Hue
|
||||
* @param {number} s Saturation
|
||||
* @param {number} l Lightness
|
||||
* @return {string}
|
||||
*/
|
||||
const hslToString = (h, s, l) => `hsl(${h}, ${s}%, ${l}%)`;
|
||||
|
||||
/**
|
||||
* Converts RGB color to string format
|
||||
* @param {number} r Red
|
||||
* @param {number} g Green
|
||||
* @param {number} b Blue
|
||||
* @param {string} format Color format
|
||||
* @return {string}
|
||||
*/
|
||||
const rgbFormat = (r, g, b, format) => {
|
||||
switch (format) {
|
||||
case 'rgb':
|
||||
return `rgb(${r}, ${g}, ${b})`;
|
||||
case 'hex':
|
||||
default:
|
||||
return `#${pad2(r.toString(16))}${pad2(g.toString(16))}${pad2(b.toString(16))}`;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate unique color from `value`
|
||||
* @param {string|number} value
|
||||
* @param {Object} [options={}]
|
||||
* @param {string} [options.format='hex']
|
||||
* The color format, it can be one of `hex`, `rgb` or `hsl`
|
||||
* @param {number|Array} [options.saturation=[50, 55]]
|
||||
* Determines the color saturation, it can be a number or a range between 0 and 100
|
||||
* @param {number|Array} [options.lightness=[50, 60]]
|
||||
* Determines the color lightness, it can be a number or a range between 0 and 100
|
||||
* @param {number} [options.differencePoint=130]
|
||||
* Determines the color brightness difference point. We use it to obtain the `isLight` value
|
||||
* in the output, it can be a number between 0 and 255
|
||||
* @return {Object}
|
||||
* @example
|
||||
*
|
||||
* ```js
|
||||
* uniqolor('Hello world!')
|
||||
* // { color: "#5cc653", isLight: true }
|
||||
*
|
||||
* uniqolor('Hello world!', { format: 'rgb' })
|
||||
* // { color: "rgb(92, 198, 83)", isLight: true }
|
||||
*
|
||||
* uniqolor('Hello world!', {
|
||||
* saturation: 30,
|
||||
* lightness: [70, 80],
|
||||
* })
|
||||
* // { color: "#afd2ac", isLight: true }
|
||||
*
|
||||
* uniqolor('Hello world!', {
|
||||
* saturation: 30,
|
||||
* lightness: [70, 80],
|
||||
* differencePoint: 200,
|
||||
* })
|
||||
* // { color: "#afd2ac", isLight: false }
|
||||
* ```
|
||||
*/
|
||||
const uniqolor = (value, {
|
||||
format = 'hex',
|
||||
saturation = [50, 55],
|
||||
lightness = [50, 60],
|
||||
differencePoint = 130,
|
||||
} = {}) => {
|
||||
const hash = Math.abs(hashCode(String(value)));
|
||||
const h = boundHashCode(hash, [0, 360]);
|
||||
const s = boundHashCode(hash, sanitizeRange(saturation, SATURATION_BOUND));
|
||||
const l = boundHashCode(hash, sanitizeRange(lightness, LIGHTNESS_BOUND));
|
||||
const [r, g, b] = hslToRgb(h, s, l);
|
||||
|
||||
return {
|
||||
color: format === 'hsl'
|
||||
? hslToString(h, s, l)
|
||||
: rgbFormat(r, g, b, format),
|
||||
isLight: rgbIsLight(r, g, b, differencePoint),
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate random color
|
||||
* @param {Object} [options={}]
|
||||
* @param {string} [options.format='hex']
|
||||
* The color format, it can be one of `hex`, `rgb` or `hsl`
|
||||
* @param {number|Array} [options.saturation=[50, 55]]
|
||||
* Determines the color saturation, it can be a number or a range between 0 and 100
|
||||
* @param {number|Array} [options.lightness=[50, 60]]
|
||||
* Determines the color lightness, it can be a number or a range between 0 and 100
|
||||
* @param {number} [options.differencePoint=130]
|
||||
* Determines the color brightness difference point. We use it to obtain the `isLight` value
|
||||
* in the output, it can be a number between 0 and 255
|
||||
* @param {Array} [options.excludeHue]
|
||||
* Exclude certain hue ranges. For example to exclude red color range: `[[0, 20], [325, 359]]`
|
||||
* @return {Object}
|
||||
* @example
|
||||
*
|
||||
* ```js
|
||||
* // Generate random color
|
||||
* uniqolor.random()
|
||||
* // { color: "#644cc8", isLight: false }
|
||||
*
|
||||
* // Generate a random color with HSL format
|
||||
* uniqolor.random({ format: 'hsl' })
|
||||
* // { color: "hsl(89, 55%, 60%)", isLight: true }
|
||||
*
|
||||
* // Generate a random color in specific saturation and lightness
|
||||
* uniqolor.random({
|
||||
* saturation: 80,
|
||||
* lightness: [70, 80],
|
||||
* })
|
||||
* // { color: "#c7b9da", isLight: true }
|
||||
*
|
||||
* // Generate a random color but exclude red color range
|
||||
* uniqolor.random({
|
||||
* excludeHue: [[0, 20], [325, 359]],
|
||||
* })
|
||||
* // {color: '#53caab', isLight: true}
|
||||
* ```
|
||||
*/
|
||||
uniqolor.random = ({
|
||||
format = 'hex',
|
||||
saturation = [50, 55],
|
||||
lightness = [50, 60],
|
||||
differencePoint = 130,
|
||||
excludeHue,
|
||||
} = {}) => {
|
||||
saturation = sanitizeRange(saturation, SATURATION_BOUND);
|
||||
lightness = sanitizeRange(lightness, LIGHTNESS_BOUND);
|
||||
|
||||
const h = excludeHue ? randomExclude(0, 359, excludeHue) : random(0, 359);
|
||||
const s = typeof saturation === 'number'
|
||||
? saturation
|
||||
: random(...saturation);
|
||||
const l = typeof lightness === 'number'
|
||||
? lightness
|
||||
: random(...lightness);
|
||||
const [r, g, b] = hslToRgb(h, s, l);
|
||||
|
||||
return {
|
||||
color: format === 'hsl'
|
||||
? hslToString(h, s, l)
|
||||
: rgbFormat(r, g, b, format),
|
||||
isLight: rgbIsLight(r, g, b, differencePoint),
|
||||
};
|
||||
};
|
||||
|
||||
export default uniqolor;
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "حفظ التعديلات التلقائي للرسائل",
|
||||
"Confirm message deletion": "تأكيد حذف الرسالة",
|
||||
"Auto-fix Markdown": "إصلاح Markdown تلقائيًا",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "تقديم علامة LaTeX و AsciiMath للمعادلات في رسائل الدردشة. مدعوم بواسطة KaTeX",
|
||||
"Render Formulas": "تقديم الصيغ",
|
||||
"Disallow embedded media from other domains in chat messages": "عدم السماح بالوسائط المضمنة من المجالات الأخرى في رسائل الدردشة.",
|
||||
"Forbid External Media": "منع وسائط خارجية",
|
||||
"Allow {{char}}: in bot messages": "السماح بـ {{char}}: في رسائل البوت",
|
||||
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "Nachrichtenänderungen automatisch speichern",
|
||||
"Confirm message deletion": "Löschung der Nachricht bestätigen",
|
||||
"Auto-fix Markdown": "Markdown automatisch reparieren",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "Rendere LaTeX- und AsciiMath-Gleichungsnotation in Chat-Nachrichten. Unterstützt von KaTeX",
|
||||
"Render Formulas": "Formeln rendern",
|
||||
"Disallow embedded media from other domains in chat messages": "Eingebettete Medien von anderen Domänen in Chat-Nachrichten nicht zulassen.",
|
||||
"Forbid External Media": "Externe Medien verbieten",
|
||||
"Allow {{char}}: in bot messages": "Erlaube {{char}}: in Bot-Nachrichten",
|
||||
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "Guardar automáticamente las Ediciones de Mensajes",
|
||||
"Confirm message deletion": "Confirmar eliminación de mensaje",
|
||||
"Auto-fix Markdown": "Auto-corregir Markdown",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "Renderizar notación de ecuaciones LaTeX y AsciiMath en mensajes de chat. Impulsado por KaTeX",
|
||||
"Render Formulas": "Renderizar fórmulas",
|
||||
"Disallow embedded media from other domains in chat messages": "No permitir medios incrustados de otros dominios en los mensajes de chat.",
|
||||
"Forbid External Media": "Prohibir Medios Externos",
|
||||
"Allow {{char}}: in bot messages": "Permitir {{char}}: en mensajes de bot",
|
||||
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "Sauvegarde automatique des modifications de message",
|
||||
"Confirm message deletion": "Confirmer la suppression du message",
|
||||
"Auto-fix Markdown": "Correction automatique du Markdown",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "Rendre la notation d'équations LaTeX et AsciiMath dans les messages de discussion. Propulsé par KaTeX",
|
||||
"Render Formulas": "Rendre les formules",
|
||||
"Disallow embedded media from other domains in chat messages": "Interdire les médias intégrés provenant d'autres domaines dans les messages de discussion.",
|
||||
"Forbid External Media": "Interdire les médias externes",
|
||||
"Allow {{char}}: in bot messages": "Autoriser {{char}} : dans les messages du bot",
|
||||
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "Sjálfvirkur vistun skilaboðabreytinga",
|
||||
"Confirm message deletion": "Staðfesta eyðingu skilaboða",
|
||||
"Auto-fix Markdown": "Sjálfvirk lagfæring Markdown",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "Gera LaTeX og AsciiMath jöfnutímanótur í spjall skilaboðum. Aflað af KaTeX",
|
||||
"Render Formulas": "Render Formúlur",
|
||||
"Disallow embedded media from other domains in chat messages": "Ekki leyfa innfellda miðla frá öðrum lénum í spjallskilaboðum.",
|
||||
"Forbid External Media": "Banna ytri miðla",
|
||||
"Allow {{char}}: in bot messages": "Leyfa {{char}}: í boðum botts",
|
||||
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "Salvataggio automatico delle modifiche ai messaggi",
|
||||
"Confirm message deletion": "Conferma eliminazione messaggio",
|
||||
"Auto-fix Markdown": "Correzione automatica di Markdown",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "Rendi la notazione dell'equazione LaTeX e AsciiMath nei messaggi di chat. Alimentato da KaTeX",
|
||||
"Render Formulas": "Renderizza formule",
|
||||
"Disallow embedded media from other domains in chat messages": "Non consentire contenuti multimediali incorporati da altri domini nei messaggi di chat.",
|
||||
"Forbid External Media": "Vietare i media esterni",
|
||||
"Allow {{char}}: in bot messages": "Consenti {{char}}: nei messaggi del bot",
|
||||
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "メッセージ編集の自動保存",
|
||||
"Confirm message deletion": "メッセージの削除を確認",
|
||||
"Auto-fix Markdown": "Markdownの自動修正",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "チャットメッセージでLaTeXおよびAsciiMathの数式表記をレンダリングします。KaTeXで動作します",
|
||||
"Render Formulas": "数式のレンダリング",
|
||||
"Disallow embedded media from other domains in chat messages": "チャットメッセージの他のドメインからの埋め込みメディアを禁止する",
|
||||
"Forbid External Media": "外部メディアを禁止",
|
||||
"Allow {{char}}: in bot messages": "ボットメッセージ内の{{char}}:を許可",
|
||||
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "메시지 편집 자동 저장",
|
||||
"Confirm message deletion": "메시지 삭제 확인",
|
||||
"Auto-fix Markdown": "Markdown 자동 수정",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "채팅 메시지에서 LaTeX 및 AsciiMath 방정식 표기법을 렌더링합니다. KaTeX 제공",
|
||||
"Render Formulas": "수식 렌더링",
|
||||
"Disallow embedded media from other domains in chat messages": "채팅 메시지에 다른 도메인의 삽입된 미디어를 허용하지 않습니다.",
|
||||
"Forbid External Media": "외부 미디어 금지",
|
||||
"Allow {{char}}: in bot messages": "봇 메시지에서 {{char}}: 허용",
|
||||
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "Automatisch opslaan van berichtbewerkingen",
|
||||
"Confirm message deletion": "Bevestig bericht verwijdering",
|
||||
"Auto-fix Markdown": "Automatisch repareren van Markdown",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "LaTeX en AsciiMath-vergelijking notatie renderen in chatberichten. Aangedreven door KaTeX",
|
||||
"Render Formulas": "Formules renderen",
|
||||
"Disallow embedded media from other domains in chat messages": "Ingesloten media van andere domeinen niet toestaan in chatberichten.",
|
||||
"Forbid External Media": "Externe media verbieden",
|
||||
"Allow {{char}}: in bot messages": "Toestaan {{char}}: in botberichten",
|
||||
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "Salvar automaticamente Edições de Mensagem",
|
||||
"Confirm message deletion": "Confirmar exclusão de mensagem",
|
||||
"Auto-fix Markdown": "Corrigir Markdown automaticamente",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "Renderizar notação de equações LaTeX e AsciiMath em mensagens de chat. Alimentado por KaTeX",
|
||||
"Render Formulas": "Renderizar Fórmulas",
|
||||
"Disallow embedded media from other domains in chat messages": "Proibir mídia incorporada de outros domínios em mensagens de bate-papo.",
|
||||
"Forbid External Media": "Proibir Mídia Externa",
|
||||
"Allow {{char}}: in bot messages": "Permitir {{char}}: em mensagens de bot",
|
||||
|
@ -241,7 +241,6 @@
|
||||
"Auto-save Message Edits": "Автоматически сохранять отредактированные сообщения",
|
||||
"Auto-fix Markdown": "Автоисправление разметки",
|
||||
"Auto-scroll Chat": "Автоматическая прокрутка чата",
|
||||
"Render Formulas": "Рендер формул",
|
||||
"Send on Enter": "Отправка на Enter",
|
||||
"Debug Menu": "Меню отладки",
|
||||
"Restore User Input": "Восстанавливать введённый текст",
|
||||
@ -423,7 +422,6 @@
|
||||
"Show arrow buttons on the last in-chat message to generate alternative AI responses. Both PC and mobile": "Показывать кнопки со стрелками на последнем сообщении в чате, чтобы генерировать альтернативные ответы ИИ. Как для ПК, так и для мобильных устройств.",
|
||||
"Allow using swiping gestures on the last in-chat message to trigger swipe generation. Mobile only, no effect on PC": "Позволяет использовать жесты смахивания на последнем сообщении в чате, чтобы вызвать альтернативную генерацию. Только для мобильных устройств, на ПК не работает.",
|
||||
"Save edits to messages without confirmation as you type": "Сохранять правки в сообщениях без подтверждения по мере ввода текста.",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "Отображение нотации уравнений LaTeX и AsciiMath в сообщениях чата. При поддержке KaTeX.",
|
||||
"Skip encoding and characters in message text, allowing a subset of HTML markup as well as Markdown": "Не кодировать символы < и > в тексте сообщения, что позволяет использовать подмножество HTML-разметки, а также Markdown.",
|
||||
"Allow AI messages in groups to contain lines spoken by other group members": "Разрешить ИИ в группах генерировать строчки за других участников группы в своих сообщениях.",
|
||||
"Requests logprobs from the API for the Token Probabilities feature": "Запросить логпробы из API для функции Token Probabilities.",
|
||||
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "Автоматичне збереження редагувань повідомлень",
|
||||
"Confirm message deletion": "Підтвердити видалення повідомлення",
|
||||
"Auto-fix Markdown": "Автоматичне виправлення Markdown",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "Відображати формул LaTeX та AsciiMath у повідомленнях чату. Працює на основі KaTeX",
|
||||
"Render Formulas": "Відображення формул",
|
||||
"Disallow embedded media from other domains in chat messages": "Заборонити вбудовані мультимедійні дані з інших доменів у повідомленнях чату.",
|
||||
"Forbid External Media": "Заборонити зовнішні медіа",
|
||||
"Allow {{char}}: in bot messages": "Дозволити {{char}}: у повідомленнях бота",
|
||||
|
@ -694,8 +694,6 @@
|
||||
"Auto-save Message Edits": "Tự động lưu Sửa Tin nhắn",
|
||||
"Confirm message deletion": "Xác nhận xóa tin nhắn",
|
||||
"Auto-fix Markdown": "Tự động sửa Markdown",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "Kết xuất ký hiệu phương trình LaTeX và AsciiMath trong tin nhắn trò chuyện. Được cung cấp bởi KaTeX",
|
||||
"Render Formulas": "Hiển thị Công thức",
|
||||
"Disallow embedded media from other domains in chat messages": "Không cho phép nhúng phương tiện từ các miền khác vào tin nhắn trò chuyện.",
|
||||
"Forbid External Media": "Cấm Phương tiện Ngoại tuyến",
|
||||
"Allow {{char}}: in bot messages": "Cho phép {{char}}: trong các Tin nhắn Bot",
|
||||
|
@ -733,8 +733,6 @@
|
||||
"Auto-save Message Edits": "自动保存消息编辑",
|
||||
"Confirm message deletion": "删除消息前确认",
|
||||
"Auto-fix Markdown": "自动修复 Markdown",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "在聊天消息中渲染LaTeX和AsciiMath方程式符号。由KaTeX提供支持",
|
||||
"Render Formulas": "渲染公式",
|
||||
"Disallow embedded media from other domains in chat messages": "禁止在聊天消息中嵌入来自其他域的媒体。",
|
||||
"Forbid External Media": "禁止外部媒体",
|
||||
"Allow {{char}}: in bot messages": "在机器人消息中允许 {{char}}: ",
|
||||
|
@ -695,8 +695,6 @@
|
||||
"Auto-save Message Edits": "自動儲存編輯的訊息",
|
||||
"Confirm message deletion": "確認刪除訊息",
|
||||
"Auto-fix Markdown": "自動修正 Markdown",
|
||||
"Render LaTeX and AsciiMath equation notation in chat messages. Powered by KaTeX": "在聊天訊息中算繪 LaTeX 和 AsciiMath 方程式標記。由 KaTeX 提供支援。",
|
||||
"Render Formulas": "算繪公式",
|
||||
"Disallow embedded media from other domains in chat messages": "禁止在聊天訊息中嵌入來自其他領域的媒體。",
|
||||
"Forbid External Media": "禁止使用外部媒體",
|
||||
"Allow {{char}}: in bot messages": "允許機器人訊息中使用 {{char}}:",
|
||||
|
@ -1,3 +1,18 @@
|
||||
import {
|
||||
showdown,
|
||||
moment,
|
||||
Fuse,
|
||||
DOMPurify,
|
||||
hljs,
|
||||
localforage,
|
||||
Handlebars,
|
||||
DiffMatchPatch,
|
||||
SVGInject,
|
||||
Popper,
|
||||
initLibraryShims,
|
||||
default as libs,
|
||||
} from './lib.js';
|
||||
|
||||
import { humanizedDateTime, favsToHotswap, getMessageTimeStamp, dragElement, isMobile, initRossMods, shouldSendOnEnter } from './scripts/RossAscends-mods.js';
|
||||
import { userStatsHandler, statMesProcess, initStats } from './scripts/stats.js';
|
||||
import {
|
||||
@ -247,7 +262,11 @@ import { AbortReason } from './scripts/util/AbortReason.js';
|
||||
import { initSystemPrompts } from './scripts/sysprompt.js';
|
||||
import { registerExtensionSlashCommands as initExtensionSlashCommands } from './scripts/extensions-slashcommands.js';
|
||||
import { ToolManager } from './scripts/tool-calling.js';
|
||||
import { addShowdownPatch } from './scripts/util/showdown-patch.js';
|
||||
import { applyBrowserFixes } from './scripts/browser-fixes.js';
|
||||
import { initServerHistory } from './scripts/server-history.js';
|
||||
import { initSettingsSearch } from './scripts/setting-search.js';
|
||||
import { initBulkEdit } from './scripts/bulk-edit.js';
|
||||
|
||||
//exporting functions and vars for mods
|
||||
export {
|
||||
@ -409,6 +428,7 @@ DOMPurify.addHook('uponSanitizeElement', (node, _, config) => {
|
||||
|
||||
// API OBJECT FOR EXTERNAL WIRING
|
||||
window['SillyTavern'] = {};
|
||||
window['SillyTavern'].libs = libs;
|
||||
|
||||
// Event source init
|
||||
export const event_types = {
|
||||
@ -490,12 +510,12 @@ console.debug('Character context menu initialized', characterContextMenu);
|
||||
|
||||
// Markdown converter
|
||||
export let mesForShowdownParse; //intended to be used as a context to compare showdown strings against
|
||||
/** @type {import('showdown').Converter} */
|
||||
let converter;
|
||||
reloadMarkdownProcessor();
|
||||
|
||||
// array for prompt token calculations
|
||||
console.debug('initializing Prompt Itemization Array on Startup');
|
||||
const promptStorage = new localforage.createInstance({ name: 'SillyTavern_Prompts' });
|
||||
const promptStorage = localforage.createInstance({ name: 'SillyTavern_Prompts' });
|
||||
export let itemizedPrompts = [];
|
||||
|
||||
export const systemUserName = 'SillyTavern System';
|
||||
@ -741,48 +761,22 @@ async function getClientVersion() {
|
||||
}
|
||||
}
|
||||
|
||||
export function reloadMarkdownProcessor(render_formulas = false) {
|
||||
if (render_formulas) {
|
||||
converter = new showdown.Converter({
|
||||
emoji: true,
|
||||
underline: true,
|
||||
tables: true,
|
||||
parseImgDimensions: true,
|
||||
simpleLineBreaks: true,
|
||||
strikethrough: true,
|
||||
disableForced4SpacesIndentedSublists: true,
|
||||
extensions: [
|
||||
showdownKatex(
|
||||
{
|
||||
delimiters: [
|
||||
{ left: '$$', right: '$$', display: true, asciimath: false },
|
||||
{ left: '$', right: '$', display: false, asciimath: true },
|
||||
],
|
||||
},
|
||||
)],
|
||||
});
|
||||
}
|
||||
else {
|
||||
converter = new showdown.Converter({
|
||||
emoji: true,
|
||||
literalMidWordUnderscores: true,
|
||||
parseImgDimensions: true,
|
||||
tables: true,
|
||||
underline: true,
|
||||
simpleLineBreaks: true,
|
||||
strikethrough: true,
|
||||
disableForced4SpacesIndentedSublists: true,
|
||||
extensions: [markdownUnderscoreExt()],
|
||||
});
|
||||
}
|
||||
export function reloadMarkdownProcessor() {
|
||||
converter = new showdown.Converter({
|
||||
emoji: true,
|
||||
literalMidWordUnderscores: true,
|
||||
parseImgDimensions: true,
|
||||
tables: true,
|
||||
underline: true,
|
||||
simpleLineBreaks: true,
|
||||
strikethrough: true,
|
||||
disableForced4SpacesIndentedSublists: true,
|
||||
extensions: [markdownUnderscoreExt()],
|
||||
});
|
||||
|
||||
// Inject the dinkus extension after creating the converter
|
||||
// Maybe move this into power_user init?
|
||||
setTimeout(() => {
|
||||
if (power_user) {
|
||||
converter.addExtension(markdownExclusionExt(), 'exclusion');
|
||||
}
|
||||
}, 1);
|
||||
converter.addExtension(markdownExclusionExt(), 'exclusion');
|
||||
|
||||
return converter;
|
||||
}
|
||||
@ -939,6 +933,9 @@ async function firstLoadInit() {
|
||||
throw new Error('Initialization failed');
|
||||
}
|
||||
|
||||
initLibraryShims();
|
||||
addShowdownPatch(showdown);
|
||||
reloadMarkdownProcessor();
|
||||
applyBrowserFixes();
|
||||
await getClientVersion();
|
||||
await readSecretState();
|
||||
@ -971,6 +968,9 @@ async function firstLoadInit() {
|
||||
initCfg();
|
||||
initLogprobs();
|
||||
initInputMarkdown();
|
||||
initServerHistory();
|
||||
initSettingsSearch();
|
||||
initBulkEdit();
|
||||
await initScrapers();
|
||||
doDailyExtensionUpdatesCheck();
|
||||
await hideLoader();
|
||||
@ -2057,8 +2057,15 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId, san
|
||||
mes = mes.replace(new RegExp(`(^|\n)${escapeRegex(ch_name)}:`, 'g'), '$1');
|
||||
}
|
||||
|
||||
/** @type {any} */
|
||||
const config = { MESSAGE_SANITIZE: true, ADD_TAGS: ['custom-style'], ...sanitizerOverrides };
|
||||
/** @type {import('dompurify').Config & { RETURN_DOM_FRAGMENT: false; RETURN_DOM: false }} */
|
||||
const config = {
|
||||
RETURN_DOM: false,
|
||||
RETURN_DOM_FRAGMENT: false,
|
||||
RETURN_TRUSTED_TYPE: false,
|
||||
MESSAGE_SANITIZE: true,
|
||||
ADD_TAGS: ['custom-style'],
|
||||
...sanitizerOverrides,
|
||||
};
|
||||
mes = encodeStyleTags(mes);
|
||||
mes = DOMPurify.sanitize(mes, config);
|
||||
mes = decodeStyleTags(mes);
|
||||
@ -2117,7 +2124,7 @@ function insertSVGIcon(mes, extra) {
|
||||
mes.find('.timestamp').after(image);
|
||||
}
|
||||
|
||||
await SVGInject(this);
|
||||
await SVGInject(image);
|
||||
};
|
||||
}
|
||||
|
||||
@ -5218,7 +5225,7 @@ async function promptItemize(itemizedPrompts, requestedMesId) {
|
||||
if (priorPromptArrayItemForRawPromptDisplay) {
|
||||
diffPrevPrompt.style.display = '';
|
||||
diffPrevPrompt.addEventListener('click', function () {
|
||||
const dmp = new diff_match_patch();
|
||||
const dmp = new DiffMatchPatch();
|
||||
const text1 = flatten(itemizedPrompts[priorPromptArrayItemForRawPromptDisplay].rawPrompt);
|
||||
const text2 = flatten(itemizedPrompts[PromptArrayItemForRawPromptDisplay].rawPrompt);
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
import { DOMPurify, Popper } from '../lib.js';
|
||||
|
||||
import { event_types, eventSource, is_send_press, main_api, substituteParams } from '../script.js';
|
||||
import { is_group_generating } from './group-chats.js';
|
||||
import { Message, TokenHandler } from './openai.js';
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { DOMPurify, Bowser } from '../lib.js';
|
||||
|
||||
import {
|
||||
characters,
|
||||
online_status,
|
||||
@ -37,7 +39,6 @@ import { getTokenCountAsync } from './tokenizers.js';
|
||||
import { textgen_types, textgenerationwebui_settings as textgen_settings, getTextGenServer } from './textgen-settings.js';
|
||||
import { debounce_timeout } from './constants.js';
|
||||
|
||||
import Bowser from '../lib/bowser.min.js';
|
||||
import { Popup } from './popup.js';
|
||||
|
||||
var RPanelPin = document.getElementById('rm_button_panel_pin');
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Fuse } from '../lib.js';
|
||||
|
||||
import { callPopup, chat_metadata, eventSource, event_types, generateQuietPrompt, getCurrentChatId, getRequestHeaders, getThumbnailUrl, saveSettingsDebounced } from '../script.js';
|
||||
import { saveMetadataDebounced } from './extensions.js';
|
||||
import { SlashCommand } from './slash-commands/SlashCommand.js';
|
||||
|
@ -30,11 +30,6 @@ const toggleBulkEditMode = (isBulkEdit) => {
|
||||
}
|
||||
};
|
||||
|
||||
characterGroupOverlay.addStateChangeCallback((state) => {
|
||||
if (state === BulkEditOverlayState.select) enableBulkEdit();
|
||||
if (state === BulkEditOverlayState.browse) disableBulkEdit();
|
||||
});
|
||||
|
||||
/**
|
||||
* Toggles bulk edit mode on/off when the edit button is clicked.
|
||||
*/
|
||||
@ -117,8 +112,13 @@ function disableBulkSelect() {
|
||||
/**
|
||||
* Entry point that runs on page load.
|
||||
*/
|
||||
jQuery(() => {
|
||||
export function initBulkEdit() {
|
||||
characterGroupOverlay.addStateChangeCallback((state) => {
|
||||
if (state === BulkEditOverlayState.select) enableBulkEdit();
|
||||
if (state === BulkEditOverlayState.browse) disableBulkEdit();
|
||||
});
|
||||
|
||||
$('#bulkEditButton').on('click', onEditButtonClick);
|
||||
$('#bulkSelectAllButton').on('click', onSelectAllButtonClick);
|
||||
$('#bulkDeleteButton').on('click', onDeleteButtonClick);
|
||||
});
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Move chat functions here from script.js (eventually)
|
||||
|
||||
import css from '../lib/css-parser.mjs';
|
||||
import { Popper, css } from '../lib.js';
|
||||
import {
|
||||
addCopyToCodeBlocks,
|
||||
appendMediaToMessage,
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { DOMPurify, Popper } from '../lib.js';
|
||||
|
||||
import { eventSource, event_types, saveSettings, saveSettingsDebounced, getRequestHeaders, animation_duration } from '../script.js';
|
||||
import { showLoader } from './loader.js';
|
||||
import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';
|
||||
|
@ -3,6 +3,7 @@ TODO:
|
||||
*/
|
||||
//const DEBUG_TONY_SAMA_FORK_MODE = true
|
||||
|
||||
import { DOMPurify } from '../../../lib.js';
|
||||
import { getRequestHeaders, processDroppedFiles, eventSource, event_types } from '../../../script.js';
|
||||
import { deleteExtension, extensionNames, getContext, installExtension, renderExtensionTemplateAsync } from '../../extensions.js';
|
||||
import { POPUP_TYPE, Popup, callGenericPopup } from '../../popup.js';
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Fuse } from '../../../lib.js';
|
||||
|
||||
import { event_types, eventSource, main_api, saveSettingsDebounced } from '../../../script.js';
|
||||
import { extension_settings, renderExtensionTemplateAsync } from '../../extensions.js';
|
||||
import { callGenericPopup, Popup, POPUP_RESULT, POPUP_TYPE } from '../../popup.js';
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Fuse } from '../../../lib.js';
|
||||
|
||||
import { callPopup, eventSource, event_types, generateRaw, getRequestHeaders, main_api, online_status, saveSettingsDebounced, substituteParams, substituteParamsExtended, system_message_types } from '../../../script.js';
|
||||
import { dragElement, isMobile } from '../../RossAscends-mods.js';
|
||||
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch, renderExtensionTemplateAsync } from '../../extensions.js';
|
||||
|
@ -1,769 +0,0 @@
|
||||
var DOCUMENT_FRAGMENT_NODE = 11;
|
||||
|
||||
function morphAttrs(fromNode, toNode) {
|
||||
var toNodeAttrs = toNode.attributes;
|
||||
var attr;
|
||||
var attrName;
|
||||
var attrNamespaceURI;
|
||||
var attrValue;
|
||||
var fromValue;
|
||||
|
||||
// document-fragments dont have attributes so lets not do anything
|
||||
if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE || fromNode.nodeType === DOCUMENT_FRAGMENT_NODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// update attributes on original DOM element
|
||||
for (var i = toNodeAttrs.length - 1; i >= 0; i--) {
|
||||
attr = toNodeAttrs[i];
|
||||
attrName = attr.name;
|
||||
attrNamespaceURI = attr.namespaceURI;
|
||||
attrValue = attr.value;
|
||||
|
||||
if (attrNamespaceURI) {
|
||||
attrName = attr.localName || attrName;
|
||||
fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName);
|
||||
|
||||
if (fromValue !== attrValue) {
|
||||
if (attr.prefix === 'xmlns'){
|
||||
attrName = attr.name; // It's not allowed to set an attribute with the XMLNS namespace without specifying the `xmlns` prefix
|
||||
}
|
||||
fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue);
|
||||
}
|
||||
} else {
|
||||
fromValue = fromNode.getAttribute(attrName);
|
||||
|
||||
if (fromValue !== attrValue) {
|
||||
fromNode.setAttribute(attrName, attrValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any extra attributes found on the original DOM element that
|
||||
// weren't found on the target element.
|
||||
var fromNodeAttrs = fromNode.attributes;
|
||||
|
||||
for (var d = fromNodeAttrs.length - 1; d >= 0; d--) {
|
||||
attr = fromNodeAttrs[d];
|
||||
attrName = attr.name;
|
||||
attrNamespaceURI = attr.namespaceURI;
|
||||
|
||||
if (attrNamespaceURI) {
|
||||
attrName = attr.localName || attrName;
|
||||
|
||||
if (!toNode.hasAttributeNS(attrNamespaceURI, attrName)) {
|
||||
fromNode.removeAttributeNS(attrNamespaceURI, attrName);
|
||||
}
|
||||
} else {
|
||||
if (!toNode.hasAttribute(attrName)) {
|
||||
fromNode.removeAttribute(attrName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var range; // Create a range object for efficently rendering strings to elements.
|
||||
var NS_XHTML = 'http://www.w3.org/1999/xhtml';
|
||||
|
||||
var doc = typeof document === 'undefined' ? undefined : document;
|
||||
var HAS_TEMPLATE_SUPPORT = !!doc && 'content' in doc.createElement('template');
|
||||
var HAS_RANGE_SUPPORT = !!doc && doc.createRange && 'createContextualFragment' in doc.createRange();
|
||||
|
||||
function createFragmentFromTemplate(str) {
|
||||
var template = doc.createElement('template');
|
||||
template.innerHTML = str;
|
||||
return template.content.childNodes[0];
|
||||
}
|
||||
|
||||
function createFragmentFromRange(str) {
|
||||
if (!range) {
|
||||
range = doc.createRange();
|
||||
range.selectNode(doc.body);
|
||||
}
|
||||
|
||||
var fragment = range.createContextualFragment(str);
|
||||
return fragment.childNodes[0];
|
||||
}
|
||||
|
||||
function createFragmentFromWrap(str) {
|
||||
var fragment = doc.createElement('body');
|
||||
fragment.innerHTML = str;
|
||||
return fragment.childNodes[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* This is about the same
|
||||
* var html = new DOMParser().parseFromString(str, 'text/html');
|
||||
* return html.body.firstChild;
|
||||
*
|
||||
* @method toElement
|
||||
* @param {String} str
|
||||
*/
|
||||
function toElement(str) {
|
||||
str = str.trim();
|
||||
if (HAS_TEMPLATE_SUPPORT) {
|
||||
// avoid restrictions on content for things like `<tr><th>Hi</th></tr>` which
|
||||
// createContextualFragment doesn't support
|
||||
// <template> support not available in IE
|
||||
return createFragmentFromTemplate(str);
|
||||
} else if (HAS_RANGE_SUPPORT) {
|
||||
return createFragmentFromRange(str);
|
||||
}
|
||||
|
||||
return createFragmentFromWrap(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if two node's names are the same.
|
||||
*
|
||||
* NOTE: We don't bother checking `namespaceURI` because you will never find two HTML elements with the same
|
||||
* nodeName and different namespace URIs.
|
||||
*
|
||||
* @param {Element} a
|
||||
* @param {Element} b The target element
|
||||
* @return {boolean}
|
||||
*/
|
||||
function compareNodeNames(fromEl, toEl) {
|
||||
var fromNodeName = fromEl.nodeName;
|
||||
var toNodeName = toEl.nodeName;
|
||||
var fromCodeStart, toCodeStart;
|
||||
|
||||
if (fromNodeName === toNodeName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
fromCodeStart = fromNodeName.charCodeAt(0);
|
||||
toCodeStart = toNodeName.charCodeAt(0);
|
||||
|
||||
// If the target element is a virtual DOM node or SVG node then we may
|
||||
// need to normalize the tag name before comparing. Normal HTML elements that are
|
||||
// in the "http://www.w3.org/1999/xhtml"
|
||||
// are converted to upper case
|
||||
if (fromCodeStart <= 90 && toCodeStart >= 97) { // from is upper and to is lower
|
||||
return fromNodeName === toNodeName.toUpperCase();
|
||||
} else if (toCodeStart <= 90 && fromCodeStart >= 97) { // to is upper and from is lower
|
||||
return toNodeName === fromNodeName.toUpperCase();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an element, optionally with a known namespace URI.
|
||||
*
|
||||
* @param {string} name the element name, e.g. 'div' or 'svg'
|
||||
* @param {string} [namespaceURI] the element's namespace URI, i.e. the value of
|
||||
* its `xmlns` attribute or its inferred namespace.
|
||||
*
|
||||
* @return {Element}
|
||||
*/
|
||||
function createElementNS(name, namespaceURI) {
|
||||
return !namespaceURI || namespaceURI === NS_XHTML ?
|
||||
doc.createElement(name) :
|
||||
doc.createElementNS(namespaceURI, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the children of one DOM element to another DOM element
|
||||
*/
|
||||
function moveChildren(fromEl, toEl) {
|
||||
var curChild = fromEl.firstChild;
|
||||
while (curChild) {
|
||||
var nextChild = curChild.nextSibling;
|
||||
toEl.appendChild(curChild);
|
||||
curChild = nextChild;
|
||||
}
|
||||
return toEl;
|
||||
}
|
||||
|
||||
function syncBooleanAttrProp(fromEl, toEl, name) {
|
||||
if (fromEl[name] !== toEl[name]) {
|
||||
fromEl[name] = toEl[name];
|
||||
if (fromEl[name]) {
|
||||
fromEl.setAttribute(name, '');
|
||||
} else {
|
||||
fromEl.removeAttribute(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var specialElHandlers = {
|
||||
OPTION: function(fromEl, toEl) {
|
||||
var parentNode = fromEl.parentNode;
|
||||
if (parentNode) {
|
||||
var parentName = parentNode.nodeName.toUpperCase();
|
||||
if (parentName === 'OPTGROUP') {
|
||||
parentNode = parentNode.parentNode;
|
||||
parentName = parentNode && parentNode.nodeName.toUpperCase();
|
||||
}
|
||||
if (parentName === 'SELECT' && !parentNode.hasAttribute('multiple')) {
|
||||
if (fromEl.hasAttribute('selected') && !toEl.selected) {
|
||||
// Workaround for MS Edge bug where the 'selected' attribute can only be
|
||||
// removed if set to a non-empty value:
|
||||
// https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12087679/
|
||||
fromEl.setAttribute('selected', 'selected');
|
||||
fromEl.removeAttribute('selected');
|
||||
}
|
||||
// We have to reset select element's selectedIndex to -1, otherwise setting
|
||||
// fromEl.selected using the syncBooleanAttrProp below has no effect.
|
||||
// The correct selectedIndex will be set in the SELECT special handler below.
|
||||
parentNode.selectedIndex = -1;
|
||||
}
|
||||
}
|
||||
syncBooleanAttrProp(fromEl, toEl, 'selected');
|
||||
},
|
||||
/**
|
||||
* The "value" attribute is special for the <input> element since it sets
|
||||
* the initial value. Changing the "value" attribute without changing the
|
||||
* "value" property will have no effect since it is only used to the set the
|
||||
* initial value. Similar for the "checked" attribute, and "disabled".
|
||||
*/
|
||||
INPUT: function(fromEl, toEl) {
|
||||
syncBooleanAttrProp(fromEl, toEl, 'checked');
|
||||
syncBooleanAttrProp(fromEl, toEl, 'disabled');
|
||||
|
||||
if (fromEl.value !== toEl.value) {
|
||||
fromEl.value = toEl.value;
|
||||
}
|
||||
|
||||
if (!toEl.hasAttribute('value')) {
|
||||
fromEl.removeAttribute('value');
|
||||
}
|
||||
},
|
||||
|
||||
TEXTAREA: function(fromEl, toEl) {
|
||||
var newValue = toEl.value;
|
||||
if (fromEl.value !== newValue) {
|
||||
fromEl.value = newValue;
|
||||
}
|
||||
|
||||
var firstChild = fromEl.firstChild;
|
||||
if (firstChild) {
|
||||
// Needed for IE. Apparently IE sets the placeholder as the
|
||||
// node value and vise versa. This ignores an empty update.
|
||||
var oldValue = firstChild.nodeValue;
|
||||
|
||||
if (oldValue == newValue || (!newValue && oldValue == fromEl.placeholder)) {
|
||||
return;
|
||||
}
|
||||
|
||||
firstChild.nodeValue = newValue;
|
||||
}
|
||||
},
|
||||
SELECT: function(fromEl, toEl) {
|
||||
if (!toEl.hasAttribute('multiple')) {
|
||||
var selectedIndex = -1;
|
||||
var i = 0;
|
||||
// We have to loop through children of fromEl, not toEl since nodes can be moved
|
||||
// from toEl to fromEl directly when morphing.
|
||||
// At the time this special handler is invoked, all children have already been morphed
|
||||
// and appended to / removed from fromEl, so using fromEl here is safe and correct.
|
||||
var curChild = fromEl.firstChild;
|
||||
var optgroup;
|
||||
var nodeName;
|
||||
while(curChild) {
|
||||
nodeName = curChild.nodeName && curChild.nodeName.toUpperCase();
|
||||
if (nodeName === 'OPTGROUP') {
|
||||
optgroup = curChild;
|
||||
curChild = optgroup.firstChild;
|
||||
} else {
|
||||
if (nodeName === 'OPTION') {
|
||||
if (curChild.hasAttribute('selected')) {
|
||||
selectedIndex = i;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
curChild = curChild.nextSibling;
|
||||
if (!curChild && optgroup) {
|
||||
curChild = optgroup.nextSibling;
|
||||
optgroup = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fromEl.selectedIndex = selectedIndex;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var ELEMENT_NODE = 1;
|
||||
var DOCUMENT_FRAGMENT_NODE$1 = 11;
|
||||
var TEXT_NODE = 3;
|
||||
var COMMENT_NODE = 8;
|
||||
|
||||
function noop() {}
|
||||
|
||||
function defaultGetNodeKey(node) {
|
||||
if (node) {
|
||||
return (node.getAttribute && node.getAttribute('id')) || node.id;
|
||||
}
|
||||
}
|
||||
|
||||
function morphdomFactory(morphAttrs) {
|
||||
|
||||
return function morphdom(fromNode, toNode, options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (typeof toNode === 'string') {
|
||||
if (fromNode.nodeName === '#document' || fromNode.nodeName === 'HTML' || fromNode.nodeName === 'BODY') {
|
||||
var toNodeHtml = toNode;
|
||||
toNode = doc.createElement('html');
|
||||
toNode.innerHTML = toNodeHtml;
|
||||
} else {
|
||||
toNode = toElement(toNode);
|
||||
}
|
||||
} else if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE$1) {
|
||||
toNode = toNode.firstElementChild;
|
||||
}
|
||||
|
||||
var getNodeKey = options.getNodeKey || defaultGetNodeKey;
|
||||
var onBeforeNodeAdded = options.onBeforeNodeAdded || noop;
|
||||
var onNodeAdded = options.onNodeAdded || noop;
|
||||
var onBeforeElUpdated = options.onBeforeElUpdated || noop;
|
||||
var onElUpdated = options.onElUpdated || noop;
|
||||
var onBeforeNodeDiscarded = options.onBeforeNodeDiscarded || noop;
|
||||
var onNodeDiscarded = options.onNodeDiscarded || noop;
|
||||
var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop;
|
||||
var skipFromChildren = options.skipFromChildren || noop;
|
||||
var addChild = options.addChild || function(parent, child){ return parent.appendChild(child); };
|
||||
var childrenOnly = options.childrenOnly === true;
|
||||
|
||||
// This object is used as a lookup to quickly find all keyed elements in the original DOM tree.
|
||||
var fromNodesLookup = Object.create(null);
|
||||
var keyedRemovalList = [];
|
||||
|
||||
function addKeyedRemoval(key) {
|
||||
keyedRemovalList.push(key);
|
||||
}
|
||||
|
||||
function walkDiscardedChildNodes(node, skipKeyedNodes) {
|
||||
if (node.nodeType === ELEMENT_NODE) {
|
||||
var curChild = node.firstChild;
|
||||
while (curChild) {
|
||||
|
||||
var key = undefined;
|
||||
|
||||
if (skipKeyedNodes && (key = getNodeKey(curChild))) {
|
||||
// If we are skipping keyed nodes then we add the key
|
||||
// to a list so that it can be handled at the very end.
|
||||
addKeyedRemoval(key);
|
||||
} else {
|
||||
// Only report the node as discarded if it is not keyed. We do this because
|
||||
// at the end we loop through all keyed elements that were unmatched
|
||||
// and then discard them in one final pass.
|
||||
onNodeDiscarded(curChild);
|
||||
if (curChild.firstChild) {
|
||||
walkDiscardedChildNodes(curChild, skipKeyedNodes);
|
||||
}
|
||||
}
|
||||
|
||||
curChild = curChild.nextSibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a DOM node out of the original DOM
|
||||
*
|
||||
* @param {Node} node The node to remove
|
||||
* @param {Node} parentNode The nodes parent
|
||||
* @param {Boolean} skipKeyedNodes If true then elements with keys will be skipped and not discarded.
|
||||
* @return {undefined}
|
||||
*/
|
||||
function removeNode(node, parentNode, skipKeyedNodes) {
|
||||
if (onBeforeNodeDiscarded(node) === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (parentNode) {
|
||||
parentNode.removeChild(node);
|
||||
}
|
||||
|
||||
onNodeDiscarded(node);
|
||||
walkDiscardedChildNodes(node, skipKeyedNodes);
|
||||
}
|
||||
|
||||
// // TreeWalker implementation is no faster, but keeping this around in case this changes in the future
|
||||
// function indexTree(root) {
|
||||
// var treeWalker = document.createTreeWalker(
|
||||
// root,
|
||||
// NodeFilter.SHOW_ELEMENT);
|
||||
//
|
||||
// var el;
|
||||
// while((el = treeWalker.nextNode())) {
|
||||
// var key = getNodeKey(el);
|
||||
// if (key) {
|
||||
// fromNodesLookup[key] = el;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // NodeIterator implementation is no faster, but keeping this around in case this changes in the future
|
||||
//
|
||||
// function indexTree(node) {
|
||||
// var nodeIterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT);
|
||||
// var el;
|
||||
// while((el = nodeIterator.nextNode())) {
|
||||
// var key = getNodeKey(el);
|
||||
// if (key) {
|
||||
// fromNodesLookup[key] = el;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
function indexTree(node) {
|
||||
if (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE$1) {
|
||||
var curChild = node.firstChild;
|
||||
while (curChild) {
|
||||
var key = getNodeKey(curChild);
|
||||
if (key) {
|
||||
fromNodesLookup[key] = curChild;
|
||||
}
|
||||
|
||||
// Walk recursively
|
||||
indexTree(curChild);
|
||||
|
||||
curChild = curChild.nextSibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
indexTree(fromNode);
|
||||
|
||||
function handleNodeAdded(el) {
|
||||
onNodeAdded(el);
|
||||
|
||||
var curChild = el.firstChild;
|
||||
while (curChild) {
|
||||
var nextSibling = curChild.nextSibling;
|
||||
|
||||
var key = getNodeKey(curChild);
|
||||
if (key) {
|
||||
var unmatchedFromEl = fromNodesLookup[key];
|
||||
// if we find a duplicate #id node in cache, replace `el` with cache value
|
||||
// and morph it to the child node.
|
||||
if (unmatchedFromEl && compareNodeNames(curChild, unmatchedFromEl)) {
|
||||
curChild.parentNode.replaceChild(unmatchedFromEl, curChild);
|
||||
morphEl(unmatchedFromEl, curChild);
|
||||
} else {
|
||||
handleNodeAdded(curChild);
|
||||
}
|
||||
} else {
|
||||
// recursively call for curChild and it's children to see if we find something in
|
||||
// fromNodesLookup
|
||||
handleNodeAdded(curChild);
|
||||
}
|
||||
|
||||
curChild = nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
function cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey) {
|
||||
// We have processed all of the "to nodes". If curFromNodeChild is
|
||||
// non-null then we still have some from nodes left over that need
|
||||
// to be removed
|
||||
while (curFromNodeChild) {
|
||||
var fromNextSibling = curFromNodeChild.nextSibling;
|
||||
if ((curFromNodeKey = getNodeKey(curFromNodeChild))) {
|
||||
// Since the node is keyed it might be matched up later so we defer
|
||||
// the actual removal to later
|
||||
addKeyedRemoval(curFromNodeKey);
|
||||
} else {
|
||||
// NOTE: we skip nested keyed nodes from being removed since there is
|
||||
// still a chance they will be matched up later
|
||||
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
|
||||
}
|
||||
curFromNodeChild = fromNextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
function morphEl(fromEl, toEl, childrenOnly) {
|
||||
var toElKey = getNodeKey(toEl);
|
||||
|
||||
if (toElKey) {
|
||||
// If an element with an ID is being morphed then it will be in the final
|
||||
// DOM so clear it out of the saved elements collection
|
||||
delete fromNodesLookup[toElKey];
|
||||
}
|
||||
|
||||
if (!childrenOnly) {
|
||||
// optional
|
||||
var beforeUpdateResult = onBeforeElUpdated(fromEl, toEl);
|
||||
if (beforeUpdateResult === false) {
|
||||
return;
|
||||
} else if (beforeUpdateResult instanceof HTMLElement) {
|
||||
fromEl = beforeUpdateResult;
|
||||
// reindex the new fromEl in case it's not in the same
|
||||
// tree as the original fromEl
|
||||
// (Phoenix LiveView sometimes returns a cloned tree,
|
||||
// but keyed lookups would still point to the original tree)
|
||||
indexTree(fromEl);
|
||||
}
|
||||
|
||||
// update attributes on original DOM element first
|
||||
morphAttrs(fromEl, toEl);
|
||||
// optional
|
||||
onElUpdated(fromEl);
|
||||
|
||||
if (onBeforeElChildrenUpdated(fromEl, toEl) === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fromEl.nodeName !== 'TEXTAREA') {
|
||||
morphChildren(fromEl, toEl);
|
||||
} else {
|
||||
specialElHandlers.TEXTAREA(fromEl, toEl);
|
||||
}
|
||||
}
|
||||
|
||||
function morphChildren(fromEl, toEl) {
|
||||
var skipFrom = skipFromChildren(fromEl, toEl);
|
||||
var curToNodeChild = toEl.firstChild;
|
||||
var curFromNodeChild = fromEl.firstChild;
|
||||
var curToNodeKey;
|
||||
var curFromNodeKey;
|
||||
|
||||
var fromNextSibling;
|
||||
var toNextSibling;
|
||||
var matchingFromEl;
|
||||
|
||||
// walk the children
|
||||
outer: while (curToNodeChild) {
|
||||
toNextSibling = curToNodeChild.nextSibling;
|
||||
curToNodeKey = getNodeKey(curToNodeChild);
|
||||
|
||||
// walk the fromNode children all the way through
|
||||
while (!skipFrom && curFromNodeChild) {
|
||||
fromNextSibling = curFromNodeChild.nextSibling;
|
||||
|
||||
if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) {
|
||||
curToNodeChild = toNextSibling;
|
||||
curFromNodeChild = fromNextSibling;
|
||||
continue outer;
|
||||
}
|
||||
|
||||
curFromNodeKey = getNodeKey(curFromNodeChild);
|
||||
|
||||
var curFromNodeType = curFromNodeChild.nodeType;
|
||||
|
||||
// this means if the curFromNodeChild doesnt have a match with the curToNodeChild
|
||||
var isCompatible = undefined;
|
||||
|
||||
if (curFromNodeType === curToNodeChild.nodeType) {
|
||||
if (curFromNodeType === ELEMENT_NODE) {
|
||||
// Both nodes being compared are Element nodes
|
||||
|
||||
if (curToNodeKey) {
|
||||
// The target node has a key so we want to match it up with the correct element
|
||||
// in the original DOM tree
|
||||
if (curToNodeKey !== curFromNodeKey) {
|
||||
// The current element in the original DOM tree does not have a matching key so
|
||||
// let's check our lookup to see if there is a matching element in the original
|
||||
// DOM tree
|
||||
if ((matchingFromEl = fromNodesLookup[curToNodeKey])) {
|
||||
if (fromNextSibling === matchingFromEl) {
|
||||
// Special case for single element removals. To avoid removing the original
|
||||
// DOM node out of the tree (since that can break CSS transitions, etc.),
|
||||
// we will instead discard the current node and wait until the next
|
||||
// iteration to properly match up the keyed target element with its matching
|
||||
// element in the original tree
|
||||
isCompatible = false;
|
||||
} else {
|
||||
// We found a matching keyed element somewhere in the original DOM tree.
|
||||
// Let's move the original DOM node into the current position and morph
|
||||
// it.
|
||||
|
||||
// NOTE: We use insertBefore instead of replaceChild because we want to go through
|
||||
// the `removeNode()` function for the node that is being discarded so that
|
||||
// all lifecycle hooks are correctly invoked
|
||||
fromEl.insertBefore(matchingFromEl, curFromNodeChild);
|
||||
|
||||
// fromNextSibling = curFromNodeChild.nextSibling;
|
||||
|
||||
if (curFromNodeKey) {
|
||||
// Since the node is keyed it might be matched up later so we defer
|
||||
// the actual removal to later
|
||||
addKeyedRemoval(curFromNodeKey);
|
||||
} else {
|
||||
// NOTE: we skip nested keyed nodes from being removed since there is
|
||||
// still a chance they will be matched up later
|
||||
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
|
||||
}
|
||||
|
||||
curFromNodeChild = matchingFromEl;
|
||||
curFromNodeKey = getNodeKey(curFromNodeChild);
|
||||
}
|
||||
} else {
|
||||
// The nodes are not compatible since the "to" node has a key and there
|
||||
// is no matching keyed node in the source tree
|
||||
isCompatible = false;
|
||||
}
|
||||
}
|
||||
} else if (curFromNodeKey) {
|
||||
// The original has a key
|
||||
isCompatible = false;
|
||||
}
|
||||
|
||||
isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild);
|
||||
if (isCompatible) {
|
||||
// We found compatible DOM elements so transform
|
||||
// the current "from" node to match the current
|
||||
// target DOM node.
|
||||
// MORPH
|
||||
morphEl(curFromNodeChild, curToNodeChild);
|
||||
}
|
||||
|
||||
} else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) {
|
||||
// Both nodes being compared are Text or Comment nodes
|
||||
isCompatible = true;
|
||||
// Simply update nodeValue on the original node to
|
||||
// change the text value
|
||||
if (curFromNodeChild.nodeValue !== curToNodeChild.nodeValue) {
|
||||
curFromNodeChild.nodeValue = curToNodeChild.nodeValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (isCompatible) {
|
||||
// Advance both the "to" child and the "from" child since we found a match
|
||||
// Nothing else to do as we already recursively called morphChildren above
|
||||
curToNodeChild = toNextSibling;
|
||||
curFromNodeChild = fromNextSibling;
|
||||
continue outer;
|
||||
}
|
||||
|
||||
// No compatible match so remove the old node from the DOM and continue trying to find a
|
||||
// match in the original DOM. However, we only do this if the from node is not keyed
|
||||
// since it is possible that a keyed node might match up with a node somewhere else in the
|
||||
// target tree and we don't want to discard it just yet since it still might find a
|
||||
// home in the final DOM tree. After everything is done we will remove any keyed nodes
|
||||
// that didn't find a home
|
||||
if (curFromNodeKey) {
|
||||
// Since the node is keyed it might be matched up later so we defer
|
||||
// the actual removal to later
|
||||
addKeyedRemoval(curFromNodeKey);
|
||||
} else {
|
||||
// NOTE: we skip nested keyed nodes from being removed since there is
|
||||
// still a chance they will be matched up later
|
||||
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
|
||||
}
|
||||
|
||||
curFromNodeChild = fromNextSibling;
|
||||
} // END: while(curFromNodeChild) {}
|
||||
|
||||
// If we got this far then we did not find a candidate match for
|
||||
// our "to node" and we exhausted all of the children "from"
|
||||
// nodes. Therefore, we will just append the current "to" node
|
||||
// to the end
|
||||
if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) {
|
||||
// MORPH
|
||||
if(!skipFrom){ addChild(fromEl, matchingFromEl); }
|
||||
morphEl(matchingFromEl, curToNodeChild);
|
||||
} else {
|
||||
var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild);
|
||||
if (onBeforeNodeAddedResult !== false) {
|
||||
if (onBeforeNodeAddedResult) {
|
||||
curToNodeChild = onBeforeNodeAddedResult;
|
||||
}
|
||||
|
||||
if (curToNodeChild.actualize) {
|
||||
curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc);
|
||||
}
|
||||
addChild(fromEl, curToNodeChild);
|
||||
handleNodeAdded(curToNodeChild);
|
||||
}
|
||||
}
|
||||
|
||||
curToNodeChild = toNextSibling;
|
||||
curFromNodeChild = fromNextSibling;
|
||||
}
|
||||
|
||||
cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey);
|
||||
|
||||
var specialElHandler = specialElHandlers[fromEl.nodeName];
|
||||
if (specialElHandler) {
|
||||
specialElHandler(fromEl, toEl);
|
||||
}
|
||||
} // END: morphChildren(...)
|
||||
|
||||
var morphedNode = fromNode;
|
||||
var morphedNodeType = morphedNode.nodeType;
|
||||
var toNodeType = toNode.nodeType;
|
||||
|
||||
if (!childrenOnly) {
|
||||
// Handle the case where we are given two DOM nodes that are not
|
||||
// compatible (e.g. <div> --> <span> or <div> --> TEXT)
|
||||
if (morphedNodeType === ELEMENT_NODE) {
|
||||
if (toNodeType === ELEMENT_NODE) {
|
||||
if (!compareNodeNames(fromNode, toNode)) {
|
||||
onNodeDiscarded(fromNode);
|
||||
morphedNode = moveChildren(fromNode, createElementNS(toNode.nodeName, toNode.namespaceURI));
|
||||
}
|
||||
} else {
|
||||
// Going from an element node to a text node
|
||||
morphedNode = toNode;
|
||||
}
|
||||
} else if (morphedNodeType === TEXT_NODE || morphedNodeType === COMMENT_NODE) { // Text or comment node
|
||||
if (toNodeType === morphedNodeType) {
|
||||
if (morphedNode.nodeValue !== toNode.nodeValue) {
|
||||
morphedNode.nodeValue = toNode.nodeValue;
|
||||
}
|
||||
|
||||
return morphedNode;
|
||||
} else {
|
||||
// Text node to something else
|
||||
morphedNode = toNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (morphedNode === toNode) {
|
||||
// The "to node" was not compatible with the "from node" so we had to
|
||||
// toss out the "from node" and use the "to node"
|
||||
onNodeDiscarded(fromNode);
|
||||
} else {
|
||||
if (toNode.isSameNode && toNode.isSameNode(morphedNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
morphEl(morphedNode, toNode, childrenOnly);
|
||||
|
||||
// We now need to loop over any keyed nodes that might need to be
|
||||
// removed. We only do the removal if we know that the keyed node
|
||||
// never found a match. When a keyed node is matched up we remove
|
||||
// it out of fromNodesLookup and we use fromNodesLookup to determine
|
||||
// if a keyed node has been matched up or not
|
||||
if (keyedRemovalList) {
|
||||
for (var i=0, len=keyedRemovalList.length; i<len; i++) {
|
||||
var elToRemove = fromNodesLookup[keyedRemovalList[i]];
|
||||
if (elToRemove) {
|
||||
removeNode(elToRemove, elToRemove.parentNode, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!childrenOnly && morphedNode !== fromNode && fromNode.parentNode) {
|
||||
if (morphedNode.actualize) {
|
||||
morphedNode = morphedNode.actualize(fromNode.ownerDocument || doc);
|
||||
}
|
||||
// If we had to swap out the from node with a new node because the old
|
||||
// node was not compatible with the target node then we need to
|
||||
// replace the old DOM node in the original DOM tree. This is only
|
||||
// possible if the original DOM node was part of a DOM tree which
|
||||
// we know is the case if it has a parent node.
|
||||
fromNode.parentNode.replaceChild(morphedNode, fromNode);
|
||||
}
|
||||
|
||||
return morphedNode;
|
||||
};
|
||||
}
|
||||
|
||||
var morphdom = morphdomFactory(morphAttrs);
|
||||
|
||||
export default morphdom;
|
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Patrick Steele-Idem <pnidem@gmail.com> (psteeleidem.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
@ -1,3 +1,4 @@
|
||||
import { hljs, morphdom } from '../../../../lib.js';
|
||||
import { POPUP_RESULT, POPUP_TYPE, Popup } from '../../../popup.js';
|
||||
import { setSlashCommandAutoComplete } from '../../../slash-commands.js';
|
||||
import { SlashCommandAbortController } from '../../../slash-commands/SlashCommandAbortController.js';
|
||||
@ -11,7 +12,6 @@ import { SlashCommandParserError } from '../../../slash-commands/SlashCommandPar
|
||||
import { SlashCommandScope } from '../../../slash-commands/SlashCommandScope.js';
|
||||
import { debounce, delay, getSortableDelay, showFontAwesomePicker } from '../../../utils.js';
|
||||
import { log, quickReplyApi, warn } from '../index.js';
|
||||
import morphdom from '../lib/morphdom-esm.js';
|
||||
import { QuickReplyContextLink } from './QuickReplyContextLink.js';
|
||||
import { QuickReplySet } from './QuickReplySet.js';
|
||||
import { ContextMenu } from './ui/ctx/ContextMenu.js';
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Popper } from '../../../lib.js';
|
||||
import {
|
||||
saveSettingsDebounced,
|
||||
systemUserName,
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Fuse } from '../lib.js';
|
||||
|
||||
import {
|
||||
shuffle,
|
||||
onlyUnique,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { moment } from '../lib.js';
|
||||
import { registerDebugFunction } from './power-user.js';
|
||||
import { updateSecretDisplay } from './secrets.js';
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Handlebars, moment, seedrandom, droll } from '../lib.js';
|
||||
import { chat, chat_metadata, main_api, getMaxContextSize, getCurrentChatId, substituteParams } from '../script.js';
|
||||
import { timestampToMoment, isDigitsOnly, getStringHash, escapeRegex, uuidv4 } from './utils.js';
|
||||
import { textgenerationwebui_banned_in_macros } from './textgen-settings.js';
|
||||
@ -329,7 +330,7 @@ function randomReplace(input, emptyListPlaceholder = '') {
|
||||
if (list.length === 0) {
|
||||
return emptyListPlaceholder;
|
||||
}
|
||||
const rng = new Math.seedrandom('added entropy.', { entropy: true });
|
||||
const rng = seedrandom('added entropy.', { entropy: true });
|
||||
const randomIndex = Math.floor(rng() * list.length);
|
||||
return list[randomIndex];
|
||||
});
|
||||
@ -359,7 +360,8 @@ function pickReplace(input, rawContent, emptyListPlaceholder = '') {
|
||||
// This allows us to get unique but repeatable picks in nearly all cases
|
||||
const combinedSeedString = `${chatIdHash}-${rawContentHash}-${offset}`;
|
||||
const finalSeed = getStringHash(combinedSeedString);
|
||||
const rng = new Math.seedrandom(finalSeed);
|
||||
// @ts-ignore - have to use numbers for legacy picks
|
||||
const rng = seedrandom(finalSeed);
|
||||
const randomIndex = Math.floor(rng() * list.length);
|
||||
return list[randomIndex];
|
||||
});
|
||||
|
@ -3,6 +3,7 @@
|
||||
* By CncAnon (@CncAnon1)
|
||||
* https://github.com/CncAnon1/TavernAITurbo
|
||||
*/
|
||||
import { Fuse, DOMPurify } from '../lib.js';
|
||||
|
||||
import {
|
||||
abortStatusCheck,
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Fuse, Handlebars } from '../lib.js';
|
||||
|
||||
import {
|
||||
saveSettingsDebounced,
|
||||
scrollChatToBottom,
|
||||
@ -178,7 +180,6 @@ let power_user = {
|
||||
console_log_prompts: false,
|
||||
request_token_probabilities: false,
|
||||
show_group_chat_queue: false,
|
||||
render_formulas: false,
|
||||
allow_name1_display: false,
|
||||
allow_name2_display: false,
|
||||
hotswap_enabled: true,
|
||||
@ -1486,7 +1487,6 @@ async function loadPowerUserSettings(settings, data) {
|
||||
$('#collapse-newlines-checkbox').prop('checked', power_user.collapse_newlines);
|
||||
$('#always-force-name2-checkbox').prop('checked', power_user.always_force_name2);
|
||||
$('#trim_sentences_checkbox').prop('checked', power_user.trim_sentences);
|
||||
$('#render_formulas').prop('checked', power_user.render_formulas);
|
||||
$('#disable_group_trimming').prop('checked', power_user.disable_group_trimming);
|
||||
$('#markdown_escape_strings').val(power_user.markdown_escape_strings);
|
||||
$('#fast_ui_mode').prop('checked', power_user.fast_ui_mode);
|
||||
@ -1593,7 +1593,7 @@ async function loadPowerUserSettings(settings, data) {
|
||||
$(`#character_sort_order option[data-order="${power_user.sort_order}"][data-field="${power_user.sort_field}"]`).prop('selected', true);
|
||||
switchReducedMotion();
|
||||
switchCompactInputArea();
|
||||
reloadMarkdownProcessor(power_user.render_formulas);
|
||||
reloadMarkdownProcessor();
|
||||
await loadInstructMode(data);
|
||||
await loadContextSettings();
|
||||
await loadSystemPrompts(data);
|
||||
@ -1823,7 +1823,7 @@ async function loadContextSettings() {
|
||||
/**
|
||||
* Fuzzy search characters by a search term
|
||||
* @param {string} searchValue - The search term
|
||||
* @returns {FuseResult[]} Results as items with their score
|
||||
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
||||
*/
|
||||
export function fuzzySearchCharacters(searchValue) {
|
||||
// @ts-ignore
|
||||
@ -1856,7 +1856,7 @@ export function fuzzySearchCharacters(searchValue) {
|
||||
* Fuzzy search world info entries by a search term
|
||||
* @param {*[]} data - WI items data array
|
||||
* @param {string} searchValue - The search term
|
||||
* @returns {FuseResult[]} Results as items with their score
|
||||
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
||||
*/
|
||||
export function fuzzySearchWorldInfo(data, searchValue) {
|
||||
// @ts-ignore
|
||||
@ -1885,7 +1885,7 @@ export function fuzzySearchWorldInfo(data, searchValue) {
|
||||
* Fuzzy search persona entries by a search term
|
||||
* @param {*[]} data - persona data array
|
||||
* @param {string} searchValue - The search term
|
||||
* @returns {FuseResult[]} Results as items with their score
|
||||
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
||||
*/
|
||||
export function fuzzySearchPersonas(data, searchValue) {
|
||||
data = data.map(x => ({ key: x, name: power_user.personas[x] ?? '', description: power_user.persona_descriptions[x]?.description ?? '' }));
|
||||
@ -1909,7 +1909,7 @@ export function fuzzySearchPersonas(data, searchValue) {
|
||||
/**
|
||||
* Fuzzy search tags by a search term
|
||||
* @param {string} searchValue - The search term
|
||||
* @returns {FuseResult[]} Results as items with their score
|
||||
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
||||
*/
|
||||
export function fuzzySearchTags(searchValue) {
|
||||
// @ts-ignore
|
||||
@ -1931,7 +1931,7 @@ export function fuzzySearchTags(searchValue) {
|
||||
/**
|
||||
* Fuzzy search groups by a search term
|
||||
* @param {string} searchValue - The search term
|
||||
* @returns {FuseResult[]} Results as items with their score
|
||||
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
||||
*/
|
||||
export function fuzzySearchGroups(searchValue) {
|
||||
// @ts-ignore
|
||||
@ -3065,7 +3065,7 @@ $(document).ready(() => {
|
||||
$('#markdown_escape_strings').on('input', function () {
|
||||
power_user.markdown_escape_strings = String($(this).val());
|
||||
saveSettingsDebounced();
|
||||
reloadMarkdownProcessor(power_user.render_formulas);
|
||||
reloadMarkdownProcessor();
|
||||
});
|
||||
|
||||
$('#start_reply_with').on('input', function () {
|
||||
@ -3417,13 +3417,6 @@ $(document).ready(() => {
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#render_formulas').on('input', function () {
|
||||
power_user.render_formulas = !!$(this).prop('checked');
|
||||
reloadMarkdownProcessor(power_user.render_formulas);
|
||||
reloadCurrentChat();
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#reload_chat').on('click', async function () {
|
||||
const currentChatId = getCurrentChatId();
|
||||
if (currentChatId !== undefined && currentChatId !== null) {
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Fuse } from '../lib.js';
|
||||
|
||||
import {
|
||||
amount_gen,
|
||||
characters,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { DOMPurify } from '../lib.js';
|
||||
import { callPopup, getRequestHeaders } from '../script.js';
|
||||
|
||||
export const SECRET_KEYS = {
|
||||
|
@ -80,7 +80,7 @@ function onServerConnectClick() {
|
||||
});
|
||||
}
|
||||
|
||||
jQuery(function () {
|
||||
export function initServerHistory() {
|
||||
$('[data-server-history]').each(createServerAutocomplete);
|
||||
$(document).on('click', '[data-server-connect]', onServerConnectClick);
|
||||
});
|
||||
}
|
||||
|
@ -49,6 +49,6 @@ function removeHighlighting() {
|
||||
$('.highlighted').removeClass('highlighted'); // Remove CSS class from previously highlighted elements
|
||||
}
|
||||
|
||||
jQuery(() => {
|
||||
export function initSettingsSearch() {
|
||||
$('#settingsSearch').on('input change', searchSettings);
|
||||
});
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Fuse, DOMPurify } from '../lib.js';
|
||||
|
||||
import {
|
||||
Generate,
|
||||
UNIQUE_APIS,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { hljs } from '../../lib.js';
|
||||
import { SlashCommandAbortController } from './SlashCommandAbortController.js';
|
||||
import { SlashCommandArgument, SlashCommandNamedArgument } from './SlashCommandArgument.js';
|
||||
import { SlashCommandClosure } from './SlashCommandClosure.js';
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { hljs } from '../../lib.js';
|
||||
import { power_user } from '../power-user.js';
|
||||
import { isTrueBoolean, uuidv4 } from '../utils.js';
|
||||
import { SlashCommand } from './SlashCommand.js';
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { DOMPurify, showdown } from '../../lib.js';
|
||||
import { sendSystemMessage, system_message_types } from '../../script.js';
|
||||
import { callGenericPopup, POPUP_TYPE } from '../popup.js';
|
||||
import { escapeHtml } from '../utils.js';
|
||||
|
@ -1,4 +1,5 @@
|
||||
// statsHelper.js
|
||||
import { moment } from '../lib.js';
|
||||
import { getRequestHeaders, callPopup, characters, this_chid } from '../script.js';
|
||||
import { humanizeGenTime } from './RossAscends-mods.js';
|
||||
import { registerDebugFunction } from './power-user.js';
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Fuse } from '../lib.js';
|
||||
|
||||
import { saveSettingsDebounced } from '../script.js';
|
||||
import { callGenericPopup, POPUP_TYPE } from './popup.js';
|
||||
import { power_user } from './power-user.js';
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { DOMPurify } from '../lib.js';
|
||||
|
||||
import {
|
||||
characters,
|
||||
saveSettingsDebounced,
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { DOMPurify, Handlebars } from '../lib.js';
|
||||
import { applyLocale } from './i18n.js';
|
||||
|
||||
/**
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { DOMPurify } from '../lib.js';
|
||||
import { isMobile } from './RossAscends-mods.js';
|
||||
import { amount_gen, callPopup, eventSource, event_types, getRequestHeaders, max_context, online_status, setGenerationParamsFromPreset } from '../script.js';
|
||||
import { textgenerationwebui_settings as textgen_settings, textgen_types } from './textgen-settings.js';
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { localforage } from '../lib.js';
|
||||
import { characters, main_api, api_server, nai_settings, online_status, this_chid } from '../script.js';
|
||||
import { power_user, registerDebugFunction } from './power-user.js';
|
||||
import { chat_completion_sources, model_list, oai_settings } from './openai.js';
|
||||
@ -135,7 +136,7 @@ const TOKENIZER_URLS = {
|
||||
},
|
||||
};
|
||||
|
||||
const objectStore = new localforage.createInstance({ name: 'SillyTavern_ChatCompletions' });
|
||||
const objectStore = localforage.createInstance({ name: 'SillyTavern_ChatCompletions' });
|
||||
|
||||
let tokenCache = {};
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { DOMPurify } from '../lib.js';
|
||||
|
||||
import { addOneMessage, chat, event_types, eventSource, main_api, saveChatConditional, system_avatar, systemUserName } from '../script.js';
|
||||
import { chat_completion_sources, oai_settings } from './openai.js';
|
||||
import { Popup } from './popup.js';
|
||||
|
30
public/scripts/util/showdown-patch.js
Normal file
30
public/scripts/util/showdown-patch.js
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Patches showdown to unrestrictedly unhash HTML spans.
|
||||
* @param {import('showdown')} showdown The showdown object to patch
|
||||
*/
|
||||
export function addShowdownPatch(showdown) {
|
||||
showdown.subParser('unhashHTMLSpans', function (text, options, globals) {
|
||||
'use strict';
|
||||
text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals);
|
||||
|
||||
for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
|
||||
var repText = globals.gHtmlSpans[i],
|
||||
// limiter to prevent infinite loop (assume 10 as limit for recurse)
|
||||
limit = 0;
|
||||
|
||||
while (/¨C(\d+)C/.test(repText)) {
|
||||
var num = RegExp.$1;
|
||||
repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]);
|
||||
if (limit === 10000) {
|
||||
console.error('maximum nesting of 10000 spans reached!!!');
|
||||
break;
|
||||
}
|
||||
++limit;
|
||||
}
|
||||
text = text.replace('¨C' + i + 'C', repText);
|
||||
}
|
||||
|
||||
text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals);
|
||||
return text;
|
||||
});
|
||||
}
|
@ -1,3 +1,10 @@
|
||||
import {
|
||||
moment,
|
||||
DOMPurify,
|
||||
Readability,
|
||||
isProbablyReaderable,
|
||||
} from '../lib.js';
|
||||
|
||||
import { getContext } from './extensions.js';
|
||||
import { characters, getRequestHeaders, this_chid } from '../script.js';
|
||||
import { isMobile } from './RossAscends-mods.js';
|
||||
@ -803,8 +810,8 @@ export function isOdd(number) {
|
||||
|
||||
/**
|
||||
* Compare two moment objects for sorting.
|
||||
* @param {moment.Moment} a The first moment object.
|
||||
* @param {moment.Moment} b The second moment object.
|
||||
* @param {import('moment').Moment} a The first moment object.
|
||||
* @param {import('moment').Moment} b The second moment object.
|
||||
* @returns {number} A negative number if a is before b, a positive number if a is after b, or 0 if they are equal.
|
||||
*/
|
||||
export function sortMoments(a, b) {
|
||||
@ -823,7 +830,7 @@ const dateCache = new Map();
|
||||
* Cached version of moment() to avoid re-parsing the same date strings.
|
||||
* Important: Moment objects are mutable, so use clone() before modifying them!
|
||||
* @param {string|number} timestamp String or number representing a date.
|
||||
* @returns {moment.Moment} Moment object
|
||||
* @returns {import('moment').Moment} Moment object
|
||||
*/
|
||||
export function timestampToMoment(timestamp) {
|
||||
if (dateCache.has(timestamp)) {
|
||||
@ -1523,38 +1530,9 @@ export async function getReadableText(document, textSelector = 'body') {
|
||||
* @returns {Promise<string>} A promise that resolves to the parsed text.
|
||||
*/
|
||||
export async function extractTextFromPDF(blob) {
|
||||
async function initPdfJs() {
|
||||
const promises = [];
|
||||
|
||||
const workerPromise = new Promise((resolve, reject) => {
|
||||
const workerScript = document.createElement('script');
|
||||
workerScript.type = 'module';
|
||||
workerScript.async = true;
|
||||
workerScript.src = 'lib/pdf.worker.mjs';
|
||||
workerScript.onload = resolve;
|
||||
workerScript.onerror = reject;
|
||||
document.head.appendChild(workerScript);
|
||||
});
|
||||
|
||||
promises.push(workerPromise);
|
||||
|
||||
const pdfjsPromise = new Promise((resolve, reject) => {
|
||||
const pdfjsScript = document.createElement('script');
|
||||
pdfjsScript.type = 'module';
|
||||
pdfjsScript.async = true;
|
||||
pdfjsScript.src = 'lib/pdf.mjs';
|
||||
pdfjsScript.onload = resolve;
|
||||
pdfjsScript.onerror = reject;
|
||||
document.head.appendChild(pdfjsScript);
|
||||
});
|
||||
|
||||
promises.push(pdfjsPromise);
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
if (!('pdfjsLib' in window)) {
|
||||
await initPdfJs();
|
||||
await import('../lib/pdf.min.mjs');
|
||||
await import('../lib/pdf.worker.min.mjs');
|
||||
}
|
||||
|
||||
const buffer = await getFileBuffer(blob);
|
||||
@ -1593,30 +1571,9 @@ export async function extractTextFromMarkdown(blob) {
|
||||
}
|
||||
|
||||
export async function extractTextFromEpub(blob) {
|
||||
async function initEpubJs() {
|
||||
const epubScript = new Promise((resolve, reject) => {
|
||||
const epubScript = document.createElement('script');
|
||||
epubScript.async = true;
|
||||
epubScript.src = 'lib/epub.min.js';
|
||||
epubScript.onload = resolve;
|
||||
epubScript.onerror = reject;
|
||||
document.head.appendChild(epubScript);
|
||||
});
|
||||
|
||||
const jszipScript = new Promise((resolve, reject) => {
|
||||
const jszipScript = document.createElement('script');
|
||||
jszipScript.async = true;
|
||||
jszipScript.src = 'lib/jszip.min.js';
|
||||
jszipScript.onload = resolve;
|
||||
jszipScript.onerror = reject;
|
||||
document.head.appendChild(jszipScript);
|
||||
});
|
||||
|
||||
return Promise.all([epubScript, jszipScript]);
|
||||
}
|
||||
|
||||
if (!('ePub' in window)) {
|
||||
await initEpubJs();
|
||||
await import('../lib/jszip.min.js');
|
||||
await import('../lib/epub.min.js');
|
||||
}
|
||||
|
||||
const book = ePub(blob);
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Fuse } from '../lib.js';
|
||||
|
||||
import { saveSettings, callPopup, substituteParams, getRequestHeaders, chat_metadata, this_chid, characters, saveCharacterDebounced, menu_type, eventSource, event_types, getExtensionPromptByName, saveMetadata, getCurrentChatId, extension_prompt_roles } from '../script.js';
|
||||
import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean, setValueByPath, flashHighlight, select2ModifyOptions, getSelect2OptionId, dynamicSelect2DataViaAjax, highlightRegex, select2ChoiceClickSubscribe, isFalseBoolean, getSanitizedFilename, checkOverwriteExistingData, getStringHash, parseStringArray, cancelDebounce } from './utils.js';
|
||||
import { extension_settings, getContext } from './extensions.js';
|
||||
|
13
server.js
13
server.js
@ -37,7 +37,7 @@ util.inspect.defaultOptions.maxStringLength = null;
|
||||
util.inspect.defaultOptions.depth = 4;
|
||||
|
||||
// local library imports
|
||||
import{ loadPlugins } from './src/plugin-loader.js';
|
||||
import { loadPlugins } from './src/plugin-loader.js';
|
||||
import {
|
||||
initUserStorage,
|
||||
getCsrfSecret,
|
||||
@ -54,6 +54,8 @@ import {
|
||||
tryAutoLogin,
|
||||
router as userDataRouter,
|
||||
} from './src/users.js';
|
||||
|
||||
import getWebpackServeMiddleware from './src/middleware/webpack-serve.js';
|
||||
import basicAuthMiddleware from './src/middleware/basicAuth.js';
|
||||
import whitelistMiddleware from './src/middleware/whitelist.js';
|
||||
import multerMonkeyPatch from './src/middleware/multerMonkeyPatch.js';
|
||||
@ -438,6 +440,8 @@ app.get('/login', async (request, response) => {
|
||||
});
|
||||
|
||||
// Host frontend assets
|
||||
const webpackMiddleware = getWebpackServeMiddleware();
|
||||
app.use(webpackMiddleware);
|
||||
app.use(express.static(process.cwd() + '/public', {}));
|
||||
|
||||
// Public API
|
||||
@ -623,6 +627,10 @@ const tavernUrl = new URL(
|
||||
(':' + server_port),
|
||||
);
|
||||
|
||||
function prepareFrontendBundle() {
|
||||
return new Promise((resolve) => webpackMiddleware.waitUntilValid(resolve));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tasks that need to be run before the server starts listening.
|
||||
*/
|
||||
@ -672,6 +680,9 @@ const preSetupTasks = async function () {
|
||||
|
||||
// Add request proxy.
|
||||
initRequestProxy({ enabled: proxyEnabled, url: proxyUrl, bypass: proxyBypass });
|
||||
|
||||
// Wait for frontend libs to compile
|
||||
await prepareFrontendBundle();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,6 @@
|
||||
import express from 'express';
|
||||
import { jsonParser } from '../express-common.js';
|
||||
import { getPipeline, getRawImage } from '../transformers.mjs';
|
||||
import { getPipeline, getRawImage } from '../transformers.js';
|
||||
|
||||
const TASK = 'image-to-text';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import express from 'express';
|
||||
|
||||
import { getPipeline } from '../transformers.mjs';
|
||||
import { getPipeline } from '../transformers.js';
|
||||
import { jsonParser } from '../express-common.js';
|
||||
|
||||
const TASK = 'text-classification';
|
||||
|
@ -2,7 +2,7 @@ import { Buffer } from 'node:buffer';
|
||||
import express from 'express';
|
||||
import wavefile from 'wavefile';
|
||||
import { jsonParser } from '../express-common.js';
|
||||
import { getPipeline } from '../transformers.mjs';
|
||||
import { getPipeline } from '../transformers.js';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
|
@ -82,7 +82,7 @@ async function getPathToTokenizer(model, fallbackModel) {
|
||||
throw new Error('Failed to extract the file name from the URL');
|
||||
}
|
||||
|
||||
const CACHE_PATH = path.join(global.DATA_ROOT, '_cache');
|
||||
const CACHE_PATH = path.join(globalThis.DATA_ROOT, '_cache');
|
||||
if (!fs.existsSync(CACHE_PATH)) {
|
||||
fs.mkdirSync(CACHE_PATH, { recursive: true });
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user