From 4dfd5c093188edc0837a499c2b32c35de51a06c0 Mon Sep 17 00:00:00 2001 From: VectorKappa Date: Tue, 3 Oct 2023 08:10:20 +0200 Subject: [PATCH] vault backup: 2023-10-03 08:10:20 --- .obsidian/app.json | 3 +- .obsidian/plugins/dataview/main.js | 19969 ++++++---------- .obsidian/plugins/dataview/manifest.json | 2 +- .../blacklisted_suggestions.txt | 3 +- .../obsidian-completr/scanned_words.txt | 3 + .obsidian/plugins/obsidian-git/main.js | 2738 ++- .obsidian/plugins/obsidian-git/manifest.json | 2 +- .obsidian/plugins/obsidian-git/styles.css | 5 + .obsidian/workspace.json | 75 +- AMiAL/AMiAL.md | 5 - AMiAL/CS/CS.md | 6 + AMiAL/CS/Ćwiczenia/1 SEM/0..md | 13 + AMiAL/CS/Ćwiczenia/Untitled.md | 3 + .../Pasted image 20221021121924.png | Bin AMiAL/{ => ICT}/!Materiały/calki_1.pdf | Bin AMiAL/{ => ICT}/!Materiały/ciagi_gr.pdf | Bin AMiAL/{ => ICT}/!Materiały/funkcje.pdf | Bin AMiAL/{ => ICT}/!Materiały/li_zesp.pdf | Bin AMiAL/{ => ICT}/!Materiały/li_zesp_odp.pdf | Bin AMiAL/{ => ICT}/!Materiały/poch_zast.pdf | Bin AMiAL/{ => ICT}/!Materiały/pochodna.pdf | Bin .../sylabus_AMiA_Teleinf_2022_23.pdf | Bin AMiAL/{ => ICT}/!Materiały/w0_intro.pdf | Bin AMiAL/{ => ICT}/!Materiały/w1_liczby_zesp.pdf | Bin AMiAL/{ => ICT}/!Materiały/w2_funkcje.pdf | Bin AMiAL/{ => ICT}/!Materiały/w3_metryki.pdf | Bin .../{ => ICT}/!Materiały/w4_granica_ciagu.pdf | Bin .../!Materiały/w5_granica_funkcji.pdf | Bin .../{ => ICT}/Wykłady/1 SEM/20221014083923.md | 0 .../{ => ICT}/Wykłady/1 SEM/20221021083844.md | 0 .../{ => ICT}/Wykłady/1 SEM/20221104082939.md | 0 .../{ => ICT}/Wykłady/1 SEM/20221123083519.md | 0 .../{ => ICT}/Wykłady/1 SEM/20221125083233.md | 0 .../{ => ICT}/Wykłady/1 SEM/20221202082251.md | 0 .../{ => ICT}/Wykłady/1 SEM/20221209083058.md | 0 AMiAL/{ => ICT}/Wykłady/1 SEM/Untitled.md | 0 .../Wykłady/2 SEM/10. Całka niewłaściwa.md | 0 .../Wykłady/2 SEM/Podstawienie Eulera.md | 0 AMiAL/{ => ICT}/Wykłady/Wykłady.md | 0 .../Ćwiczenia/1 SEM/20221014121234.md | 0 .../Ćwiczenia/1 SEM/20221021120444.md | 0 .../Ćwiczenia/1 SEM/20221028120723.md | 0 .../Ćwiczenia/1 SEM/20221118121118.md | 0 .../Ćwiczenia/1 SEM/20221123123903.md | 0 .../Ćwiczenia/1 SEM/20221202121227.md | 0 .../Ćwiczenia/1 SEM/20221209121051.md | 0 .../Ćwiczenia/2 SEM/20230303081617.md | 0 .../Ćwiczenia/Zadania/Całki/Zadanie 1.md | 0 .../Ćwiczenia/Zadania/Całki/Zadanie 2.md | 0 .../Ćwiczenia/Zadania/Całki/Zadanie 5.md | 0 .../Ćwiczenia/Zadania/Całki_Zast/Zadanie 2.md | 0 .../Ćwiczenia/Zadania/Pochodne/Zadanie 1.md | 0 .../Ćwiczenia/Zadania/Pochodne/Zadanie 2.md | 0 .../Ćwiczenia/Zadania/Różniczki/Zadanie 1.md | 0 .../{ => ICT}/Ćwiczenia/Zadania/Untitled 1.md | 0 AMiAL/{ => ICT}/Ćwiczenia/Zadania/Untitled.md | 0 .../Ćwiczenia/Zadania/ciagi_gr/Zadanie 1.md | 0 .../Ćwiczenia/Zadania/funkcje/Zadanie 1.md | 0 .../Ćwiczenia/Zadania/funkcje/Zadanie 2.md | 0 .../Ćwiczenia/Zadania/li_zesp/Zadanie 1.md | 0 PI/Ćwiczenia/3. Projektowanie rozkazów.md | 6 +- 61 files changed, 9102 insertions(+), 13731 deletions(-) create mode 100644 AMiAL/CS/CS.md create mode 100644 AMiAL/CS/Ćwiczenia/1 SEM/0..md create mode 100644 AMiAL/CS/Ćwiczenia/Untitled.md rename AMiAL/{ => ICT}/!Materiały/Pasted image 20221021121924.png (100%) rename AMiAL/{ => ICT}/!Materiały/calki_1.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/ciagi_gr.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/funkcje.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/li_zesp.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/li_zesp_odp.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/poch_zast.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/pochodna.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/sylabus_AMiA_Teleinf_2022_23.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/w0_intro.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/w1_liczby_zesp.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/w2_funkcje.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/w3_metryki.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/w4_granica_ciagu.pdf (100%) rename AMiAL/{ => ICT}/!Materiały/w5_granica_funkcji.pdf (100%) rename AMiAL/{ => ICT}/Wykłady/1 SEM/20221014083923.md (100%) rename AMiAL/{ => ICT}/Wykłady/1 SEM/20221021083844.md (100%) rename AMiAL/{ => ICT}/Wykłady/1 SEM/20221104082939.md (100%) rename AMiAL/{ => ICT}/Wykłady/1 SEM/20221123083519.md (100%) rename AMiAL/{ => ICT}/Wykłady/1 SEM/20221125083233.md (100%) rename AMiAL/{ => ICT}/Wykłady/1 SEM/20221202082251.md (100%) rename AMiAL/{ => ICT}/Wykłady/1 SEM/20221209083058.md (100%) rename AMiAL/{ => ICT}/Wykłady/1 SEM/Untitled.md (100%) rename AMiAL/{ => ICT}/Wykłady/2 SEM/10. Całka niewłaściwa.md (100%) rename AMiAL/{ => ICT}/Wykłady/2 SEM/Podstawienie Eulera.md (100%) rename AMiAL/{ => ICT}/Wykłady/Wykłady.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/1 SEM/20221014121234.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/1 SEM/20221021120444.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/1 SEM/20221028120723.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/1 SEM/20221118121118.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/1 SEM/20221123123903.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/1 SEM/20221202121227.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/1 SEM/20221209121051.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/2 SEM/20230303081617.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/Całki/Zadanie 1.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/Całki/Zadanie 2.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/Całki/Zadanie 5.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/Całki_Zast/Zadanie 2.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/Pochodne/Zadanie 1.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/Pochodne/Zadanie 2.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/Różniczki/Zadanie 1.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/Untitled 1.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/Untitled.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/ciagi_gr/Zadanie 1.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/funkcje/Zadanie 1.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/funkcje/Zadanie 2.md (100%) rename AMiAL/{ => ICT}/Ćwiczenia/Zadania/li_zesp/Zadanie 1.md (100%) diff --git a/.obsidian/app.json b/.obsidian/app.json index dc93200..8c45038 100644 --- a/.obsidian/app.json +++ b/.obsidian/app.json @@ -10,5 +10,6 @@ "margin": "0", "downscalePercent": 100 }, - "alwaysUpdateLinks": true + "alwaysUpdateLinks": true, + "propertiesInDocument": "source" } \ No newline at end of file diff --git a/.obsidian/plugins/dataview/main.js b/.obsidian/plugins/dataview/main.js index 82a0608..3446133 100644 --- a/.obsidian/plugins/dataview/main.js +++ b/.obsidian/plugins/dataview/main.js @@ -695,7 +695,7 @@ function intlConfigString(localeStr, numberingSystem, outputCalendar) { function mapMonths(f) { const ms = []; for (let i = 1; i <= 12; i++) { - const dt = DateTime.utc(2016, i, 1); + const dt = DateTime.utc(2009, i, 1); ms.push(f(dt)); } return ms; @@ -710,8 +710,8 @@ function mapWeekdays(f) { return ms; } -function listStuff(loc, length, defaultOK, englishFn, intlFn) { - const mode = loc.listingMode(defaultOK); +function listStuff(loc, length, englishFn, intlFn) { + const mode = loc.listingMode(); if (mode === "error") { return null; @@ -772,9 +772,13 @@ class PolyNumberFormatter { class PolyDateFormatter { constructor(dt, intl, opts) { this.opts = opts; + this.originalZone = undefined; let z = undefined; - if (dt.zone.isUniversal) { + if (this.opts.timeZone) { + // Don't apply any workarounds if a timeZone is explicitly provided in opts + this.dt = dt; + } else if (dt.zone.type === "fixed") { // UTC-8 or Etc/UTC-8 are not part of tzdata, only Etc/GMT+8 and the like. // That is why fixed-offset TZ is set to that unless it is: // 1. Representing offset 0 when UTC is used to maintain previous behavior and does not become GMT. @@ -787,25 +791,23 @@ class PolyDateFormatter { z = offsetZ; this.dt = dt; } else { - // Not all fixed-offset zones like Etc/+4:30 are present in tzdata. - // So we have to make do. Two cases: - // 1. The format options tell us to show the zone. We can't do that, so the best - // we can do is format the date in UTC. - // 2. The format options don't tell us to show the zone. Then we can adjust them - // the time and tell the formatter to show it to us in UTC, so that the time is right - // and the bad zone doesn't show up. + // Not all fixed-offset zones like Etc/+4:30 are present in tzdata so + // we manually apply the offset and substitute the zone as needed. z = "UTC"; - if (opts.timeZoneName) { - this.dt = dt; - } else { - this.dt = dt.offset === 0 ? dt : DateTime.fromMillis(dt.ts + dt.offset * 60 * 1000); - } + this.dt = dt.offset === 0 ? dt : dt.setZone("UTC").plus({ minutes: dt.offset }); + this.originalZone = dt.zone; } } else if (dt.zone.type === "system") { this.dt = dt; - } else { + } else if (dt.zone.type === "iana") { this.dt = dt; z = dt.zone.name; + } else { + // Custom zones can have any offset / offsetName so we just manually + // apply the offset and substitute the zone as needed. + z = "UTC"; + this.dt = dt.setZone("UTC").plus({ minutes: dt.offset }); + this.originalZone = dt.zone; } const intlOpts = { ...this.opts }; @@ -814,11 +816,35 @@ class PolyDateFormatter { } format() { + if (this.originalZone) { + // If we have to substitute in the actual zone name, we have to use + // formatToParts so that the timezone can be replaced. + return this.formatToParts() + .map(({ value }) => value) + .join(""); + } return this.dtf.format(this.dt.toJSDate()); } formatToParts() { - return this.dtf.formatToParts(this.dt.toJSDate()); + const parts = this.dtf.formatToParts(this.dt.toJSDate()); + if (this.originalZone) { + return parts.map((part) => { + if (part.type === "timeZoneName") { + const offsetName = this.originalZone.offsetName(this.dt.ts, { + locale: this.dt.locale, + format: this.opts.timeZoneName, + }); + return { + ...part, + value: offsetName, + }; + } else { + return part; + } + }); + } + return parts; } resolvedOptions() { @@ -937,8 +963,8 @@ class Locale { return this.clone({ ...alts, defaultToEN: false }); } - months(length, format = false, defaultOK = true) { - return listStuff(this, length, defaultOK, months, () => { + months(length, format = false) { + return listStuff(this, length, months, () => { const intl = format ? { month: length, day: "numeric" } : { month: length }, formatStr = format ? "format" : "standalone"; if (!this.monthsCache[formatStr][length]) { @@ -948,8 +974,8 @@ class Locale { }); } - weekdays(length, format = false, defaultOK = true) { - return listStuff(this, length, defaultOK, weekdays, () => { + weekdays(length, format = false) { + return listStuff(this, length, weekdays, () => { const intl = format ? { weekday: length, year: "numeric", month: "long", day: "numeric" } : { weekday: length }, @@ -963,11 +989,10 @@ class Locale { }); } - meridiems(defaultOK = true) { + meridiems() { return listStuff( this, undefined, - defaultOK, () => meridiems, () => { // In theory there could be aribitrary day periods. We're gonna assume there are exactly two @@ -984,8 +1009,8 @@ class Locale { ); } - eras(length, defaultOK = true) { - return listStuff(this, length, defaultOK, eras, () => { + eras(length) { + return listStuff(this, length, eras, () => { const intl = { era: length }; // This is problematic. Different calendars are going to define eras totally differently. What I need is the minimum set of dates @@ -1211,7 +1236,7 @@ function normalizeZone(input, defaultZone) { else return FixedOffsetZone.parseSpecifier(lowered) || IANAZone.create(input); } else if (isNumber(input)) { return FixedOffsetZone.instance(input); - } else if (typeof input === "object" && input.offset && typeof input.offset === "number") { + } else if (typeof input === "object" && "offset" in input && typeof input.offset === "function") { // This is dumb, but the instanceof check above doesn't seem to really work // so we're duck checking it return input; @@ -1328,10 +1353,10 @@ class Settings { /** * Set the cutoff year after which a string encoding a year as two digits is interpreted to occur in the current century. * @type {number} - * @example Settings.twoDigitCutoffYear = 0 // cut-off year is 0, so all 'yy' are interpretted as current century + * @example Settings.twoDigitCutoffYear = 0 // cut-off year is 0, so all 'yy' are interpreted as current century * @example Settings.twoDigitCutoffYear = 50 // '49' -> 1949; '50' -> 2050 - * @example Settings.twoDigitCutoffYear = 1950 // interpretted as 50 - * @example Settings.twoDigitCutoffYear = 2050 // ALSO interpretted as 50 + * @example Settings.twoDigitCutoffYear = 1950 // interpreted as 50 + * @example Settings.twoDigitCutoffYear = 2050 // ALSO interpreted as 50 */ static set twoDigitCutoffYear(cutoffYear) { twoDigitCutoffYear = cutoffYear % 100; @@ -1513,7 +1538,7 @@ function daysInMonth(year, month) { } } -// covert a calendar object to a local timestamp (epoch, but with the offset baked in) +// convert a calendar object to a local timestamp (epoch, but with the offset baked in) function objToLocalTS(obj) { let d = Date.UTC( obj.year, @@ -1528,7 +1553,10 @@ function objToLocalTS(obj) { // for legacy reasons, years between 0 and 99 are interpreted as 19XX; revert that if (obj.year < 100 && obj.year >= 0) { d = new Date(d); - d.setUTCFullYear(d.getUTCFullYear() - 1900); + // set the month and day again, this is necessary because year 2000 is a leap year, but year 100 is not + // so if obj.year is in 99, but obj.day makes it roll over into year 100, + // the calculations done by Date.UTC are using year 2000 - which is incorrect + d.setUTCFullYear(obj.year, obj.month - 1, obj.day); } return +d; } @@ -1836,6 +1864,9 @@ class Formatter { } static parseFormat(fmt) { + // white-space is always considered a literal in user-provided formats + // the " " token has a special meaning (see unitForToken) + let current = null, currentFull = "", bracketed = false; @@ -1844,7 +1875,7 @@ class Formatter { const c = fmt.charAt(i); if (c === "'") { if (currentFull.length > 0) { - splits.push({ literal: bracketed, val: currentFull }); + splits.push({ literal: bracketed || /^\s+$/.test(currentFull), val: currentFull }); } current = null; currentFull = ""; @@ -1855,7 +1886,7 @@ class Formatter { currentFull += c; } else { if (currentFull.length > 0) { - splits.push({ literal: false, val: currentFull }); + splits.push({ literal: /^\s+$/.test(currentFull), val: currentFull }); } currentFull = c; current = c; @@ -1863,7 +1894,7 @@ class Formatter { } if (currentFull.length > 0) { - splits.push({ literal: bracketed, val: currentFull }); + splits.push({ literal: bracketed || /^\s+$/.test(currentFull), val: currentFull }); } return splits; @@ -1887,24 +1918,25 @@ class Formatter { return df.format(); } - formatDateTime(dt, opts = {}) { - const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); - return df.format(); + dtFormatter(dt, opts = {}) { + return this.loc.dtFormatter(dt, { ...this.opts, ...opts }); } - formatDateTimeParts(dt, opts = {}) { - const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); - return df.formatToParts(); + formatDateTime(dt, opts) { + return this.dtFormatter(dt, opts).format(); } - formatInterval(interval, opts = {}) { - const df = this.loc.dtFormatter(interval.start, { ...this.opts, ...opts }); + formatDateTimeParts(dt, opts) { + return this.dtFormatter(dt, opts).formatToParts(); + } + + formatInterval(interval, opts) { + const df = this.dtFormatter(interval.start, opts); return df.dtf.formatRange(interval.start.toJSDate(), interval.end.toJSDate()); } - resolvedOptions(dt, opts = {}) { - const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts }); - return df.resolvedOptions(); + resolvedOptions(dt, opts) { + return this.dtFormatter(dt, opts).resolvedOptions(); } num(n, p = 0) { @@ -1959,7 +1991,7 @@ class Formatter { era = (length) => knownEnglish ? eraForDateTime(dt, length) : string({ era: length }, "era"), tokenToString = (token) => { - // Where possible: http://cldr.unicode.org/translation/date-time-1/date-time#TOC-Standalone-vs.-Format-Styles + // Where possible: https://cldr.unicode.org/translation/date-time/date-time-symbols switch (token) { // ms case "S": @@ -2636,28 +2668,61 @@ function clone$1(dur, alts, clear = false) { return new Duration(conf); } -function antiTrunc(n) { - return n < 0 ? Math.floor(n) : Math.ceil(n); -} - -// NB: mutates parameters -function convert(matrix, fromMap, fromUnit, toMap, toUnit) { - const conv = matrix[toUnit][fromUnit], - raw = fromMap[fromUnit] / conv, - sameSign = Math.sign(raw) === Math.sign(toMap[toUnit]), - // ok, so this is wild, but see the matrix in the tests - added = - !sameSign && toMap[toUnit] !== 0 && Math.abs(raw) <= 1 ? antiTrunc(raw) : Math.trunc(raw); - toMap[toUnit] += added; - fromMap[fromUnit] -= added * conv; +function durationToMillis(matrix, vals) { + let sum = vals.milliseconds ?? 0; + for (const unit of reverseUnits.slice(1)) { + if (vals[unit]) { + sum += vals[unit] * matrix[unit]["milliseconds"]; + } + } + return sum; } // NB: mutates parameters function normalizeValues(matrix, vals) { - reverseUnits.reduce((previous, current) => { + // the logic below assumes the overall value of the duration is positive + // if this is not the case, factor is used to make it so + const factor = durationToMillis(matrix, vals) < 0 ? -1 : 1; + + orderedUnits$1.reduceRight((previous, current) => { if (!isUndefined(vals[current])) { if (previous) { - convert(matrix, vals, previous, vals, current); + const previousVal = vals[previous] * factor; + const conv = matrix[current][previous]; + + // if (previousVal < 0): + // lower order unit is negative (e.g. { years: 2, days: -2 }) + // normalize this by reducing the higher order unit by the appropriate amount + // and increasing the lower order unit + // this can never make the higher order unit negative, because this function only operates + // on positive durations, so the amount of time represented by the lower order unit cannot + // be larger than the higher order unit + // else: + // lower order unit is positive (e.g. { years: 2, days: 450 } or { years: -2, days: 450 }) + // in this case we attempt to convert as much as possible from the lower order unit into + // the higher order one + // + // Math.floor takes care of both of these cases, rounding away from 0 + // if previousVal < 0 it makes the absolute value larger + // if previousVal >= it makes the absolute value smaller + const rollUp = Math.floor(previousVal / conv); + vals[current] += rollUp * factor; + vals[previous] -= rollUp * conv * factor; + } + return current; + } else { + return previous; + } + }, null); + + // try to convert any decimals into smaller units if possible + // for example for { years: 2.5, days: 0, seconds: 0 } we want to get { years: 2, days: 182, hours: 12 } + orderedUnits$1.reduce((previous, current) => { + if (!isUndefined(vals[current])) { + if (previous) { + const fraction = vals[previous] % 1; + vals[previous] -= fraction; + vals[current] += fraction * matrix[previous][current]; } return current; } else { @@ -2973,6 +3038,8 @@ class Duration { * ``` */ toHuman(opts = {}) { + if (!this.isValid) return INVALID$2; + const l = orderedUnits$1 .map((unit) => { const val = this.values[unit]; @@ -3059,26 +3126,11 @@ class Duration { includePrefix: false, format: "extended", ...opts, + includeOffset: false, }; - const value = this.shiftTo("hours", "minutes", "seconds", "milliseconds"); - - let fmt = opts.format === "basic" ? "hhmm" : "hh:mm"; - - if (!opts.suppressSeconds || value.seconds !== 0 || value.milliseconds !== 0) { - fmt += opts.format === "basic" ? "ss" : ":ss"; - if (!opts.suppressMilliseconds || value.milliseconds !== 0) { - fmt += ".SSS"; - } - } - - let str = value.toFormat(fmt); - - if (opts.includePrefix) { - str = "T" + str; - } - - return str; + const dateTime = DateTime.fromMillis(millis, { zone: "UTC" }); + return dateTime.toISOTime(opts); } /** @@ -3102,7 +3154,9 @@ class Duration { * @return {number} */ toMillis() { - return this.as("milliseconds"); + if (!this.isValid) return NaN; + + return durationToMillis(this.matrix, this.values); } /** @@ -3212,8 +3266,17 @@ class Duration { /** * Reduce this Duration to its canonical representation in its current units. + * Assuming the overall value of the Duration is positive, this means: + * - excessive values for lower-order units are converted to higher-order units (if possible, see first and second example) + * - negative lower-order units are converted to higher order units (there must be such a higher order unit, otherwise + * the overall value would be negative, see second example) + * - fractional values for higher-order units are converted to lower-order units (if possible, see fourth example) + * + * If the overall value is negative, the result of this method is equivalent to `this.negate().normalize().negate()`. * @example Duration.fromObject({ years: 2, days: 5000 }).normalize().toObject() //=> { years: 15, days: 255 } + * @example Duration.fromObject({ days: 5000 }).normalize().toObject() //=> { days: 5000 } * @example Duration.fromObject({ hours: 12, minutes: -45 }).normalize().toObject() //=> { hours: 11, minutes: 15 } + * @example Duration.fromObject({ years: 2.5, days: 0, hours: 0 }).normalize().toObject() //=> { years: 2, days: 182, hours: 12 } * @return {Duration} */ normalize() { @@ -3270,16 +3333,12 @@ class Duration { own += vals[k]; } + // only keep the integer part for now in the hopes of putting any decimal part + // into a smaller unit later const i = Math.trunc(own); built[k] = i; accumulated[k] = (own * 1000 - i * 1000) / 1000; - // plus anything further down the chain that should be rolled up in to this - for (const down in vals) { - if (orderedUnits$1.indexOf(down) > orderedUnits$1.indexOf(k)) { - convert(this.matrix, vals, down, built, k); - } - } // otherwise, keep it in the wings to boil it later } else if (isNumber(vals[k])) { accumulated[k] = vals[k]; @@ -3295,7 +3354,8 @@ class Duration { } } - return clone$1(this, { values: built }, true).normalize(); + normalizeValues(this.matrix, built); + return clone$1(this, { values: built }, true); } /** @@ -3692,7 +3752,7 @@ class Interval { if (!this.isValid) return NaN; const start = this.start.startOf(unit), end = this.end.startOf(unit); - return Math.floor(end.diff(start, unit).get(unit)) + 1; + return Math.floor(end.diff(start, unit).get(unit)) + (end.valueOf() !== this.end.valueOf()); } /** @@ -4275,6 +4335,14 @@ function highOrderDiffs(cursor, later, units) { const earlier = cursor; let lowestOrder, highWater; + /* This loop tries to diff using larger units first. + If we overshoot, we backtrack and try the next smaller unit. + "cursor" starts out at the earlier timestamp and moves closer and closer to "later" + as we use smaller and smaller units. + highWater keeps track of where we would be if we added one more of the smallest unit, + this is used later to potentially convert any difference smaller than the smallest higher order unit + into a fraction of that smallest higher order unit + */ for (const [unit, differ] of differs) { if (units.indexOf(unit) >= 0) { lowestOrder = unit; @@ -4283,8 +4351,20 @@ function highOrderDiffs(cursor, later, units) { highWater = earlier.plus(results); if (highWater > later) { + // we overshot the end point, backtrack cursor by 1 results[unit]--; cursor = earlier.plus(results); + + // if we are still overshooting now, we need to backtrack again + // this happens in certain situations when diffing times in different zones, + // because this calculation ignores time zones + if (cursor > later) { + // keep the "overshot by 1" around as highWater + highWater = cursor; + // backtrack cursor by 1 + results[unit]--; + cursor = earlier.plus(results); + } } else { cursor = highWater; } @@ -4447,6 +4527,10 @@ function escapeToken(value) { return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); } +/** + * @param token + * @param {Locale} loc + */ function unitForToken(token, loc) { const one = digitRegex(loc), two = digitRegex(loc, "{2}"), @@ -4467,9 +4551,9 @@ function unitForToken(token, loc) { switch (t.val) { // era case "G": - return oneOf(loc.eras("short", false), 0); + return oneOf(loc.eras("short"), 0); case "GG": - return oneOf(loc.eras("long", false), 0); + return oneOf(loc.eras("long"), 0); // years case "y": return intUnit(oneToSix); @@ -4487,17 +4571,17 @@ function unitForToken(token, loc) { case "MM": return intUnit(two); case "MMM": - return oneOf(loc.months("short", true, false), 1); + return oneOf(loc.months("short", true), 1); case "MMMM": - return oneOf(loc.months("long", true, false), 1); + return oneOf(loc.months("long", true), 1); case "L": return intUnit(oneOrTwo); case "LL": return intUnit(two); case "LLL": - return oneOf(loc.months("short", false, false), 1); + return oneOf(loc.months("short", false), 1); case "LLLL": - return oneOf(loc.months("long", false, false), 1); + return oneOf(loc.months("long", false), 1); // dates case "d": return intUnit(oneOrTwo); @@ -4557,13 +4641,13 @@ function unitForToken(token, loc) { case "c": return intUnit(one); case "EEE": - return oneOf(loc.weekdays("short", false, false), 1); + return oneOf(loc.weekdays("short", false), 1); case "EEEE": - return oneOf(loc.weekdays("long", false, false), 1); + return oneOf(loc.weekdays("long", false), 1); case "ccc": - return oneOf(loc.weekdays("short", true, false), 1); + return oneOf(loc.weekdays("short", true), 1); case "cccc": - return oneOf(loc.weekdays("long", true, false), 1); + return oneOf(loc.weekdays("long", true), 1); // offset/zone case "Z": case "ZZ": @@ -4574,6 +4658,10 @@ function unitForToken(token, loc) { // because we don't have any way to figure out what they are case "z": return simple(/[a-z_+-/]{1,256}?/i); + // this special-case "token" represents a place where a macro-token expanded into a white-space literal + // in this case we accept any non-newline white-space + case " ": + return simple(/[^\S\n\r]/); default: return literal(t); } @@ -4609,10 +4697,14 @@ const partTypeStyleToTokenVal = { }, dayperiod: "a", dayPeriod: "a", - hour: { + hour12: { numeric: "h", "2-digit": "hh", }, + hour24: { + numeric: "H", + "2-digit": "HH", + }, minute: { numeric: "m", "2-digit": "mm", @@ -4627,19 +4719,39 @@ const partTypeStyleToTokenVal = { }, }; -function tokenForPart(part, formatOpts) { +function tokenForPart(part, formatOpts, resolvedOpts) { const { type, value } = part; if (type === "literal") { + const isSpace = /^\s+$/.test(value); return { - literal: true, - val: value, + literal: !isSpace, + val: isSpace ? " " : value, }; } const style = formatOpts[type]; - let val = partTypeStyleToTokenVal[type]; + // The user might have explicitly specified hour12 or hourCycle + // if so, respect their decision + // if not, refer back to the resolvedOpts, which are based on the locale + let actualType = type; + if (type === "hour") { + if (formatOpts.hour12 != null) { + actualType = formatOpts.hour12 ? "hour12" : "hour24"; + } else if (formatOpts.hourCycle != null) { + if (formatOpts.hourCycle === "h11" || formatOpts.hourCycle === "h12") { + actualType = "hour12"; + } else { + actualType = "hour24"; + } + } else { + // tokens only differentiate between 24 hours or not, + // so we do not need to check hourCycle here, which is less supported anyways + actualType = resolvedOpts.hour12 ? "hour12" : "hour24"; + } + } + let val = partTypeStyleToTokenVal[actualType]; if (typeof val === "object") { val = val[style]; } @@ -4828,8 +4940,10 @@ function formatOptsToTokens(formatOpts, locale) { } const formatter = Formatter.create(locale, formatOpts); - const parts = formatter.formatDateTimeParts(getDummyDateTime()); - return parts.map((p) => tokenForPart(p, formatOpts)); + const df = formatter.dtFormatter(getDummyDateTime()); + const parts = df.formatToParts(); + const resolvedOpts = df.resolvedOptions(); + return parts.map((p) => tokenForPart(p, formatOpts, resolvedOpts)); } const nonLeapLadder = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], @@ -5103,7 +5217,7 @@ function adjustTime(inst, dur) { // by handling the zone options function parseDataToDateTime(parsed, parsedZone, opts, format, text, specificOffset) { const { setZone, zone } = opts; - if (parsed && Object.keys(parsed).length !== 0) { + if ((parsed && Object.keys(parsed).length !== 0) || parsedZone) { const interpretationZone = parsedZone || zone, inst = DateTime.fromObject(parsed, { ...opts, @@ -5159,14 +5273,14 @@ function toISOTime( if (extended) { c += ":"; c += padStart(o.c.minute); - if (o.c.second !== 0 || !suppressSeconds) { + if (o.c.millisecond !== 0 || o.c.second !== 0 || !suppressSeconds) { c += ":"; } } else { c += padStart(o.c.minute); } - if (o.c.second !== 0 || !suppressSeconds) { + if (o.c.millisecond !== 0 || o.c.second !== 0 || !suppressSeconds) { c += padStart(o.c.second); if (o.c.millisecond !== 0 || !suppressMilliseconds) { @@ -5829,7 +5943,7 @@ class DateTime { /** * Create an invalid DateTime. - * @param {DateTime} reason - simple string of why this DateTime is invalid. Should not contain parameters or anything else data-dependent + * @param {string} reason - simple string of why this DateTime is invalid. Should not contain parameters or anything else data-dependent. * @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information * @return {DateTime} */ @@ -6178,6 +6292,43 @@ class DateTime { } } + /** + * Get those DateTimes which have the same local time as this DateTime, but a different offset from UTC + * in this DateTime's zone. During DST changes local time can be ambiguous, for example + * `2023-10-29T02:30:00` in `Europe/Berlin` can have offset `+01:00` or `+02:00`. + * This method will return both possible DateTimes if this DateTime's local time is ambiguous. + * @returns {DateTime[]} + */ + getPossibleOffsets() { + if (!this.isValid || this.isOffsetFixed) { + return [this]; + } + const dayMs = 86400000; + const minuteMs = 60000; + const localTS = objToLocalTS(this.c); + const oEarlier = this.zone.offset(localTS - dayMs); + const oLater = this.zone.offset(localTS + dayMs); + + const o1 = this.zone.offset(localTS - oEarlier * minuteMs); + const o2 = this.zone.offset(localTS - oLater * minuteMs); + if (o1 === o2) { + return [this]; + } + const ts1 = localTS - o1 * minuteMs; + const ts2 = localTS - o2 * minuteMs; + const c1 = tsToObj(ts1, o1); + const c2 = tsToObj(ts2, o2); + if ( + c1.hour === c2.hour && + c1.minute === c2.minute && + c1.second === c2.second && + c1.millisecond === c2.millisecond + ) { + return [clone(this, { ts: ts1 }), clone(this, { ts: ts2 })]; + } + return [this]; + } + /** * Returns true if this DateTime is in a leap year, false otherwise * @example DateTime.local(2016).isInLeapYear //=> true @@ -7180,7 +7331,7 @@ function friendlyDateTime(dateTimeish) { } } -const VERSION = "3.2.1"; +const VERSION = "3.4.3"; var Luxon = /*#__PURE__*/Object.freeze({ __proto__: null, @@ -7197,2292 +7348,2303 @@ var Luxon = /*#__PURE__*/Object.freeze({ Settings: Settings }); -//////////////////// -// Query Settings // -//////////////////// -const DEFAULT_QUERY_SETTINGS = { - renderNullAs: "\\-", - taskCompletionTracking: false, - taskCompletionUseEmojiShorthand: false, - taskCompletionText: "completion", - taskCompletionDateFormat: "yyyy-MM-dd", - recursiveSubTaskCompletion: false, - warnOnEmptyResult: true, - refreshEnabled: true, - refreshInterval: 2500, - defaultDateFormat: "MMMM dd, yyyy", - defaultDateTimeFormat: "h:mm a - MMMM dd, yyyy", - maxRecursiveRenderDepth: 4, - tableIdColumnName: "File", - tableGroupColumnName: "Group", - showResultCount: true, -}; -const DEFAULT_EXPORT_SETTINGS = { - allowHtml: true, -}; -/** Default settings for dataview on install. */ -const DEFAULT_SETTINGS = { - ...DEFAULT_QUERY_SETTINGS, - ...DEFAULT_EXPORT_SETTINGS, - ...{ - inlineQueryPrefix: "=", - inlineJsQueryPrefix: "$=", - inlineQueriesInCodeblocks: true, - enableInlineDataview: true, - enableDataviewJs: false, - enableInlineDataviewJs: false, - prettyRenderInlineFields: true, - dataviewJsKeyword: "dataviewjs", - }, +//////////////////// +// Query Settings // +//////////////////// +const DEFAULT_QUERY_SETTINGS = { + renderNullAs: "\\-", + taskCompletionTracking: false, + taskCompletionUseEmojiShorthand: false, + taskCompletionText: "completion", + taskCompletionDateFormat: "yyyy-MM-dd", + recursiveSubTaskCompletion: false, + warnOnEmptyResult: true, + refreshEnabled: true, + refreshInterval: 2500, + defaultDateFormat: "MMMM dd, yyyy", + defaultDateTimeFormat: "h:mm a - MMMM dd, yyyy", + maxRecursiveRenderDepth: 4, + tableIdColumnName: "File", + tableGroupColumnName: "Group", + showResultCount: true, +}; +const DEFAULT_EXPORT_SETTINGS = { + allowHtml: true, +}; +/** Default settings for dataview on install. */ +const DEFAULT_SETTINGS = { + ...DEFAULT_QUERY_SETTINGS, + ...DEFAULT_EXPORT_SETTINGS, + ...{ + inlineQueryPrefix: "=", + inlineJsQueryPrefix: "$=", + inlineQueriesInCodeblocks: true, + enableInlineDataview: true, + enableDataviewJs: false, + enableInlineDataviewJs: false, + prettyRenderInlineFields: true, + dataviewJsKeyword: "dataviewjs", + }, }; -/** Functional return type for error handling. */ -class Success { - constructor(value) { - this.value = value; - this.successful = true; - } - map(f) { - return new Success(f(this.value)); - } - flatMap(f) { - return f(this.value); - } - mapErr(f) { - return this; - } - bimap(succ, _fail) { - return this.map(succ); - } - orElse(_value) { - return this.value; - } - cast() { - return this; - } - orElseThrow(_message) { - return this.value; - } -} -/** Functional return type for error handling. */ -class Failure { - constructor(error) { - this.error = error; - this.successful = false; - } - map(_f) { - return this; - } - flatMap(_f) { - return this; - } - mapErr(f) { - return new Failure(f(this.error)); - } - bimap(_succ, fail) { - return this.mapErr(fail); - } - orElse(value) { - return value; - } - cast() { - return this; - } - orElseThrow(message) { - if (message) - throw new Error(message(this.error)); - else - throw new Error("" + this.error); - } -} -/** Monadic 'Result' type which encapsulates whether a procedure succeeded or failed, as well as it's return value. */ -var Result; -(function (Result) { - /** Construct a new success result wrapping the given value. */ - function success(value) { - return new Success(value); - } - Result.success = success; - /** Construct a new failure value wrapping the given error. */ - function failure(error) { - return new Failure(error); - } - Result.failure = failure; - /** Join two results with a bi-function and return a new result. */ - function flatMap2(first, second, f) { - if (first.successful) { - if (second.successful) - return f(first.value, second.value); - else - return failure(second.error); - } - else { - return failure(first.error); - } - } - Result.flatMap2 = flatMap2; - /** Join two results with a bi-function and return a new result. */ - function map2(first, second, f) { - return flatMap2(first, second, (a, b) => success(f(a, b))); - } - Result.map2 = map2; +/** Functional return type for error handling. */ +class Success { + constructor(value) { + this.value = value; + this.successful = true; + } + map(f) { + return new Success(f(this.value)); + } + flatMap(f) { + return f(this.value); + } + mapErr(f) { + return this; + } + bimap(succ, _fail) { + return this.map(succ); + } + orElse(_value) { + return this.value; + } + cast() { + return this; + } + orElseThrow(_message) { + return this.value; + } +} +/** Functional return type for error handling. */ +class Failure { + constructor(error) { + this.error = error; + this.successful = false; + } + map(_f) { + return this; + } + flatMap(_f) { + return this; + } + mapErr(f) { + return new Failure(f(this.error)); + } + bimap(_succ, fail) { + return this.mapErr(fail); + } + orElse(value) { + return value; + } + cast() { + return this; + } + orElseThrow(message) { + if (message) + throw new Error(message(this.error)); + else + throw new Error("" + this.error); + } +} +/** Monadic 'Result' type which encapsulates whether a procedure succeeded or failed, as well as it's return value. */ +var Result; +(function (Result) { + /** Construct a new success result wrapping the given value. */ + function success(value) { + return new Success(value); + } + Result.success = success; + /** Construct a new failure value wrapping the given error. */ + function failure(error) { + return new Failure(error); + } + Result.failure = failure; + /** Join two results with a bi-function and return a new result. */ + function flatMap2(first, second, f) { + if (first.successful) { + if (second.successful) + return f(first.value, second.value); + else + return failure(second.error); + } + else { + return failure(first.error); + } + } + Result.flatMap2 = flatMap2; + /** Join two results with a bi-function and return a new result. */ + function map2(first, second, f) { + return flatMap2(first, second, (a, b) => success(f(a, b))); + } + Result.map2 = map2; })(Result || (Result = {})); var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; -function commonjsRequire (path) { - throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.'); +function getDefaultExportFromCjs (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } var parsimmon_umd_min = {exports: {}}; +parsimmon_umd_min.exports; + (function (module, exports) { -!function(n,t){module.exports=t();}("undefined"!=typeof self?self:commonjsGlobal,function(){return function(n){var t={};function r(e){if(t[e])return t[e].exports;var u=t[e]={i:e,l:!1,exports:{}};return n[e].call(u.exports,u,u.exports,r),u.l=!0,u.exports}return r.m=n,r.c=t,r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{configurable:!1,enumerable:!0,get:e});},r.r=function(n){Object.defineProperty(n,"__esModule",{value:!0});},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},r.p="",r(r.s=0)}([function(n,t,r){function e(n){if(!(this instanceof e))return new e(n);this._=n;}var u=e.prototype;function o(n,t){for(var r=0;r>7),buf:function(n){var t=i(function(n,t,r,e){return n.concat(r===e.length-1?Buffer.from([t,0]).readUInt16BE(0):e.readUInt16BE(r))},[],n);return Buffer.from(a(function(n){return (n<<1&65535)>>8},t))}(r.buf)};}),r}function c(){return "undefined"!=typeof Buffer}function s(){if(!c())throw new Error("Buffer global does not exist; please use webpack if you need to parse Buffers in the browser.")}function l(n){s();var t=i(function(n,t){return n+t},0,n);if(t%8!=0)throw new Error("The bits ["+n.join(", ")+"] add up to "+t+" which is not an even number of bytes; the total should be divisible by 8");var r,u=t/8,o=(r=function(n){return n>48},i(function(n,t){return n||(r(t)?t:n)},null,n));if(o)throw new Error(o+" bit range requested exceeds 48 bit (6 byte) Number max.");return new e(function(t,r){var e=u+r;return e>t.length?x(r,u.toString()+" bytes"):b(e,i(function(n,t){var r=f(t,n.buf);return {coll:n.coll.concat(r.v),buf:r.buf}},{coll:[],buf:t.slice(r,e)},n).coll)})}function h(n,t){return new e(function(r,e){return s(),e+t>r.length?x(e,t+" bytes for "+n):b(e+t,r.slice(e,e+t))})}function p(n,t){if("number"!=typeof(r=t)||Math.floor(r)!==r||t<0||t>6)throw new Error(n+" requires integer length in range [0, 6].");var r;}function d(n){return p("uintBE",n),h("uintBE("+n+")",n).map(function(t){return t.readUIntBE(0,n)})}function v(n){return p("uintLE",n),h("uintLE("+n+")",n).map(function(t){return t.readUIntLE(0,n)})}function g(n){return p("intBE",n),h("intBE("+n+")",n).map(function(t){return t.readIntBE(0,n)})}function m(n){return p("intLE",n),h("intLE("+n+")",n).map(function(t){return t.readIntLE(0,n)})}function y(n){return n instanceof e}function E(n){return "[object Array]"==={}.toString.call(n)}function w(n){return c()&&Buffer.isBuffer(n)}function b(n,t){return {status:!0,index:n,value:t,furthest:-1,expected:[]}}function x(n,t){return E(t)||(t=[t]),{status:!1,index:-1,value:null,furthest:n,expected:t}}function B(n,t){if(!t)return n;if(n.furthest>t.furthest)return n;var r=n.furthest===t.furthest?function(n,t){if(function(){if(void 0!==e._supportsSet)return e._supportsSet;var n="undefined"!=typeof Set;return e._supportsSet=n,n}()&&Array.from){for(var r=new Set(n),u=0;u=0;){if(i in r){e=r[i].line,0===o&&(o=r[i].lineStart);break}("\n"===n.charAt(i)||"\r"===n.charAt(i)&&"\n"!==n.charAt(i+1))&&(u++,0===o&&(o=i+1)),i--;}var a=e+u,f=t-o;return r[t]={line:a,lineStart:o},{offset:t,line:a+1,column:f+1}}function _(n){if(!y(n))throw new Error("not a parser: "+n)}function L(n,t){return "string"==typeof n?n.charAt(t):n[t]}function O(n){if("number"!=typeof n)throw new Error("not a number: "+n)}function k(n){if("function"!=typeof n)throw new Error("not a function: "+n)}function P(n){if("string"!=typeof n)throw new Error("not a string: "+n)}var q=2,A=3,I=8,F=5*I,M=4*I,z=" ";function R(n,t){return new Array(t+1).join(n)}function U(n,t,r){var e=t-n.length;return e<=0?n:R(r,e)+n}function W(n,t,r,e){return {from:n-t>0?n-t:0,to:n+r>e?e:n+r}}function D(n,t){var r,e,u,o,f,c=t.index,s=c.offset,l=1;if(s===n.length)return "Got the end of the input";if(w(n)){var h=s-s%I,p=s-h,d=W(h,F,M+I,n.length),v=a(function(n){return a(function(n){return U(n.toString(16),2,"0")},n)},function(n,t){var r=n.length,e=[],u=0;if(r<=t)return [n.slice()];for(var o=0;o=4&&(r+=1),l=2,u=a(function(n){return n.length<=4?n.join(" "):n.slice(0,4).join(" ")+" "+n.slice(4).join(" ")},v),(f=(8*(o.to>0?o.to-1:o.to)).toString(16).length)<2&&(f=2);}else {var g=n.split(/\r\n|[\n\r\u2028\u2029]/);r=c.column-1,e=c.line-1,o=W(e,q,A,g.length),u=g.slice(o.from,o.to),f=o.to.toString().length;}var m=e-o.from;return w(n)&&(f=(8*(o.to>0?o.to-1:o.to)).toString(16).length)<2&&(f=2),i(function(t,e,u){var i,a=u===m,c=a?"> ":z;return i=w(n)?U((8*(o.from+u)).toString(16),f,"0"):U((o.from+u+1).toString(),f," "),[].concat(t,[c+i+" | "+e],a?[z+R(" ",f)+" | "+U("",r," ")+R("^",l)]:[])},[],u).join("\n")}function N(n,t){return ["\n","-- PARSING FAILED "+R("-",50),"\n\n",D(n,t),"\n\n",(r=t.expected,1===r.length?"Expected:\n\n"+r[0]:"Expected one of the following: \n\n"+r.join(", ")),"\n"].join("");var r;}function G(n){return void 0!==n.flags?n.flags:[n.global?"g":"",n.ignoreCase?"i":"",n.multiline?"m":"",n.unicode?"u":"",n.sticky?"y":""].join("")}function C(){for(var n=[].slice.call(arguments),t=n.length,r=0;r=2?O(t):t=0;var r=function(n){return RegExp("^(?:"+n.source+")",G(n))}(n),u=""+n;return e(function(n,e){var o=r.exec(n.slice(e));if(o){if(0<=t&&t<=o.length){var i=o[0],a=o[t];return b(e+i.length,a)}return x(e,"valid match group (0 to "+o.length+") in "+u)}return x(e,u)})}function X(n){return e(function(t,r){return b(r,n)})}function Y(n){return e(function(t,r){return x(r,n)})}function Z(n){if(y(n))return e(function(t,r){var e=n._(t,r);return e.index=r,e.value="",e});if("string"==typeof n)return Z(K(n));if(n instanceof RegExp)return Z(Q(n));throw new Error("not a string, regexp, or parser: "+n)}function $(n){return _(n),e(function(t,r){var e=n._(t,r),u=t.slice(r,e.index);return e.status?x(r,'not "'+u+'"'):b(r,null)})}function nn(n){return k(n),e(function(t,r){var e=L(t,r);return r=n.length?x(t,"any character/byte"):b(t+1,L(n,t))}),on=e(function(n,t){return b(n.length,n.slice(t))}),an=e(function(n,t){return t=0}).desc(t)},e.optWhitespace=hn,e.Parser=e,e.range=function(n,t){return nn(function(r){return n<=r&&r<=t}).desc(n+"-"+t)},e.regex=Q,e.regexp=Q,e.sepBy=V,e.sepBy1=H,e.seq=C,e.seqMap=J,e.seqObj=function(){for(var n,t={},r=0,u=(n=arguments,Array.prototype.slice.call(n)),o=u.length,i=0;i255)throw new Error("Value specified to byte constructor ("+n+"=0x"+n.toString(16)+") is larger in value than a single byte.");var t=(n>15?"0x":"0x0")+n.toString(16);return e(function(r,e){var u=L(r,e);return u===n?b(e+1,u):x(e,t)})},buffer:function(n){return h("buffer",n).map(function(n){return Buffer.from(n)})},encodedString:function(n,t){return h("string",t).map(function(t){return t.toString(n)})},uintBE:d,uint8BE:d(1),uint16BE:d(2),uint32BE:d(4),uintLE:v,uint8LE:v(1),uint16LE:v(2),uint32LE:v(4),intBE:g,int8BE:g(1),int16BE:g(2),int32BE:g(4),intLE:m,int8LE:m(1),int16LE:m(2),int32LE:m(4),floatBE:h("floatBE",4).map(function(n){return n.readFloatBE(0)}),floatLE:h("floatLE",4).map(function(n){return n.readFloatLE(0)}),doubleBE:h("doubleBE",8).map(function(n){return n.readDoubleBE(0)}),doubleLE:h("doubleLE",8).map(function(n){return n.readDoubleLE(0)})},n.exports=e;}])}); -}(parsimmon_umd_min)); + !function(n,t){module.exports=t();}("undefined"!=typeof self?self:commonjsGlobal,function(){return function(n){var t={};function r(e){if(t[e])return t[e].exports;var u=t[e]={i:e,l:!1,exports:{}};return n[e].call(u.exports,u,u.exports,r),u.l=!0,u.exports}return r.m=n,r.c=t,r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{configurable:!1,enumerable:!0,get:e});},r.r=function(n){Object.defineProperty(n,"__esModule",{value:!0});},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},r.p="",r(r.s=0)}([function(n,t,r){function e(n){if(!(this instanceof e))return new e(n);this._=n;}var u=e.prototype;function o(n,t){for(var r=0;r>7),buf:function(n){var t=i(function(n,t,r,e){return n.concat(r===e.length-1?Buffer.from([t,0]).readUInt16BE(0):e.readUInt16BE(r))},[],n);return Buffer.from(a(function(n){return (n<<1&65535)>>8},t))}(r.buf)};}),r}function c(){return "undefined"!=typeof Buffer}function s(){if(!c())throw new Error("Buffer global does not exist; please use webpack if you need to parse Buffers in the browser.")}function l(n){s();var t=i(function(n,t){return n+t},0,n);if(t%8!=0)throw new Error("The bits ["+n.join(", ")+"] add up to "+t+" which is not an even number of bytes; the total should be divisible by 8");var r,u=t/8,o=(r=function(n){return n>48},i(function(n,t){return n||(r(t)?t:n)},null,n));if(o)throw new Error(o+" bit range requested exceeds 48 bit (6 byte) Number max.");return new e(function(t,r){var e=u+r;return e>t.length?x(r,u.toString()+" bytes"):b(e,i(function(n,t){var r=f(t,n.buf);return {coll:n.coll.concat(r.v),buf:r.buf}},{coll:[],buf:t.slice(r,e)},n).coll)})}function h(n,t){return new e(function(r,e){return s(),e+t>r.length?x(e,t+" bytes for "+n):b(e+t,r.slice(e,e+t))})}function p(n,t){if("number"!=typeof(r=t)||Math.floor(r)!==r||t<0||t>6)throw new Error(n+" requires integer length in range [0, 6].");var r;}function d(n){return p("uintBE",n),h("uintBE("+n+")",n).map(function(t){return t.readUIntBE(0,n)})}function v(n){return p("uintLE",n),h("uintLE("+n+")",n).map(function(t){return t.readUIntLE(0,n)})}function g(n){return p("intBE",n),h("intBE("+n+")",n).map(function(t){return t.readIntBE(0,n)})}function m(n){return p("intLE",n),h("intLE("+n+")",n).map(function(t){return t.readIntLE(0,n)})}function y(n){return n instanceof e}function E(n){return "[object Array]"==={}.toString.call(n)}function w(n){return c()&&Buffer.isBuffer(n)}function b(n,t){return {status:!0,index:n,value:t,furthest:-1,expected:[]}}function x(n,t){return E(t)||(t=[t]),{status:!1,index:-1,value:null,furthest:n,expected:t}}function B(n,t){if(!t)return n;if(n.furthest>t.furthest)return n;var r=n.furthest===t.furthest?function(n,t){if(function(){if(void 0!==e._supportsSet)return e._supportsSet;var n="undefined"!=typeof Set;return e._supportsSet=n,n}()&&Array.from){for(var r=new Set(n),u=0;u=0;){if(i in r){e=r[i].line,0===o&&(o=r[i].lineStart);break}("\n"===n.charAt(i)||"\r"===n.charAt(i)&&"\n"!==n.charAt(i+1))&&(u++,0===o&&(o=i+1)),i--;}var a=e+u,f=t-o;return r[t]={line:a,lineStart:o},{offset:t,line:a+1,column:f+1}}function _(n){if(!y(n))throw new Error("not a parser: "+n)}function L(n,t){return "string"==typeof n?n.charAt(t):n[t]}function O(n){if("number"!=typeof n)throw new Error("not a number: "+n)}function k(n){if("function"!=typeof n)throw new Error("not a function: "+n)}function P(n){if("string"!=typeof n)throw new Error("not a string: "+n)}var q=2,A=3,I=8,F=5*I,M=4*I,z=" ";function R(n,t){return new Array(t+1).join(n)}function U(n,t,r){var e=t-n.length;return e<=0?n:R(r,e)+n}function W(n,t,r,e){return {from:n-t>0?n-t:0,to:n+r>e?e:n+r}}function D(n,t){var r,e,u,o,f,c=t.index,s=c.offset,l=1;if(s===n.length)return "Got the end of the input";if(w(n)){var h=s-s%I,p=s-h,d=W(h,F,M+I,n.length),v=a(function(n){return a(function(n){return U(n.toString(16),2,"0")},n)},function(n,t){var r=n.length,e=[],u=0;if(r<=t)return [n.slice()];for(var o=0;o=4&&(r+=1),l=2,u=a(function(n){return n.length<=4?n.join(" "):n.slice(0,4).join(" ")+" "+n.slice(4).join(" ")},v),(f=(8*(o.to>0?o.to-1:o.to)).toString(16).length)<2&&(f=2);}else {var g=n.split(/\r\n|[\n\r\u2028\u2029]/);r=c.column-1,e=c.line-1,o=W(e,q,A,g.length),u=g.slice(o.from,o.to),f=o.to.toString().length;}var m=e-o.from;return w(n)&&(f=(8*(o.to>0?o.to-1:o.to)).toString(16).length)<2&&(f=2),i(function(t,e,u){var i,a=u===m,c=a?"> ":z;return i=w(n)?U((8*(o.from+u)).toString(16),f,"0"):U((o.from+u+1).toString(),f," "),[].concat(t,[c+i+" | "+e],a?[z+R(" ",f)+" | "+U("",r," ")+R("^",l)]:[])},[],u).join("\n")}function N(n,t){return ["\n","-- PARSING FAILED "+R("-",50),"\n\n",D(n,t),"\n\n",(r=t.expected,1===r.length?"Expected:\n\n"+r[0]:"Expected one of the following: \n\n"+r.join(", ")),"\n"].join("");var r;}function G(n){return void 0!==n.flags?n.flags:[n.global?"g":"",n.ignoreCase?"i":"",n.multiline?"m":"",n.unicode?"u":"",n.sticky?"y":""].join("")}function C(){for(var n=[].slice.call(arguments),t=n.length,r=0;r=2?O(t):t=0;var r=function(n){return RegExp("^(?:"+n.source+")",G(n))}(n),u=""+n;return e(function(n,e){var o=r.exec(n.slice(e));if(o){if(0<=t&&t<=o.length){var i=o[0],a=o[t];return b(e+i.length,a)}return x(e,"valid match group (0 to "+o.length+") in "+u)}return x(e,u)})}function X(n){return e(function(t,r){return b(r,n)})}function Y(n){return e(function(t,r){return x(r,n)})}function Z(n){if(y(n))return e(function(t,r){var e=n._(t,r);return e.index=r,e.value="",e});if("string"==typeof n)return Z(K(n));if(n instanceof RegExp)return Z(Q(n));throw new Error("not a string, regexp, or parser: "+n)}function $(n){return _(n),e(function(t,r){var e=n._(t,r),u=t.slice(r,e.index);return e.status?x(r,'not "'+u+'"'):b(r,null)})}function nn(n){return k(n),e(function(t,r){var e=L(t,r);return r=n.length?x(t,"any character/byte"):b(t+1,L(n,t))}),on=e(function(n,t){return b(n.length,n.slice(t))}),an=e(function(n,t){return t=0}).desc(t)},e.optWhitespace=hn,e.Parser=e,e.range=function(n,t){return nn(function(r){return n<=r&&r<=t}).desc(n+"-"+t)},e.regex=Q,e.regexp=Q,e.sepBy=V,e.sepBy1=H,e.seq=C,e.seqMap=J,e.seqObj=function(){for(var n,t={},r=0,u=(n=arguments,Array.prototype.slice.call(n)),o=u.length,i=0;i255)throw new Error("Value specified to byte constructor ("+n+"=0x"+n.toString(16)+") is larger in value than a single byte.");var t=(n>15?"0x":"0x0")+n.toString(16);return e(function(r,e){var u=L(r,e);return u===n?b(e+1,u):x(e,t)})},buffer:function(n){return h("buffer",n).map(function(n){return Buffer.from(n)})},encodedString:function(n,t){return h("string",t).map(function(t){return t.toString(n)})},uintBE:d,uint8BE:d(1),uint16BE:d(2),uint32BE:d(4),uintLE:v,uint8LE:v(1),uint16LE:v(2),uint32LE:v(4),intBE:g,int8BE:g(1),int16BE:g(2),int32BE:g(4),intLE:m,int8LE:m(1),int16LE:m(2),int32LE:m(4),floatBE:h("floatBE",4).map(function(n){return n.readFloatBE(0)}),floatLE:h("floatLE",4).map(function(n){return n.readFloatLE(0)}),doubleBE:h("doubleBE",8).map(function(n){return n.readDoubleBE(0)}),doubleLE:h("doubleLE",8).map(function(n){return n.readDoubleLE(0)})},n.exports=e;}])}); +} (parsimmon_umd_min, parsimmon_umd_min.exports)); + +var parsimmon_umd_minExports = parsimmon_umd_min.exports; var emojiRegex = () => { // https://mths.be/emoji - return /(?:[#*0-9]\uFE0F?\u20E3|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]\uFE0F?|[\u261D\u270C\u270D](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\u270A\u270B](?:\uD83C[\uDFFB-\uDFFF])?|[\u23E9-\u23EC\u23F0\u23F3\u25FD\u2693\u26A1\u26AB\u26C5\u26CE\u26D4\u26EA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2795-\u2797\u27B0\u27BF\u2B50]|\u26F9(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\u2764\uFE0F?(?:\u200D(?:\uD83D\uDD25|\uD83E\uDE79))?|\uD83C(?:[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]\uFE0F?|[\uDF85\uDFC2\uDFC7](?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC3\uDFC4\uDFCA](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDFCB\uDFCC](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|\uDFF3\uFE0F?(?:\u200D(?:\u26A7\uFE0F?|\uD83C\uDF08))?|\uDFF4(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDC73\uDB40\uDC63\uDB40\uDC74|\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F)?)|\uD83D(?:[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3]\uFE0F?|[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD74\uDD90](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEDD-\uDEDF\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB\uDFF0]|\uDC08(?:\u200D\u2B1B)?|\uDC15(?:\u200D\uD83E\uDDBA)?|\uDC3B(?:\u200D\u2744\uFE0F?)?|\uDC41\uFE0F?(?:\u200D\uD83D\uDDE8\uFE0F?)?|\uDC68(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE])))?))?|\uDC69(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?[\uDC68\uDC69]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?))|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFE])))?))?|\uDC6F(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDD75(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDE2E(?:\u200D\uD83D\uDCA8)?|\uDE35(?:\u200D\uD83D\uDCAB)?|\uDE36(?:\u200D\uD83C\uDF2B\uFE0F?)?)|\uD83E(?:[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF6](?:\uD83C[\uDFFB-\uDFFF])?|[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDDDE\uDDDF](?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD0D\uDD0E\uDD10-\uDD17\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCC\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7C\uDE80-\uDE86\uDE90-\uDEAC\uDEB0-\uDEBA\uDEC0-\uDEC2\uDED0-\uDED9\uDEE0-\uDEE7]|\uDD3C(?:\u200D[\u2640\u2642]\uFE0F?|\uD83C[\uDFFB-\uDFFF])?|\uDDD1(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?))?|\uDEF1(?:\uD83C(?:\uDFFB(?:\u200D\uD83E\uDEF2\uD83C[\uDFFC-\uDFFF])?|\uDFFC(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFD-\uDFFF])?|\uDFFD(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])?|\uDFFE(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFD\uDFFF])?|\uDFFF(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFE])?))?))/g; + return /[#*0-9]\uFE0F?\u20E3|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]\uFE0F?|[\u261D\u270C\u270D](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\u270A\u270B](?:\uD83C[\uDFFB-\uDFFF])?|[\u23E9-\u23EC\u23F0\u23F3\u25FD\u2693\u26A1\u26AB\u26C5\u26CE\u26D4\u26EA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2795-\u2797\u27B0\u27BF\u2B50]|\u26F9(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\u2764\uFE0F?(?:\u200D(?:\uD83D\uDD25|\uD83E\uDE79))?|\uD83C(?:[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]\uFE0F?|[\uDF85\uDFC2\uDFC7](?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC3\uDFC4\uDFCA](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDFCB\uDFCC](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|\uDFF3\uFE0F?(?:\u200D(?:\u26A7\uFE0F?|\uD83C\uDF08))?|\uDFF4(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDC73\uDB40\uDC63\uDB40\uDC74|\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F)?)|\uD83D(?:[\uDC08\uDC26](?:\u200D\u2B1B)?|[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3]\uFE0F?|[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD74\uDD90](?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?|[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC25\uDC27-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEDC-\uDEDF\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB\uDFF0]|\uDC15(?:\u200D\uD83E\uDDBA)?|\uDC3B(?:\u200D\u2744\uFE0F?)?|\uDC41\uFE0F?(?:\u200D\uD83D\uDDE8\uFE0F?)?|\uDC68(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE])))?))?|\uDC69(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?[\uDC68\uDC69]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?))|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFE])))?))?|\uDC6F(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDD75(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDE2E(?:\u200D\uD83D\uDCA8)?|\uDE35(?:\u200D\uD83D\uDCAB)?|\uDE36(?:\u200D\uD83C\uDF2B\uFE0F?)?)|\uD83E(?:[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF8](?:\uD83C[\uDFFB-\uDFFF])?|[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDDDE\uDDDF](?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD0D\uDD0E\uDD10-\uDD17\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCC\uDDD0\uDDE0-\uDDFF\uDE70-\uDE7C\uDE80-\uDE88\uDE90-\uDEBD\uDEBF-\uDEC2\uDECE-\uDEDB\uDEE0-\uDEE8]|\uDD3C(?:\u200D[\u2640\u2642]\uFE0F?|\uD83C[\uDFFB-\uDFFF])?|\uDDD1(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF-\uDDB3\uDDBC\uDDBD]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF])))?))?|\uDEF1(?:\uD83C(?:\uDFFB(?:\u200D\uD83E\uDEF2\uD83C[\uDFFC-\uDFFF])?|\uDFFC(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFD-\uDFFF])?|\uDFFD(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])?|\uDFFE(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFD\uDFFF])?|\uDFFF(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFE])?))?)/g; }; -/** Normalize a duration to all of the proper units. */ -function normalizeDuration(dur) { - if (dur === undefined || dur === null) - return dur; - return dur.shiftToAll().normalize(); -} -/** Strip the time components of a date time object. */ -function stripTime(dt) { - if (dt === null || dt === undefined) - return dt; - return DateTime.fromObject({ - year: dt.year, - month: dt.month, - day: dt.day, - }); -} -/** Get the folder containing the given path (i.e., like computing 'path/..'). */ -function getParentFolder(path) { - return path.split("/").slice(0, -1).join("/"); -} -/** Get the "title" for a file, by stripping other parts of the path as well as the extension. */ -function getFileTitle(path) { - if (path.includes("/")) - path = path.substring(path.lastIndexOf("/") + 1); - if (path.endsWith(".md")) - path = path.substring(0, path.length - 3); - return path; -} -/** Get the extension of a file from the file path. */ -function getExtension(path) { - if (!path.includes(".")) - return ""; - return path.substring(path.lastIndexOf(".") + 1); -} -/** Parse all subtags out of the given tag. I.e., #hello/i/am would yield [#hello/i/am, #hello/i, #hello]. */ -function extractSubtags(tag) { - let result = [tag]; - while (tag.includes("/")) { - tag = tag.substring(0, tag.lastIndexOf("/")); - result.push(tag); - } - return result; -} -/** Try calling the given function; on failure, return the error message. */ -function tryOrPropogate(func) { - try { - return func(); - } - catch (error) { - return Result.failure("" + error + "\n\n" + error.stack); - } -} -/** Try asynchronously calling the given function; on failure, return the error message. */ -async function asyncTryOrPropogate(func) { - try { - return await func(); - } - catch (error) { - return Result.failure("" + error + "\n\n" + error.stack); - } -} -/** - * Escape regex characters in a string. - * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions. - */ -function escapeRegex(str) { - return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); -} -/** A parsimmon parser which canonicalizes variable names while properly respecting emoji. */ -const VAR_NAME_CANONICALIZER = parsimmon_umd_min.exports.alt(parsimmon_umd_min.exports.regex(new RegExp(emojiRegex(), "")), parsimmon_umd_min.exports.regex(/[0-9\p{Letter}_-]+/u).map(str => str.toLocaleLowerCase()), parsimmon_umd_min.exports.whitespace.map(_ => "-"), parsimmon_umd_min.exports.any.map(_ => "")) - .many() - .map(result => result.join("")); -/** Convert an arbitrary variable name into something JS/query friendly. */ -function canonicalizeVarName(name) { - return VAR_NAME_CANONICALIZER.tryParse(name); -} -const HEADER_CANONICALIZER = parsimmon_umd_min.exports.alt(parsimmon_umd_min.exports.regex(new RegExp(emojiRegex(), "")), parsimmon_umd_min.exports.regex(/[0-9\p{Letter}_-]+/u), parsimmon_umd_min.exports.whitespace.map(_ => " "), parsimmon_umd_min.exports.any.map(_ => " ")) - .many() - .map(result => { - return result.join("").split(/\s+/).join(" ").trim(); -}); -/** - * Normalizes the text in a header to be something that is actually linkable to. This mimics - * how Obsidian does it's normalization, collapsing repeated spaces and stripping out control characters. - */ -function normalizeHeaderForLink(header) { - return HEADER_CANONICALIZER.tryParse(header); -} -/** Render a DateTime in a minimal format to save space. */ -function renderMinimalDate(time, settings, locale) { - // If there is no relevant time specified, fall back to just rendering the date. - if (time.second == 0 && time.minute == 0 && time.hour == 0) { - return time.toLocal().toFormat(settings.defaultDateFormat, { locale }); - } - return time.toLocal().toFormat(settings.defaultDateTimeFormat, { locale }); -} -/** Render a duration in a minimal format to save space. */ -function renderMinimalDuration(dur) { - dur = normalizeDuration(dur); - // toHuman outputs zero quantities e.g. "0 seconds" - dur = Duration.fromObject(Object.fromEntries(Object.entries(dur.toObject()).filter(([, quantity]) => quantity > 0))); - return dur.toHuman(); -} -/** Determine if two sets are equal in contents. */ -function setsEqual(first, second) { - if (first.size != second.size) - return false; - for (let elem of first) - if (!second.has(elem)) - return false; - return true; +/** Normalize a duration to all of the proper units. */ +function normalizeDuration(dur) { + if (dur === undefined || dur === null) + return dur; + return dur.shiftToAll().normalize(); +} +/** Strip the time components of a date time object. */ +function stripTime(dt) { + if (dt === null || dt === undefined) + return dt; + return DateTime.fromObject({ + year: dt.year, + month: dt.month, + day: dt.day, + }); +} +/** Get the folder containing the given path (i.e., like computing 'path/..'). */ +function getParentFolder(path) { + return path.split("/").slice(0, -1).join("/"); +} +/** Get the "title" for a file, by stripping other parts of the path as well as the extension. */ +function getFileTitle(path) { + if (path.includes("/")) + path = path.substring(path.lastIndexOf("/") + 1); + if (path.endsWith(".md")) + path = path.substring(0, path.length - 3); + return path; +} +/** Get the extension of a file from the file path. */ +function getExtension(path) { + if (!path.includes(".")) + return ""; + return path.substring(path.lastIndexOf(".") + 1); +} +/** Parse all subtags out of the given tag. I.e., #hello/i/am would yield [#hello/i/am, #hello/i, #hello]. */ +function extractSubtags(tag) { + let result = [tag]; + while (tag.includes("/")) { + tag = tag.substring(0, tag.lastIndexOf("/")); + result.push(tag); + } + return result; +} +/** Try calling the given function; on failure, return the error message. */ +function tryOrPropogate(func) { + try { + return func(); + } + catch (error) { + return Result.failure("" + error + "\n\n" + error.stack); + } +} +/** Try asynchronously calling the given function; on failure, return the error message. */ +async function asyncTryOrPropogate(func) { + try { + return await func(); + } + catch (error) { + return Result.failure("" + error + "\n\n" + error.stack); + } +} +/** + * Escape regex characters in a string. + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions. + */ +function escapeRegex(str) { + return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} +/** A parsimmon parser which canonicalizes variable names while properly respecting emoji. */ +const VAR_NAME_CANONICALIZER = parsimmon_umd_minExports.alt(parsimmon_umd_minExports.regex(new RegExp(emojiRegex(), "")), parsimmon_umd_minExports.regex(/[0-9\p{Letter}_-]+/u).map(str => str.toLocaleLowerCase()), parsimmon_umd_minExports.whitespace.map(_ => "-"), parsimmon_umd_minExports.any.map(_ => "")) + .many() + .map(result => result.join("")); +/** Convert an arbitrary variable name into something JS/query friendly. */ +function canonicalizeVarName(name) { + return VAR_NAME_CANONICALIZER.tryParse(name); +} +const HEADER_CANONICALIZER = parsimmon_umd_minExports.alt(parsimmon_umd_minExports.regex(new RegExp(emojiRegex(), "")), parsimmon_umd_minExports.regex(/[0-9\p{Letter}_-]+/u), parsimmon_umd_minExports.whitespace.map(_ => " "), parsimmon_umd_minExports.any.map(_ => " ")) + .many() + .map(result => { + return result.join("").split(/\s+/).join(" ").trim(); +}); +/** + * Normalizes the text in a header to be something that is actually linkable to. This mimics + * how Obsidian does it's normalization, collapsing repeated spaces and stripping out control characters. + */ +function normalizeHeaderForLink(header) { + return HEADER_CANONICALIZER.tryParse(header); +} +/** Render a DateTime in a minimal format to save space. */ +function renderMinimalDate(time, settings, locale) { + // If there is no relevant time specified, fall back to just rendering the date. + if (time.second == 0 && time.minute == 0 && time.hour == 0) { + return time.toLocal().toFormat(settings.defaultDateFormat, { locale }); + } + return time.toLocal().toFormat(settings.defaultDateTimeFormat, { locale }); +} +/** Render a duration in a minimal format to save space. */ +function renderMinimalDuration(dur) { + dur = normalizeDuration(dur); + // toHuman outputs zero quantities e.g. "0 seconds" + dur = Duration.fromObject(Object.fromEntries(Object.entries(dur.toObject()).filter(([, quantity]) => quantity != 0))); + return dur.toHuman(); +} +/** Determine if two sets are equal in contents. */ +function setsEqual(first, second) { + if (first.size != second.size) + return false; + for (let elem of first) + if (!second.has(elem)) + return false; + return true; } -var Values; -(function (Values) { - /** Convert an arbitrary value into a reasonable, Markdown-friendly string if possible. */ - function toString(field, setting = DEFAULT_QUERY_SETTINGS, recursive = false) { - let wrapped = wrapValue(field); - if (!wrapped) - return setting.renderNullAs; - switch (wrapped.type) { - case "null": - return setting.renderNullAs; - case "string": - return wrapped.value; - case "number": - case "boolean": - return "" + wrapped.value; - case "html": - return wrapped.value.outerHTML; - case "widget": - return wrapped.value.markdown(); - case "link": - return wrapped.value.markdown(); - case "function": - return ""; - case "array": - let result = ""; - if (recursive) - result += "["; - result += wrapped.value.map(f => toString(f, setting, true)).join(", "); - if (recursive) - result += "]"; - return result; - case "object": - return ("{ " + - Object.entries(wrapped.value) - .map(e => e[0] + ": " + toString(e[1], setting, true)) - .join(", ") + - " }"); - case "date": - if (wrapped.value.second == 0 && wrapped.value.hour == 0 && wrapped.value.minute == 0) { - return wrapped.value.toFormat(setting.defaultDateFormat); - } - return wrapped.value.toFormat(setting.defaultDateTimeFormat); - case "duration": - return renderMinimalDuration(wrapped.value); - } - } - Values.toString = toString; - /** Wrap a literal value so you can switch on it easily. */ - function wrapValue(val) { - if (isNull(val)) - return { type: "null", value: val }; - else if (isNumber(val)) - return { type: "number", value: val }; - else if (isString(val)) - return { type: "string", value: val }; - else if (isBoolean(val)) - return { type: "boolean", value: val }; - else if (isDuration(val)) - return { type: "duration", value: val }; - else if (isDate(val)) - return { type: "date", value: val }; - else if (isWidget(val)) - return { type: "widget", value: val }; - else if (isArray(val)) - return { type: "array", value: val }; - else if (isLink(val)) - return { type: "link", value: val }; - else if (isFunction(val)) - return { type: "function", value: val }; - else if (isHtml(val)) - return { type: "html", value: val }; - else if (isObject(val)) - return { type: "object", value: val }; - else - return undefined; - } - Values.wrapValue = wrapValue; - /** Recursively map complex objects at the leaves. */ - function mapLeaves(val, func) { - if (isObject(val)) { - let result = {}; - for (let [key, value] of Object.entries(val)) - result[key] = mapLeaves(value, func); - return result; - } - else if (isArray(val)) { - let result = []; - for (let value of val) - result.push(mapLeaves(value, func)); - return result; - } - else { - return func(val); - } - } - Values.mapLeaves = mapLeaves; - /** Compare two arbitrary JavaScript values. Produces a total ordering over ANY possible dataview value. */ - function compareValue(val1, val2, linkNormalizer) { - var _a, _b; - // Handle undefined/nulls first. - if (val1 === undefined) - val1 = null; - if (val2 === undefined) - val2 = null; - if (val1 === null && val2 === null) - return 0; - else if (val1 === null) - return -1; - else if (val2 === null) - return 1; - // A non-null value now which we can wrap & compare on. - let wrap1 = wrapValue(val1); - let wrap2 = wrapValue(val2); - if (wrap1 === undefined && wrap2 === undefined) - return 0; - else if (wrap1 === undefined) - return -1; - else if (wrap2 === undefined) - return 1; - // Short-circuit on different types or on reference equality. - if (wrap1.type != wrap2.type) - return wrap1.type.localeCompare(wrap2.type); - if (wrap1.value === wrap2.value) - return 0; - switch (wrap1.type) { - case "string": - return wrap1.value.localeCompare(wrap2.value); - case "number": - if (wrap1.value < wrap2.value) - return -1; - else if (wrap1.value == wrap2.value) - return 0; - return 1; - case "null": - return 0; - case "boolean": - if (wrap1.value == wrap2.value) - return 0; - else - return wrap1.value ? 1 : -1; - case "link": - let link1 = wrap1.value; - let link2 = wrap2.value; - let normalize = linkNormalizer !== null && linkNormalizer !== void 0 ? linkNormalizer : ((x) => x); - // We can't compare by file name or display, since that would break link equality. Compare by path. - let pathCompare = normalize(link1.path).localeCompare(normalize(link2.path)); - if (pathCompare != 0) - return pathCompare; - // Then compare by type. - let typeCompare = link1.type.localeCompare(link2.type); - if (typeCompare != 0) - return typeCompare; - // Then compare by subpath existence. - if (link1.subpath && !link2.subpath) - return 1; - if (!link1.subpath && link2.subpath) - return -1; - if (!link1.subpath && !link2.subpath) - return 0; - // Since both have a subpath, compare by subpath. - return ((_a = link1.subpath) !== null && _a !== void 0 ? _a : "").localeCompare((_b = link2.subpath) !== null && _b !== void 0 ? _b : ""); - case "date": - return wrap1.value < wrap2.value - ? -1 - : wrap1.value.equals(wrap2.value) - ? 0 - : 1; - case "duration": - return wrap1.value < wrap2.value - ? -1 - : wrap1.value.equals(wrap2.value) - ? 0 - : 1; - case "array": - let f1 = wrap1.value; - let f2 = wrap2.value; - for (let index = 0; index < Math.min(f1.length, f2.length); index++) { - let comp = compareValue(f1[index], f2[index]); - if (comp != 0) - return comp; - } - return f1.length - f2.length; - case "object": - let o1 = wrap1.value; - let o2 = wrap2.value; - let k1 = Array.from(Object.keys(o1)); - let k2 = Array.from(Object.keys(o2)); - k1.sort(); - k2.sort(); - let keyCompare = compareValue(k1, k2); - if (keyCompare != 0) - return keyCompare; - for (let key of k1) { - let comp = compareValue(o1[key], o2[key]); - if (comp != 0) - return comp; - } - return 0; - case "widget": - case "html": - case "function": - return 0; - } - } - Values.compareValue = compareValue; - /** Find the corresponding Dataveiw type for an arbitrary value. */ - function typeOf(val) { - var _a; - return (_a = wrapValue(val)) === null || _a === void 0 ? void 0 : _a.type; - } - Values.typeOf = typeOf; - /** Determine if the given value is "truthy" (i.e., is non-null and has data in it). */ - function isTruthy(field) { - let wrapped = wrapValue(field); - if (!wrapped) - return false; - switch (wrapped.type) { - case "number": - return wrapped.value != 0; - case "string": - return wrapped.value.length > 0; - case "boolean": - return wrapped.value; - case "link": - return !!wrapped.value.path; - case "date": - return wrapped.value.toMillis() != 0; - case "duration": - return wrapped.value.as("seconds") != 0; - case "object": - return Object.keys(wrapped.value).length > 0; - case "array": - return wrapped.value.length > 0; - case "null": - return false; - case "html": - case "widget": - case "function": - return true; - } - } - Values.isTruthy = isTruthy; - /** Deep copy a field. */ - function deepCopy(field) { - if (field === null || field === undefined) - return field; - if (Values.isArray(field)) { - return [].concat(field.map(v => deepCopy(v))); - } - else if (Values.isObject(field)) { - let result = {}; - for (let [key, value] of Object.entries(field)) - result[key] = deepCopy(value); - return result; - } - else { - return field; - } - } - Values.deepCopy = deepCopy; - function isString(val) { - return typeof val == "string"; - } - Values.isString = isString; - function isNumber(val) { - return typeof val == "number"; - } - Values.isNumber = isNumber; - function isDate(val) { - return val instanceof DateTime; - } - Values.isDate = isDate; - function isDuration(val) { - return val instanceof Duration; - } - Values.isDuration = isDuration; - function isNull(val) { - return val === null || val === undefined; - } - Values.isNull = isNull; - function isArray(val) { - return Array.isArray(val); - } - Values.isArray = isArray; - function isBoolean(val) { - return typeof val === "boolean"; - } - Values.isBoolean = isBoolean; - function isLink(val) { - return val instanceof Link; - } - Values.isLink = isLink; - function isWidget(val) { - return val instanceof Widget; - } - Values.isWidget = isWidget; - function isHtml(val) { - if (typeof HTMLElement !== "undefined") { - return val instanceof HTMLElement; - } - else { - return false; - } - } - Values.isHtml = isHtml; - /** Checks if the given value is an object (and not any other dataview-recognized object-like type). */ - function isObject(val) { - return (typeof val == "object" && - !isHtml(val) && - !isWidget(val) && - !isArray(val) && - !isDuration(val) && - !isDate(val) && - !isLink(val) && - val !== undefined && - !isNull(val)); - } - Values.isObject = isObject; - function isFunction(val) { - return typeof val == "function"; - } - Values.isFunction = isFunction; -})(Values || (Values = {})); -/////////////// -// Groupings // -/////////////// -var Groupings; -(function (Groupings) { - /** Determines if the given group entry is a standalone value, or a grouping of sub-entries. */ - function isElementGroup(entry) { - return Values.isObject(entry) && Object.keys(entry).length == 2 && "key" in entry && "rows" in entry; - } - Groupings.isElementGroup = isElementGroup; - /** Determines if the given array is a grouping array. */ - function isGrouping(entry) { - for (let element of entry) - if (!isElementGroup(element)) - return false; - return true; - } - Groupings.isGrouping = isGrouping; - /** Count the total number of elements in a recursive grouping. */ - function count(elements) { - if (isGrouping(elements)) { - let result = 0; - for (let subgroup of elements) - result += count(subgroup.rows); - return result; - } - else { - return elements.length; - } - } - Groupings.count = count; -})(Groupings || (Groupings = {})); -////////// -// LINK // -////////// -/** The Obsidian 'link', used for uniquely describing a file, header, or block. */ -class Link { - constructor(fields) { - Object.assign(this, fields); - } - /** Create a link to a specific file. */ - static file(path, embed = false, display) { - return new Link({ - path, - embed, - display, - subpath: undefined, - type: "file", - }); - } - static infer(linkpath, embed = false, display) { - if (linkpath.includes("#^")) { - let split = linkpath.split("#^"); - return Link.block(split[0], split[1], embed, display); - } - else if (linkpath.includes("#")) { - let split = linkpath.split("#"); - return Link.header(split[0], split[1], embed, display); - } - else - return Link.file(linkpath, embed, display); - } - /** Create a link to a specific file and header in that file. */ - static header(path, header, embed, display) { - // Headers need to be normalized to alpha-numeric & with extra spacing removed. - return new Link({ - path, - embed, - display, - subpath: normalizeHeaderForLink(header), - type: "header", - }); - } - /** Create a link to a specific file and block in that file. */ - static block(path, blockId, embed, display) { - return new Link({ - path, - embed, - display, - subpath: blockId, - type: "block", - }); - } - static fromObject(object) { - return new Link(object); - } - /** Checks for link equality (i.e., that the links are pointing to the same exact location). */ - equals(other) { - if (other == undefined || other == null) - return false; - return this.path == other.path && this.type == other.type && this.subpath == other.subpath; - } - /** Convert this link to it's markdown representation. */ - toString() { - return this.markdown(); - } - /** Convert this link to a raw object which is serialization-friendly. */ - toObject() { - return { path: this.path, type: this.type, subpath: this.subpath, display: this.display, embed: this.embed }; - } - /** Update this link with a new path. */ - //@ts-ignore; error appeared after updating Obsidian to 0.15.4; it also updated other packages but didn't say which - withPath(path) { - return new Link(Object.assign({}, this, { path })); - } - /** Return a new link which points to the same location but with a new display value. */ - withDisplay(display) { - return new Link(Object.assign({}, this, { display })); - } - /** Convert a file link into a link to a specific header. */ - withHeader(header) { - return Link.header(this.path, header, this.embed, this.display); - } - /** Convert any link into a link to its file. */ - toFile() { - return Link.file(this.path, this.embed, this.display); - } - /** Convert this link into an embedded link. */ - toEmbed() { - if (this.embed) { - return this; - } - else { - let link = new Link(this); - link.embed = true; - return link; - } - } - /** Convert this link into a non-embedded link. */ - fromEmbed() { - if (!this.embed) { - return this; - } - else { - let link = new Link(this); - link.embed = false; - return link; - } - } - /** Convert this link to markdown so it can be rendered. */ - markdown() { - let result = (this.embed ? "!" : "") + "[[" + this.obsidianLink(); - if (this.display) { - result += "|" + this.display; - } - else { - result += "|" + getFileTitle(this.path); - if (this.type == "header" || this.type == "block") - result += " > " + this.subpath; - } - result += "]]"; - return result; - } - /** Convert the inner part of the link to something that Obsidian can open / understand. */ - obsidianLink() { - var _a, _b; - const escaped = this.path.replace("|", "\\|"); - if (this.type == "header") - return escaped + "#" + ((_a = this.subpath) === null || _a === void 0 ? void 0 : _a.replace("|", "\\|")); - if (this.type == "block") - return escaped + "#^" + ((_b = this.subpath) === null || _b === void 0 ? void 0 : _b.replace("|", "\\|")); - else - return escaped; - } - /** The stripped name of the file this link points to. */ - fileName() { - return getFileTitle(this.path).replace(".md", ""); - } -} -///////////////// -// WIDGET BASE // -///////////////// -/** - * A trivial base class which just defines the '$widget' identifier type. Subtypes of - * widget are responsible for adding whatever metadata is relevant. If you want your widget - * to have rendering functionality (which you probably do), you should extend `RenderWidget`. - */ -class Widget { - constructor($widget) { - this.$widget = $widget; - } -} -/** A trivial widget which renders a (key, value) pair, and allows accessing the key and value. */ -class ListPairWidget extends Widget { - constructor(key, value) { - super("dataview:list-pair"); - this.key = key; - this.value = value; - } - markdown() { - return `${Values.toString(this.key)}: ${Values.toString(this.value)}`; - } -} -/** A simple widget which renders an external link. */ -class ExternalLinkWidget extends Widget { - constructor(url, display) { - super("dataview:external-link"); - this.url = url; - this.display = display; - } - markdown() { - var _a; - return `[${(_a = this.display) !== null && _a !== void 0 ? _a : this.url}](${this.url})`; - } -} -var Widgets; -(function (Widgets) { - /** Create a list pair widget matching the given key and value. */ - function listPair(key, value) { - return new ListPairWidget(key, value); - } - Widgets.listPair = listPair; - /** Create an external link widget which renders an external Obsidian link. */ - function externalLink(url, display) { - return new ExternalLinkWidget(url, display); - } - Widgets.externalLink = externalLink; - /** Checks if the given widget is a list pair widget. */ - function isListPair(widget) { - return widget.$widget === "dataview:list-pair"; - } - Widgets.isListPair = isListPair; - function isExternalLink(widget) { - return widget.$widget === "dataview:external-link"; - } - Widgets.isExternalLink = isExternalLink; - /** Determines if the given widget is any kind of built-in widget with special rendering handling. */ - function isBuiltin(widget) { - return isListPair(widget) || isExternalLink(widget); - } - Widgets.isBuiltin = isBuiltin; +var Values; +(function (Values) { + /** Convert an arbitrary value into a reasonable, Markdown-friendly string if possible. */ + function toString(field, setting = DEFAULT_QUERY_SETTINGS, recursive = false) { + let wrapped = wrapValue(field); + if (!wrapped) + return setting.renderNullAs; + switch (wrapped.type) { + case "null": + return setting.renderNullAs; + case "string": + return wrapped.value; + case "number": + case "boolean": + return "" + wrapped.value; + case "html": + return wrapped.value.outerHTML; + case "widget": + return wrapped.value.markdown(); + case "link": + return wrapped.value.markdown(); + case "function": + return ""; + case "array": + let result = ""; + if (recursive) + result += "["; + result += wrapped.value.map(f => toString(f, setting, true)).join(", "); + if (recursive) + result += "]"; + return result; + case "object": + return ("{ " + + Object.entries(wrapped.value) + .map(e => e[0] + ": " + toString(e[1], setting, true)) + .join(", ") + + " }"); + case "date": + if (wrapped.value.second == 0 && wrapped.value.hour == 0 && wrapped.value.minute == 0) { + return wrapped.value.toFormat(setting.defaultDateFormat); + } + return wrapped.value.toFormat(setting.defaultDateTimeFormat); + case "duration": + return renderMinimalDuration(wrapped.value); + } + } + Values.toString = toString; + /** Wrap a literal value so you can switch on it easily. */ + function wrapValue(val) { + if (isNull(val)) + return { type: "null", value: val }; + else if (isNumber(val)) + return { type: "number", value: val }; + else if (isString(val)) + return { type: "string", value: val }; + else if (isBoolean(val)) + return { type: "boolean", value: val }; + else if (isDuration(val)) + return { type: "duration", value: val }; + else if (isDate(val)) + return { type: "date", value: val }; + else if (isWidget(val)) + return { type: "widget", value: val }; + else if (isArray(val)) + return { type: "array", value: val }; + else if (isLink(val)) + return { type: "link", value: val }; + else if (isFunction(val)) + return { type: "function", value: val }; + else if (isHtml(val)) + return { type: "html", value: val }; + else if (isObject(val)) + return { type: "object", value: val }; + else + return undefined; + } + Values.wrapValue = wrapValue; + /** Recursively map complex objects at the leaves. */ + function mapLeaves(val, func) { + if (isObject(val)) { + let result = {}; + for (let [key, value] of Object.entries(val)) + result[key] = mapLeaves(value, func); + return result; + } + else if (isArray(val)) { + let result = []; + for (let value of val) + result.push(mapLeaves(value, func)); + return result; + } + else { + return func(val); + } + } + Values.mapLeaves = mapLeaves; + /** Compare two arbitrary JavaScript values. Produces a total ordering over ANY possible dataview value. */ + function compareValue(val1, val2, linkNormalizer) { + var _a, _b; + // Handle undefined/nulls first. + if (val1 === undefined) + val1 = null; + if (val2 === undefined) + val2 = null; + if (val1 === null && val2 === null) + return 0; + else if (val1 === null) + return -1; + else if (val2 === null) + return 1; + // A non-null value now which we can wrap & compare on. + let wrap1 = wrapValue(val1); + let wrap2 = wrapValue(val2); + if (wrap1 === undefined && wrap2 === undefined) + return 0; + else if (wrap1 === undefined) + return -1; + else if (wrap2 === undefined) + return 1; + // Short-circuit on different types or on reference equality. + if (wrap1.type != wrap2.type) + return wrap1.type.localeCompare(wrap2.type); + if (wrap1.value === wrap2.value) + return 0; + switch (wrap1.type) { + case "string": + return wrap1.value.localeCompare(wrap2.value); + case "number": + if (wrap1.value < wrap2.value) + return -1; + else if (wrap1.value == wrap2.value) + return 0; + return 1; + case "null": + return 0; + case "boolean": + if (wrap1.value == wrap2.value) + return 0; + else + return wrap1.value ? 1 : -1; + case "link": + let link1 = wrap1.value; + let link2 = wrap2.value; + let normalize = linkNormalizer !== null && linkNormalizer !== void 0 ? linkNormalizer : ((x) => x); + // We can't compare by file name or display, since that would break link equality. Compare by path. + let pathCompare = normalize(link1.path).localeCompare(normalize(link2.path)); + if (pathCompare != 0) + return pathCompare; + // Then compare by type. + let typeCompare = link1.type.localeCompare(link2.type); + if (typeCompare != 0) + return typeCompare; + // Then compare by subpath existence. + if (link1.subpath && !link2.subpath) + return 1; + if (!link1.subpath && link2.subpath) + return -1; + if (!link1.subpath && !link2.subpath) + return 0; + // Since both have a subpath, compare by subpath. + return ((_a = link1.subpath) !== null && _a !== void 0 ? _a : "").localeCompare((_b = link2.subpath) !== null && _b !== void 0 ? _b : ""); + case "date": + return wrap1.value < wrap2.value + ? -1 + : wrap1.value.equals(wrap2.value) + ? 0 + : 1; + case "duration": + return wrap1.value < wrap2.value + ? -1 + : wrap1.value.equals(wrap2.value) + ? 0 + : 1; + case "array": + let f1 = wrap1.value; + let f2 = wrap2.value; + for (let index = 0; index < Math.min(f1.length, f2.length); index++) { + let comp = compareValue(f1[index], f2[index]); + if (comp != 0) + return comp; + } + return f1.length - f2.length; + case "object": + let o1 = wrap1.value; + let o2 = wrap2.value; + let k1 = Array.from(Object.keys(o1)); + let k2 = Array.from(Object.keys(o2)); + k1.sort(); + k2.sort(); + let keyCompare = compareValue(k1, k2); + if (keyCompare != 0) + return keyCompare; + for (let key of k1) { + let comp = compareValue(o1[key], o2[key]); + if (comp != 0) + return comp; + } + return 0; + case "widget": + case "html": + case "function": + return 0; + } + } + Values.compareValue = compareValue; + /** Find the corresponding Dataveiw type for an arbitrary value. */ + function typeOf(val) { + var _a; + return (_a = wrapValue(val)) === null || _a === void 0 ? void 0 : _a.type; + } + Values.typeOf = typeOf; + /** Determine if the given value is "truthy" (i.e., is non-null and has data in it). */ + function isTruthy(field) { + let wrapped = wrapValue(field); + if (!wrapped) + return false; + switch (wrapped.type) { + case "number": + return wrapped.value != 0; + case "string": + return wrapped.value.length > 0; + case "boolean": + return wrapped.value; + case "link": + return !!wrapped.value.path; + case "date": + return wrapped.value.toMillis() != 0; + case "duration": + return wrapped.value.as("seconds") != 0; + case "object": + return Object.keys(wrapped.value).length > 0; + case "array": + return wrapped.value.length > 0; + case "null": + return false; + case "html": + case "widget": + case "function": + return true; + } + } + Values.isTruthy = isTruthy; + /** Deep copy a field. */ + function deepCopy(field) { + if (field === null || field === undefined) + return field; + if (Values.isArray(field)) { + return [].concat(field.map(v => deepCopy(v))); + } + else if (Values.isObject(field)) { + let result = {}; + for (let [key, value] of Object.entries(field)) + result[key] = deepCopy(value); + return result; + } + else { + return field; + } + } + Values.deepCopy = deepCopy; + function isString(val) { + return typeof val == "string"; + } + Values.isString = isString; + function isNumber(val) { + return typeof val == "number"; + } + Values.isNumber = isNumber; + function isDate(val) { + return val instanceof DateTime; + } + Values.isDate = isDate; + function isDuration(val) { + return val instanceof Duration; + } + Values.isDuration = isDuration; + function isNull(val) { + return val === null || val === undefined; + } + Values.isNull = isNull; + function isArray(val) { + return Array.isArray(val); + } + Values.isArray = isArray; + function isBoolean(val) { + return typeof val === "boolean"; + } + Values.isBoolean = isBoolean; + function isLink(val) { + return val instanceof Link; + } + Values.isLink = isLink; + function isWidget(val) { + return val instanceof Widget; + } + Values.isWidget = isWidget; + function isHtml(val) { + if (typeof HTMLElement !== "undefined") { + return val instanceof HTMLElement; + } + else { + return false; + } + } + Values.isHtml = isHtml; + /** Checks if the given value is an object (and not any other dataview-recognized object-like type). */ + function isObject(val) { + return (typeof val == "object" && + !isHtml(val) && + !isWidget(val) && + !isArray(val) && + !isDuration(val) && + !isDate(val) && + !isLink(val) && + val !== undefined && + !isNull(val)); + } + Values.isObject = isObject; + function isFunction(val) { + return typeof val == "function"; + } + Values.isFunction = isFunction; +})(Values || (Values = {})); +/////////////// +// Groupings // +/////////////// +var Groupings; +(function (Groupings) { + /** Determines if the given group entry is a standalone value, or a grouping of sub-entries. */ + function isElementGroup(entry) { + return Values.isObject(entry) && Object.keys(entry).length == 2 && "key" in entry && "rows" in entry; + } + Groupings.isElementGroup = isElementGroup; + /** Determines if the given array is a grouping array. */ + function isGrouping(entry) { + for (let element of entry) + if (!isElementGroup(element)) + return false; + return true; + } + Groupings.isGrouping = isGrouping; + /** Count the total number of elements in a recursive grouping. */ + function count(elements) { + if (isGrouping(elements)) { + let result = 0; + for (let subgroup of elements) + result += count(subgroup.rows); + return result; + } + else { + return elements.length; + } + } + Groupings.count = count; +})(Groupings || (Groupings = {})); +////////// +// LINK // +////////// +/** The Obsidian 'link', used for uniquely describing a file, header, or block. */ +class Link { + /** Create a link to a specific file. */ + static file(path, embed = false, display) { + return new Link({ + path, + embed, + display, + subpath: undefined, + type: "file", + }); + } + static infer(linkpath, embed = false, display) { + if (linkpath.includes("#^")) { + let split = linkpath.split("#^"); + return Link.block(split[0], split[1], embed, display); + } + else if (linkpath.includes("#")) { + let split = linkpath.split("#"); + return Link.header(split[0], split[1], embed, display); + } + else + return Link.file(linkpath, embed, display); + } + /** Create a link to a specific file and header in that file. */ + static header(path, header, embed, display) { + // Headers need to be normalized to alpha-numeric & with extra spacing removed. + return new Link({ + path, + embed, + display, + subpath: normalizeHeaderForLink(header), + type: "header", + }); + } + /** Create a link to a specific file and block in that file. */ + static block(path, blockId, embed, display) { + return new Link({ + path, + embed, + display, + subpath: blockId, + type: "block", + }); + } + static fromObject(object) { + return new Link(object); + } + constructor(fields) { + Object.assign(this, fields); + } + /** Checks for link equality (i.e., that the links are pointing to the same exact location). */ + equals(other) { + if (other == undefined || other == null) + return false; + return this.path == other.path && this.type == other.type && this.subpath == other.subpath; + } + /** Convert this link to it's markdown representation. */ + toString() { + return this.markdown(); + } + /** Convert this link to a raw object which is serialization-friendly. */ + toObject() { + return { path: this.path, type: this.type, subpath: this.subpath, display: this.display, embed: this.embed }; + } + /** Update this link with a new path. */ + //@ts-ignore; error appeared after updating Obsidian to 0.15.4; it also updated other packages but didn't say which + withPath(path) { + return new Link(Object.assign({}, this, { path })); + } + /** Return a new link which points to the same location but with a new display value. */ + withDisplay(display) { + return new Link(Object.assign({}, this, { display })); + } + /** Convert a file link into a link to a specific header. */ + withHeader(header) { + return Link.header(this.path, header, this.embed, this.display); + } + /** Convert any link into a link to its file. */ + toFile() { + return Link.file(this.path, this.embed, this.display); + } + /** Convert this link into an embedded link. */ + toEmbed() { + if (this.embed) { + return this; + } + else { + let link = new Link(this); + link.embed = true; + return link; + } + } + /** Convert this link into a non-embedded link. */ + fromEmbed() { + if (!this.embed) { + return this; + } + else { + let link = new Link(this); + link.embed = false; + return link; + } + } + /** Convert this link to markdown so it can be rendered. */ + markdown() { + let result = (this.embed ? "!" : "") + "[[" + this.obsidianLink(); + if (this.display) { + result += "|" + this.display; + } + else { + result += "|" + getFileTitle(this.path); + if (this.type == "header" || this.type == "block") + result += " > " + this.subpath; + } + result += "]]"; + return result; + } + /** Convert the inner part of the link to something that Obsidian can open / understand. */ + obsidianLink() { + var _a, _b; + const escaped = this.path.replace("|", "\\|"); + if (this.type == "header") + return escaped + "#" + ((_a = this.subpath) === null || _a === void 0 ? void 0 : _a.replace("|", "\\|")); + if (this.type == "block") + return escaped + "#^" + ((_b = this.subpath) === null || _b === void 0 ? void 0 : _b.replace("|", "\\|")); + else + return escaped; + } + /** The stripped name of the file this link points to. */ + fileName() { + return getFileTitle(this.path).replace(".md", ""); + } +} +///////////////// +// WIDGET BASE // +///////////////// +/** + * A trivial base class which just defines the '$widget' identifier type. Subtypes of + * widget are responsible for adding whatever metadata is relevant. If you want your widget + * to have rendering functionality (which you probably do), you should extend `RenderWidget`. + */ +class Widget { + constructor($widget) { + this.$widget = $widget; + } +} +/** A trivial widget which renders a (key, value) pair, and allows accessing the key and value. */ +class ListPairWidget extends Widget { + constructor(key, value) { + super("dataview:list-pair"); + this.key = key; + this.value = value; + } + markdown() { + return `${Values.toString(this.key)}: ${Values.toString(this.value)}`; + } +} +/** A simple widget which renders an external link. */ +class ExternalLinkWidget extends Widget { + constructor(url, display) { + super("dataview:external-link"); + this.url = url; + this.display = display; + } + markdown() { + var _a; + return `[${(_a = this.display) !== null && _a !== void 0 ? _a : this.url}](${this.url})`; + } +} +var Widgets; +(function (Widgets) { + /** Create a list pair widget matching the given key and value. */ + function listPair(key, value) { + return new ListPairWidget(key, value); + } + Widgets.listPair = listPair; + /** Create an external link widget which renders an external Obsidian link. */ + function externalLink(url, display) { + return new ExternalLinkWidget(url, display); + } + Widgets.externalLink = externalLink; + /** Checks if the given widget is a list pair widget. */ + function isListPair(widget) { + return widget.$widget === "dataview:list-pair"; + } + Widgets.isListPair = isListPair; + function isExternalLink(widget) { + return widget.$widget === "dataview:external-link"; + } + Widgets.isExternalLink = isExternalLink; + /** Determines if the given widget is any kind of built-in widget with special rendering handling. */ + function isBuiltin(widget) { + return isListPair(widget) || isExternalLink(widget); + } + Widgets.isBuiltin = isBuiltin; })(Widgets || (Widgets = {})); -/** Implementation of DataArray, minus the dynamic variable access, which is implemented via proxy. */ -class DataArrayImpl { - constructor(values, settings, defaultComparator = Values.compareValue) { - this.values = values; - this.settings = settings; - this.defaultComparator = defaultComparator; - this.length = values.length; - } - static wrap(arr, settings, defaultComparator = Values.compareValue) { - return new Proxy(new DataArrayImpl(arr, settings, defaultComparator), DataArrayImpl.ARRAY_PROXY); - } - lwrap(values) { - return DataArrayImpl.wrap(values, this.settings, this.defaultComparator); - } - where(predicate) { - return this.lwrap(this.values.filter(predicate)); - } - filter(predicate) { - return this.where(predicate); - } - map(f) { - return this.lwrap(this.values.map(f)); - } - flatMap(f) { - let result = []; - for (let index = 0; index < this.length; index++) { - let value = f(this.values[index], index, this.values); - if (!value || value.length == 0) - continue; - for (let r of value) - result.push(r); - } - return this.lwrap(result); - } - mutate(f) { - for (let index = 0; index < this.values.length; index++) { - f(this.values[index], index, this.values); - } - return this; - } - limit(count) { - return this.lwrap(this.values.slice(0, count)); - } - slice(start, end) { - return this.lwrap(this.values.slice(start, end)); - } - concat(other) { - return this.lwrap(this.values.concat(other.values)); - } - /** Return the first index of the given (optionally starting the search) */ - indexOf(element, fromIndex) { - return this.findIndex(e => this.defaultComparator(e, element) == 0, fromIndex); - } - /** Return the first element that satisfies the given predicate. */ - find(pred) { - let index = this.findIndex(pred); - if (index == -1) - return undefined; - else - return this.values[index]; - } - findIndex(pred, fromIndex) { - for (let index = fromIndex !== null && fromIndex !== void 0 ? fromIndex : 0; index < this.length; index++) { - if (pred(this.values[index], index, this.values)) - return index; - } - return -1; - } - includes(element) { - return this.indexOf(element, 0) != -1; - } - join(sep) { - return this.map(s => Values.toString(s, this.settings)) - .array() - .join(sep !== null && sep !== void 0 ? sep : ", "); - } - sort(key, direction, comparator) { - if (this.values.length == 0) - return this; - let realComparator = comparator !== null && comparator !== void 0 ? comparator : this.defaultComparator; - let realKey = key !== null && key !== void 0 ? key : ((l) => l); - // Associate each entry with it's index for the key function, and then do a normal sort. - let copy = [].concat(this.array()).map((elem, index) => { - return { index: index, value: elem }; - }); - copy.sort((a, b) => { - let aKey = realKey(a.value, a.index, this.values); - let bKey = realKey(b.value, b.index, this.values); - return direction === "desc" ? -realComparator(aKey, bKey) : realComparator(aKey, bKey); - }); - return this.lwrap(copy.map(e => e.value)); - } - sortInPlace(key, direction, comparator) { - if (this.values.length == 0) - return this; - let realComparator = comparator !== null && comparator !== void 0 ? comparator : this.defaultComparator; - let realKey = key !== null && key !== void 0 ? key : ((l) => l); - this.values.sort((a, b) => { - let aKey = realKey(a); - let bKey = realKey(b); - return direction == "desc" ? -realComparator(aKey, bKey) : realComparator(aKey, bKey); - }); - return this; - } - groupBy(key, comparator) { - if (this.values.length == 0) - return this.lwrap([]); - // JavaScript sucks and we can't make hash maps over arbitrary types (only strings/ints), so - // we do a poor man algorithm where we SORT, followed by grouping. - let intermediate = this.sort(key, "asc", comparator); - comparator = comparator !== null && comparator !== void 0 ? comparator : this.defaultComparator; - let result = []; - let currentRow = [intermediate[0]]; - let current = key(intermediate[0], 0, intermediate.values); - for (let index = 1; index < intermediate.length; index++) { - let newKey = key(intermediate[index], index, intermediate.values); - if (comparator(current, newKey) != 0) { - result.push({ key: current, rows: this.lwrap(currentRow) }); - current = newKey; - currentRow = [intermediate[index]]; - } - else { - currentRow.push(intermediate[index]); - } - } - result.push({ key: current, rows: this.lwrap(currentRow) }); - return this.lwrap(result); - } - groupIn(key, comparator) { - if (Groupings.isGrouping(this.values)) { - return this.map(v => { - return { - key: v.key, - rows: DataArray.wrap(v.rows, this.settings).groupIn(key, comparator), - }; - }); - } - else { - return this.groupBy(key, comparator); - } - } - distinct(key, comparator) { - if (this.values.length == 0) - return this; - let realKey = key !== null && key !== void 0 ? key : (x => x); - // For similar reasons to groupBy, do a sort and take the first element of each block. - let intermediate = this.map((x, index) => { - return { key: realKey(x, index, this.values), value: x }; - }).sort(x => x.key, "asc", comparator); - comparator = comparator !== null && comparator !== void 0 ? comparator : this.defaultComparator; - let result = [intermediate[0].value]; - for (let index = 1; index < intermediate.length; index++) { - if (comparator(intermediate[index - 1].key, intermediate[index].key) != 0) { - result.push(intermediate[index].value); - } - } - return this.lwrap(result); - } - every(f) { - return this.values.every(f); - } - some(f) { - return this.values.some(f); - } - none(f) { - return this.values.every((v, i, a) => !f(v, i, a)); - } - first() { - return this.values.length > 0 ? this.values[0] : undefined; - } - last() { - return this.values.length > 0 ? this.values[this.values.length - 1] : undefined; - } - to(key) { - let result = []; - for (let child of this.values) { - let value = child[key]; - if (value === undefined || value === null) - continue; - if (Array.isArray(value) || DataArray.isDataArray(value)) - value.forEach(v => result.push(v)); - else - result.push(value); - } - return this.lwrap(result); - } - into(key) { - let result = []; - for (let child of this.values) { - let value = child[key]; - if (value === undefined || value === null) - continue; - result.push(value); - } - return this.lwrap(result); - } - expand(key) { - let result = []; - let queue = [].concat(this.values); - while (queue.length > 0) { - let next = queue.pop(); - let value = next[key]; - if (value === undefined || value === null) - continue; - if (Array.isArray(value)) - value.forEach(v => queue.push(v)); - else if (value instanceof DataArrayImpl) - value.forEach(v => queue.push(v)); - else - queue.push(value); - result.push(next); - } - return this.lwrap(result); - } - forEach(f) { - for (let index = 0; index < this.values.length; index++) { - f(this.values[index], index, this.values); - } - } - array() { - return [].concat(this.values); - } - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - toString() { - return "[" + this.values.join(", ") + "]"; - } -} -DataArrayImpl.ARRAY_FUNCTIONS = new Set([ - "where", - "filter", - "map", - "flatMap", - "mutate", - "slice", - "concat", - "indexOf", - "limit", - "find", - "findIndex", - "includes", - "join", - "sort", - "sortInPlace", - "groupBy", - "groupIn", - "distinct", - "every", - "some", - "none", - "first", - "last", - "to", - "into", - "lwrap", - "expand", - "forEach", - "length", - "values", - "array", - "defaultComparator", - "toString", - "settings", -]); -DataArrayImpl.ARRAY_PROXY = { - get: function (target, prop, reciever) { - if (typeof prop === "symbol") - return target[prop]; - else if (typeof prop === "number") - return target.values[prop]; - else if (prop === "constructor") - return target.values.constructor; - else if (!isNaN(parseInt(prop))) - return target.values[parseInt(prop)]; - else if (DataArrayImpl.ARRAY_FUNCTIONS.has(prop.toString())) - return target[prop.toString()]; - return target.to(prop); - }, -}; -/** Provides utility functions for generating data arrays. */ -var DataArray; -(function (DataArray) { - /** Create a new Dataview data array. */ - function wrap(raw, settings) { - if (isDataArray(raw)) - return raw; - return DataArrayImpl.wrap(raw, settings); - } - DataArray.wrap = wrap; - /** Create a new DataArray from an iterable object. */ - function from(raw, settings) { - if (isDataArray(raw)) - return raw; - let data = []; - for (let elem of raw) - data.push(elem); - return DataArrayImpl.wrap(data, settings); - } - DataArray.from = from; - /** Return true if the given object is a data array. */ - function isDataArray(obj) { - return obj instanceof DataArrayImpl; - } - DataArray.isDataArray = isDataArray; -})(DataArray || (DataArray = {})); -// A scary looking polyfill, sure, but it fixes up data array/array interop for us. -const oldArrayIsArray = Array.isArray; -Array.isArray = (arg) => { - return oldArrayIsArray(arg) || DataArray.isDataArray(arg); +/** Implementation of DataArray, minus the dynamic variable access, which is implemented via proxy. */ +class DataArrayImpl { + static wrap(arr, settings, defaultComparator = Values.compareValue) { + return new Proxy(new DataArrayImpl(arr, settings, defaultComparator), DataArrayImpl.ARRAY_PROXY); + } + constructor(values, settings, defaultComparator = Values.compareValue) { + this.values = values; + this.settings = settings; + this.defaultComparator = defaultComparator; + this.length = values.length; + } + lwrap(values) { + return DataArrayImpl.wrap(values, this.settings, this.defaultComparator); + } + where(predicate) { + return this.lwrap(this.values.filter(predicate)); + } + filter(predicate) { + return this.where(predicate); + } + map(f) { + return this.lwrap(this.values.map(f)); + } + flatMap(f) { + let result = []; + for (let index = 0; index < this.length; index++) { + let value = f(this.values[index], index, this.values); + if (!value || value.length == 0) + continue; + for (let r of value) + result.push(r); + } + return this.lwrap(result); + } + mutate(f) { + for (let index = 0; index < this.values.length; index++) { + f(this.values[index], index, this.values); + } + return this; + } + limit(count) { + return this.lwrap(this.values.slice(0, count)); + } + slice(start, end) { + return this.lwrap(this.values.slice(start, end)); + } + concat(other) { + return this.lwrap(this.values.concat(other.values)); + } + /** Return the first index of the given (optionally starting the search) */ + indexOf(element, fromIndex) { + return this.findIndex(e => this.defaultComparator(e, element) == 0, fromIndex); + } + /** Return the first element that satisfies the given predicate. */ + find(pred) { + let index = this.findIndex(pred); + if (index == -1) + return undefined; + else + return this.values[index]; + } + findIndex(pred, fromIndex) { + for (let index = fromIndex !== null && fromIndex !== void 0 ? fromIndex : 0; index < this.length; index++) { + if (pred(this.values[index], index, this.values)) + return index; + } + return -1; + } + includes(element) { + return this.indexOf(element, 0) != -1; + } + join(sep) { + return this.map(s => Values.toString(s, this.settings)) + .array() + .join(sep !== null && sep !== void 0 ? sep : ", "); + } + sort(key, direction, comparator) { + if (this.values.length == 0) + return this; + let realComparator = comparator !== null && comparator !== void 0 ? comparator : this.defaultComparator; + let realKey = key !== null && key !== void 0 ? key : ((l) => l); + // Associate each entry with it's index for the key function, and then do a normal sort. + let copy = [].concat(this.array()).map((elem, index) => { + return { index: index, value: elem }; + }); + copy.sort((a, b) => { + let aKey = realKey(a.value, a.index, this.values); + let bKey = realKey(b.value, b.index, this.values); + return direction === "desc" ? -realComparator(aKey, bKey) : realComparator(aKey, bKey); + }); + return this.lwrap(copy.map(e => e.value)); + } + sortInPlace(key, direction, comparator) { + if (this.values.length == 0) + return this; + let realComparator = comparator !== null && comparator !== void 0 ? comparator : this.defaultComparator; + let realKey = key !== null && key !== void 0 ? key : ((l) => l); + this.values.sort((a, b) => { + let aKey = realKey(a); + let bKey = realKey(b); + return direction == "desc" ? -realComparator(aKey, bKey) : realComparator(aKey, bKey); + }); + return this; + } + groupBy(key, comparator) { + if (this.values.length == 0) + return this.lwrap([]); + // JavaScript sucks and we can't make hash maps over arbitrary types (only strings/ints), so + // we do a poor man algorithm where we SORT, followed by grouping. + let intermediate = this.sort(key, "asc", comparator); + comparator = comparator !== null && comparator !== void 0 ? comparator : this.defaultComparator; + let result = []; + let currentRow = [intermediate[0]]; + let current = key(intermediate[0], 0, intermediate.values); + for (let index = 1; index < intermediate.length; index++) { + let newKey = key(intermediate[index], index, intermediate.values); + if (comparator(current, newKey) != 0) { + result.push({ key: current, rows: this.lwrap(currentRow) }); + current = newKey; + currentRow = [intermediate[index]]; + } + else { + currentRow.push(intermediate[index]); + } + } + result.push({ key: current, rows: this.lwrap(currentRow) }); + return this.lwrap(result); + } + groupIn(key, comparator) { + if (Groupings.isGrouping(this.values)) { + return this.map(v => { + return { + key: v.key, + rows: DataArray.wrap(v.rows, this.settings).groupIn(key, comparator), + }; + }); + } + else { + return this.groupBy(key, comparator); + } + } + distinct(key, comparator) { + if (this.values.length == 0) + return this; + let realKey = key !== null && key !== void 0 ? key : (x => x); + // For similar reasons to groupBy, do a sort and take the first element of each block. + let intermediate = this.map((x, index) => { + return { key: realKey(x, index, this.values), value: x }; + }).sort(x => x.key, "asc", comparator); + comparator = comparator !== null && comparator !== void 0 ? comparator : this.defaultComparator; + let result = [intermediate[0].value]; + for (let index = 1; index < intermediate.length; index++) { + if (comparator(intermediate[index - 1].key, intermediate[index].key) != 0) { + result.push(intermediate[index].value); + } + } + return this.lwrap(result); + } + every(f) { + return this.values.every(f); + } + some(f) { + return this.values.some(f); + } + none(f) { + return this.values.every((v, i, a) => !f(v, i, a)); + } + first() { + return this.values.length > 0 ? this.values[0] : undefined; + } + last() { + return this.values.length > 0 ? this.values[this.values.length - 1] : undefined; + } + to(key) { + let result = []; + for (let child of this.values) { + let value = child[key]; + if (value === undefined || value === null) + continue; + if (Array.isArray(value) || DataArray.isDataArray(value)) + value.forEach(v => result.push(v)); + else + result.push(value); + } + return this.lwrap(result); + } + into(key) { + let result = []; + for (let child of this.values) { + let value = child[key]; + if (value === undefined || value === null) + continue; + result.push(value); + } + return this.lwrap(result); + } + expand(key) { + let result = []; + let queue = [].concat(this.values); + while (queue.length > 0) { + let next = queue.pop(); + let value = next[key]; + if (value === undefined || value === null) + continue; + if (Array.isArray(value)) + value.forEach(v => queue.push(v)); + else if (value instanceof DataArrayImpl) + value.forEach(v => queue.push(v)); + else + queue.push(value); + result.push(next); + } + return this.lwrap(result); + } + forEach(f) { + for (let index = 0; index < this.values.length; index++) { + f(this.values[index], index, this.values); + } + } + array() { + return [].concat(this.values); + } + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + toString() { + return "[" + this.values.join(", ") + "]"; + } +} +DataArrayImpl.ARRAY_FUNCTIONS = new Set([ + "where", + "filter", + "map", + "flatMap", + "mutate", + "slice", + "concat", + "indexOf", + "limit", + "find", + "findIndex", + "includes", + "join", + "sort", + "sortInPlace", + "groupBy", + "groupIn", + "distinct", + "every", + "some", + "none", + "first", + "last", + "to", + "into", + "lwrap", + "expand", + "forEach", + "length", + "values", + "array", + "defaultComparator", + "toString", + "settings", +]); +DataArrayImpl.ARRAY_PROXY = { + get: function (target, prop, reciever) { + if (typeof prop === "symbol") + return target[prop]; + else if (typeof prop === "number") + return target.values[prop]; + else if (prop === "constructor") + return target.values.constructor; + else if (!isNaN(parseInt(prop))) + return target.values[parseInt(prop)]; + else if (DataArrayImpl.ARRAY_FUNCTIONS.has(prop.toString())) + return target[prop.toString()]; + return target.to(prop); + }, +}; +/** Provides utility functions for generating data arrays. */ +var DataArray; +(function (DataArray) { + /** Create a new Dataview data array. */ + function wrap(raw, settings) { + if (isDataArray(raw)) + return raw; + return DataArrayImpl.wrap(raw, settings); + } + DataArray.wrap = wrap; + /** Create a new DataArray from an iterable object. */ + function from(raw, settings) { + if (isDataArray(raw)) + return raw; + let data = []; + for (let elem of raw) + data.push(elem); + return DataArrayImpl.wrap(data, settings); + } + DataArray.from = from; + /** Return true if the given object is a data array. */ + function isDataArray(obj) { + return obj instanceof DataArrayImpl; + } + DataArray.isDataArray = isDataArray; +})(DataArray || (DataArray = {})); +// A scary looking polyfill, sure, but it fixes up data array/array interop for us. +const oldArrayIsArray = Array.isArray; +Array.isArray = (arg) => { + return oldArrayIsArray(arg) || DataArray.isDataArray(arg); }; -/** Test-environment-friendly function which fetches the current system locale. */ -function currentLocale() { - if (typeof window === "undefined") - return "en-US"; - return window.navigator.language; +/** Test-environment-friendly function which fetches the current system locale. */ +function currentLocale() { + if (typeof window === "undefined") + return "en-US"; + return window.navigator.language; } -/** Render simple fields compactly, removing wrapping content like paragraph and span. */ -async function renderCompactMarkdown(markdown, container, sourcePath, component) { - let subcontainer = container.createSpan(); - await obsidian.MarkdownRenderer.renderMarkdown(markdown, subcontainer, sourcePath, component); - let paragraph = subcontainer.querySelector(":scope > p"); - if (subcontainer.children.length == 1 && paragraph) { - while (paragraph.firstChild) { - subcontainer.appendChild(paragraph.firstChild); - } - subcontainer.removeChild(paragraph); - } -} -/** Render a pre block with an error in it; returns the element to allow for dynamic updating. */ -function renderErrorPre(container, error) { - let pre = container.createEl("pre", { cls: ["dataview", "dataview-error"] }); - pre.appendText(error); - return pre; -} -/** Render a static codeblock. */ -function renderCodeBlock(container, source, language) { - let code = container.createEl("code", { cls: ["dataview"] }); - if (language) - code.classList.add("language-" + language); - code.appendText(source); - return code; -} -/** Prettily render a value into a container with the given settings. */ -async function renderValue(field, container, originFile, component, settings, expandList = false, context = "root", depth = 0) { - var _a, _b, _c; - // Prevent infinite recursion. - if (depth > settings.maxRecursiveRenderDepth) { - container.appendText("..."); - return; - } - if (Values.isNull(field)) { - await renderCompactMarkdown(settings.renderNullAs, container, originFile, component); - } - else if (Values.isDate(field)) { - container.appendText(renderMinimalDate(field, settings, currentLocale())); - } - else if (Values.isDuration(field)) { - container.appendText(renderMinimalDuration(field)); - } - else if (Values.isString(field) || Values.isBoolean(field) || Values.isNumber(field)) { - await renderCompactMarkdown("" + field, container, originFile, component); - } - else if (Values.isLink(field)) { - await renderCompactMarkdown(field.markdown(), container, originFile, component); - } - else if (Values.isHtml(field)) { - container.appendChild(field); - } - else if (Values.isWidget(field)) { - if (Widgets.isListPair(field)) { - await renderValue(field.key, container, originFile, component, settings, expandList, context, depth); - container.appendText(": "); - await renderValue(field.value, container, originFile, component, settings, expandList, context, depth); - } - else if (Widgets.isExternalLink(field)) { - let elem = document.createElement("a"); - elem.textContent = (_a = field.display) !== null && _a !== void 0 ? _a : field.url; - elem.rel = "noopener"; - elem.target = "_blank"; - elem.classList.add("external-link"); - elem.href = field.url; - container.appendChild(elem); - } - else { - container.appendText(``); - } - } - else if (Values.isFunction(field)) { - container.appendText(""); - } - else if (Values.isArray(field) || DataArray.isDataArray(field)) { - if (expandList) { - let list = container.createEl("ul", { - cls: [ - "dataview", - "dataview-ul", - context == "list" ? "dataview-result-list-ul" : "dataview-result-list-root-ul", - ], - }); - for (let child of field) { - let li = list.createEl("li", { cls: "dataview-result-list-li" }); - await renderValue(child, li, originFile, component, settings, expandList, "list", depth + 1); - } - } - else { - if (field.length == 0) { - container.appendText(""); - return; - } - let span = container.createEl("span", { cls: ["dataview", "dataview-result-list-span"] }); - let first = true; - for (let val of field) { - if (first) - first = false; - else - span.appendText(", "); - await renderValue(val, span, originFile, component, settings, expandList, "list", depth + 1); - } - } - } - else if (Values.isObject(field)) { - // Don't render classes in case they have recursive references; spoopy. - if (((_b = field === null || field === void 0 ? void 0 : field.constructor) === null || _b === void 0 ? void 0 : _b.name) && ((_c = field === null || field === void 0 ? void 0 : field.constructor) === null || _c === void 0 ? void 0 : _c.name) != "Object") { - container.appendText(`<${field.constructor.name}>`); - return; - } - if (expandList) { - let list = container.createEl("ul", { cls: ["dataview", "dataview-ul", "dataview-result-object-ul"] }); - for (let [key, value] of Object.entries(field)) { - let li = list.createEl("li", { cls: ["dataview", "dataview-li", "dataview-result-object-li"] }); - li.appendText(key + ": "); - await renderValue(value, li, originFile, component, settings, expandList, "list", depth + 1); - } - } - else { - if (Object.keys(field).length == 0) { - container.appendText(""); - return; - } - let span = container.createEl("span", { cls: ["dataview", "dataview-result-object-span"] }); - let first = true; - for (let [key, value] of Object.entries(field)) { - if (first) - first = false; - else - span.appendText(", "); - span.appendText(key + ": "); - await renderValue(value, span, originFile, component, settings, expandList, "list", depth + 1); - } - } - } - else { - container.appendText("Unrecognized: " + JSON.stringify(field)); - } +/** Render simple fields compactly, removing wrapping content like paragraph and span. */ +async function renderCompactMarkdown(markdown, container, sourcePath, component) { + let subcontainer = container.createSpan(); + await obsidian.MarkdownRenderer.renderMarkdown(markdown, subcontainer, sourcePath, component); + let paragraph = subcontainer.querySelector(":scope > p"); + if (subcontainer.children.length == 1 && paragraph) { + while (paragraph.firstChild) { + subcontainer.appendChild(paragraph.firstChild); + } + subcontainer.removeChild(paragraph); + } +} +/** Render a pre block with an error in it; returns the element to allow for dynamic updating. */ +function renderErrorPre(container, error) { + let pre = container.createEl("pre", { cls: ["dataview", "dataview-error"] }); + pre.appendText(error); + return pre; +} +/** Render a static codeblock. */ +function renderCodeBlock(container, source, language) { + let code = container.createEl("code", { cls: ["dataview"] }); + if (language) + code.classList.add("language-" + language); + code.appendText(source); + return code; +} +/** Prettily render a value into a container with the given settings. */ +async function renderValue(field, container, originFile, component, settings, expandList = false, context = "root", depth = 0) { + var _a, _b, _c; + // Prevent infinite recursion. + if (depth > settings.maxRecursiveRenderDepth) { + container.appendText("..."); + return; + } + if (Values.isNull(field)) { + await renderCompactMarkdown(settings.renderNullAs, container, originFile, component); + } + else if (Values.isDate(field)) { + container.appendText(renderMinimalDate(field, settings, currentLocale())); + } + else if (Values.isDuration(field)) { + container.appendText(renderMinimalDuration(field)); + } + else if (Values.isString(field) || Values.isBoolean(field) || Values.isNumber(field)) { + await renderCompactMarkdown("" + field, container, originFile, component); + } + else if (Values.isLink(field)) { + await renderCompactMarkdown(field.markdown(), container, originFile, component); + } + else if (Values.isHtml(field)) { + container.appendChild(field); + } + else if (Values.isWidget(field)) { + if (Widgets.isListPair(field)) { + await renderValue(field.key, container, originFile, component, settings, expandList, context, depth); + container.appendText(": "); + await renderValue(field.value, container, originFile, component, settings, expandList, context, depth); + } + else if (Widgets.isExternalLink(field)) { + let elem = document.createElement("a"); + elem.textContent = (_a = field.display) !== null && _a !== void 0 ? _a : field.url; + elem.rel = "noopener"; + elem.target = "_blank"; + elem.classList.add("external-link"); + elem.href = field.url; + container.appendChild(elem); + } + else { + container.appendText(``); + } + } + else if (Values.isFunction(field)) { + container.appendText(""); + } + else if (Values.isArray(field) || DataArray.isDataArray(field)) { + if (expandList) { + let list = container.createEl("ul", { + cls: [ + "dataview", + "dataview-ul", + context == "list" ? "dataview-result-list-ul" : "dataview-result-list-root-ul", + ], + }); + for (let child of field) { + let li = list.createEl("li", { cls: "dataview-result-list-li" }); + await renderValue(child, li, originFile, component, settings, expandList, "list", depth + 1); + } + } + else { + if (field.length == 0) { + container.appendText(""); + return; + } + let span = container.createEl("span", { cls: ["dataview", "dataview-result-list-span"] }); + let first = true; + for (let val of field) { + if (first) + first = false; + else + span.appendText(", "); + await renderValue(val, span, originFile, component, settings, expandList, "list", depth + 1); + } + } + } + else if (Values.isObject(field)) { + // Don't render classes in case they have recursive references; spoopy. + if (((_b = field === null || field === void 0 ? void 0 : field.constructor) === null || _b === void 0 ? void 0 : _b.name) && ((_c = field === null || field === void 0 ? void 0 : field.constructor) === null || _c === void 0 ? void 0 : _c.name) != "Object") { + container.appendText(`<${field.constructor.name}>`); + return; + } + if (expandList) { + let list = container.createEl("ul", { cls: ["dataview", "dataview-ul", "dataview-result-object-ul"] }); + for (let [key, value] of Object.entries(field)) { + let li = list.createEl("li", { cls: ["dataview", "dataview-li", "dataview-result-object-li"] }); + li.appendText(key + ": "); + await renderValue(value, li, originFile, component, settings, expandList, "list", depth + 1); + } + } + else { + if (Object.keys(field).length == 0) { + container.appendText(""); + return; + } + let span = container.createEl("span", { cls: ["dataview", "dataview-result-object-span"] }); + let first = true; + for (let [key, value] of Object.entries(field)) { + if (first) + first = false; + else + span.appendText(", "); + span.appendText(key + ": "); + await renderValue(value, span, originFile, component, settings, expandList, "list", depth + 1); + } + } + } + else { + container.appendText("Unrecognized: " + JSON.stringify(field)); + } } var papaparse_min = {exports: {}}; /* @license Papa Parse -v5.3.2 +v5.4.1 https://github.com/mholt/PapaParse License: MIT */ +papaparse_min.exports; (function (module, exports) { -!function(e,t){module.exports=t();}(commonjsGlobal,function s(){var f="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==f?f:{};var n=!f.document&&!!f.postMessage,o=n&&/blob:/i.test((f.location||{}).protocol),a={},h=0,b={parse:function(e,t){var i=(t=t||{}).dynamicTyping||!1;M(i)&&(t.dynamicTypingFunction=i,i={});if(t.dynamicTyping=i,t.transform=!!M(t.transform)&&t.transform,t.worker&&b.WORKERS_SUPPORTED){var r=function(){if(!b.WORKERS_SUPPORTED)return !1;var e=(i=f.URL||f.webkitURL||null,r=s.toString(),b.BLOB_URL||(b.BLOB_URL=i.createObjectURL(new Blob(["(",r,")();"],{type:"text/javascript"})))),t=new f.Worker(e);var i,r;return t.onmessage=_,t.id=h++,a[t.id]=t}();return r.userStep=t.step,r.userChunk=t.chunk,r.userComplete=t.complete,r.userError=t.error,t.step=M(t.step),t.chunk=M(t.chunk),t.complete=M(t.complete),t.error=M(t.error),delete t.worker,void r.postMessage({input:e,config:t,workerId:r.id})}var n=null;b.NODE_STREAM_INPUT,"string"==typeof e?n=t.download?new l(t):new p(t):!0===e.readable&&M(e.read)&&M(e.on)?n=new g(t):(f.File&&e instanceof File||e instanceof Object)&&(n=new c(t));return n.stream(e)},unparse:function(e,t){var n=!1,_=!0,m=",",y="\r\n",s='"',a=s+s,i=!1,r=null,o=!1;!function(){if("object"!=typeof t)return;"string"!=typeof t.delimiter||b.BAD_DELIMITERS.filter(function(e){return -1!==t.delimiter.indexOf(e)}).length||(m=t.delimiter);("boolean"==typeof t.quotes||"function"==typeof t.quotes||Array.isArray(t.quotes))&&(n=t.quotes);"boolean"!=typeof t.skipEmptyLines&&"string"!=typeof t.skipEmptyLines||(i=t.skipEmptyLines);"string"==typeof t.newline&&(y=t.newline);"string"==typeof t.quoteChar&&(s=t.quoteChar);"boolean"==typeof t.header&&(_=t.header);if(Array.isArray(t.columns)){if(0===t.columns.length)throw new Error("Option columns is empty");r=t.columns;}void 0!==t.escapeChar&&(a=t.escapeChar+s);("boolean"==typeof t.escapeFormulae||t.escapeFormulae instanceof RegExp)&&(o=t.escapeFormulae instanceof RegExp?t.escapeFormulae:/^[=+\-@\t\r].*$/);}();var h=new RegExp(j(s),"g");"string"==typeof e&&(e=JSON.parse(e));if(Array.isArray(e)){if(!e.length||Array.isArray(e[0]))return u(null,e,i);if("object"==typeof e[0])return u(r||Object.keys(e[0]),e,i)}else if("object"==typeof e)return "string"==typeof e.data&&(e.data=JSON.parse(e.data)),Array.isArray(e.data)&&(e.fields||(e.fields=e.meta&&e.meta.fields||r),e.fields||(e.fields=Array.isArray(e.data[0])?e.fields:"object"==typeof e.data[0]?Object.keys(e.data[0]):[]),Array.isArray(e.data[0])||"object"==typeof e.data[0]||(e.data=[e.data])),u(e.fields||[],e.data||[],i);throw new Error("Unable to serialize unrecognized input");function u(e,t,i){var r="";"string"==typeof e&&(e=JSON.parse(e)),"string"==typeof t&&(t=JSON.parse(t));var n=Array.isArray(e)&&0=this._config.preview;if(o)f.postMessage({results:n,workerId:b.WORKER_ID,finished:a});else if(M(this._config.chunk)&&!t){if(this._config.chunk(n,this._handle),this._handle.paused()||this._handle.aborted())return void(this._halted=!0);n=void 0,this._completeResults=void 0;}return this._config.step||this._config.chunk||(this._completeResults.data=this._completeResults.data.concat(n.data),this._completeResults.errors=this._completeResults.errors.concat(n.errors),this._completeResults.meta=n.meta),this._completed||!a||!M(this._config.complete)||n&&n.meta.aborted||(this._config.complete(this._completeResults,this._input),this._completed=!0),a||n&&n.meta.paused||this._nextChunk(),n}this._halted=!0;},this._sendError=function(e){M(this._config.error)?this._config.error(e):o&&this._config.error&&f.postMessage({workerId:b.WORKER_ID,error:e,finished:!1});};}function l(e){var r;(e=e||{}).chunkSize||(e.chunkSize=b.RemoteChunkSize),u.call(this,e),this._nextChunk=n?function(){this._readChunk(),this._chunkLoaded();}:function(){this._readChunk();},this.stream=function(e){this._input=e,this._nextChunk();},this._readChunk=function(){if(this._finished)this._chunkLoaded();else {if(r=new XMLHttpRequest,this._config.withCredentials&&(r.withCredentials=this._config.withCredentials),n||(r.onload=v(this._chunkLoaded,this),r.onerror=v(this._chunkError,this)),r.open(this._config.downloadRequestBody?"POST":"GET",this._input,!n),this._config.downloadRequestHeaders){var e=this._config.downloadRequestHeaders;for(var t in e)r.setRequestHeader(t,e[t]);}if(this._config.chunkSize){var i=this._start+this._config.chunkSize-1;r.setRequestHeader("Range","bytes="+this._start+"-"+i);}try{r.send(this._config.downloadRequestBody);}catch(e){this._chunkError(e.message);}n&&0===r.status&&this._chunkError();}},this._chunkLoaded=function(){4===r.readyState&&(r.status<200||400<=r.status?this._chunkError():(this._start+=this._config.chunkSize?this._config.chunkSize:r.responseText.length,this._finished=!this._config.chunkSize||this._start>=function(e){var t=e.getResponseHeader("Content-Range");if(null===t)return -1;return parseInt(t.substring(t.lastIndexOf("/")+1))}(r),this.parseChunk(r.responseText)));},this._chunkError=function(e){var t=r.statusText||e;this._sendError(new Error(t));};}function c(e){var r,n;(e=e||{}).chunkSize||(e.chunkSize=b.LocalChunkSize),u.call(this,e);var s="undefined"!=typeof FileReader;this.stream=function(e){this._input=e,n=e.slice||e.webkitSlice||e.mozSlice,s?((r=new FileReader).onload=v(this._chunkLoaded,this),r.onerror=v(this._chunkError,this)):r=new FileReaderSync,this._nextChunk();},this._nextChunk=function(){this._finished||this._config.preview&&!(this._rowCount=this._input.size,this.parseChunk(e.target.result);},this._chunkError=function(){this._sendError(r.error);};}function p(e){var i;u.call(this,e=e||{}),this.stream=function(e){return i=e,this._nextChunk()},this._nextChunk=function(){if(!this._finished){var e,t=this._config.chunkSize;return t?(e=i.substring(0,t),i=i.substring(t)):(e=i,i=""),this._finished=!i,this.parseChunk(e)}};}function g(e){u.call(this,e=e||{});var t=[],i=!0,r=!1;this.pause=function(){u.prototype.pause.apply(this,arguments),this._input.pause();},this.resume=function(){u.prototype.resume.apply(this,arguments),this._input.resume();},this.stream=function(e){this._input=e,this._input.on("data",this._streamData),this._input.on("end",this._streamEnd),this._input.on("error",this._streamError);},this._checkIsFinished=function(){r&&1===t.length&&(this._finished=!0);},this._nextChunk=function(){this._checkIsFinished(),t.length?this.parseChunk(t.shift()):i=!0;},this._streamData=v(function(e){try{t.push("string"==typeof e?e:e.toString(this._config.encoding)),i&&(i=!1,this._checkIsFinished(),this.parseChunk(t.shift()));}catch(e){this._streamError(e);}},this),this._streamError=v(function(e){this._streamCleanUp(),this._sendError(e);},this),this._streamEnd=v(function(){this._streamCleanUp(),r=!0,this._streamData("");},this),this._streamCleanUp=v(function(){this._input.removeListener("data",this._streamData),this._input.removeListener("end",this._streamEnd),this._input.removeListener("error",this._streamError);},this);}function i(m){var a,o,h,r=Math.pow(2,53),n=-r,s=/^\s*-?(\d+\.?|\.\d+|\d+\.\d+)([eE][-+]?\d+)?\s*$/,u=/^(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))$/,t=this,i=0,f=0,d=!1,e=!1,l=[],c={data:[],errors:[],meta:{}};if(M(m.step)){var p=m.step;m.step=function(e){if(c=e,_())g();else {if(g(),0===c.data.length)return;i+=e.data.length,m.preview&&i>m.preview?o.abort():(c.data=c.data[0],p(c,t));}};}function y(e){return "greedy"===m.skipEmptyLines?""===e.join("").trim():1===e.length&&0===e[0].length}function g(){return c&&h&&(k("Delimiter","UndetectableDelimiter","Unable to auto-detect delimiting character; defaulted to '"+b.DefaultDelimiter+"'"),h=!1),m.skipEmptyLines&&(c.data=c.data.filter(function(e){return !y(e)})),_()&&function(){if(!c)return;function e(e,t){M(m.transformHeader)&&(e=m.transformHeader(e,t)),l.push(e);}if(Array.isArray(c.data[0])){for(var t=0;_()&&t=l.length?"__parsed_extra":l[i]),m.transform&&(s=m.transform(s,n)),s=v(n,s),"__parsed_extra"===n?(r[n]=r[n]||[],r[n].push(s)):r[n]=s;}return m.header&&(i>l.length?k("FieldMismatch","TooManyFields","Too many fields: expected "+l.length+" fields but parsed "+i,f+t):i=r.length/2?"\r\n":"\r"}(e,r)),h=!1,m.delimiter)M(m.delimiter)&&(m.delimiter=m.delimiter(e),c.meta.delimiter=m.delimiter);else {var n=function(e,t,i,r,n){var s,a,o,h;n=n||[",","\t","|",";",b.RECORD_SEP,b.UNIT_SEP];for(var u=0;u=D)return C(!0)}else for(m=F,F++;;){if(-1===(m=r.indexOf(S,m+1)))return i||u.push({type:"Quotes",code:"MissingQuotes",message:"Quoted field unterminated",row:h.length,index:F}),E();if(m===n-1)return E(r.substring(F,m).replace(_,S));if(S!==L||r[m+1]!==L){if(S===L||0===m||r[m-1]!==L){-1!==p&&p=D)return C(!0);break}u.push({type:"Quotes",code:"InvalidQuotes",message:"Trailing quote on quoted field is malformed",row:h.length,index:F}),m++;}}else m++;}return E();function k(e){h.push(e),d=F;}function b(e){var t=0;if(-1!==e){var i=r.substring(m+1,e);i&&""===i.trim()&&(t=i.length);}return t}function E(e){return i||(void 0===e&&(e=r.substring(F)),f.push(e),F=n,k(f),o&&R()),C()}function w(e){F=e,k(f),f=[],g=r.indexOf(x,F);}function C(e){return {data:h,errors:u,meta:{delimiter:O,linebreak:x,aborted:z,truncated:!!e,cursor:d+(t||0)}}}function R(){T(C()),h=[],u=[];}},this.abort=function(){z=!0;},this.getCharIndex=function(){return F};}function _(e){var t=e.data,i=a[t.workerId],r=!1;if(t.error)i.userError(t.error,t.file);else if(t.results&&t.results.data){var n={abort:function(){r=!0,m(t.workerId,{data:[],errors:[],meta:{aborted:!0}});},pause:y,resume:y};if(M(i.userStep)){for(var s=0;s=this._config.preview;if(o)f.postMessage({results:n,workerId:b.WORKER_ID,finished:a});else if(J(this._config.chunk)&&!t){if(this._config.chunk(n,this._handle),this._handle.paused()||this._handle.aborted())return void(this._halted=!0);n=void 0,this._completeResults=void 0;}return this._config.step||this._config.chunk||(this._completeResults.data=this._completeResults.data.concat(n.data),this._completeResults.errors=this._completeResults.errors.concat(n.errors),this._completeResults.meta=n.meta),this._completed||!a||!J(this._config.complete)||n&&n.meta.aborted||(this._config.complete(this._completeResults,this._input),this._completed=!0),a||n&&n.meta.paused||this._nextChunk(),n}this._halted=!0;},this._sendError=function(e){J(this._config.error)?this._config.error(e):o&&this._config.error&&f.postMessage({workerId:b.WORKER_ID,error:e,finished:!1});};}function l(e){var i;(e=e||{}).chunkSize||(e.chunkSize=b.RemoteChunkSize),h.call(this,e),this._nextChunk=n?function(){this._readChunk(),this._chunkLoaded();}:function(){this._readChunk();},this.stream=function(e){this._input=e,this._nextChunk();},this._readChunk=function(){if(this._finished)this._chunkLoaded();else {if(i=new XMLHttpRequest,this._config.withCredentials&&(i.withCredentials=this._config.withCredentials),n||(i.onload=v(this._chunkLoaded,this),i.onerror=v(this._chunkError,this)),i.open(this._config.downloadRequestBody?"POST":"GET",this._input,!n),this._config.downloadRequestHeaders){var e=this._config.downloadRequestHeaders;for(var t in e)i.setRequestHeader(t,e[t]);}if(this._config.chunkSize){var r=this._start+this._config.chunkSize-1;i.setRequestHeader("Range","bytes="+this._start+"-"+r);}try{i.send(this._config.downloadRequestBody);}catch(e){this._chunkError(e.message);}n&&0===i.status&&this._chunkError();}},this._chunkLoaded=function(){4===i.readyState&&(i.status<200||400<=i.status?this._chunkError():(this._start+=this._config.chunkSize?this._config.chunkSize:i.responseText.length,this._finished=!this._config.chunkSize||this._start>=function(e){var t=e.getResponseHeader("Content-Range");if(null===t)return -1;return parseInt(t.substring(t.lastIndexOf("/")+1))}(i),this.parseChunk(i.responseText)));},this._chunkError=function(e){var t=i.statusText||e;this._sendError(new Error(t));};}function c(e){var i,n;(e=e||{}).chunkSize||(e.chunkSize=b.LocalChunkSize),h.call(this,e);var s="undefined"!=typeof FileReader;this.stream=function(e){this._input=e,n=e.slice||e.webkitSlice||e.mozSlice,s?((i=new FileReader).onload=v(this._chunkLoaded,this),i.onerror=v(this._chunkError,this)):i=new FileReaderSync,this._nextChunk();},this._nextChunk=function(){this._finished||this._config.preview&&!(this._rowCount=this._input.size,this.parseChunk(e.target.result);},this._chunkError=function(){this._sendError(i.error);};}function p(e){var r;h.call(this,e=e||{}),this.stream=function(e){return r=e,this._nextChunk()},this._nextChunk=function(){if(!this._finished){var e,t=this._config.chunkSize;return t?(e=r.substring(0,t),r=r.substring(t)):(e=r,r=""),this._finished=!r,this.parseChunk(e)}};}function g(e){h.call(this,e=e||{});var t=[],r=!0,i=!1;this.pause=function(){h.prototype.pause.apply(this,arguments),this._input.pause();},this.resume=function(){h.prototype.resume.apply(this,arguments),this._input.resume();},this.stream=function(e){this._input=e,this._input.on("data",this._streamData),this._input.on("end",this._streamEnd),this._input.on("error",this._streamError);},this._checkIsFinished=function(){i&&1===t.length&&(this._finished=!0);},this._nextChunk=function(){this._checkIsFinished(),t.length?this.parseChunk(t.shift()):r=!0;},this._streamData=v(function(e){try{t.push("string"==typeof e?e:e.toString(this._config.encoding)),r&&(r=!1,this._checkIsFinished(),this.parseChunk(t.shift()));}catch(e){this._streamError(e);}},this),this._streamError=v(function(e){this._streamCleanUp(),this._sendError(e);},this),this._streamEnd=v(function(){this._streamCleanUp(),i=!0,this._streamData("");},this),this._streamCleanUp=v(function(){this._input.removeListener("data",this._streamData),this._input.removeListener("end",this._streamEnd),this._input.removeListener("error",this._streamError);},this);}function r(m){var a,o,u,i=Math.pow(2,53),n=-i,s=/^\s*-?(\d+\.?|\.\d+|\d+\.\d+)([eE][-+]?\d+)?\s*$/,h=/^((\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)))$/,t=this,r=0,f=0,d=!1,e=!1,l=[],c={data:[],errors:[],meta:{}};if(J(m.step)){var p=m.step;m.step=function(e){if(c=e,_())g();else {if(g(),0===c.data.length)return;r+=e.data.length,m.preview&&r>m.preview?o.abort():(c.data=c.data[0],p(c,t));}};}function y(e){return "greedy"===m.skipEmptyLines?""===e.join("").trim():1===e.length&&0===e[0].length}function g(){return c&&u&&(k("Delimiter","UndetectableDelimiter","Unable to auto-detect delimiting character; defaulted to '"+b.DefaultDelimiter+"'"),u=!1),m.skipEmptyLines&&(c.data=c.data.filter(function(e){return !y(e)})),_()&&function(){if(!c)return;function e(e,t){J(m.transformHeader)&&(e=m.transformHeader(e,t)),l.push(e);}if(Array.isArray(c.data[0])){for(var t=0;_()&&t=l.length?"__parsed_extra":l[r]),m.transform&&(s=m.transform(s,n)),s=v(n,s),"__parsed_extra"===n?(i[n]=i[n]||[],i[n].push(s)):i[n]=s;}return m.header&&(r>l.length?k("FieldMismatch","TooManyFields","Too many fields: expected "+l.length+" fields but parsed "+r,f+t):r=i.length/2?"\r\n":"\r"}(e,i)),u=!1,m.delimiter)J(m.delimiter)&&(m.delimiter=m.delimiter(e),c.meta.delimiter=m.delimiter);else {var n=function(e,t,r,i,n){var s,a,o,u;n=n||[",","\t","|",";",b.RECORD_SEP,b.UNIT_SEP];for(var h=0;h=N)return L(!0)}else for(S=W,W++;;){if(-1===(S=i.indexOf(z,S+1)))return r||h.push({type:"Quotes",code:"MissingQuotes",message:"Quoted field unterminated",row:u.length,index:W}),T();if(S===n-1)return T(i.substring(W,S).replace(C,z));if(z!==K||i[S+1]!==K){if(z===K||0===S||i[S-1]!==K){-1!==w&&w=N)return L(!0);break}h.push({type:"Quotes",code:"InvalidQuotes",message:"Trailing quote on quoted field is malformed",row:u.length,index:W}),S++;}}else S++;}return T();function I(e){u.push(e),d=W;}function A(e){var t=0;if(-1!==e){var r=i.substring(S+1,e);r&&""===r.trim()&&(t=r.length);}return t}function T(e){return r||(void 0===e&&(e=i.substring(W)),f.push(e),W=n,I(f),o&&F()),L()}function D(e){W=e,I(f),f=[],R=i.indexOf(P,W);}function L(e){return {data:u,errors:h,meta:{delimiter:M,linebreak:P,aborted:H,truncated:!!e,cursor:d+(t||0)}}}function F(){q(L()),u=[],h=[];}},this.abort=function(){H=!0;},this.getCharIndex=function(){return W};}function _(e){var t=e.data,r=a[t.workerId],i=!1;if(t.error)r.userError(t.error,t.file);else if(t.results&&t.results.data){var n={abort:function(){i=!0,m(t.workerId,{data:[],errors:[],meta:{aborted:!0}});},pause:y,resume:y};if(J(r.userStep)){for(var s=0;s" || op == ">=" || op == "!=" || op == "="; - } - Fields.isCompareOp = isCompareOp; - Fields.NULL = Fields.literal(null); +var papaparse_minExports = papaparse_min.exports; + +/** Utility methods for creating & comparing fields. */ +var Fields; +(function (Fields) { + function variable(name) { + return { type: "variable", name }; + } + Fields.variable = variable; + function literal(value) { + return { type: "literal", value }; + } + Fields.literal = literal; + function binaryOp(left, op, right) { + return { type: "binaryop", left, op, right }; + } + Fields.binaryOp = binaryOp; + function index(obj, index) { + return { type: "index", object: obj, index }; + } + Fields.index = index; + /** Converts a string in dot-notation-format into a variable which indexes. */ + function indexVariable(name) { + let parts = name.split("."); + let result = Fields.variable(parts[0]); + for (let index = 1; index < parts.length; index++) { + result = Fields.index(result, Fields.literal(parts[index])); + } + return result; + } + Fields.indexVariable = indexVariable; + function lambda(args, value) { + return { type: "lambda", arguments: args, value }; + } + Fields.lambda = lambda; + function func(func, args) { + return { type: "function", func, arguments: args }; + } + Fields.func = func; + function list(values) { + return { type: "list", values }; + } + Fields.list = list; + function object(values) { + return { type: "object", values }; + } + Fields.object = object; + function negate(child) { + return { type: "negated", child }; + } + Fields.negate = negate; + function isCompareOp(op) { + return op == "<=" || op == "<" || op == ">" || op == ">=" || op == "!=" || op == "="; + } + Fields.isCompareOp = isCompareOp; + Fields.NULL = Fields.literal(null); })(Fields || (Fields = {})); -/** AST implementation for queries over data sources. */ -/** Utility functions for creating and manipulating sources. */ -var Sources; -(function (Sources) { - /** Create a source which searches from a tag. */ - function tag(tag) { - return { type: "tag", tag }; - } - Sources.tag = tag; - /** Create a source which fetches from a CSV file. */ - function csv(path) { - return { type: "csv", path }; - } - Sources.csv = csv; - /** Create a source which searches for files under a folder prefix. */ - function folder(prefix) { - return { type: "folder", folder: prefix }; - } - Sources.folder = folder; - /** Create a source which searches for files which link to/from a given file. */ - function link(file, incoming) { - return { type: "link", file, direction: incoming ? "incoming" : "outgoing" }; - } - Sources.link = link; - /** Create a source which joins two sources by a logical operator (and/or). */ - function binaryOp(left, op, right) { - return { type: "binaryop", left, op, right }; - } - Sources.binaryOp = binaryOp; - /** Create a source which takes the intersection of two sources. */ - function and(left, right) { - return { type: "binaryop", left, op: "&", right }; - } - Sources.and = and; - /** Create a source which takes the union of two sources. */ - function or(left, right) { - return { type: "binaryop", left, op: "|", right }; - } - Sources.or = or; - /** Create a source which negates the underlying source. */ - function negate(child) { - return { type: "negate", child }; - } - Sources.negate = negate; - function empty() { - return { type: "empty" }; - } - Sources.empty = empty; +/** AST implementation for queries over data sources. */ +/** Utility functions for creating and manipulating sources. */ +var Sources; +(function (Sources) { + /** Create a source which searches from a tag. */ + function tag(tag) { + return { type: "tag", tag }; + } + Sources.tag = tag; + /** Create a source which fetches from a CSV file. */ + function csv(path) { + return { type: "csv", path }; + } + Sources.csv = csv; + /** Create a source which searches for files under a folder prefix. */ + function folder(prefix) { + return { type: "folder", folder: prefix }; + } + Sources.folder = folder; + /** Create a source which searches for files which link to/from a given file. */ + function link(file, incoming) { + return { type: "link", file, direction: incoming ? "incoming" : "outgoing" }; + } + Sources.link = link; + /** Create a source which joins two sources by a logical operator (and/or). */ + function binaryOp(left, op, right) { + return { type: "binaryop", left, op, right }; + } + Sources.binaryOp = binaryOp; + /** Create a source which takes the intersection of two sources. */ + function and(left, right) { + return { type: "binaryop", left, op: "&", right }; + } + Sources.and = and; + /** Create a source which takes the union of two sources. */ + function or(left, right) { + return { type: "binaryop", left, op: "|", right }; + } + Sources.or = or; + /** Create a source which negates the underlying source. */ + function negate(child) { + return { type: "negate", child }; + } + Sources.negate = negate; + function empty() { + return { type: "empty" }; + } + Sources.empty = empty; })(Sources || (Sources = {})); -/** Emoji regex without any additional flags. */ -const EMOJI_REGEX = new RegExp(emojiRegex(), ""); -/** Provides a lookup table for unit durations of the given type. */ -const DURATION_TYPES = { - year: Duration.fromObject({ years: 1 }), - years: Duration.fromObject({ years: 1 }), - yr: Duration.fromObject({ years: 1 }), - yrs: Duration.fromObject({ years: 1 }), - month: Duration.fromObject({ months: 1 }), - months: Duration.fromObject({ months: 1 }), - mo: Duration.fromObject({ months: 1 }), - mos: Duration.fromObject({ months: 1 }), - week: Duration.fromObject({ weeks: 1 }), - weeks: Duration.fromObject({ weeks: 1 }), - wk: Duration.fromObject({ weeks: 1 }), - wks: Duration.fromObject({ weeks: 1 }), - w: Duration.fromObject({ weeks: 1 }), - day: Duration.fromObject({ days: 1 }), - days: Duration.fromObject({ days: 1 }), - d: Duration.fromObject({ days: 1 }), - hour: Duration.fromObject({ hours: 1 }), - hours: Duration.fromObject({ hours: 1 }), - hr: Duration.fromObject({ hours: 1 }), - hrs: Duration.fromObject({ hours: 1 }), - h: Duration.fromObject({ hours: 1 }), - minute: Duration.fromObject({ minutes: 1 }), - minutes: Duration.fromObject({ minutes: 1 }), - min: Duration.fromObject({ minutes: 1 }), - mins: Duration.fromObject({ minutes: 1 }), - m: Duration.fromObject({ minutes: 1 }), - second: Duration.fromObject({ seconds: 1 }), - seconds: Duration.fromObject({ seconds: 1 }), - sec: Duration.fromObject({ seconds: 1 }), - secs: Duration.fromObject({ seconds: 1 }), - s: Duration.fromObject({ seconds: 1 }), -}; -/** Shorthand for common dates (relative to right now). */ -const DATE_SHORTHANDS = { - now: () => DateTime.local(), - today: () => DateTime.local().startOf("day"), - yesterday: () => DateTime.local() - .startOf("day") - .minus(Duration.fromObject({ days: 1 })), - tomorrow: () => DateTime.local() - .startOf("day") - .plus(Duration.fromObject({ days: 1 })), - sow: () => DateTime.local().startOf("week"), - "start-of-week": () => DateTime.local().startOf("week"), - eow: () => DateTime.local().endOf("week"), - "end-of-week": () => DateTime.local().endOf("week"), - soy: () => DateTime.local().startOf("year"), - "start-of-year": () => DateTime.local().startOf("year"), - eoy: () => DateTime.local().endOf("year"), - "end-of-year": () => DateTime.local().endOf("year"), - som: () => DateTime.local().startOf("month"), - "start-of-month": () => DateTime.local().startOf("month"), - eom: () => DateTime.local().endOf("month"), - "end-of-month": () => DateTime.local().endOf("month"), -}; -/** - * Keywords which cannot be used as variables directly. Use `row.` if it is a variable you have defined and want - * to access. - */ -const KEYWORDS = ["FROM", "WHERE", "LIMIT", "GROUP", "FLATTEN"]; -/////////////// -// Utilities // -/////////////// -/** Split on unescaped pipes in an inner link. */ -function splitOnUnescapedPipe(link) { - let pipe = -1; - while ((pipe = link.indexOf("|", pipe + 1)) >= 0) { - if (pipe > 0 && link[pipe - 1] == "\\") - continue; - return [link.substring(0, pipe).replace(/\\\|/g, "|"), link.substring(pipe + 1)]; - } - return [link.replace(/\\\|/g, "|"), undefined]; -} -/** Attempt to parse the inside of a link to pull out display name, subpath, etc. */ -function parseInnerLink(rawlink) { - let [link, display] = splitOnUnescapedPipe(rawlink); - return Link.infer(link, false, display); -} -/** Create a left-associative binary parser which parses the given sub-element and separator. Handles whitespace. */ -function createBinaryParser(child, sep, combine) { - return parsimmon_umd_min.exports.seqMap(child, parsimmon_umd_min.exports.seq(parsimmon_umd_min.exports.optWhitespace, sep, parsimmon_umd_min.exports.optWhitespace, child).many(), (first, rest) => { - if (rest.length == 0) - return first; - let node = combine(first, rest[0][1], rest[0][3]); - for (let index = 1; index < rest.length; index++) { - node = combine(node, rest[index][1], rest[index][3]); - } - return node; - }); -} -function chainOpt(base, ...funcs) { - return parsimmon_umd_min.exports.custom((success, failure) => { - return (input, i) => { - let result = base._(input, i); - if (!result.status) - return result; - for (let func of funcs) { - let next = func(result.value)._(input, result.index); - if (!next.status) - return result; - result = next; - } - return result; - }; - }); -} -const EXPRESSION = parsimmon_umd_min.exports.createLanguage({ - // A floating point number; the decimal point is optional. - number: q => parsimmon_umd_min.exports.regexp(/-?[0-9]+(\.[0-9]+)?/) - .map(str => Number.parseFloat(str)) - .desc("number"), - // A quote-surrounded string which supports escape characters ('\'). - string: q => parsimmon_umd_min.exports.string('"') - .then(parsimmon_umd_min.exports.alt(q.escapeCharacter, parsimmon_umd_min.exports.noneOf('"\\')) - .atLeast(0) - .map(chars => chars.join(""))) - .skip(parsimmon_umd_min.exports.string('"')) - .desc("string"), - escapeCharacter: _ => parsimmon_umd_min.exports.string("\\") - .then(parsimmon_umd_min.exports.any) - .map(escaped => { - // If we are escaping a backslash or a quote, pass in on in escaped form - if (escaped === '"') - return '"'; - if (escaped === "\\") - return "\\"; - else - return "\\" + escaped; - }), - // A boolean true/false value. - bool: _ => parsimmon_umd_min.exports.regexp(/true|false|True|False/) - .map(str => str.toLowerCase() == "true") - .desc("boolean ('true' or 'false')"), - // A tag of the form '#stuff/hello-there'. - tag: _ => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("#"), parsimmon_umd_min.exports.alt(parsimmon_umd_min.exports.regexp(/[^\u2000-\u206F\u2E00-\u2E7F'!"#$%&()*+,.:;<=>?@^`{|}~\[\]\\\s]/).desc("text")).many(), (start, rest) => start + rest.join("")).desc("tag ('#hello/stuff')"), - // A variable identifier, which is alphanumeric and must start with a letter or... emoji. - identifier: _ => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.alt(parsimmon_umd_min.exports.regexp(/\p{Letter}/u), parsimmon_umd_min.exports.regexp(EMOJI_REGEX).desc("text")), parsimmon_umd_min.exports.alt(parsimmon_umd_min.exports.regexp(/[0-9\p{Letter}_-]/u), parsimmon_umd_min.exports.regexp(EMOJI_REGEX).desc("text")).many(), (first, rest) => first + rest.join("")).desc("variable identifier"), - // An Obsidian link of the form [[]]. - link: _ => parsimmon_umd_min.exports.regexp(/\[\[([^\[\]]*?)\]\]/u, 1) - .map(linkInner => parseInnerLink(linkInner)) - .desc("file link"), - // An embeddable link which can start with '!'. This overlaps with the normal negation operator, so it is only - // provided for metadata parsing. - embedLink: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("!").atMost(1), q.link, (p, l) => { - if (p.length > 0) - l.embed = true; - return l; - }).desc("file link"), - // Binary plus or minus operator. - binaryPlusMinus: _ => parsimmon_umd_min.exports.regexp(/\+|-/) - .map(str => str) - .desc("'+' or '-'"), - // Binary times or divide operator. - binaryMulDiv: _ => parsimmon_umd_min.exports.regexp(/\*|\/|%/) - .map(str => str) - .desc("'*' or '/' or '%'"), - // Binary comparison operator. - binaryCompareOp: _ => parsimmon_umd_min.exports.regexp(/>=|<=|!=|>|<|=/) - .map(str => str) - .desc("'>=' or '<=' or '!=' or '=' or '>' or '<'"), - // Binary boolean combination operator. - binaryBooleanOp: _ => parsimmon_umd_min.exports.regexp(/and|or|&|\|/i) - .map(str => { - if (str.toLowerCase() == "and") - return "&"; - else if (str.toLowerCase() == "or") - return "|"; - else - return str; - }) - .desc("'and' or 'or'"), - // A date which can be YYYY-MM[-DDTHH:mm:ss]. - rootDate: _ => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.regexp(/\d{4}/), parsimmon_umd_min.exports.string("-"), parsimmon_umd_min.exports.regexp(/\d{2}/), (year, _, month) => { - return DateTime.fromObject({ year: Number.parseInt(year), month: Number.parseInt(month) }); - }).desc("date in format YYYY-MM[-DDTHH-MM-SS.MS]"), - dateShorthand: _ => parsimmon_umd_min.exports.alt(...Object.keys(DATE_SHORTHANDS) - .sort((a, b) => b.length - a.length) - .map(parsimmon_umd_min.exports.string)), - date: q => chainOpt(q.rootDate, (ym) => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("-"), parsimmon_umd_min.exports.regexp(/\d{2}/), (_, day) => ym.set({ day: Number.parseInt(day) })), (ymd) => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("T"), parsimmon_umd_min.exports.regexp(/\d{2}/), (_, hour) => ymd.set({ hour: Number.parseInt(hour) })), (ymdh) => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string(":"), parsimmon_umd_min.exports.regexp(/\d{2}/), (_, minute) => ymdh.set({ minute: Number.parseInt(minute) })), (ymdhm) => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string(":"), parsimmon_umd_min.exports.regexp(/\d{2}/), (_, second) => ymdhm.set({ second: Number.parseInt(second) })), (ymdhms) => parsimmon_umd_min.exports.alt(parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("."), parsimmon_umd_min.exports.regexp(/\d{3}/), (_, millisecond) => ymdhms.set({ millisecond: Number.parseInt(millisecond) })), parsimmon_umd_min.exports.succeed(ymdhms) // pass - ), (dt) => parsimmon_umd_min.exports.alt(parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("+").or(parsimmon_umd_min.exports.string("-")), parsimmon_umd_min.exports.regexp(/\d{1,2}(:\d{2})?/), (pm, hr) => dt.setZone("UTC" + pm + hr, { keepLocalTime: true })), parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("Z"), () => dt.setZone("utc", { keepLocalTime: true })), parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("["), parsimmon_umd_min.exports.regexp(/[0-9A-Za-z+-\/]+/u), parsimmon_umd_min.exports.string("]"), (_a, zone, _b) => dt.setZone(zone, { keepLocalTime: true })))) - .assert((dt) => dt.isValid, "valid date") - .desc("date in format YYYY-MM[-DDTHH-MM-SS.MS]"), - // A date, plus various shorthand times of day it could be. - datePlus: q => parsimmon_umd_min.exports.alt(q.dateShorthand.map(d => DATE_SHORTHANDS[d]()), q.date).desc("date in format YYYY-MM[-DDTHH-MM-SS.MS] or in shorthand"), - // A duration of time. - durationType: _ => parsimmon_umd_min.exports.alt(...Object.keys(DURATION_TYPES) - .sort((a, b) => b.length - a.length) - .map(parsimmon_umd_min.exports.string)), - duration: q => parsimmon_umd_min.exports.seqMap(q.number, parsimmon_umd_min.exports.optWhitespace, q.durationType, (count, _, t) => DURATION_TYPES[t].mapUnits(x => x * count)) - .sepBy1(parsimmon_umd_min.exports.string(",").trim(parsimmon_umd_min.exports.optWhitespace).or(parsimmon_umd_min.exports.optWhitespace)) - .map(durations => durations.reduce((p, c) => p.plus(c))) - .desc("duration like 4hr2min"), - // A raw null value. - rawNull: _ => parsimmon_umd_min.exports.string("null"), - // Source parsing. - tagSource: q => q.tag.map(tag => Sources.tag(tag)), - csvSource: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("csv(").skip(parsimmon_umd_min.exports.optWhitespace), q.string, parsimmon_umd_min.exports.string(")"), (_1, path, _2) => Sources.csv(path)), - linkIncomingSource: q => q.link.map(link => Sources.link(link.path, true)), - linkOutgoingSource: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("outgoing(").skip(parsimmon_umd_min.exports.optWhitespace), q.link, parsimmon_umd_min.exports.string(")"), (_1, link, _2) => Sources.link(link.path, false)), - folderSource: q => q.string.map(str => Sources.folder(str)), - parensSource: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("("), parsimmon_umd_min.exports.optWhitespace, q.source, parsimmon_umd_min.exports.optWhitespace, parsimmon_umd_min.exports.string(")"), (_1, _2, field, _3, _4) => field), - negateSource: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.alt(parsimmon_umd_min.exports.string("-"), parsimmon_umd_min.exports.string("!")), q.atomSource, (_, source) => Sources.negate(source)), - atomSource: q => parsimmon_umd_min.exports.alt(q.parensSource, q.negateSource, q.linkOutgoingSource, q.linkIncomingSource, q.folderSource, q.tagSource, q.csvSource), - binaryOpSource: q => createBinaryParser(q.atomSource, q.binaryBooleanOp.map(s => s), Sources.binaryOp), - source: q => q.binaryOpSource, - // Field parsing. - variableField: q => q.identifier - .chain(r => { - if (KEYWORDS.includes(r.toUpperCase())) { - return parsimmon_umd_min.exports.fail("Variable fields cannot be a keyword (" + KEYWORDS.join(" or ") + ")"); - } - else { - return parsimmon_umd_min.exports.succeed(Fields.variable(r)); - } - }) - .desc("variable"), - numberField: q => q.number.map(val => Fields.literal(val)).desc("number"), - stringField: q => q.string.map(val => Fields.literal(val)).desc("string"), - boolField: q => q.bool.map(val => Fields.literal(val)).desc("boolean"), - dateField: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("date("), parsimmon_umd_min.exports.optWhitespace, q.datePlus, parsimmon_umd_min.exports.optWhitespace, parsimmon_umd_min.exports.string(")"), (prefix, _1, date, _2, postfix) => Fields.literal(date)).desc("date"), - durationField: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("dur("), parsimmon_umd_min.exports.optWhitespace, q.duration, parsimmon_umd_min.exports.optWhitespace, parsimmon_umd_min.exports.string(")"), (prefix, _1, dur, _2, postfix) => Fields.literal(dur)).desc("duration"), - nullField: q => q.rawNull.map(_ => Fields.NULL), - linkField: q => q.link.map(f => Fields.literal(f)), - listField: q => q.field - .sepBy(parsimmon_umd_min.exports.string(",").trim(parsimmon_umd_min.exports.optWhitespace)) - .wrap(parsimmon_umd_min.exports.string("[").skip(parsimmon_umd_min.exports.optWhitespace), parsimmon_umd_min.exports.optWhitespace.then(parsimmon_umd_min.exports.string("]"))) - .map(l => Fields.list(l)) - .desc("list ('[1, 2, 3]')"), - objectField: q => parsimmon_umd_min.exports.seqMap(q.identifier.or(q.string), parsimmon_umd_min.exports.string(":").trim(parsimmon_umd_min.exports.optWhitespace), q.field, (name, _sep, value) => { - return { name, value }; - }) - .sepBy(parsimmon_umd_min.exports.string(",").trim(parsimmon_umd_min.exports.optWhitespace)) - .wrap(parsimmon_umd_min.exports.string("{").skip(parsimmon_umd_min.exports.optWhitespace), parsimmon_umd_min.exports.optWhitespace.then(parsimmon_umd_min.exports.string("}"))) - .map(vals => { - let res = {}; - for (let entry of vals) - res[entry.name] = entry.value; - return Fields.object(res); - }) - .desc("object ('{ a: 1, b: 2 }')"), - atomInlineField: q => parsimmon_umd_min.exports.alt(q.date, q.duration.map(d => normalizeDuration(d)), q.string, q.tag, q.embedLink, q.bool, q.number, q.rawNull), - inlineFieldList: q => q.atomInlineField.sepBy(parsimmon_umd_min.exports.string(",").trim(parsimmon_umd_min.exports.optWhitespace).lookahead(q.atomInlineField)), - inlineField: q => parsimmon_umd_min.exports.alt(parsimmon_umd_min.exports.seqMap(q.atomInlineField, parsimmon_umd_min.exports.string(",").trim(parsimmon_umd_min.exports.optWhitespace), q.inlineFieldList, (f, _s, l) => [f].concat(l)), q.atomInlineField), - atomField: q => parsimmon_umd_min.exports.alt( - // Place embed links above negated fields as they are the special parser case '![[thing]]' and are generally unambigious. - q.embedLink.map(l => Fields.literal(l)), q.negatedField, q.linkField, q.listField, q.objectField, q.lambdaField, q.parensField, q.boolField, q.numberField, q.stringField, q.dateField, q.durationField, q.nullField, q.variableField), - indexField: q => parsimmon_umd_min.exports.seqMap(q.atomField, parsimmon_umd_min.exports.alt(q.dotPostfix, q.indexPostfix, q.functionPostfix).many(), (obj, postfixes) => { - let result = obj; - for (let post of postfixes) { - switch (post.type) { - case "dot": - result = Fields.index(result, Fields.literal(post.field)); - break; - case "index": - result = Fields.index(result, post.field); - break; - case "function": - result = Fields.func(result, post.fields); - break; - } - } - return result; - }), - negatedField: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("!"), q.indexField, (_, field) => Fields.negate(field)).desc("negated field"), - parensField: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("("), parsimmon_umd_min.exports.optWhitespace, q.field, parsimmon_umd_min.exports.optWhitespace, parsimmon_umd_min.exports.string(")"), (_1, _2, field, _3, _4) => field), - lambdaField: q => parsimmon_umd_min.exports.seqMap(q.identifier - .sepBy(parsimmon_umd_min.exports.string(",").trim(parsimmon_umd_min.exports.optWhitespace)) - .wrap(parsimmon_umd_min.exports.string("(").trim(parsimmon_umd_min.exports.optWhitespace), parsimmon_umd_min.exports.string(")").trim(parsimmon_umd_min.exports.optWhitespace)), parsimmon_umd_min.exports.string("=>").trim(parsimmon_umd_min.exports.optWhitespace), q.field, (ident, _ignore, value) => { - return { type: "lambda", arguments: ident, value }; - }), - dotPostfix: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("."), q.identifier, (_, field) => { - return { type: "dot", field: field }; - }), - indexPostfix: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("["), parsimmon_umd_min.exports.optWhitespace, q.field, parsimmon_umd_min.exports.optWhitespace, parsimmon_umd_min.exports.string("]"), (_, _2, field, _3, _4) => { - return { type: "index", field }; - }), - functionPostfix: q => parsimmon_umd_min.exports.seqMap(parsimmon_umd_min.exports.string("("), parsimmon_umd_min.exports.optWhitespace, q.field.sepBy(parsimmon_umd_min.exports.string(",").trim(parsimmon_umd_min.exports.optWhitespace)), parsimmon_umd_min.exports.optWhitespace, parsimmon_umd_min.exports.string(")"), (_, _1, fields, _2, _3) => { - return { type: "function", fields }; - }), - // The precedence hierarchy of operators - multiply/divide, add/subtract, compare, and then boolean operations. - binaryMulDivField: q => createBinaryParser(q.indexField, q.binaryMulDiv, Fields.binaryOp), - binaryPlusMinusField: q => createBinaryParser(q.binaryMulDivField, q.binaryPlusMinus, Fields.binaryOp), - binaryCompareField: q => createBinaryParser(q.binaryPlusMinusField, q.binaryCompareOp, Fields.binaryOp), - binaryBooleanField: q => createBinaryParser(q.binaryCompareField, q.binaryBooleanOp, Fields.binaryOp), - binaryOpField: q => q.binaryBooleanField, - field: q => q.binaryOpField, -}); -/** - * Attempt to parse a field from the given text, returning a string error if the - * parse failed. - */ -function parseField(text) { - try { - return Result.success(EXPRESSION.field.tryParse(text)); - } - catch (error) { - return Result.failure("" + error); - } +/** Emoji regex without any additional flags. */ +const EMOJI_REGEX = new RegExp(emojiRegex(), ""); +/** Provides a lookup table for unit durations of the given type. */ +const DURATION_TYPES = { + year: Duration.fromObject({ years: 1 }), + years: Duration.fromObject({ years: 1 }), + yr: Duration.fromObject({ years: 1 }), + yrs: Duration.fromObject({ years: 1 }), + month: Duration.fromObject({ months: 1 }), + months: Duration.fromObject({ months: 1 }), + mo: Duration.fromObject({ months: 1 }), + mos: Duration.fromObject({ months: 1 }), + week: Duration.fromObject({ weeks: 1 }), + weeks: Duration.fromObject({ weeks: 1 }), + wk: Duration.fromObject({ weeks: 1 }), + wks: Duration.fromObject({ weeks: 1 }), + w: Duration.fromObject({ weeks: 1 }), + day: Duration.fromObject({ days: 1 }), + days: Duration.fromObject({ days: 1 }), + d: Duration.fromObject({ days: 1 }), + hour: Duration.fromObject({ hours: 1 }), + hours: Duration.fromObject({ hours: 1 }), + hr: Duration.fromObject({ hours: 1 }), + hrs: Duration.fromObject({ hours: 1 }), + h: Duration.fromObject({ hours: 1 }), + minute: Duration.fromObject({ minutes: 1 }), + minutes: Duration.fromObject({ minutes: 1 }), + min: Duration.fromObject({ minutes: 1 }), + mins: Duration.fromObject({ minutes: 1 }), + m: Duration.fromObject({ minutes: 1 }), + second: Duration.fromObject({ seconds: 1 }), + seconds: Duration.fromObject({ seconds: 1 }), + sec: Duration.fromObject({ seconds: 1 }), + secs: Duration.fromObject({ seconds: 1 }), + s: Duration.fromObject({ seconds: 1 }), +}; +/** Shorthand for common dates (relative to right now). */ +const DATE_SHORTHANDS = { + now: () => DateTime.local(), + today: () => DateTime.local().startOf("day"), + yesterday: () => DateTime.local() + .startOf("day") + .minus(Duration.fromObject({ days: 1 })), + tomorrow: () => DateTime.local() + .startOf("day") + .plus(Duration.fromObject({ days: 1 })), + sow: () => DateTime.local().startOf("week"), + "start-of-week": () => DateTime.local().startOf("week"), + eow: () => DateTime.local().endOf("week"), + "end-of-week": () => DateTime.local().endOf("week"), + soy: () => DateTime.local().startOf("year"), + "start-of-year": () => DateTime.local().startOf("year"), + eoy: () => DateTime.local().endOf("year"), + "end-of-year": () => DateTime.local().endOf("year"), + som: () => DateTime.local().startOf("month"), + "start-of-month": () => DateTime.local().startOf("month"), + eom: () => DateTime.local().endOf("month"), + "end-of-month": () => DateTime.local().endOf("month"), +}; +/** + * Keywords which cannot be used as variables directly. Use `row.` if it is a variable you have defined and want + * to access. + */ +const KEYWORDS = ["FROM", "WHERE", "LIMIT", "GROUP", "FLATTEN"]; +/////////////// +// Utilities // +/////////////// +/** Split on unescaped pipes in an inner link. */ +function splitOnUnescapedPipe(link) { + let pipe = -1; + while ((pipe = link.indexOf("|", pipe + 1)) >= 0) { + if (pipe > 0 && link[pipe - 1] == "\\") + continue; + return [link.substring(0, pipe).replace(/\\\|/g, "|"), link.substring(pipe + 1)]; + } + return [link.replace(/\\\|/g, "|"), undefined]; +} +/** Attempt to parse the inside of a link to pull out display name, subpath, etc. */ +function parseInnerLink(rawlink) { + let [link, display] = splitOnUnescapedPipe(rawlink); + return Link.infer(link, false, display); +} +/** Create a left-associative binary parser which parses the given sub-element and separator. Handles whitespace. */ +function createBinaryParser(child, sep, combine) { + return parsimmon_umd_minExports.seqMap(child, parsimmon_umd_minExports.seq(parsimmon_umd_minExports.optWhitespace, sep, parsimmon_umd_minExports.optWhitespace, child).many(), (first, rest) => { + if (rest.length == 0) + return first; + let node = combine(first, rest[0][1], rest[0][3]); + for (let index = 1; index < rest.length; index++) { + node = combine(node, rest[index][1], rest[index][3]); + } + return node; + }); +} +function chainOpt(base, ...funcs) { + return parsimmon_umd_minExports.custom((success, failure) => { + return (input, i) => { + let result = base._(input, i); + if (!result.status) + return result; + for (let func of funcs) { + let next = func(result.value)._(input, result.index); + if (!next.status) + return result; + result = next; + } + return result; + }; + }); +} +const EXPRESSION = parsimmon_umd_minExports.createLanguage({ + // A floating point number; the decimal point is optional. + number: q => parsimmon_umd_minExports.regexp(/-?[0-9]+(\.[0-9]+)?/) + .map(str => Number.parseFloat(str)) + .desc("number"), + // A quote-surrounded string which supports escape characters ('\'). + string: q => parsimmon_umd_minExports.string('"') + .then(parsimmon_umd_minExports.alt(q.escapeCharacter, parsimmon_umd_minExports.noneOf('"\\')) + .atLeast(0) + .map(chars => chars.join(""))) + .skip(parsimmon_umd_minExports.string('"')) + .desc("string"), + escapeCharacter: _ => parsimmon_umd_minExports.string("\\") + .then(parsimmon_umd_minExports.any) + .map(escaped => { + // If we are escaping a backslash or a quote, pass in on in escaped form + if (escaped === '"') + return '"'; + if (escaped === "\\") + return "\\"; + else + return "\\" + escaped; + }), + // A boolean true/false value. + bool: _ => parsimmon_umd_minExports.regexp(/true|false|True|False/) + .map(str => str.toLowerCase() == "true") + .desc("boolean ('true' or 'false')"), + // A tag of the form '#stuff/hello-there'. + tag: _ => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("#"), parsimmon_umd_minExports.alt(parsimmon_umd_minExports.regexp(/[^\u2000-\u206F\u2E00-\u2E7F'!"#$%&()*+,.:;<=>?@^`{|}~\[\]\\\s]/).desc("text")).many(), (start, rest) => start + rest.join("")).desc("tag ('#hello/stuff')"), + // A variable identifier, which is alphanumeric and must start with a letter or... emoji. + identifier: _ => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.alt(parsimmon_umd_minExports.regexp(/\p{Letter}/u), parsimmon_umd_minExports.regexp(EMOJI_REGEX).desc("text")), parsimmon_umd_minExports.alt(parsimmon_umd_minExports.regexp(/[0-9\p{Letter}_-]/u), parsimmon_umd_minExports.regexp(EMOJI_REGEX).desc("text")).many(), (first, rest) => first + rest.join("")).desc("variable identifier"), + // An Obsidian link of the form [[]]. + link: _ => parsimmon_umd_minExports.regexp(/\[\[([^\[\]]*?)\]\]/u, 1) + .map(linkInner => parseInnerLink(linkInner)) + .desc("file link"), + // An embeddable link which can start with '!'. This overlaps with the normal negation operator, so it is only + // provided for metadata parsing. + embedLink: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("!").atMost(1), q.link, (p, l) => { + if (p.length > 0) + l.embed = true; + return l; + }).desc("file link"), + // Binary plus or minus operator. + binaryPlusMinus: _ => parsimmon_umd_minExports.regexp(/\+|-/) + .map(str => str) + .desc("'+' or '-'"), + // Binary times or divide operator. + binaryMulDiv: _ => parsimmon_umd_minExports.regexp(/\*|\/|%/) + .map(str => str) + .desc("'*' or '/' or '%'"), + // Binary comparison operator. + binaryCompareOp: _ => parsimmon_umd_minExports.regexp(/>=|<=|!=|>|<|=/) + .map(str => str) + .desc("'>=' or '<=' or '!=' or '=' or '>' or '<'"), + // Binary boolean combination operator. + binaryBooleanOp: _ => parsimmon_umd_minExports.regexp(/and|or|&|\|/i) + .map(str => { + if (str.toLowerCase() == "and") + return "&"; + else if (str.toLowerCase() == "or") + return "|"; + else + return str; + }) + .desc("'and' or 'or'"), + // A date which can be YYYY-MM[-DDTHH:mm:ss]. + rootDate: _ => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.regexp(/\d{4}/), parsimmon_umd_minExports.string("-"), parsimmon_umd_minExports.regexp(/\d{2}/), (year, _, month) => { + return DateTime.fromObject({ year: Number.parseInt(year), month: Number.parseInt(month) }); + }).desc("date in format YYYY-MM[-DDTHH-MM-SS.MS]"), + dateShorthand: _ => parsimmon_umd_minExports.alt(...Object.keys(DATE_SHORTHANDS) + .sort((a, b) => b.length - a.length) + .map(parsimmon_umd_minExports.string)), + date: q => chainOpt(q.rootDate, (ym) => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("-"), parsimmon_umd_minExports.regexp(/\d{2}/), (_, day) => ym.set({ day: Number.parseInt(day) })), (ymd) => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("T"), parsimmon_umd_minExports.regexp(/\d{2}/), (_, hour) => ymd.set({ hour: Number.parseInt(hour) })), (ymdh) => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string(":"), parsimmon_umd_minExports.regexp(/\d{2}/), (_, minute) => ymdh.set({ minute: Number.parseInt(minute) })), (ymdhm) => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string(":"), parsimmon_umd_minExports.regexp(/\d{2}/), (_, second) => ymdhm.set({ second: Number.parseInt(second) })), (ymdhms) => parsimmon_umd_minExports.alt(parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("."), parsimmon_umd_minExports.regexp(/\d{3}/), (_, millisecond) => ymdhms.set({ millisecond: Number.parseInt(millisecond) })), parsimmon_umd_minExports.succeed(ymdhms) // pass + ), (dt) => parsimmon_umd_minExports.alt(parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("+").or(parsimmon_umd_minExports.string("-")), parsimmon_umd_minExports.regexp(/\d{1,2}(:\d{2})?/), (pm, hr) => dt.setZone("UTC" + pm + hr, { keepLocalTime: true })), parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("Z"), () => dt.setZone("utc", { keepLocalTime: true })), parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("["), parsimmon_umd_minExports.regexp(/[0-9A-Za-z+-\/]+/u), parsimmon_umd_minExports.string("]"), (_a, zone, _b) => dt.setZone(zone, { keepLocalTime: true })))) + .assert((dt) => dt.isValid, "valid date") + .desc("date in format YYYY-MM[-DDTHH-MM-SS.MS]"), + // A date, plus various shorthand times of day it could be. + datePlus: q => parsimmon_umd_minExports.alt(q.dateShorthand.map(d => DATE_SHORTHANDS[d]()), q.date).desc("date in format YYYY-MM[-DDTHH-MM-SS.MS] or in shorthand"), + // A duration of time. + durationType: _ => parsimmon_umd_minExports.alt(...Object.keys(DURATION_TYPES) + .sort((a, b) => b.length - a.length) + .map(parsimmon_umd_minExports.string)), + duration: q => parsimmon_umd_minExports.seqMap(q.number, parsimmon_umd_minExports.optWhitespace, q.durationType, (count, _, t) => DURATION_TYPES[t].mapUnits(x => x * count)) + .sepBy1(parsimmon_umd_minExports.string(",").trim(parsimmon_umd_minExports.optWhitespace).or(parsimmon_umd_minExports.optWhitespace)) + .map(durations => durations.reduce((p, c) => p.plus(c))) + .desc("duration like 4hr2min"), + // A raw null value. + rawNull: _ => parsimmon_umd_minExports.string("null"), + // Source parsing. + tagSource: q => q.tag.map(tag => Sources.tag(tag)), + csvSource: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("csv(").skip(parsimmon_umd_minExports.optWhitespace), q.string, parsimmon_umd_minExports.string(")"), (_1, path, _2) => Sources.csv(path)), + linkIncomingSource: q => q.link.map(link => Sources.link(link.path, true)), + linkOutgoingSource: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("outgoing(").skip(parsimmon_umd_minExports.optWhitespace), q.link, parsimmon_umd_minExports.string(")"), (_1, link, _2) => Sources.link(link.path, false)), + folderSource: q => q.string.map(str => Sources.folder(str)), + parensSource: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("("), parsimmon_umd_minExports.optWhitespace, q.source, parsimmon_umd_minExports.optWhitespace, parsimmon_umd_minExports.string(")"), (_1, _2, field, _3, _4) => field), + negateSource: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.alt(parsimmon_umd_minExports.string("-"), parsimmon_umd_minExports.string("!")), q.atomSource, (_, source) => Sources.negate(source)), + atomSource: q => parsimmon_umd_minExports.alt(q.parensSource, q.negateSource, q.linkOutgoingSource, q.linkIncomingSource, q.folderSource, q.tagSource, q.csvSource), + binaryOpSource: q => createBinaryParser(q.atomSource, q.binaryBooleanOp.map(s => s), Sources.binaryOp), + source: q => q.binaryOpSource, + // Field parsing. + variableField: q => q.identifier + .chain(r => { + if (KEYWORDS.includes(r.toUpperCase())) { + return parsimmon_umd_minExports.fail("Variable fields cannot be a keyword (" + KEYWORDS.join(" or ") + ")"); + } + else { + return parsimmon_umd_minExports.succeed(Fields.variable(r)); + } + }) + .desc("variable"), + numberField: q => q.number.map(val => Fields.literal(val)).desc("number"), + stringField: q => q.string.map(val => Fields.literal(val)).desc("string"), + boolField: q => q.bool.map(val => Fields.literal(val)).desc("boolean"), + dateField: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("date("), parsimmon_umd_minExports.optWhitespace, q.datePlus, parsimmon_umd_minExports.optWhitespace, parsimmon_umd_minExports.string(")"), (prefix, _1, date, _2, postfix) => Fields.literal(date)).desc("date"), + durationField: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("dur("), parsimmon_umd_minExports.optWhitespace, q.duration, parsimmon_umd_minExports.optWhitespace, parsimmon_umd_minExports.string(")"), (prefix, _1, dur, _2, postfix) => Fields.literal(dur)).desc("duration"), + nullField: q => q.rawNull.map(_ => Fields.NULL), + linkField: q => q.link.map(f => Fields.literal(f)), + listField: q => q.field + .sepBy(parsimmon_umd_minExports.string(",").trim(parsimmon_umd_minExports.optWhitespace)) + .wrap(parsimmon_umd_minExports.string("[").skip(parsimmon_umd_minExports.optWhitespace), parsimmon_umd_minExports.optWhitespace.then(parsimmon_umd_minExports.string("]"))) + .map(l => Fields.list(l)) + .desc("list ('[1, 2, 3]')"), + objectField: q => parsimmon_umd_minExports.seqMap(q.identifier.or(q.string), parsimmon_umd_minExports.string(":").trim(parsimmon_umd_minExports.optWhitespace), q.field, (name, _sep, value) => { + return { name, value }; + }) + .sepBy(parsimmon_umd_minExports.string(",").trim(parsimmon_umd_minExports.optWhitespace)) + .wrap(parsimmon_umd_minExports.string("{").skip(parsimmon_umd_minExports.optWhitespace), parsimmon_umd_minExports.optWhitespace.then(parsimmon_umd_minExports.string("}"))) + .map(vals => { + let res = {}; + for (let entry of vals) + res[entry.name] = entry.value; + return Fields.object(res); + }) + .desc("object ('{ a: 1, b: 2 }')"), + atomInlineField: q => parsimmon_umd_minExports.alt(q.date, q.duration.map(d => normalizeDuration(d)), q.string, q.tag, q.embedLink, q.bool, q.number, q.rawNull), + inlineFieldList: q => q.atomInlineField.sepBy(parsimmon_umd_minExports.string(",").trim(parsimmon_umd_minExports.optWhitespace).lookahead(q.atomInlineField)), + inlineField: q => parsimmon_umd_minExports.alt(parsimmon_umd_minExports.seqMap(q.atomInlineField, parsimmon_umd_minExports.string(",").trim(parsimmon_umd_minExports.optWhitespace), q.inlineFieldList, (f, _s, l) => [f].concat(l)), q.atomInlineField), + atomField: q => parsimmon_umd_minExports.alt( + // Place embed links above negated fields as they are the special parser case '![[thing]]' and are generally unambigious. + q.embedLink.map(l => Fields.literal(l)), q.negatedField, q.linkField, q.listField, q.objectField, q.lambdaField, q.parensField, q.boolField, q.numberField, q.stringField, q.dateField, q.durationField, q.nullField, q.variableField), + indexField: q => parsimmon_umd_minExports.seqMap(q.atomField, parsimmon_umd_minExports.alt(q.dotPostfix, q.indexPostfix, q.functionPostfix).many(), (obj, postfixes) => { + let result = obj; + for (let post of postfixes) { + switch (post.type) { + case "dot": + result = Fields.index(result, Fields.literal(post.field)); + break; + case "index": + result = Fields.index(result, post.field); + break; + case "function": + result = Fields.func(result, post.fields); + break; + } + } + return result; + }), + negatedField: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("!"), q.indexField, (_, field) => Fields.negate(field)).desc("negated field"), + parensField: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("("), parsimmon_umd_minExports.optWhitespace, q.field, parsimmon_umd_minExports.optWhitespace, parsimmon_umd_minExports.string(")"), (_1, _2, field, _3, _4) => field), + lambdaField: q => parsimmon_umd_minExports.seqMap(q.identifier + .sepBy(parsimmon_umd_minExports.string(",").trim(parsimmon_umd_minExports.optWhitespace)) + .wrap(parsimmon_umd_minExports.string("(").trim(parsimmon_umd_minExports.optWhitespace), parsimmon_umd_minExports.string(")").trim(parsimmon_umd_minExports.optWhitespace)), parsimmon_umd_minExports.string("=>").trim(parsimmon_umd_minExports.optWhitespace), q.field, (ident, _ignore, value) => { + return { type: "lambda", arguments: ident, value }; + }), + dotPostfix: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("."), q.identifier, (_, field) => { + return { type: "dot", field: field }; + }), + indexPostfix: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("["), parsimmon_umd_minExports.optWhitespace, q.field, parsimmon_umd_minExports.optWhitespace, parsimmon_umd_minExports.string("]"), (_, _2, field, _3, _4) => { + return { type: "index", field }; + }), + functionPostfix: q => parsimmon_umd_minExports.seqMap(parsimmon_umd_minExports.string("("), parsimmon_umd_minExports.optWhitespace, q.field.sepBy(parsimmon_umd_minExports.string(",").trim(parsimmon_umd_minExports.optWhitespace)), parsimmon_umd_minExports.optWhitespace, parsimmon_umd_minExports.string(")"), (_, _1, fields, _2, _3) => { + return { type: "function", fields }; + }), + // The precedence hierarchy of operators - multiply/divide, add/subtract, compare, and then boolean operations. + binaryMulDivField: q => createBinaryParser(q.indexField, q.binaryMulDiv, Fields.binaryOp), + binaryPlusMinusField: q => createBinaryParser(q.binaryMulDivField, q.binaryPlusMinus, Fields.binaryOp), + binaryCompareField: q => createBinaryParser(q.binaryPlusMinusField, q.binaryCompareOp, Fields.binaryOp), + binaryBooleanField: q => createBinaryParser(q.binaryCompareField, q.binaryBooleanOp, Fields.binaryOp), + binaryOpField: q => q.binaryBooleanField, + field: q => q.binaryOpField, +}); +/** + * Attempt to parse a field from the given text, returning a string error if the + * parse failed. + */ +function parseField(text) { + try { + return Result.success(EXPRESSION.field.tryParse(text)); + } + catch (error) { + return Result.failure("" + error); + } } -/** Parse inline fields and other embedded metadata in a line. */ -/** The wrapper characters that can be used to define an inline field. */ -const INLINE_FIELD_WRAPPERS = Object.freeze({ - "[": "]", - "(": ")", -}); -/** - * Find a matching closing bracket that occurs at or after `start`, respecting nesting and escapes. If found, - * returns the value contained within and the string index after the end of the value. - */ -function findClosing(line, start, open, close) { - let nesting = 0; - let escaped = false; - for (let index = start; index < line.length; index++) { - let char = line.charAt(index); - // Allows for double escapes like '\\' to be rendered normally. - if (char == "\\") { - escaped = !escaped; - continue; - } - // If escaped, ignore the next character for computing nesting, regardless of what it is. - if (escaped) { - escaped = false; - continue; - } - if (char == open) - nesting++; - else if (char == close) - nesting--; - // Only occurs if we are on a close character and trhere is no more nesting. - if (nesting < 0) - return { value: line.substring(start, index).trim(), endIndex: index + 1 }; - escaped = false; - } - return undefined; -} -/** Find the '::' separator in an inline field. */ -function findSeparator(line, start) { - let sep = line.indexOf("::", start); - if (sep < 0) - return undefined; - return { key: line.substring(start, sep).trim(), valueIndex: sep + 2 }; -} -/** Try to completely parse an inline field starting at the given position. Assuems `start` is on a wrapping character. */ -function findSpecificInlineField(line, start) { - let open = line.charAt(start); - let key = findSeparator(line, start + 1); - if (key === undefined) - return undefined; - // Fail the match if we find any separator characters (not allowed in keys). - for (let sep of Object.keys(INLINE_FIELD_WRAPPERS).concat(Object.values(INLINE_FIELD_WRAPPERS))) { - if (key.key.includes(sep)) - return undefined; - } - let value = findClosing(line, key.valueIndex, open, INLINE_FIELD_WRAPPERS[open]); - if (value === undefined) - return undefined; - return { - key: key.key, - value: value.value, - start: start, - startValue: key.valueIndex, - end: value.endIndex, - wrapping: open, - }; -} -/** Parse a textual inline field value into something we can work with. */ -function parseInlineValue(value) { - // Empty inline values (i.e., no text) should map to null to match long-term Dataview semantics. - // Null is also a more universal type to deal with than strings, since all functions accept nulls. - if (value.trim() == "") - return null; - // The stripped literal field parser understands all of the non-array/non-object fields and can parse them for us. - // Inline field objects are not currently supported; inline array objects have to be handled by the parser - // separately. - let inline = EXPRESSION.inlineField.parse(value); - if (inline.status) - return inline.value; - else - return value; -} -/** Extracts inline fields of the form '[key:: value]' from a line of text. This is done in a relatively - * "robust" way to avoid failing due to bad nesting or other interfering Markdown symbols: - * - * - Look for any wrappers ('[' and '(') in the line, trying to parse whatever comes after it as an inline key::. - * - If successful, scan until you find a matching end bracket, and parse whatever remains as an inline value. - */ -function extractInlineFields(line, includeTaskFields = false) { - let fields = []; - for (let wrapper of Object.keys(INLINE_FIELD_WRAPPERS)) { - let foundIndex = line.indexOf(wrapper); - while (foundIndex >= 0) { - let parsedField = findSpecificInlineField(line, foundIndex); - if (!parsedField) { - foundIndex = line.indexOf(wrapper, foundIndex + 1); - continue; - } - fields.push(parsedField); - foundIndex = line.indexOf(wrapper, parsedField.end); - } - } - if (includeTaskFields) - fields = fields.concat(extractSpecialTaskFields(line)); - fields.sort((a, b) => a.start - b.start); - let filteredFields = []; - for (let i = 0; i < fields.length; i++) { - if (i == 0 || filteredFields[filteredFields.length - 1].end < fields[i].start) { - filteredFields.push(fields[i]); - } - } - return filteredFields; -} -/** Validates that a raw field name has a valid form. */ -const FULL_LINE_KEY_PART = parsimmon_umd_min.exports.alt(parsimmon_umd_min.exports.regexp(new RegExp(emojiRegex(), "u")), parsimmon_umd_min.exports.regexp(/[0-9\p{Letter}\w\s_/-]+/u)) - .many() - .map(parts => parts.join("")); -parsimmon_umd_min.exports.regexp(/[^0-9\w\p{Letter}]*/u) - .then(FULL_LINE_KEY_PART) - .skip(parsimmon_umd_min.exports.regexp(/[_\*~`]*/u)); -const CREATED_DATE_REGEX = /\u{2795}\s*(\d{4}-\d{2}-\d{2})/u; -const DUE_DATE_REGEX = /(?:\u{1F4C5}|\u{1F4C6}|\u{1F5D3}\u{FE0F}?)\s*(\d{4}-\d{2}-\d{2})/u; -const DONE_DATE_REGEX = /\u{2705}\s*(\d{4}-\d{2}-\d{2})/u; -const SCHEDULED_DATE_REGEX = /[\u{23F3}\u{231B}]\s*(\d{4}-\d{2}-\d{2})/u; -const START_DATE_REGEX = /\u{1F6EB}\s*(\d{4}-\d{2}-\d{2})/u; -const EMOJI_REGEXES = [ - { regex: CREATED_DATE_REGEX, key: "created" }, - { regex: START_DATE_REGEX, key: "start" }, - { regex: SCHEDULED_DATE_REGEX, key: "scheduled" }, - { regex: DUE_DATE_REGEX, key: "due" }, - { regex: DONE_DATE_REGEX, key: "completion" }, -]; -/** Parse special completed/due/done task fields which are marked via emoji. */ -function extractSpecialTaskFields(line) { - let results = []; - for (let { regex, key } of EMOJI_REGEXES) { - const match = regex.exec(line); - if (!match) - continue; - results.push({ - key, - value: match[1], - start: match.index, - startValue: match.index + 1, - end: match.index + match[0].length, - wrapping: "emoji-shorthand", - }); - } - return results; -} -/** Sets or replaces the value of an inline field; if the value is 'undefined', deletes the key. */ -function setInlineField(source, key, value) { - let existing = extractInlineFields(source); - let existingKeys = existing.filter(f => f.key == key); - // Don't do anything if there are duplicate keys OR the key already doesn't exist. - if (existingKeys.length > 2 || (existingKeys.length == 0 && !value)) - return source; - let existingKey = existingKeys[0]; - let annotation = value ? `[${key}:: ${value}]` : ""; - if (existingKey) { - let prefix = source.substring(0, existingKey.start); - let suffix = source.substring(existingKey.end); - if (annotation) - return `${prefix}${annotation}${suffix}`; - else - return `${prefix}${suffix.trimStart()}`; - } - else if (annotation) { - return `${source.trimEnd()} ${annotation}`; - } - return source; -} -function setEmojiShorthandCompletionField(source, value) { - const existing = extractInlineFields(source, true); - const existingKeys = existing.filter(f => f.key === "completion" && f.wrapping === "emoji-shorthand"); - // Don't do anything if there are duplicate keys OR the key already doesn't exist. - if (existingKeys.length > 2 || (existingKeys.length == 0 && !value)) - return source; - /* No wrapper, add own spacing at start */ - const annotation = value ? ` ✅ ${value}` : ""; - let existingKey = existingKeys[0]; - if (existingKey) { - const prefix = source.substring(0, existingKey.start); - const suffix = source.substring(existingKey.end); - return `${prefix.trimEnd()}${annotation}${suffix}`; - } - else { - return `${source.trimEnd()}${annotation}`; - } +/** Parse inline fields and other embedded metadata in a line. */ +/** The wrapper characters that can be used to define an inline field. */ +const INLINE_FIELD_WRAPPERS = Object.freeze({ + "[": "]", + "(": ")", +}); +/** + * Find a matching closing bracket that occurs at or after `start`, respecting nesting and escapes. If found, + * returns the value contained within and the string index after the end of the value. + */ +function findClosing(line, start, open, close) { + let nesting = 0; + let escaped = false; + for (let index = start; index < line.length; index++) { + let char = line.charAt(index); + // Allows for double escapes like '\\' to be rendered normally. + if (char == "\\") { + escaped = !escaped; + continue; + } + // If escaped, ignore the next character for computing nesting, regardless of what it is. + if (escaped) { + escaped = false; + continue; + } + if (char == open) + nesting++; + else if (char == close) + nesting--; + // Only occurs if we are on a close character and trhere is no more nesting. + if (nesting < 0) + return { value: line.substring(start, index).trim(), endIndex: index + 1 }; + escaped = false; + } + return undefined; +} +/** Find the '::' separator in an inline field. */ +function findSeparator(line, start) { + let sep = line.indexOf("::", start); + if (sep < 0) + return undefined; + return { key: line.substring(start, sep).trim(), valueIndex: sep + 2 }; +} +/** Try to completely parse an inline field starting at the given position. Assuems `start` is on a wrapping character. */ +function findSpecificInlineField(line, start) { + let open = line.charAt(start); + let key = findSeparator(line, start + 1); + if (key === undefined) + return undefined; + // Fail the match if we find any separator characters (not allowed in keys). + for (let sep of Object.keys(INLINE_FIELD_WRAPPERS).concat(Object.values(INLINE_FIELD_WRAPPERS))) { + if (key.key.includes(sep)) + return undefined; + } + let value = findClosing(line, key.valueIndex, open, INLINE_FIELD_WRAPPERS[open]); + if (value === undefined) + return undefined; + return { + key: key.key, + value: value.value, + start: start, + startValue: key.valueIndex, + end: value.endIndex, + wrapping: open, + }; +} +/** Parse a textual inline field value into something we can work with. */ +function parseInlineValue(value) { + // Empty inline values (i.e., no text) should map to null to match long-term Dataview semantics. + // Null is also a more universal type to deal with than strings, since all functions accept nulls. + if (value.trim() == "") + return null; + // The stripped literal field parser understands all of the non-array/non-object fields and can parse them for us. + // Inline field objects are not currently supported; inline array objects have to be handled by the parser + // separately. + let inline = EXPRESSION.inlineField.parse(value); + if (inline.status) + return inline.value; + else + return value; +} +/** Extracts inline fields of the form '[key:: value]' from a line of text. This is done in a relatively + * "robust" way to avoid failing due to bad nesting or other interfering Markdown symbols: + * + * - Look for any wrappers ('[' and '(') in the line, trying to parse whatever comes after it as an inline key::. + * - If successful, scan until you find a matching end bracket, and parse whatever remains as an inline value. + */ +function extractInlineFields(line, includeTaskFields = false) { + let fields = []; + for (let wrapper of Object.keys(INLINE_FIELD_WRAPPERS)) { + let foundIndex = line.indexOf(wrapper); + while (foundIndex >= 0) { + let parsedField = findSpecificInlineField(line, foundIndex); + if (!parsedField) { + foundIndex = line.indexOf(wrapper, foundIndex + 1); + continue; + } + fields.push(parsedField); + foundIndex = line.indexOf(wrapper, parsedField.end); + } + } + if (includeTaskFields) + fields = fields.concat(extractSpecialTaskFields(line)); + fields.sort((a, b) => a.start - b.start); + let filteredFields = []; + for (let i = 0; i < fields.length; i++) { + if (i == 0 || filteredFields[filteredFields.length - 1].end < fields[i].start) { + filteredFields.push(fields[i]); + } + } + return filteredFields; +} +/** Validates that a raw field name has a valid form. */ +const FULL_LINE_KEY_PART = parsimmon_umd_minExports.alt(parsimmon_umd_minExports.regexp(new RegExp(emojiRegex(), "u")), parsimmon_umd_minExports.regexp(/[0-9\p{Letter}\w\s_/-]+/u)) + .many() + .map(parts => parts.join("")); +parsimmon_umd_minExports.regexp(/[^0-9\w\p{Letter}]*/u) + .then(FULL_LINE_KEY_PART) + .skip(parsimmon_umd_minExports.regexp(/[_\*~`]*/u)); +const CREATED_DATE_REGEX = /\u{2795}\s*(\d{4}-\d{2}-\d{2})/u; +const DUE_DATE_REGEX = /(?:\u{1F4C5}|\u{1F4C6}|\u{1F5D3}\u{FE0F}?)\s*(\d{4}-\d{2}-\d{2})/u; +const DONE_DATE_REGEX = /\u{2705}\s*(\d{4}-\d{2}-\d{2})/u; +const SCHEDULED_DATE_REGEX = /[\u{23F3}\u{231B}]\s*(\d{4}-\d{2}-\d{2})/u; +const START_DATE_REGEX = /\u{1F6EB}\s*(\d{4}-\d{2}-\d{2})/u; +const EMOJI_REGEXES = [ + { regex: CREATED_DATE_REGEX, key: "created" }, + { regex: START_DATE_REGEX, key: "start" }, + { regex: SCHEDULED_DATE_REGEX, key: "scheduled" }, + { regex: DUE_DATE_REGEX, key: "due" }, + { regex: DONE_DATE_REGEX, key: "completion" }, +]; +/** Parse special completed/due/done task fields which are marked via emoji. */ +function extractSpecialTaskFields(line) { + let results = []; + for (let { regex, key } of EMOJI_REGEXES) { + const match = regex.exec(line); + if (!match) + continue; + results.push({ + key, + value: match[1], + start: match.index, + startValue: match.index + 1, + end: match.index + match[0].length, + wrapping: "emoji-shorthand", + }); + } + return results; +} +/** Sets or replaces the value of an inline field; if the value is 'undefined', deletes the key. */ +function setInlineField(source, key, value) { + let existing = extractInlineFields(source); + let existingKeys = existing.filter(f => f.key == key); + // Don't do anything if there are duplicate keys OR the key already doesn't exist. + if (existingKeys.length > 2 || (existingKeys.length == 0 && !value)) + return source; + let existingKey = existingKeys[0]; + let annotation = value ? `[${key}:: ${value}]` : ""; + if (existingKey) { + let prefix = source.substring(0, existingKey.start); + let suffix = source.substring(existingKey.end); + if (annotation) + return `${prefix}${annotation}${suffix}`; + else + return `${prefix}${suffix.trimStart()}`; + } + else if (annotation) { + return `${source.trimEnd()} ${annotation}`; + } + return source; +} +function setEmojiShorthandCompletionField(source, value) { + const existing = extractInlineFields(source, true); + const existingKeys = existing.filter(f => f.key === "completion" && f.wrapping === "emoji-shorthand"); + // Don't do anything if there are duplicate keys OR the key already doesn't exist. + if (existingKeys.length > 2 || (existingKeys.length == 0 && !value)) + return source; + /* No wrapper, add own spacing at start */ + const annotation = value ? ` ✅ ${value}` : ""; + let existingKey = existingKeys[0]; + if (existingKey) { + const prefix = source.substring(0, existingKey.start); + const suffix = source.substring(existingKey.end); + return `${prefix.trimEnd()}${annotation}${suffix}`; + } + else { + return `${source.trimEnd()}${annotation}`; + } } -/** All extracted markdown file metadata obtained from a file. */ -class PageMetadata { - constructor(path, init) { - this.path = path; - this.fields = new Map(); - this.frontmatter = {}; - this.tags = new Set(); - this.aliases = new Set(); - this.links = []; - Object.assign(this, init); - this.lists = (this.lists || []).map(l => new ListItem$1(l)); - } - /** Canonicalize raw links and other data in partial data with normalizers, returning a completed object. */ - static canonicalize(data, linkNormalizer) { - // Mutate the data for now, which is probably a bad idea but... all well. - if (data.frontmatter) { - data.frontmatter = Values.mapLeaves(data.frontmatter, t => Values.isLink(t) ? linkNormalizer(t) : t); - } - if (data.fields) { - for (let [key, value] of data.fields.entries()) { - data.fields.set(key, Values.mapLeaves(value, t => (Values.isLink(t) ? linkNormalizer(t) : t))); - } - } - if (data.lists) { - for (let item of data.lists) { - for (let [key, value] of item.fields.entries()) { - item.fields.set(key, value.map(x => Values.mapLeaves(x, t => (Values.isLink(t) ? linkNormalizer(t) : t)))); - } - } - } - if (data.links) { - data.links = data.links.map(l => linkNormalizer(l)); - } - // This is pretty ugly, but it's not possible to normalize on the worker thread that does parsing. - // The best way to improve this is to instead just canonicalize the entire data object; I can try to - // optimize `Values.mapLeaves` to only mutate if it actually changes things. - return new PageMetadata(data.path, data); - } - /** The name (based on path) of this file. */ - name() { - return getFileTitle(this.path); - } - /** The containing folder (based on path) of this file. */ - folder() { - return getParentFolder(this.path); - } - /** The extension of this file (likely 'md'). */ - extension() { - return getExtension(this.path); - } - /** Return a set of tags AND all of their parent tags (so #hello/yes would become #hello, #hello/yes). */ - fullTags() { - let result = new Set(); - for (let tag of this.tags) { - for (let subtag of extractSubtags(tag)) - result.add(subtag); - } - return result; - } - /** Convert all links in this file to file links. */ - fileLinks() { - // We want to make them distinct, but where links are not raw links we - // now keep the additional metadata. - let distinctLinks = new Set(this.links); - return Array.from(distinctLinks); - } - /** Map this metadata to a full object; uses the index for additional data lookups. */ - serialize(index, cache) { - // Convert list items via the canonicalization cache. - let realCache = cache !== null && cache !== void 0 ? cache : new ListSerializationCache(this.lists); - let result = { - file: { - path: this.path, - folder: this.folder(), - name: this.name(), - link: Link.file(this.path), - outlinks: this.fileLinks(), - inlinks: Array.from(index.links.getInverse(this.path)).map(l => Link.file(l)), - etags: Array.from(this.tags), - tags: Array.from(this.fullTags()), - aliases: Array.from(this.aliases), - lists: this.lists.map(l => realCache.get(l.line)), - tasks: this.lists.filter(l => !!l.task).map(l => realCache.get(l.line)), - ctime: this.ctime, - cday: stripTime(this.ctime), - mtime: this.mtime, - mday: stripTime(this.mtime), - size: this.size, - starred: index.starred.starred(this.path), - frontmatter: Values.deepCopy(this.frontmatter), - ext: this.extension(), - }, - }; - // Add the current day if present. - if (this.day) - result.file.day = this.day; - // Then append the computed fields. - for (let [key, value] of this.fields.entries()) { - if (key in result) - continue; // Don't allow fields to override existing keys. - result[key] = value; - } - return result; - } -} -/** A list item inside of a list. */ -class ListItem$1 { - constructor(init) { - Object.assign(this, init); - this.fields = this.fields || new Map(); - this.tags = this.tags || new Set(); - this.children = this.children || []; - this.links = this.links || []; - } - id() { - return `${this.file().path}-${this.line}`; - } - file() { - return this.link.toFile(); - } - markdown() { - if (this.task) - return `${this.symbol} [${this.task.completed ? "x" : " "}] ${this.text}`; - else - return `${this.symbol} ${this.text}`; - } - created() { - var _a, _b, _c; - return (_c = ((_b = (_a = this.fields.get("created")) !== null && _a !== void 0 ? _a : this.fields.get("ctime")) !== null && _b !== void 0 ? _b : this.fields.get("cday"))) === null || _c === void 0 ? void 0 : _c[0]; - } - due() { - var _a, _b, _c; - return (_c = ((_b = (_a = this.fields.get("due")) !== null && _a !== void 0 ? _a : this.fields.get("duetime")) !== null && _b !== void 0 ? _b : this.fields.get("dueday"))) === null || _c === void 0 ? void 0 : _c[0]; - } - completed() { - var _a, _b, _c, _d; - return (_d = ((_c = (_b = (_a = this.fields.get("completed")) !== null && _a !== void 0 ? _a : this.fields.get("completion")) !== null && _b !== void 0 ? _b : this.fields.get("comptime")) !== null && _c !== void 0 ? _c : this.fields.get("compday"))) === null || _d === void 0 ? void 0 : _d[0]; - } - start() { - var _a; - return (_a = this.fields.get("start")) === null || _a === void 0 ? void 0 : _a[0]; - } - scheduled() { - var _a; - return (_a = this.fields.get("scheduled")) === null || _a === void 0 ? void 0 : _a[0]; - } - /** Create an API-friendly copy of this list item. De-duplication is done via the provided cache. */ - serialize(cache) { - // Map children to their serialized/de-duplicated equivalents right away. - let children = this.children.map(l => cache.get(l)).filter((l) => l !== undefined); - let result = { - symbol: this.symbol, - link: this.link, - section: this.section, - text: this.text, - tags: Array.from(this.tags), - line: this.line, - lineCount: this.lineCount, - list: this.list, - outlinks: Array.from(this.links), - path: this.link.path, - children: children, - task: !!this.task, - annotated: this.fields.size > 0, - position: Values.deepCopy(this.position), - subtasks: children, - real: !!this.task, - header: this.section, // @deprecated, use 'item.section' instead. - }; - if (this.parent || this.parent === 0) - result.parent = this.parent; - if (this.blockId) - result.blockId = this.blockId; - addFields(this.fields, result); - if (this.task) { - result.status = this.task.status; - result.checked = this.task.checked; - result.completed = this.task.completed; - result.fullyCompleted = this.task.fullyCompleted; - let created = this.created(), due = this.due(), completed = this.completed(), start = this.start(), scheduled = this.scheduled(); - if (created) - result.created = Values.deepCopy(created); - if (due) - result.due = Values.deepCopy(due); - if (completed) - result.completion = Values.deepCopy(completed); - if (start) - result.start = Values.deepCopy(start); - if (scheduled) - result.scheduled = Values.deepCopy(scheduled); - } - return result; - } -} -////////////////////////////////////////// -// Conversion / Serialization Utilities // -////////////////////////////////////////// -/** De-duplicates list items across section metadata and page metadata. */ -class ListSerializationCache { - constructor(listItems) { - this.listItems = {}; - this.cache = {}; - this.seen = new Set(); - for (let item of listItems) - this.listItems[item.line] = item; - } - get(lineno) { - if (lineno in this.cache) - return this.cache[lineno]; - else if (this.seen.has(lineno)) { - console.log(`Dataview: Encountered a circular list (line number ${lineno}; children ${this.listItems[lineno].children.join(", ")})`); - return undefined; - } - this.seen.add(lineno); - let result = this.listItems[lineno].serialize(this); - this.cache[lineno] = result; - return result; - } -} -function addFields(fields, target) { - for (let [key, values] of fields.entries()) { - if (key in target) - continue; - target[key] = values.length == 1 ? values[0] : values; - } - return target; +/** All extracted markdown file metadata obtained from a file. */ +class PageMetadata { + constructor(path, init) { + this.path = path; + this.fields = new Map(); + this.frontmatter = {}; + this.tags = new Set(); + this.aliases = new Set(); + this.links = []; + Object.assign(this, init); + this.lists = (this.lists || []).map(l => new ListItem$1(l)); + } + /** Canonicalize raw links and other data in partial data with normalizers, returning a completed object. */ + static canonicalize(data, linkNormalizer) { + // Mutate the data for now, which is probably a bad idea but... all well. + if (data.frontmatter) { + data.frontmatter = Values.mapLeaves(data.frontmatter, t => Values.isLink(t) ? linkNormalizer(t) : t); + } + if (data.fields) { + for (let [key, value] of data.fields.entries()) { + data.fields.set(key, Values.mapLeaves(value, t => (Values.isLink(t) ? linkNormalizer(t) : t))); + } + } + if (data.lists) { + for (let item of data.lists) { + for (let [key, value] of item.fields.entries()) { + item.fields.set(key, value.map(x => Values.mapLeaves(x, t => (Values.isLink(t) ? linkNormalizer(t) : t)))); + } + } + } + if (data.links) { + data.links = data.links.map(l => linkNormalizer(l)); + } + // This is pretty ugly, but it's not possible to normalize on the worker thread that does parsing. + // The best way to improve this is to instead just canonicalize the entire data object; I can try to + // optimize `Values.mapLeaves` to only mutate if it actually changes things. + return new PageMetadata(data.path, data); + } + /** The name (based on path) of this file. */ + name() { + return getFileTitle(this.path); + } + /** The containing folder (based on path) of this file. */ + folder() { + return getParentFolder(this.path); + } + /** The extension of this file (likely 'md'). */ + extension() { + return getExtension(this.path); + } + /** Return a set of tags AND all of their parent tags (so #hello/yes would become #hello, #hello/yes). */ + fullTags() { + let result = new Set(); + for (let tag of this.tags) { + for (let subtag of extractSubtags(tag)) + result.add(subtag); + } + return result; + } + /** Convert all links in this file to file links. */ + fileLinks() { + // We want to make them distinct, but where links are not raw links we + // now keep the additional metadata. + let distinctLinks = new Set(this.links); + return Array.from(distinctLinks); + } + /** Map this metadata to a full object; uses the index for additional data lookups. */ + serialize(index, cache) { + // Convert list items via the canonicalization cache. + let realCache = cache !== null && cache !== void 0 ? cache : new ListSerializationCache(this.lists); + let result = { + file: { + path: this.path, + folder: this.folder(), + name: this.name(), + link: Link.file(this.path), + outlinks: this.fileLinks(), + inlinks: Array.from(index.links.getInverse(this.path)).map(l => Link.file(l)), + etags: Array.from(this.tags), + tags: Array.from(this.fullTags()), + aliases: Array.from(this.aliases), + lists: this.lists.map(l => realCache.get(l.line)), + tasks: this.lists.filter(l => !!l.task).map(l => realCache.get(l.line)), + ctime: this.ctime, + cday: stripTime(this.ctime), + mtime: this.mtime, + mday: stripTime(this.mtime), + size: this.size, + starred: index.starred.starred(this.path), + frontmatter: Values.deepCopy(this.frontmatter), + ext: this.extension(), + }, + }; + // Add the current day if present. + if (this.day) + result.file.day = this.day; + // Then append the computed fields. + for (let [key, value] of this.fields.entries()) { + if (key in result) + continue; // Don't allow fields to override existing keys. + result[key] = value; + } + return result; + } +} +/** A list item inside of a list. */ +class ListItem$1 { + constructor(init) { + Object.assign(this, init); + this.fields = this.fields || new Map(); + this.tags = this.tags || new Set(); + this.children = this.children || []; + this.links = this.links || []; + } + id() { + return `${this.file().path}-${this.line}`; + } + file() { + return this.link.toFile(); + } + markdown() { + if (this.task) + return `${this.symbol} [${this.task.completed ? "x" : " "}] ${this.text}`; + else + return `${this.symbol} ${this.text}`; + } + created() { + var _a, _b, _c; + return (_c = ((_b = (_a = this.fields.get("created")) !== null && _a !== void 0 ? _a : this.fields.get("ctime")) !== null && _b !== void 0 ? _b : this.fields.get("cday"))) === null || _c === void 0 ? void 0 : _c[0]; + } + due() { + var _a, _b, _c; + return (_c = ((_b = (_a = this.fields.get("due")) !== null && _a !== void 0 ? _a : this.fields.get("duetime")) !== null && _b !== void 0 ? _b : this.fields.get("dueday"))) === null || _c === void 0 ? void 0 : _c[0]; + } + completed() { + var _a, _b, _c, _d; + return (_d = ((_c = (_b = (_a = this.fields.get("completed")) !== null && _a !== void 0 ? _a : this.fields.get("completion")) !== null && _b !== void 0 ? _b : this.fields.get("comptime")) !== null && _c !== void 0 ? _c : this.fields.get("compday"))) === null || _d === void 0 ? void 0 : _d[0]; + } + start() { + var _a; + return (_a = this.fields.get("start")) === null || _a === void 0 ? void 0 : _a[0]; + } + scheduled() { + var _a; + return (_a = this.fields.get("scheduled")) === null || _a === void 0 ? void 0 : _a[0]; + } + /** Create an API-friendly copy of this list item. De-duplication is done via the provided cache. */ + serialize(cache) { + // Map children to their serialized/de-duplicated equivalents right away. + let children = this.children.map(l => cache.get(l)).filter((l) => l !== undefined); + let result = { + symbol: this.symbol, + link: this.link, + section: this.section, + text: this.text, + tags: Array.from(this.tags), + line: this.line, + lineCount: this.lineCount, + list: this.list, + outlinks: Array.from(this.links), + path: this.link.path, + children: children, + task: !!this.task, + annotated: this.fields.size > 0, + position: Values.deepCopy(this.position), + subtasks: children, + real: !!this.task, + header: this.section, // @deprecated, use 'item.section' instead. + }; + if (this.parent || this.parent === 0) + result.parent = this.parent; + if (this.blockId) + result.blockId = this.blockId; + addFields(this.fields, result); + if (this.task) { + result.status = this.task.status; + result.checked = this.task.checked; + result.completed = this.task.completed; + result.fullyCompleted = this.task.fullyCompleted; + let created = this.created(), due = this.due(), completed = this.completed(), start = this.start(), scheduled = this.scheduled(); + if (created) + result.created = Values.deepCopy(created); + if (due) + result.due = Values.deepCopy(due); + if (completed) + result.completion = Values.deepCopy(completed); + if (start) + result.start = Values.deepCopy(start); + if (scheduled) + result.scheduled = Values.deepCopy(scheduled); + } + return result; + } +} +////////////////////////////////////////// +// Conversion / Serialization Utilities // +////////////////////////////////////////// +/** De-duplicates list items across section metadata and page metadata. */ +class ListSerializationCache { + constructor(listItems) { + this.listItems = {}; + this.cache = {}; + this.seen = new Set(); + for (let item of listItems) + this.listItems[item.line] = item; + } + get(lineno) { + if (lineno in this.cache) + return this.cache[lineno]; + else if (this.seen.has(lineno)) { + console.log(`Dataview: Encountered a circular list (line number ${lineno}; children ${this.listItems[lineno].children.join(", ")})`); + return undefined; + } + this.seen.add(lineno); + let result = this.listItems[lineno].serialize(this); + this.cache[lineno] = result; + return result; + } +} +function addFields(fields, target) { + for (let [key, values] of fields.entries()) { + if (key in target) + continue; + target[key] = values.length == 1 ? values[0] : values; + } + return target; } -/** Importer for markdown documents. */ -// TODO: Consider using an actual parser in leiu of a more expensive regex. -const LIST_ITEM_REGEX = /^[\s>]*(\d+\.|\d+\)|\*|-|\+)\s*(\[.{0,1}\])?\s*(.*)$/mu; -/** Recursively convert frontmatter into fields. We have to dance around YAML structure. */ -function parseFrontmatter(value) { - if (value == null) { - return null; - } - else if (typeof value === "object") { - if (Array.isArray(value)) { - let result = []; - for (let child of value) { - result.push(parseFrontmatter(child)); - } - return result; - } - else if (value instanceof Date) { - let dateParse = DateTime.fromJSDate(value); - return dateParse; - } - else { - let object = value; - let result = {}; - for (let key in object) { - result[key] = parseFrontmatter(object[key]); - } - return result; - } - } - else if (typeof value === "number") { - return value; - } - else if (typeof value === "boolean") { - return value; - } - else if (typeof value === "string") { - let dateParse = EXPRESSION.date.parse(value); - if (dateParse.status) - return dateParse.value; - let durationParse = EXPRESSION.duration.parse(value); - if (durationParse.status) - return durationParse.value; - let linkParse = EXPRESSION.embedLink.parse(value); - if (linkParse.status) - return linkParse.value; - return value; - } - // Backup if we don't understand the type. - return null; +/** Importer for markdown documents. */ +// TODO: Consider using an actual parser in leiu of a more expensive regex. +const LIST_ITEM_REGEX = /^[\s>]*(\d+\.|\d+\)|\*|-|\+)\s*(\[.{0,1}\])?\s*(.*)$/mu; +/** Recursively convert frontmatter into fields. We have to dance around YAML structure. */ +function parseFrontmatter(value) { + if (value == null) { + return null; + } + else if (typeof value === "object") { + if (Array.isArray(value)) { + let result = []; + for (let child of value) { + result.push(parseFrontmatter(child)); + } + return result; + } + else if (value instanceof Date) { + let dateParse = DateTime.fromJSDate(value); + return dateParse; + } + else { + let object = value; + let result = {}; + for (let key in object) { + result[key] = parseFrontmatter(object[key]); + } + return result; + } + } + else if (typeof value === "number") { + return value; + } + else if (typeof value === "boolean") { + return value; + } + else if (typeof value === "string") { + let dateParse = EXPRESSION.date.parse(value); + if (dateParse.status) + return dateParse.value; + let durationParse = EXPRESSION.duration.parse(value); + if (durationParse.status) + return durationParse.value; + let linkParse = EXPRESSION.embedLink.parse(value); + if (linkParse.status) + return linkParse.value; + return value; + } + // Backup if we don't understand the type. + return null; } -/** Parse a CSV file into a collection of data rows. */ -function parseCsv(content) { - let parsed = papaparse_min.exports.parse(content, { - header: true, - skipEmptyLines: true, - comments: "#", - dynamicTyping: true, - }); - let rows = []; - for (let parsedRow of parsed.data) { - let fields = parseFrontmatter(parsedRow); - let result = {}; - for (let [key, value] of Object.entries(fields)) { - result[key] = value; - result[canonicalizeVarName(key)] = value; - } - rows.push(result); - } - return rows; +/** Parse a CSV file into a collection of data rows. */ +function parseCsv(content) { + let parsed = papaparse_minExports.parse(content, { + header: true, + skipEmptyLines: true, + comments: "#", + dynamicTyping: true, + }); + let rows = []; + for (let parsedRow of parsed.data) { + let fields = parseFrontmatter(parsedRow); + let result = {}; + for (let [key, value] of Object.entries(fields)) { + result[key] = value; + result[canonicalizeVarName(key)] = value; + } + rows.push(result); + } + return rows; } -/** Simplifies passing dataview values across the JS web worker barrier. */ -var Transferable; -(function (Transferable) { - /** Convert a literal value to a serializer-friendly transferable value. */ - function transferable(value) { - // Handle simple universal types first. - if (value instanceof Map) { - let copied = new Map(); - for (let [key, val] of value.entries()) - copied.set(transferable(key), transferable(val)); - return copied; - } - else if (value instanceof Set) { - let copied = new Set(); - for (let val of value) - copied.add(transferable(val)); - return copied; - } - let wrapped = Values.wrapValue(value); - if (wrapped === undefined) - throw Error("Unrecognized transferable value: " + value); - switch (wrapped.type) { - case "null": - case "number": - case "string": - case "boolean": - return wrapped.value; - case "date": - return { - "___transfer-type": "date", - value: transferable(wrapped.value.toObject()), - options: { - zone: wrapped.value.zone.equals(SystemZone.instance) ? undefined : wrapped.value.zoneName, - }, - }; - case "duration": - return { "___transfer-type": "duration", value: transferable(wrapped.value.toObject()) }; - case "array": - return wrapped.value.map(v => transferable(v)); - case "link": - return { "___transfer-type": "link", value: transferable(wrapped.value.toObject()) }; - case "object": - let result = {}; - for (let [key, value] of Object.entries(wrapped.value)) - result[key] = transferable(value); - return result; - } - } - Transferable.transferable = transferable; - /** Convert a transferable value back to a literal value we can work with. */ - function value(transferable) { - if (transferable === null) { - return null; - } - else if (transferable === undefined) { - return undefined; - } - else if (transferable instanceof Map) { - let real = new Map(); - for (let [key, val] of transferable.entries()) - real.set(value(key), value(val)); - return real; - } - else if (transferable instanceof Set) { - let real = new Set(); - for (let val of transferable) - real.add(value(val)); - return real; - } - else if (Array.isArray(transferable)) { - return transferable.map(v => value(v)); - } - else if (typeof transferable === "object") { - if ("___transfer-type" in transferable) { - switch (transferable["___transfer-type"]) { - case "date": - let dateOpts = value(transferable.options); - let dateData = value(transferable.value); - return DateTime.fromObject(dateData, { zone: dateOpts.zone }); - case "duration": - return Duration.fromObject(value(transferable.value)); - case "link": - return Link.fromObject(value(transferable.value)); - default: - throw Error(`Unrecognized transfer type '${transferable["___transfer-type"]}'`); - } - } - let result = {}; - for (let [key, val] of Object.entries(transferable)) - result[key] = value(val); - return result; - } - return transferable; - } - Transferable.value = value; +/** Simplifies passing dataview values across the JS web worker barrier. */ +var Transferable; +(function (Transferable) { + /** Convert a literal value to a serializer-friendly transferable value. */ + function transferable(value) { + // Handle simple universal types first. + if (value instanceof Map) { + let copied = new Map(); + for (let [key, val] of value.entries()) + copied.set(transferable(key), transferable(val)); + return copied; + } + else if (value instanceof Set) { + let copied = new Set(); + for (let val of value) + copied.add(transferable(val)); + return copied; + } + let wrapped = Values.wrapValue(value); + if (wrapped === undefined) + throw Error("Unrecognized transferable value: " + value); + switch (wrapped.type) { + case "null": + case "number": + case "string": + case "boolean": + return wrapped.value; + case "date": + return { + "___transfer-type": "date", + value: transferable(wrapped.value.toObject()), + options: { + zone: wrapped.value.zone.equals(SystemZone.instance) ? undefined : wrapped.value.zoneName, + }, + }; + case "duration": + return { "___transfer-type": "duration", value: transferable(wrapped.value.toObject()) }; + case "array": + return wrapped.value.map(v => transferable(v)); + case "link": + return { "___transfer-type": "link", value: transferable(wrapped.value.toObject()) }; + case "object": + let result = {}; + for (let [key, value] of Object.entries(wrapped.value)) + result[key] = transferable(value); + return result; + } + } + Transferable.transferable = transferable; + /** Convert a transferable value back to a literal value we can work with. */ + function value(transferable) { + if (transferable === null) { + return null; + } + else if (transferable === undefined) { + return undefined; + } + else if (transferable instanceof Map) { + let real = new Map(); + for (let [key, val] of transferable.entries()) + real.set(value(key), value(val)); + return real; + } + else if (transferable instanceof Set) { + let real = new Set(); + for (let val of transferable) + real.add(value(val)); + return real; + } + else if (Array.isArray(transferable)) { + return transferable.map(v => value(v)); + } + else if (typeof transferable === "object") { + if ("___transfer-type" in transferable) { + switch (transferable["___transfer-type"]) { + case "date": + let dateOpts = value(transferable.options); + let dateData = value(transferable.value); + return DateTime.fromObject(dateData, { zone: dateOpts.zone }); + case "duration": + return Duration.fromObject(value(transferable.value)); + case "link": + return Link.fromObject(value(transferable.value)); + default: + throw Error(`Unrecognized transfer type '${transferable["___transfer-type"]}'`); + } + } + let result = {}; + for (let [key, val] of Object.entries(transferable)) + result[key] = value(val); + return result; + } + return transferable; + } + Transferable.value = value; })(Transferable || (Transferable = {})); +function commonjsRequire(path) { + throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.'); +} + var localforage$1 = {exports: {}}; /*! @@ -9491,2877 +9653,2879 @@ var localforage$1 = {exports: {}}; https://localforage.github.io/localForage (c) 2013-2017 Mozilla, Apache License 2.0 */ +localforage$1.exports; (function (module, exports) { -(function(f){{module.exports=f();}})(function(){return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof commonjsRequire=="function"&&commonjsRequire;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw (f.code="MODULE_NOT_FOUND", f)}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r);}return n[o].exports}var i=typeof commonjsRequire=="function"&&commonjsRequire;for(var o=0;o element; its readystatechange event will be fired asynchronously once it is inserted - // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called. - var scriptEl = global.document.createElement('script'); - scriptEl.onreadystatechange = function () { - nextTick(); + // Create a {#if metadata} -function create_catch_block(ctx) { - return { - c: noop, - m: noop, - p: noop, - i: noop, - o: noop, - d: noop - }; -} - -// (8:37) ; export let metadata; {#if metadata} -function create_pending_block(ctx) { - return { - c: noop, - m: noop, - p: noop, - i: noop, - o: noop, - d: noop - }; -} - -function create_fragment$5(ctx) { - let current_block_type_index; - let if_block; - let if_block_anchor; - let current; - const if_block_creators = [create_if_block$1, create_else_block]; - const if_blocks = []; - - function select_block_type(ctx, dirty) { - if (/*metadata*/ ctx[0]) return 0; - return 1; - } - - current_block_type_index = select_block_type(ctx); - if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx); - - return { - c() { - if_block.c(); - if_block_anchor = empty(); - }, - m(target, anchor) { - if_blocks[current_block_type_index].m(target, anchor); - insert(target, if_block_anchor, anchor); - current = true; - }, - p(ctx, [dirty]) { - let previous_block_index = current_block_type_index; - current_block_type_index = select_block_type(ctx); - - if (current_block_type_index === previous_block_index) { - if_blocks[current_block_type_index].p(ctx, dirty); - } else { - group_outros(); - - transition_out(if_blocks[previous_block_index], 1, 1, () => { - if_blocks[previous_block_index] = null; - }); - - check_outros(); - if_block = if_blocks[current_block_type_index]; - - if (!if_block) { - if_block = if_blocks[current_block_type_index] = if_block_creators[current_block_type_index](ctx); - if_block.c(); - } else { - if_block.p(ctx, dirty); - } - - transition_in(if_block, 1); - if_block.m(if_block_anchor.parentNode, if_block_anchor); - } - }, - i(local) { - if (current) return; - transition_in(if_block); - current = true; - }, - o(local) { - transition_out(if_block); - current = false; - }, - d(detaching) { - if_blocks[current_block_type_index].d(detaching); - if (detaching) detach(if_block_anchor); - } - }; -} - -function instance$5($$self, $$props, $$invalidate) { - let { $$slots: slots = {}, $$scope } = $$props; - - let { metadata } = $$props; - - $$self.$$set = $$props => { - if ("metadata" in $$props) $$invalidate(0, metadata = $$props.metadata); - if ("$$scope" in $$props) $$invalidate(1, $$scope = $$props.$$scope); - }; - - return [metadata, $$scope, slots]; -} - -class MetadataResolver extends SvelteComponent { - constructor(options) { - super(); - init(this, options, instance$5, create_fragment$5, not_equal, { metadata: 0 }); - } -} - -function isMacOS() { - return navigator.appVersion.indexOf("Mac") !== -1; -} -function isMetaPressed(e) { - return isMacOS() ? e.metaKey : e.ctrlKey; -} -function getDaysOfWeek(..._args) { - return window.moment.weekdaysShort(true); -} -function isWeekend(date) { - return date.isoWeekday() === 6 || date.isoWeekday() === 7; -} -function getStartOfWeek(days) { - return days[0].weekday(0); -} -/** - * Generate a 2D array of daily information to power - * the calendar view. - */ -function getMonth(displayedMonth, ..._args) { - const locale = window.moment().locale(); - const month = []; - let week; - const startOfMonth = displayedMonth.clone().locale(locale).date(1); - const startOffset = startOfMonth.weekday(); - let date = startOfMonth.clone().subtract(startOffset, "days"); - for (let _day = 0; _day < 42; _day++) { - if (_day % 7 === 0) { - week = { - days: [], - weekNum: date.week(), - }; - month.push(week); - } - week.days.push(date); - date = date.clone().add(1, "days"); - } - return month; -} - -/* src/components/Day.svelte generated by Svelte v3.35.0 */ - -function add_css$4() { - var style = element("style"); - style.id = "svelte-q3wqg9-style"; - style.textContent = ".day.svelte-q3wqg9{background-color:var(--color-background-day);border-radius:4px;color:var(--color-text-day);cursor:pointer;font-size:0.8em;height:100%;padding:4px;position:relative;text-align:center;transition:background-color 0.1s ease-in, color 0.1s ease-in;vertical-align:baseline}.day.svelte-q3wqg9:hover{background-color:var(--interactive-hover)}.day.active.svelte-q3wqg9:hover{background-color:var(--interactive-accent-hover)}.adjacent-month.svelte-q3wqg9{opacity:0.25}.today.svelte-q3wqg9{color:var(--color-text-today)}.day.svelte-q3wqg9:active,.active.svelte-q3wqg9,.active.today.svelte-q3wqg9{color:var(--text-on-accent);background-color:var(--interactive-accent)}.dot-container.svelte-q3wqg9{display:flex;flex-wrap:wrap;justify-content:center;line-height:6px;min-height:6px}"; - append(document.head, style); -} - -function get_each_context$2(ctx, list, i) { - const child_ctx = ctx.slice(); - child_ctx[11] = list[i]; - return child_ctx; -} - -// (36:8) {#each metadata.dots as dot} -function create_each_block$2(ctx) { - let dot; - let current; - const dot_spread_levels = [/*dot*/ ctx[11]]; - let dot_props = {}; - - for (let i = 0; i < dot_spread_levels.length; i += 1) { - dot_props = assign(dot_props, dot_spread_levels[i]); - } - - dot = new Dot({ props: dot_props }); - - return { - c() { - create_component(dot.$$.fragment); - }, - m(target, anchor) { - mount_component(dot, target, anchor); - current = true; - }, - p(ctx, dirty) { - const dot_changes = (dirty & /*metadata*/ 128) - ? get_spread_update(dot_spread_levels, [get_spread_object(/*dot*/ ctx[11])]) - : {}; - - dot.$set(dot_changes); - }, - i(local) { - if (current) return; - transition_in(dot.$$.fragment, local); - current = true; - }, - o(local) { - transition_out(dot.$$.fragment, local); - current = false; - }, - d(detaching) { - destroy_component(dot, detaching); - } - }; -} - -// (22:2) -function create_default_slot$1(ctx) { - let div1; - let t0_value = /*date*/ ctx[0].format("D") + ""; - let t0; - let t1; - let div0; - let div1_class_value; - let current; - let mounted; - let dispose; - let each_value = /*metadata*/ ctx[7].dots; - let each_blocks = []; - - for (let i = 0; i < each_value.length; i += 1) { - each_blocks[i] = create_each_block$2(get_each_context$2(ctx, each_value, i)); - } - - const out = i => transition_out(each_blocks[i], 1, 1, () => { - each_blocks[i] = null; - }); - - let div1_levels = [ - { - class: div1_class_value = `day ${/*metadata*/ ctx[7].classes.join(" ")}` - }, - /*metadata*/ ctx[7].dataAttributes || {} - ]; - - let div1_data = {}; - - for (let i = 0; i < div1_levels.length; i += 1) { - div1_data = assign(div1_data, div1_levels[i]); - } - - return { - c() { - div1 = element("div"); - t0 = text(t0_value); - t1 = space(); - div0 = element("div"); - - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].c(); - } - - attr(div0, "class", "dot-container svelte-q3wqg9"); - set_attributes(div1, div1_data); - toggle_class(div1, "active", /*selectedId*/ ctx[6] === getDateUID_1(/*date*/ ctx[0], "day")); - toggle_class(div1, "adjacent-month", !/*date*/ ctx[0].isSame(/*displayedMonth*/ ctx[5], "month")); - toggle_class(div1, "today", /*date*/ ctx[0].isSame(/*today*/ ctx[4], "day")); - toggle_class(div1, "svelte-q3wqg9", true); - }, - m(target, anchor) { - insert(target, div1, anchor); - append(div1, t0); - append(div1, t1); - append(div1, div0); - - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].m(div0, null); - } - - current = true; - - if (!mounted) { - dispose = [ - listen(div1, "click", function () { - if (is_function(/*onClick*/ ctx[2] && /*click_handler*/ ctx[8])) (/*onClick*/ ctx[2] && /*click_handler*/ ctx[8]).apply(this, arguments); - }), - listen(div1, "contextmenu", function () { - if (is_function(/*onContextMenu*/ ctx[3] && /*contextmenu_handler*/ ctx[9])) (/*onContextMenu*/ ctx[3] && /*contextmenu_handler*/ ctx[9]).apply(this, arguments); - }), - listen(div1, "pointerover", function () { - if (is_function(/*onHover*/ ctx[1] && /*pointerover_handler*/ ctx[10])) (/*onHover*/ ctx[1] && /*pointerover_handler*/ ctx[10]).apply(this, arguments); - }) - ]; - - mounted = true; - } - }, - p(new_ctx, dirty) { - ctx = new_ctx; - if ((!current || dirty & /*date*/ 1) && t0_value !== (t0_value = /*date*/ ctx[0].format("D") + "")) set_data(t0, t0_value); - - if (dirty & /*metadata*/ 128) { - each_value = /*metadata*/ ctx[7].dots; - let i; - - for (i = 0; i < each_value.length; i += 1) { - const child_ctx = get_each_context$2(ctx, each_value, i); - - if (each_blocks[i]) { - each_blocks[i].p(child_ctx, dirty); - transition_in(each_blocks[i], 1); - } else { - each_blocks[i] = create_each_block$2(child_ctx); - each_blocks[i].c(); - transition_in(each_blocks[i], 1); - each_blocks[i].m(div0, null); - } - } - - group_outros(); - - for (i = each_value.length; i < each_blocks.length; i += 1) { - out(i); - } - - check_outros(); - } - - set_attributes(div1, div1_data = get_spread_update(div1_levels, [ - (!current || dirty & /*metadata*/ 128 && div1_class_value !== (div1_class_value = `day ${/*metadata*/ ctx[7].classes.join(" ")}`)) && { class: div1_class_value }, - dirty & /*metadata*/ 128 && (/*metadata*/ ctx[7].dataAttributes || {}) - ])); - - toggle_class(div1, "active", /*selectedId*/ ctx[6] === getDateUID_1(/*date*/ ctx[0], "day")); - toggle_class(div1, "adjacent-month", !/*date*/ ctx[0].isSame(/*displayedMonth*/ ctx[5], "month")); - toggle_class(div1, "today", /*date*/ ctx[0].isSame(/*today*/ ctx[4], "day")); - toggle_class(div1, "svelte-q3wqg9", true); - }, - i(local) { - if (current) return; - - for (let i = 0; i < each_value.length; i += 1) { - transition_in(each_blocks[i]); - } - - current = true; - }, - o(local) { - each_blocks = each_blocks.filter(Boolean); - - for (let i = 0; i < each_blocks.length; i += 1) { - transition_out(each_blocks[i]); - } - - current = false; - }, - d(detaching) { - if (detaching) detach(div1); - destroy_each(each_blocks, detaching); - mounted = false; - run_all(dispose); - } - }; -} - -function create_fragment$4(ctx) { - let td; - let metadataresolver; - let current; - - metadataresolver = new MetadataResolver({ - props: { - metadata: /*metadata*/ ctx[7], - $$slots: { - default: [ - create_default_slot$1, - ({ metadata }) => ({ 7: metadata }), - ({ metadata }) => metadata ? 128 : 0 - ] - }, - $$scope: { ctx } - } - }); - - return { - c() { - td = element("td"); - create_component(metadataresolver.$$.fragment); - }, - m(target, anchor) { - insert(target, td, anchor); - mount_component(metadataresolver, td, null); - current = true; - }, - p(ctx, [dirty]) { - const metadataresolver_changes = {}; - if (dirty & /*metadata*/ 128) metadataresolver_changes.metadata = /*metadata*/ ctx[7]; - - if (dirty & /*$$scope, metadata, selectedId, date, displayedMonth, today, onClick, onContextMenu, onHover*/ 16639) { - metadataresolver_changes.$$scope = { dirty, ctx }; - } - - metadataresolver.$set(metadataresolver_changes); - }, - i(local) { - if (current) return; - transition_in(metadataresolver.$$.fragment, local); - current = true; - }, - o(local) { - transition_out(metadataresolver.$$.fragment, local); - current = false; - }, - d(detaching) { - if (detaching) detach(td); - destroy_component(metadataresolver); - } - }; -} - -function instance$4($$self, $$props, $$invalidate) { - - - let { date } = $$props; - let { metadata } = $$props; - let { onHover } = $$props; - let { onClick } = $$props; - let { onContextMenu } = $$props; - let { today } = $$props; - let { displayedMonth = null } = $$props; - let { selectedId = null } = $$props; - const click_handler = e => onClick(date, isMetaPressed(e)); - const contextmenu_handler = e => onContextMenu(date, e); - const pointerover_handler = e => onHover(date, e.target, isMetaPressed(e)); - - $$self.$$set = $$props => { - if ("date" in $$props) $$invalidate(0, date = $$props.date); - if ("metadata" in $$props) $$invalidate(7, metadata = $$props.metadata); - if ("onHover" in $$props) $$invalidate(1, onHover = $$props.onHover); - if ("onClick" in $$props) $$invalidate(2, onClick = $$props.onClick); - if ("onContextMenu" in $$props) $$invalidate(3, onContextMenu = $$props.onContextMenu); - if ("today" in $$props) $$invalidate(4, today = $$props.today); - if ("displayedMonth" in $$props) $$invalidate(5, displayedMonth = $$props.displayedMonth); - if ("selectedId" in $$props) $$invalidate(6, selectedId = $$props.selectedId); - }; - - return [ - date, - onHover, - onClick, - onContextMenu, - today, - displayedMonth, - selectedId, - metadata, - click_handler, - contextmenu_handler, - pointerover_handler - ]; -} - -class Day extends SvelteComponent { - constructor(options) { - super(); - if (!document.getElementById("svelte-q3wqg9-style")) add_css$4(); - - init(this, options, instance$4, create_fragment$4, not_equal, { - date: 0, - metadata: 7, - onHover: 1, - onClick: 2, - onContextMenu: 3, - today: 4, - displayedMonth: 5, - selectedId: 6 - }); - } -} - -/* src/components/Arrow.svelte generated by Svelte v3.35.0 */ - -function add_css$3() { - var style = element("style"); - style.id = "svelte-156w7na-style"; - style.textContent = ".arrow.svelte-156w7na.svelte-156w7na{align-items:center;cursor:pointer;display:flex;justify-content:center;width:24px}.arrow.is-mobile.svelte-156w7na.svelte-156w7na{width:32px}.right.svelte-156w7na.svelte-156w7na{transform:rotate(180deg)}.arrow.svelte-156w7na svg.svelte-156w7na{color:var(--color-arrow);height:16px;width:16px}"; - append(document.head, style); -} - -function create_fragment$3(ctx) { - let div; - let svg; - let path; - let mounted; - let dispose; - - return { - c() { - div = element("div"); - svg = svg_element("svg"); - path = svg_element("path"); - attr(path, "fill", "currentColor"); - attr(path, "d", "M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z"); - attr(svg, "focusable", "false"); - attr(svg, "role", "img"); - attr(svg, "xmlns", "http://www.w3.org/2000/svg"); - attr(svg, "viewBox", "0 0 320 512"); - attr(svg, "class", "svelte-156w7na"); - attr(div, "class", "arrow svelte-156w7na"); - attr(div, "aria-label", /*tooltip*/ ctx[1]); - toggle_class(div, "is-mobile", /*isMobile*/ ctx[3]); - toggle_class(div, "right", /*direction*/ ctx[2] === "right"); - }, - m(target, anchor) { - insert(target, div, anchor); - append(div, svg); - append(svg, path); - - if (!mounted) { - dispose = listen(div, "click", function () { - if (is_function(/*onClick*/ ctx[0])) /*onClick*/ ctx[0].apply(this, arguments); - }); - - mounted = true; - } - }, - p(new_ctx, [dirty]) { - ctx = new_ctx; - - if (dirty & /*tooltip*/ 2) { - attr(div, "aria-label", /*tooltip*/ ctx[1]); - } - - if (dirty & /*direction*/ 4) { - toggle_class(div, "right", /*direction*/ ctx[2] === "right"); - } - }, - i: noop, - o: noop, - d(detaching) { - if (detaching) detach(div); - mounted = false; - dispose(); - } - }; -} - -function instance$3($$self, $$props, $$invalidate) { - let { onClick } = $$props; - let { tooltip } = $$props; - let { direction } = $$props; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let isMobile = window.app.isMobile; - - $$self.$$set = $$props => { - if ("onClick" in $$props) $$invalidate(0, onClick = $$props.onClick); - if ("tooltip" in $$props) $$invalidate(1, tooltip = $$props.tooltip); - if ("direction" in $$props) $$invalidate(2, direction = $$props.direction); - }; - - return [onClick, tooltip, direction, isMobile]; -} - -class Arrow extends SvelteComponent { - constructor(options) { - super(); - if (!document.getElementById("svelte-156w7na-style")) add_css$3(); - init(this, options, instance$3, create_fragment$3, safe_not_equal, { onClick: 0, tooltip: 1, direction: 2 }); - } -} - -/* src/components/Nav.svelte generated by Svelte v3.35.0 */ - -function add_css$2() { - var style = element("style"); - style.id = "svelte-1vwr9dd-style"; - style.textContent = ".nav.svelte-1vwr9dd.svelte-1vwr9dd{align-items:center;display:flex;margin:0.6em 0 1em;padding:0 8px;width:100%}.nav.is-mobile.svelte-1vwr9dd.svelte-1vwr9dd{padding:0}.title.svelte-1vwr9dd.svelte-1vwr9dd{color:var(--color-text-title);font-size:1.5em;margin:0}.is-mobile.svelte-1vwr9dd .title.svelte-1vwr9dd{font-size:1.3em}.month.svelte-1vwr9dd.svelte-1vwr9dd{font-weight:500;text-transform:capitalize}.year.svelte-1vwr9dd.svelte-1vwr9dd{color:var(--interactive-accent)}.right-nav.svelte-1vwr9dd.svelte-1vwr9dd{display:flex;justify-content:center;margin-left:auto}.reset-button.svelte-1vwr9dd.svelte-1vwr9dd{cursor:pointer;border-radius:4px;color:var(--text-muted);font-size:0.7em;font-weight:600;letter-spacing:1px;margin:0 4px;padding:0px 4px;text-transform:uppercase}.is-mobile.svelte-1vwr9dd .reset-button.svelte-1vwr9dd{display:none}"; - append(document.head, style); -} - -function create_fragment$2(ctx) { - let div2; - let h3; - let span0; - let t0_value = /*displayedMonth*/ ctx[0].format("MMM") + ""; - let t0; - let t1; - let span1; - let t2_value = /*displayedMonth*/ ctx[0].format("YYYY") + ""; - let t2; - let t3; - let div1; - let arrow0; - let t4; - let div0; - let t6; - let arrow1; - let current; - let mounted; - let dispose; - - arrow0 = new Arrow({ - props: { - direction: "left", - onClick: /*decrementDisplayedMonth*/ ctx[3], - tooltip: "Previous Month" - } - }); - - arrow1 = new Arrow({ - props: { - direction: "right", - onClick: /*incrementDisplayedMonth*/ ctx[2], - tooltip: "Next Month" - } - }); - - return { - c() { - div2 = element("div"); - h3 = element("h3"); - span0 = element("span"); - t0 = text(t0_value); - t1 = space(); - span1 = element("span"); - t2 = text(t2_value); - t3 = space(); - div1 = element("div"); - create_component(arrow0.$$.fragment); - t4 = space(); - div0 = element("div"); - div0.textContent = `${/*todayDisplayStr*/ ctx[4]}`; - t6 = space(); - create_component(arrow1.$$.fragment); - attr(span0, "class", "month svelte-1vwr9dd"); - attr(span1, "class", "year svelte-1vwr9dd"); - attr(h3, "class", "title svelte-1vwr9dd"); - attr(div0, "class", "reset-button svelte-1vwr9dd"); - attr(div1, "class", "right-nav svelte-1vwr9dd"); - attr(div2, "class", "nav svelte-1vwr9dd"); - toggle_class(div2, "is-mobile", /*isMobile*/ ctx[5]); - }, - m(target, anchor) { - insert(target, div2, anchor); - append(div2, h3); - append(h3, span0); - append(span0, t0); - append(h3, t1); - append(h3, span1); - append(span1, t2); - append(div2, t3); - append(div2, div1); - mount_component(arrow0, div1, null); - append(div1, t4); - append(div1, div0); - append(div1, t6); - mount_component(arrow1, div1, null); - current = true; - - if (!mounted) { - dispose = [ - listen(h3, "click", function () { - if (is_function(/*resetDisplayedMonth*/ ctx[1])) /*resetDisplayedMonth*/ ctx[1].apply(this, arguments); - }), - listen(div0, "click", function () { - if (is_function(/*resetDisplayedMonth*/ ctx[1])) /*resetDisplayedMonth*/ ctx[1].apply(this, arguments); - }) - ]; - - mounted = true; - } - }, - p(new_ctx, [dirty]) { - ctx = new_ctx; - if ((!current || dirty & /*displayedMonth*/ 1) && t0_value !== (t0_value = /*displayedMonth*/ ctx[0].format("MMM") + "")) set_data(t0, t0_value); - if ((!current || dirty & /*displayedMonth*/ 1) && t2_value !== (t2_value = /*displayedMonth*/ ctx[0].format("YYYY") + "")) set_data(t2, t2_value); - const arrow0_changes = {}; - if (dirty & /*decrementDisplayedMonth*/ 8) arrow0_changes.onClick = /*decrementDisplayedMonth*/ ctx[3]; - arrow0.$set(arrow0_changes); - const arrow1_changes = {}; - if (dirty & /*incrementDisplayedMonth*/ 4) arrow1_changes.onClick = /*incrementDisplayedMonth*/ ctx[2]; - arrow1.$set(arrow1_changes); - }, - i(local) { - if (current) return; - transition_in(arrow0.$$.fragment, local); - transition_in(arrow1.$$.fragment, local); - current = true; - }, - o(local) { - transition_out(arrow0.$$.fragment, local); - transition_out(arrow1.$$.fragment, local); - current = false; - }, - d(detaching) { - if (detaching) detach(div2); - destroy_component(arrow0); - destroy_component(arrow1); - mounted = false; - run_all(dispose); - } - }; -} - -function instance$2($$self, $$props, $$invalidate) { - - let { displayedMonth } = $$props; - let { today } = $$props; - let { resetDisplayedMonth } = $$props; - let { incrementDisplayedMonth } = $$props; - let { decrementDisplayedMonth } = $$props; - - // Get the word 'Today' but localized to the current language - const todayDisplayStr = today.calendar().split(/\d|\s/)[0]; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let isMobile = window.app.isMobile; - - $$self.$$set = $$props => { - if ("displayedMonth" in $$props) $$invalidate(0, displayedMonth = $$props.displayedMonth); - if ("today" in $$props) $$invalidate(6, today = $$props.today); - if ("resetDisplayedMonth" in $$props) $$invalidate(1, resetDisplayedMonth = $$props.resetDisplayedMonth); - if ("incrementDisplayedMonth" in $$props) $$invalidate(2, incrementDisplayedMonth = $$props.incrementDisplayedMonth); - if ("decrementDisplayedMonth" in $$props) $$invalidate(3, decrementDisplayedMonth = $$props.decrementDisplayedMonth); - }; - - return [ - displayedMonth, - resetDisplayedMonth, - incrementDisplayedMonth, - decrementDisplayedMonth, - todayDisplayStr, - isMobile, - today - ]; -} - -class Nav extends SvelteComponent { - constructor(options) { - super(); - if (!document.getElementById("svelte-1vwr9dd-style")) add_css$2(); - - init(this, options, instance$2, create_fragment$2, safe_not_equal, { - displayedMonth: 0, - today: 6, - resetDisplayedMonth: 1, - incrementDisplayedMonth: 2, - decrementDisplayedMonth: 3 - }); - } -} - -/* src/components/WeekNum.svelte generated by Svelte v3.35.0 */ - -function add_css$1() { - var style = element("style"); - style.id = "svelte-egt0yd-style"; - style.textContent = "td.svelte-egt0yd{border-right:1px solid var(--background-modifier-border)}.week-num.svelte-egt0yd{background-color:var(--color-background-weeknum);border-radius:4px;color:var(--color-text-weeknum);cursor:pointer;font-size:0.65em;height:100%;padding:4px;text-align:center;transition:background-color 0.1s ease-in, color 0.1s ease-in;vertical-align:baseline}.week-num.svelte-egt0yd:hover{background-color:var(--interactive-hover)}.week-num.active.svelte-egt0yd:hover{background-color:var(--interactive-accent-hover)}.active.svelte-egt0yd{color:var(--text-on-accent);background-color:var(--interactive-accent)}.dot-container.svelte-egt0yd{display:flex;flex-wrap:wrap;justify-content:center;line-height:6px;min-height:6px}"; - append(document.head, style); -} - -function get_each_context$1(ctx, list, i) { - const child_ctx = ctx.slice(); - child_ctx[11] = list[i]; - return child_ctx; -} - -// (35:8) {#each metadata.dots as dot} -function create_each_block$1(ctx) { - let dot; - let current; - const dot_spread_levels = [/*dot*/ ctx[11]]; - let dot_props = {}; - - for (let i = 0; i < dot_spread_levels.length; i += 1) { - dot_props = assign(dot_props, dot_spread_levels[i]); - } - - dot = new Dot({ props: dot_props }); - - return { - c() { - create_component(dot.$$.fragment); - }, - m(target, anchor) { - mount_component(dot, target, anchor); - current = true; - }, - p(ctx, dirty) { - const dot_changes = (dirty & /*metadata*/ 64) - ? get_spread_update(dot_spread_levels, [get_spread_object(/*dot*/ ctx[11])]) - : {}; - - dot.$set(dot_changes); - }, - i(local) { - if (current) return; - transition_in(dot.$$.fragment, local); - current = true; - }, - o(local) { - transition_out(dot.$$.fragment, local); - current = false; - }, - d(detaching) { - destroy_component(dot, detaching); - } - }; -} - -// (24:2) -function create_default_slot(ctx) { - let div1; - let t0; - let t1; - let div0; - let div1_class_value; - let current; - let mounted; - let dispose; - let each_value = /*metadata*/ ctx[6].dots; - let each_blocks = []; - - for (let i = 0; i < each_value.length; i += 1) { - each_blocks[i] = create_each_block$1(get_each_context$1(ctx, each_value, i)); - } - - const out = i => transition_out(each_blocks[i], 1, 1, () => { - each_blocks[i] = null; - }); - - return { - c() { - div1 = element("div"); - t0 = text(/*weekNum*/ ctx[0]); - t1 = space(); - div0 = element("div"); - - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].c(); - } - - attr(div0, "class", "dot-container svelte-egt0yd"); - attr(div1, "class", div1_class_value = "" + (null_to_empty(`week-num ${/*metadata*/ ctx[6].classes.join(" ")}`) + " svelte-egt0yd")); - toggle_class(div1, "active", /*selectedId*/ ctx[5] === getDateUID_1(/*days*/ ctx[1][0], "week")); - }, - m(target, anchor) { - insert(target, div1, anchor); - append(div1, t0); - append(div1, t1); - append(div1, div0); - - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].m(div0, null); - } - - current = true; - - if (!mounted) { - dispose = [ - listen(div1, "click", function () { - if (is_function(/*onClick*/ ctx[3] && /*click_handler*/ ctx[8])) (/*onClick*/ ctx[3] && /*click_handler*/ ctx[8]).apply(this, arguments); - }), - listen(div1, "contextmenu", function () { - if (is_function(/*onContextMenu*/ ctx[4] && /*contextmenu_handler*/ ctx[9])) (/*onContextMenu*/ ctx[4] && /*contextmenu_handler*/ ctx[9]).apply(this, arguments); - }), - listen(div1, "pointerover", function () { - if (is_function(/*onHover*/ ctx[2] && /*pointerover_handler*/ ctx[10])) (/*onHover*/ ctx[2] && /*pointerover_handler*/ ctx[10]).apply(this, arguments); - }) - ]; - - mounted = true; - } - }, - p(new_ctx, dirty) { - ctx = new_ctx; - if (!current || dirty & /*weekNum*/ 1) set_data(t0, /*weekNum*/ ctx[0]); - - if (dirty & /*metadata*/ 64) { - each_value = /*metadata*/ ctx[6].dots; - let i; - - for (i = 0; i < each_value.length; i += 1) { - const child_ctx = get_each_context$1(ctx, each_value, i); - - if (each_blocks[i]) { - each_blocks[i].p(child_ctx, dirty); - transition_in(each_blocks[i], 1); - } else { - each_blocks[i] = create_each_block$1(child_ctx); - each_blocks[i].c(); - transition_in(each_blocks[i], 1); - each_blocks[i].m(div0, null); - } - } - - group_outros(); - - for (i = each_value.length; i < each_blocks.length; i += 1) { - out(i); - } - - check_outros(); - } - - if (!current || dirty & /*metadata*/ 64 && div1_class_value !== (div1_class_value = "" + (null_to_empty(`week-num ${/*metadata*/ ctx[6].classes.join(" ")}`) + " svelte-egt0yd"))) { - attr(div1, "class", div1_class_value); - } - - if (dirty & /*metadata, selectedId, getDateUID, days*/ 98) { - toggle_class(div1, "active", /*selectedId*/ ctx[5] === getDateUID_1(/*days*/ ctx[1][0], "week")); - } - }, - i(local) { - if (current) return; - - for (let i = 0; i < each_value.length; i += 1) { - transition_in(each_blocks[i]); - } - - current = true; - }, - o(local) { - each_blocks = each_blocks.filter(Boolean); - - for (let i = 0; i < each_blocks.length; i += 1) { - transition_out(each_blocks[i]); - } - - current = false; - }, - d(detaching) { - if (detaching) detach(div1); - destroy_each(each_blocks, detaching); - mounted = false; - run_all(dispose); - } - }; -} - -function create_fragment$1(ctx) { - let td; - let metadataresolver; - let current; - - metadataresolver = new MetadataResolver({ - props: { - metadata: /*metadata*/ ctx[6], - $$slots: { - default: [ - create_default_slot, - ({ metadata }) => ({ 6: metadata }), - ({ metadata }) => metadata ? 64 : 0 - ] - }, - $$scope: { ctx } - } - }); - - return { - c() { - td = element("td"); - create_component(metadataresolver.$$.fragment); - attr(td, "class", "svelte-egt0yd"); - }, - m(target, anchor) { - insert(target, td, anchor); - mount_component(metadataresolver, td, null); - current = true; - }, - p(ctx, [dirty]) { - const metadataresolver_changes = {}; - if (dirty & /*metadata*/ 64) metadataresolver_changes.metadata = /*metadata*/ ctx[6]; - - if (dirty & /*$$scope, metadata, selectedId, days, onClick, startOfWeek, onContextMenu, onHover, weekNum*/ 16639) { - metadataresolver_changes.$$scope = { dirty, ctx }; - } - - metadataresolver.$set(metadataresolver_changes); - }, - i(local) { - if (current) return; - transition_in(metadataresolver.$$.fragment, local); - current = true; - }, - o(local) { - transition_out(metadataresolver.$$.fragment, local); - current = false; - }, - d(detaching) { - if (detaching) detach(td); - destroy_component(metadataresolver); - } - }; -} - -function instance$1($$self, $$props, $$invalidate) { - - - let { weekNum } = $$props; - let { days } = $$props; - let { metadata } = $$props; - let { onHover } = $$props; - let { onClick } = $$props; - let { onContextMenu } = $$props; - let { selectedId = null } = $$props; - let startOfWeek; - const click_handler = e => onClick(startOfWeek, isMetaPressed(e)); - const contextmenu_handler = e => onContextMenu(days[0], e); - const pointerover_handler = e => onHover(startOfWeek, e.target, isMetaPressed(e)); - - $$self.$$set = $$props => { - if ("weekNum" in $$props) $$invalidate(0, weekNum = $$props.weekNum); - if ("days" in $$props) $$invalidate(1, days = $$props.days); - if ("metadata" in $$props) $$invalidate(6, metadata = $$props.metadata); - if ("onHover" in $$props) $$invalidate(2, onHover = $$props.onHover); - if ("onClick" in $$props) $$invalidate(3, onClick = $$props.onClick); - if ("onContextMenu" in $$props) $$invalidate(4, onContextMenu = $$props.onContextMenu); - if ("selectedId" in $$props) $$invalidate(5, selectedId = $$props.selectedId); - }; - - $$self.$$.update = () => { - if ($$self.$$.dirty & /*days*/ 2) { - $$invalidate(7, startOfWeek = getStartOfWeek(days)); - } - }; - - return [ - weekNum, - days, - onHover, - onClick, - onContextMenu, - selectedId, - metadata, - startOfWeek, - click_handler, - contextmenu_handler, - pointerover_handler - ]; -} - -class WeekNum extends SvelteComponent { - constructor(options) { - super(); - if (!document.getElementById("svelte-egt0yd-style")) add_css$1(); - - init(this, options, instance$1, create_fragment$1, not_equal, { - weekNum: 0, - days: 1, - metadata: 6, - onHover: 2, - onClick: 3, - onContextMenu: 4, - selectedId: 5 - }); - } -} - -async function metadataReducer(promisedMetadata) { - const meta = { - dots: [], - classes: [], - dataAttributes: {}, - }; - const metas = await Promise.all(promisedMetadata); - return metas.reduce((acc, meta) => ({ - classes: [...acc.classes, ...(meta.classes || [])], - dataAttributes: Object.assign(acc.dataAttributes, meta.dataAttributes), - dots: [...acc.dots, ...(meta.dots || [])], - }), meta); -} -function getDailyMetadata(sources, date, ..._args) { - return metadataReducer(sources.map((source) => source.getDailyMetadata(date))); -} -function getWeeklyMetadata(sources, date, ..._args) { - return metadataReducer(sources.map((source) => source.getWeeklyMetadata(date))); -} - -/* src/components/Calendar.svelte generated by Svelte v3.35.0 */ - -function add_css() { - var style = element("style"); - style.id = "svelte-pcimu8-style"; - style.textContent = ".container.svelte-pcimu8{--color-background-heading:transparent;--color-background-day:transparent;--color-background-weeknum:transparent;--color-background-weekend:transparent;--color-dot:var(--text-muted);--color-arrow:var(--text-muted);--color-button:var(--text-muted);--color-text-title:var(--text-normal);--color-text-heading:var(--text-muted);--color-text-day:var(--text-normal);--color-text-today:var(--interactive-accent);--color-text-weeknum:var(--text-muted)}.container.svelte-pcimu8{padding:0 8px}.container.is-mobile.svelte-pcimu8{padding:0}th.svelte-pcimu8{text-align:center}.weekend.svelte-pcimu8{background-color:var(--color-background-weekend)}.calendar.svelte-pcimu8{border-collapse:collapse;width:100%}th.svelte-pcimu8{background-color:var(--color-background-heading);color:var(--color-text-heading);font-size:0.6em;letter-spacing:1px;padding:4px;text-transform:uppercase}"; - append(document.head, style); -} - -function get_each_context(ctx, list, i) { - const child_ctx = ctx.slice(); - child_ctx[18] = list[i]; - return child_ctx; -} - -function get_each_context_1(ctx, list, i) { - const child_ctx = ctx.slice(); - child_ctx[21] = list[i]; - return child_ctx; -} - -function get_each_context_2(ctx, list, i) { - const child_ctx = ctx.slice(); - child_ctx[24] = list[i]; - return child_ctx; -} - -function get_each_context_3(ctx, list, i) { - const child_ctx = ctx.slice(); - child_ctx[27] = list[i]; - return child_ctx; -} - -// (55:6) {#if showWeekNums} -function create_if_block_2(ctx) { - let col; - - return { - c() { - col = element("col"); - }, - m(target, anchor) { - insert(target, col, anchor); - }, - d(detaching) { - if (detaching) detach(col); - } - }; -} - -// (58:6) {#each month[1].days as date} -function create_each_block_3(ctx) { - let col; - - return { - c() { - col = element("col"); - attr(col, "class", "svelte-pcimu8"); - toggle_class(col, "weekend", isWeekend(/*date*/ ctx[27])); - }, - m(target, anchor) { - insert(target, col, anchor); - }, - p(ctx, dirty) { - if (dirty & /*isWeekend, month*/ 16384) { - toggle_class(col, "weekend", isWeekend(/*date*/ ctx[27])); - } - }, - d(detaching) { - if (detaching) detach(col); - } - }; -} - -// (64:8) {#if showWeekNums} -function create_if_block_1(ctx) { - let th; - - return { - c() { - th = element("th"); - th.textContent = "W"; - attr(th, "class", "svelte-pcimu8"); - }, - m(target, anchor) { - insert(target, th, anchor); - }, - d(detaching) { - if (detaching) detach(th); - } - }; -} - -// (67:8) {#each daysOfWeek as dayOfWeek} -function create_each_block_2(ctx) { - let th; - let t_value = /*dayOfWeek*/ ctx[24] + ""; - let t; - - return { - c() { - th = element("th"); - t = text(t_value); - attr(th, "class", "svelte-pcimu8"); - }, - m(target, anchor) { - insert(target, th, anchor); - append(th, t); - }, - p(ctx, dirty) { - if (dirty & /*daysOfWeek*/ 32768 && t_value !== (t_value = /*dayOfWeek*/ ctx[24] + "")) set_data(t, t_value); - }, - d(detaching) { - if (detaching) detach(th); - } - }; -} - -// (75:10) {#if showWeekNums} -function create_if_block(ctx) { - let weeknum; - let current; - - const weeknum_spread_levels = [ - /*week*/ ctx[18], - { - metadata: getWeeklyMetadata(/*sources*/ ctx[8], /*week*/ ctx[18].days[0], /*today*/ ctx[10]) - }, - { onClick: /*onClickWeek*/ ctx[7] }, - { - onContextMenu: /*onContextMenuWeek*/ ctx[5] - }, - { onHover: /*onHoverWeek*/ ctx[3] }, - { selectedId: /*selectedId*/ ctx[9] } - ]; - - let weeknum_props = {}; - - for (let i = 0; i < weeknum_spread_levels.length; i += 1) { - weeknum_props = assign(weeknum_props, weeknum_spread_levels[i]); - } - - weeknum = new WeekNum({ props: weeknum_props }); - - return { - c() { - create_component(weeknum.$$.fragment); - }, - m(target, anchor) { - mount_component(weeknum, target, anchor); - current = true; - }, - p(ctx, dirty) { - const weeknum_changes = (dirty & /*month, getWeeklyMetadata, sources, today, onClickWeek, onContextMenuWeek, onHoverWeek, selectedId*/ 18344) - ? get_spread_update(weeknum_spread_levels, [ - dirty & /*month*/ 16384 && get_spread_object(/*week*/ ctx[18]), - dirty & /*getWeeklyMetadata, sources, month, today*/ 17664 && { - metadata: getWeeklyMetadata(/*sources*/ ctx[8], /*week*/ ctx[18].days[0], /*today*/ ctx[10]) - }, - dirty & /*onClickWeek*/ 128 && { onClick: /*onClickWeek*/ ctx[7] }, - dirty & /*onContextMenuWeek*/ 32 && { - onContextMenu: /*onContextMenuWeek*/ ctx[5] - }, - dirty & /*onHoverWeek*/ 8 && { onHover: /*onHoverWeek*/ ctx[3] }, - dirty & /*selectedId*/ 512 && { selectedId: /*selectedId*/ ctx[9] } - ]) - : {}; - - weeknum.$set(weeknum_changes); - }, - i(local) { - if (current) return; - transition_in(weeknum.$$.fragment, local); - current = true; - }, - o(local) { - transition_out(weeknum.$$.fragment, local); - current = false; - }, - d(detaching) { - destroy_component(weeknum, detaching); - } - }; -} - -// (85:10) {#each week.days as day (day.format())} -function create_each_block_1(key_1, ctx) { - let first; - let day; - let current; - - day = new Day({ - props: { - date: /*day*/ ctx[21], - today: /*today*/ ctx[10], - displayedMonth: /*displayedMonth*/ ctx[0], - onClick: /*onClickDay*/ ctx[6], - onContextMenu: /*onContextMenuDay*/ ctx[4], - onHover: /*onHoverDay*/ ctx[2], - metadata: getDailyMetadata(/*sources*/ ctx[8], /*day*/ ctx[21], /*today*/ ctx[10]), - selectedId: /*selectedId*/ ctx[9] - } - }); - - return { - key: key_1, - first: null, - c() { - first = empty(); - create_component(day.$$.fragment); - this.first = first; - }, - m(target, anchor) { - insert(target, first, anchor); - mount_component(day, target, anchor); - current = true; - }, - p(new_ctx, dirty) { - ctx = new_ctx; - const day_changes = {}; - if (dirty & /*month*/ 16384) day_changes.date = /*day*/ ctx[21]; - if (dirty & /*today*/ 1024) day_changes.today = /*today*/ ctx[10]; - if (dirty & /*displayedMonth*/ 1) day_changes.displayedMonth = /*displayedMonth*/ ctx[0]; - if (dirty & /*onClickDay*/ 64) day_changes.onClick = /*onClickDay*/ ctx[6]; - if (dirty & /*onContextMenuDay*/ 16) day_changes.onContextMenu = /*onContextMenuDay*/ ctx[4]; - if (dirty & /*onHoverDay*/ 4) day_changes.onHover = /*onHoverDay*/ ctx[2]; - if (dirty & /*sources, month, today*/ 17664) day_changes.metadata = getDailyMetadata(/*sources*/ ctx[8], /*day*/ ctx[21], /*today*/ ctx[10]); - if (dirty & /*selectedId*/ 512) day_changes.selectedId = /*selectedId*/ ctx[9]; - day.$set(day_changes); - }, - i(local) { - if (current) return; - transition_in(day.$$.fragment, local); - current = true; - }, - o(local) { - transition_out(day.$$.fragment, local); - current = false; - }, - d(detaching) { - if (detaching) detach(first); - destroy_component(day, detaching); - } - }; -} - -// (73:6) {#each month as week (week.weekNum)} -function create_each_block(key_1, ctx) { - let tr; - let t0; - let each_blocks = []; - let each_1_lookup = new Map(); - let t1; - let current; - let if_block = /*showWeekNums*/ ctx[1] && create_if_block(ctx); - let each_value_1 = /*week*/ ctx[18].days; - const get_key = ctx => /*day*/ ctx[21].format(); - - for (let i = 0; i < each_value_1.length; i += 1) { - let child_ctx = get_each_context_1(ctx, each_value_1, i); - let key = get_key(child_ctx); - each_1_lookup.set(key, each_blocks[i] = create_each_block_1(key, child_ctx)); - } - - return { - key: key_1, - first: null, - c() { - tr = element("tr"); - if (if_block) if_block.c(); - t0 = space(); - - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].c(); - } - - t1 = space(); - this.first = tr; - }, - m(target, anchor) { - insert(target, tr, anchor); - if (if_block) if_block.m(tr, null); - append(tr, t0); - - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].m(tr, null); - } - - append(tr, t1); - current = true; - }, - p(new_ctx, dirty) { - ctx = new_ctx; - - if (/*showWeekNums*/ ctx[1]) { - if (if_block) { - if_block.p(ctx, dirty); - - if (dirty & /*showWeekNums*/ 2) { - transition_in(if_block, 1); - } - } else { - if_block = create_if_block(ctx); - if_block.c(); - transition_in(if_block, 1); - if_block.m(tr, t0); - } - } else if (if_block) { - group_outros(); - - transition_out(if_block, 1, 1, () => { - if_block = null; - }); - - check_outros(); - } - - if (dirty & /*month, today, displayedMonth, onClickDay, onContextMenuDay, onHoverDay, getDailyMetadata, sources, selectedId*/ 18261) { - each_value_1 = /*week*/ ctx[18].days; - group_outros(); - each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value_1, each_1_lookup, tr, outro_and_destroy_block, create_each_block_1, t1, get_each_context_1); - check_outros(); - } - }, - i(local) { - if (current) return; - transition_in(if_block); - - for (let i = 0; i < each_value_1.length; i += 1) { - transition_in(each_blocks[i]); - } - - current = true; - }, - o(local) { - transition_out(if_block); - - for (let i = 0; i < each_blocks.length; i += 1) { - transition_out(each_blocks[i]); - } - - current = false; - }, - d(detaching) { - if (detaching) detach(tr); - if (if_block) if_block.d(); - - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].d(); - } - } - }; -} - -function create_fragment(ctx) { - let div; - let nav; - let t0; - let table; - let colgroup; - let t1; - let t2; - let thead; - let tr; - let t3; - let t4; - let tbody; - let each_blocks = []; - let each2_lookup = new Map(); - let current; - - nav = new Nav({ - props: { - today: /*today*/ ctx[10], - displayedMonth: /*displayedMonth*/ ctx[0], - incrementDisplayedMonth: /*incrementDisplayedMonth*/ ctx[11], - decrementDisplayedMonth: /*decrementDisplayedMonth*/ ctx[12], - resetDisplayedMonth: /*resetDisplayedMonth*/ ctx[13] - } - }); - - let if_block0 = /*showWeekNums*/ ctx[1] && create_if_block_2(); - let each_value_3 = /*month*/ ctx[14][1].days; - let each_blocks_2 = []; - - for (let i = 0; i < each_value_3.length; i += 1) { - each_blocks_2[i] = create_each_block_3(get_each_context_3(ctx, each_value_3, i)); - } - - let if_block1 = /*showWeekNums*/ ctx[1] && create_if_block_1(); - let each_value_2 = /*daysOfWeek*/ ctx[15]; - let each_blocks_1 = []; - - for (let i = 0; i < each_value_2.length; i += 1) { - each_blocks_1[i] = create_each_block_2(get_each_context_2(ctx, each_value_2, i)); - } - - let each_value = /*month*/ ctx[14]; - const get_key = ctx => /*week*/ ctx[18].weekNum; - - for (let i = 0; i < each_value.length; i += 1) { - let child_ctx = get_each_context(ctx, each_value, i); - let key = get_key(child_ctx); - each2_lookup.set(key, each_blocks[i] = create_each_block(key, child_ctx)); - } - - return { - c() { - div = element("div"); - create_component(nav.$$.fragment); - t0 = space(); - table = element("table"); - colgroup = element("colgroup"); - if (if_block0) if_block0.c(); - t1 = space(); - - for (let i = 0; i < each_blocks_2.length; i += 1) { - each_blocks_2[i].c(); - } - - t2 = space(); - thead = element("thead"); - tr = element("tr"); - if (if_block1) if_block1.c(); - t3 = space(); - - for (let i = 0; i < each_blocks_1.length; i += 1) { - each_blocks_1[i].c(); - } - - t4 = space(); - tbody = element("tbody"); - - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].c(); - } - - attr(table, "class", "calendar svelte-pcimu8"); - attr(div, "id", "calendar-container"); - attr(div, "class", "container svelte-pcimu8"); - toggle_class(div, "is-mobile", /*isMobile*/ ctx[16]); - }, - m(target, anchor) { - insert(target, div, anchor); - mount_component(nav, div, null); - append(div, t0); - append(div, table); - append(table, colgroup); - if (if_block0) if_block0.m(colgroup, null); - append(colgroup, t1); - - for (let i = 0; i < each_blocks_2.length; i += 1) { - each_blocks_2[i].m(colgroup, null); - } - - append(table, t2); - append(table, thead); - append(thead, tr); - if (if_block1) if_block1.m(tr, null); - append(tr, t3); - - for (let i = 0; i < each_blocks_1.length; i += 1) { - each_blocks_1[i].m(tr, null); - } - - append(table, t4); - append(table, tbody); - - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].m(tbody, null); - } - - current = true; - }, - p(ctx, [dirty]) { - const nav_changes = {}; - if (dirty & /*today*/ 1024) nav_changes.today = /*today*/ ctx[10]; - if (dirty & /*displayedMonth*/ 1) nav_changes.displayedMonth = /*displayedMonth*/ ctx[0]; - nav.$set(nav_changes); - - if (/*showWeekNums*/ ctx[1]) { - if (if_block0) ; else { - if_block0 = create_if_block_2(); - if_block0.c(); - if_block0.m(colgroup, t1); - } - } else if (if_block0) { - if_block0.d(1); - if_block0 = null; - } - - if (dirty & /*isWeekend, month*/ 16384) { - each_value_3 = /*month*/ ctx[14][1].days; - let i; - - for (i = 0; i < each_value_3.length; i += 1) { - const child_ctx = get_each_context_3(ctx, each_value_3, i); - - if (each_blocks_2[i]) { - each_blocks_2[i].p(child_ctx, dirty); - } else { - each_blocks_2[i] = create_each_block_3(child_ctx); - each_blocks_2[i].c(); - each_blocks_2[i].m(colgroup, null); - } - } - - for (; i < each_blocks_2.length; i += 1) { - each_blocks_2[i].d(1); - } - - each_blocks_2.length = each_value_3.length; - } - - if (/*showWeekNums*/ ctx[1]) { - if (if_block1) ; else { - if_block1 = create_if_block_1(); - if_block1.c(); - if_block1.m(tr, t3); - } - } else if (if_block1) { - if_block1.d(1); - if_block1 = null; - } - - if (dirty & /*daysOfWeek*/ 32768) { - each_value_2 = /*daysOfWeek*/ ctx[15]; - let i; - - for (i = 0; i < each_value_2.length; i += 1) { - const child_ctx = get_each_context_2(ctx, each_value_2, i); - - if (each_blocks_1[i]) { - each_blocks_1[i].p(child_ctx, dirty); - } else { - each_blocks_1[i] = create_each_block_2(child_ctx); - each_blocks_1[i].c(); - each_blocks_1[i].m(tr, null); - } - } - - for (; i < each_blocks_1.length; i += 1) { - each_blocks_1[i].d(1); - } - - each_blocks_1.length = each_value_2.length; - } - - if (dirty & /*month, today, displayedMonth, onClickDay, onContextMenuDay, onHoverDay, getDailyMetadata, sources, selectedId, getWeeklyMetadata, onClickWeek, onContextMenuWeek, onHoverWeek, showWeekNums*/ 18431) { - each_value = /*month*/ ctx[14]; - group_outros(); - each_blocks = update_keyed_each(each_blocks, dirty, get_key, 1, ctx, each_value, each2_lookup, tbody, outro_and_destroy_block, create_each_block, null, get_each_context); - check_outros(); - } - }, - i(local) { - if (current) return; - transition_in(nav.$$.fragment, local); - - for (let i = 0; i < each_value.length; i += 1) { - transition_in(each_blocks[i]); - } - - current = true; - }, - o(local) { - transition_out(nav.$$.fragment, local); - - for (let i = 0; i < each_blocks.length; i += 1) { - transition_out(each_blocks[i]); - } - - current = false; - }, - d(detaching) { - if (detaching) detach(div); - destroy_component(nav); - if (if_block0) if_block0.d(); - destroy_each(each_blocks_2, detaching); - if (if_block1) if_block1.d(); - destroy_each(each_blocks_1, detaching); - - for (let i = 0; i < each_blocks.length; i += 1) { - each_blocks[i].d(); - } - } - }; -} - -function instance($$self, $$props, $$invalidate) { - - - let { localeData } = $$props; - let { showWeekNums = false } = $$props; - let { onHoverDay } = $$props; - let { onHoverWeek } = $$props; - let { onContextMenuDay } = $$props; - let { onContextMenuWeek } = $$props; - let { onClickDay } = $$props; - let { onClickWeek } = $$props; - let { sources = [] } = $$props; - let { selectedId } = $$props; - let { today = window.moment() } = $$props; - let { displayedMonth = today } = $$props; - let month; - let daysOfWeek; - - // eslint-disable-next-line @typescript-eslint/no-explicit-any - let isMobile = window.app.isMobile; - - function incrementDisplayedMonth() { - $$invalidate(0, displayedMonth = displayedMonth.clone().add(1, "month")); - } - - function decrementDisplayedMonth() { - $$invalidate(0, displayedMonth = displayedMonth.clone().subtract(1, "month")); - } - - function resetDisplayedMonth() { - $$invalidate(0, displayedMonth = today.clone()); - } - - $$self.$$set = $$props => { - if ("localeData" in $$props) $$invalidate(17, localeData = $$props.localeData); - if ("showWeekNums" in $$props) $$invalidate(1, showWeekNums = $$props.showWeekNums); - if ("onHoverDay" in $$props) $$invalidate(2, onHoverDay = $$props.onHoverDay); - if ("onHoverWeek" in $$props) $$invalidate(3, onHoverWeek = $$props.onHoverWeek); - if ("onContextMenuDay" in $$props) $$invalidate(4, onContextMenuDay = $$props.onContextMenuDay); - if ("onContextMenuWeek" in $$props) $$invalidate(5, onContextMenuWeek = $$props.onContextMenuWeek); - if ("onClickDay" in $$props) $$invalidate(6, onClickDay = $$props.onClickDay); - if ("onClickWeek" in $$props) $$invalidate(7, onClickWeek = $$props.onClickWeek); - if ("sources" in $$props) $$invalidate(8, sources = $$props.sources); - if ("selectedId" in $$props) $$invalidate(9, selectedId = $$props.selectedId); - if ("today" in $$props) $$invalidate(10, today = $$props.today); - if ("displayedMonth" in $$props) $$invalidate(0, displayedMonth = $$props.displayedMonth); - }; - - $$self.$$.update = () => { - if ($$self.$$.dirty & /*displayedMonth, localeData*/ 131073) { - $$invalidate(14, month = getMonth(displayedMonth, localeData)); - } - - if ($$self.$$.dirty & /*today, localeData*/ 132096) { - $$invalidate(15, daysOfWeek = getDaysOfWeek(today, localeData)); - } - }; - - return [ - displayedMonth, - showWeekNums, - onHoverDay, - onHoverWeek, - onContextMenuDay, - onContextMenuWeek, - onClickDay, - onClickWeek, - sources, - selectedId, - today, - incrementDisplayedMonth, - decrementDisplayedMonth, - resetDisplayedMonth, - month, - daysOfWeek, - isMobile, - localeData - ]; -} - -class Calendar extends SvelteComponent { - constructor(options) { - super(); - if (!document.getElementById("svelte-pcimu8-style")) add_css(); - - init(this, options, instance, create_fragment, not_equal, { - localeData: 17, - showWeekNums: 1, - onHoverDay: 2, - onHoverWeek: 3, - onContextMenuDay: 4, - onContextMenuWeek: 5, - onClickDay: 6, - onClickWeek: 7, - sources: 8, - selectedId: 9, - today: 10, - displayedMonth: 0, - incrementDisplayedMonth: 11, - decrementDisplayedMonth: 12, - resetDisplayedMonth: 13 - }); - } - - get incrementDisplayedMonth() { - return this.$$.ctx[11]; - } - - get decrementDisplayedMonth() { - return this.$$.ctx[12]; - } - - get resetDisplayedMonth() { - return this.$$.ctx[13]; - } -} - -/** Generic code for embedded Dataviews. */ -class DataviewRefreshableRenderer extends obsidian.MarkdownRenderChild { - constructor(container, index, app, settings) { - super(container); - this.container = container; - this.index = index; - this.app = app; - this.settings = settings; - this.maybeRefresh = () => { - // If the index revision has changed recently, then queue a reload. - // But only if we're mounted in the DOM and auto-refreshing is active. - if (this.lastReload != this.index.revision && this.container.isShown() && this.settings.refreshEnabled) { - this.lastReload = this.index.revision; - this.render(); - } - }; - this.lastReload = 0; - } - onload() { - this.render(); - this.lastReload = this.index.revision; - // Refresh after index changes stop. - this.registerEvent(this.app.workspace.on("dataview:refresh-views", this.maybeRefresh)); - // ...or when the DOM is shown (sidebar expands, tab selected, nodes scrolled into view). - this.register(this.container.onNodeInserted(this.maybeRefresh)); - } -} - -class DataviewCalendarRenderer extends DataviewRefreshableRenderer { - constructor(query, container, index, origin, settings, app) { - super(container, index, app, settings); - this.query = query; - this.container = container; - this.index = index; - this.origin = origin; - this.settings = settings; - this.app = app; - } - async render() { - var _a; - this.container.innerHTML = ""; - let maybeResult = await asyncTryOrPropogate(() => executeCalendar(this.query, this.index, this.origin, this.settings)); - if (!maybeResult.successful) { - renderErrorPre(this.container, "Dataview: " + maybeResult.error); - return; - } - else if (maybeResult.value.data.length == 0 && this.settings.warnOnEmptyResult) { - renderErrorPre(this.container, "Dataview: Query returned 0 results."); - return; - } - let dateMap = new Map(); - for (let data of maybeResult.value.data) { - const dot = { - color: "default", - className: "note", - isFilled: true, - link: data.link, - }; - const d = data.date.toFormat("yyyyLLdd"); - if (!dateMap.has(d)) { - dateMap.set(d, [dot]); - } - else { - (_a = dateMap.get(d)) === null || _a === void 0 ? void 0 : _a.push(dot); - } - } - const querySource = { - getDailyMetadata: async (date) => { - return { - dots: dateMap.get(date.format("YYYYMMDD")) || [], - }; - }, - }; - const sources = [querySource]; - const renderer = this; - this.calendar = new Calendar({ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - target: this.container, - props: { - onHoverDay(date, targetEl) { - const vals = dateMap.get(date.format("YYYYMMDD")); - if (!vals || vals.length == 0) { - return; - } - if ((vals === null || vals === void 0 ? void 0 : vals.length) == 0) { - return; - } - renderer.app.workspace.trigger("link-hover", {}, targetEl, vals[0].link.path, vals[0].link.path); - }, - onClickDay: async (date) => { - const vals = dateMap.get(date.format("YYYYMMDD")); - if (!vals || vals.length == 0) { - return; - } - if ((vals === null || vals === void 0 ? void 0 : vals.length) == 0) { - return; - } - const file = renderer.app.metadataCache.getFirstLinkpathDest(vals[0].link.path, ""); - if (file == null) { - return; - } - const leaf = renderer.app.workspace.getUnpinnedLeaf(); - await leaf.openFile(file, { active: true }); - }, - showWeekNums: false, - sources, - }, - }); - } - onClose() { - if (this.calendar) { - this.calendar.$destroy(); - } - return Promise.resolve(); - } -} - -/** Fancy wrappers for the JavaScript API, used both by external plugins AND by the dataview javascript view. */ -/** Asynchronous API calls related to file / system IO. */ -class DataviewInlineIOApi { - constructor(api, currentFile) { - this.api = api; - this.currentFile = currentFile; - } - /** Load the contents of a CSV asynchronously, returning a data array of rows (or undefined if it does not exist). */ - async csv(path, originFile) { - return this.api.csv(path, originFile || this.currentFile); - } - /** Asynchronously load the contents of any link or path in an Obsidian vault. */ - async load(path, originFile) { - return this.api.load(path, originFile || this.currentFile); - } - /** Normalize a link or path relative to an optional origin file. Returns a textual fully-qualified-path. */ - normalize(path, originFile) { - return this.api.normalize(path, originFile || this.currentFile); - } -} -class DataviewInlineApi { - constructor(api, component, container, currentFilePath) { - var _a, _b; - /** Value utilities which allow for type-checking and comparisons. */ - this.value = Values; - /** Widget utility functions for creating built-in widgets. */ - this.widget = Widgets; - /** Re-exporting of luxon for people who can't easily require it. Sorry! */ - this.luxon = Luxon; - this.index = api.index; - this.app = api.app; - this.settings = api.settings; - this.component = component; - this.container = container; - this.currentFilePath = currentFilePath; - this.api = api; - this.io = new DataviewInlineIOApi(this.api.io, this.currentFilePath); - // Set up the evaluation context with variables from the current file. - let fileMeta = (_b = (_a = this.index.pages.get(this.currentFilePath)) === null || _a === void 0 ? void 0 : _a.serialize(this.index)) !== null && _b !== void 0 ? _b : {}; - this.evaluationContext = new Context(defaultLinkHandler(this.index, this.currentFilePath), this.settings, { - this: fileMeta, - }); - this.func = Functions.bindAll(DEFAULT_FUNCTIONS, this.evaluationContext); - } - ///////////////////////////// - // Index + Data Collection // - ///////////////////////////// - /** Return an array of paths (as strings) corresponding to pages which match the query. */ - pagePaths(query) { - return this.api.pagePaths(query, this.currentFilePath); - } - /** Map a page path to the actual data contained within that page. */ - page(path) { - return this.api.page(path, this.currentFilePath); - } - /** Return an array of page objects corresponding to pages which match the query. */ - pages(query) { - return this.api.pages(query, this.currentFilePath); - } - /** Return the information about the current page. */ - current() { - return this.page(this.currentFilePath); - } - /////////////////////////////// - // Dataview Query Evaluation // - /////////////////////////////// - /** Execute a Dataview query, returning the results in programmatic form. */ - async query(source, originFile, settings) { - return this.api.query(source, originFile !== null && originFile !== void 0 ? originFile : this.currentFilePath, settings); - } - /** Error-throwing version of {@link query}. */ - async tryQuery(source, originFile, settings) { - return this.api.tryQuery(source, originFile !== null && originFile !== void 0 ? originFile : this.currentFilePath, settings); - } - /** Execute a Dataview query, returning the results in Markdown. */ - async queryMarkdown(source, originFile, settings) { - return this.api.queryMarkdown(source, originFile !== null && originFile !== void 0 ? originFile : this.currentFilePath, settings); - } - /** Error-throwing version of {@link queryMarkdown}. */ - async tryQueryMarkdown(source, originFile, settings) { - return this.api.tryQueryMarkdown(source, originFile !== null && originFile !== void 0 ? originFile : this.currentFilePath, settings); - } - /** - * Evaluate a dataview expression (like '2 + 2' or 'link("hello")'), returning the evaluated result. - * This takes an optional second argument which provides definitions for variables, such as: - * - * ``` - * dv.evaluate("x + 6", { x: 2 }) = 8 - * dv.evaluate('link(target)', { target: "Okay" }) = [[Okay]] - * ``` - * - * Note that `this` is implicitly available and refers to the current file. - * - * This method returns a Result type instead of throwing an error; you can check the result of the - * execution via `result.successful` and obtain `result.value` or `result.error` resultingly. If - * you'd rather this method throw on an error, use `dv.tryEvaluate`. - */ - evaluate(expression, context) { - let field = EXPRESSION.field.parse(expression); - if (!field.status) - return Result.failure(`Failed to parse expression "${expression}"`); - return this.evaluationContext.evaluate(field.value, context); - } - /** Error-throwing version of `dv.evaluate`. */ - tryEvaluate(expression, context) { - return this.evaluate(expression, context).orElseThrow(); - } - /** Execute a Dataview query and embed it into the current view. */ - async execute(source) { - this.api.execute(source, this.container, this.component, this.currentFilePath); - } - /** Execute a DataviewJS query and embed it into the current view. */ - async executeJs(code) { - this.api.executeJs(code, this.container, this.component, this.currentFilePath); - } - ///////////// - // Utility // - ///////////// - /** - * Convert an input element or array into a Dataview data-array. If the input is already a data array, - * it is returned unchanged. - */ - array(raw) { - return this.api.array(raw); - } - /** Return true if theg given value is a javascript array OR a dataview data array. */ - isArray(raw) { - return this.api.isArray(raw); - } - /** Return true if the given value is a dataview data array; this returns FALSE for plain JS arrays. */ - isDataArray(raw) { - return DataArray.isDataArray(raw); - } - /** Create a dataview file link to the given path. */ - fileLink(path, embed = false, display) { - return Link.file(path, embed, display); - } - /** Create a dataview section link to the given path. */ - sectionLink(path, section, embed = false, display) { - return Link.header(path, section, embed, display); - } - /** Create a dataview block link to the given path. */ - blockLink(path, blockId, embed = false, display) { - return Link.block(path, blockId, embed, display); - } - /** Attempt to extract a date from a string, link or date. */ - date(pathlike) { - return this.api.date(pathlike); - } - /** Attempt to extract a duration from a string or duration. */ - duration(dur) { - return this.api.duration(dur); - } - /** Parse a raw textual value into a complex Dataview type, if possible. */ - parse(value) { - return this.api.parse(value); - } - /** Convert a basic JS type into a Dataview type by parsing dates, links, durations, and so on. */ - literal(value) { - return this.api.literal(value); - } - /** Deep clone the given literal, returning a new literal which is independent of the original. */ - clone(value) { - return Values.deepCopy(value); - } - /** - * Compare two arbitrary JavaScript values using Dataview's default comparison rules. Returns a negative value if - * a < b, 0 if a = b, and a positive value if a > b. - */ - compare(a, b) { - return Values.compareValue(a, b); - } - /** Return true if the two given JavaScript values are equal using Dataview's default comparison rules. */ - equal(a, b) { - return this.compare(a, b) == 0; - } - ///////////////////////// - // Rendering Functions // - ///////////////////////// - /** Render an HTML element, containing arbitrary text. */ - el(el, text, { container = this.container, ...options } = {}) { - let wrapped = Values.wrapValue(text); - if (wrapped === null || wrapped === undefined) { - return container.createEl(el, Object.assign({ text }, options)); - } - let _el = container.createEl(el, options); - renderValue(wrapped.value, _el, this.currentFilePath, this.component, this.settings, true); - return _el; - } - /** Render an HTML header; the level can be anything from 1 - 6. */ - header(level, text, options) { - let header = { 1: "h1", 2: "h2", 3: "h3", 4: "h4", 5: "h5", 6: "h6" }[level]; - if (!header) - throw Error(`Unrecognized level '${level}' (expected 1, 2, 3, 4, 5, or 6)`); - return this.el(header, text, options); - } - /** Render an HTML paragraph, containing arbitrary text. */ - paragraph(text, options) { - return this.el("p", text, options); - } - /** Render an inline span, containing arbitrary text. */ - span(text, options) { - return this.el("span", text, options); - } - /** - * Render HTML from the output of a template "view" saved as a file in the vault. - * Takes a filename and arbitrary input data. - */ - async view(viewName, input) { - // Look for `${viewName}.js` first, then for `${viewName}/view.js`. - let simpleViewFile = this.app.metadataCache.getFirstLinkpathDest(viewName + ".js", this.currentFilePath); - if (simpleViewFile) { - let contents = await this.app.vault.read(simpleViewFile); - if (contents.contains("await")) - contents = "(async () => { " + contents + " })()"; - let func = new Function("dv", "input", contents); - try { - // This may directly render, in which case it will likely return undefined or null. - let result = await Promise.resolve(func(this, input)); - if (result) - await renderValue(result, this.container, this.currentFilePath, this.component, this.settings, true); - } - catch (ex) { - renderErrorPre(this.container, `Dataview: Failed to execute view '${simpleViewFile.path}'.\n\n${ex}`); - } - return; - } - // No `{viewName}.js`, so look for a folder instead. - let viewPath = `${viewName}/view.js`; - let viewFile = this.app.metadataCache.getFirstLinkpathDest(viewPath, this.currentFilePath); - if (!viewFile) { - renderErrorPre(this.container, `Dataview: custom view not found for '${viewPath}' or '${viewName}.js'.`); - return; - } - let viewContents = await this.app.vault.read(viewFile); - if (viewContents.contains("await")) - viewContents = "(async () => { " + viewContents + " })()"; - let viewFunction = new Function("dv", "input", viewContents); - try { - let result = await Promise.resolve(viewFunction(this, input)); - if (result) - await renderValue(result, this.container, this.currentFilePath, this.component, this.settings, true); - } - catch (ex) { - renderErrorPre(this.container, `Dataview: Error while executing view '${viewFile.path}'.\n\n${ex}`); - } - // Check for optional CSS. - let cssFile = this.app.metadataCache.getFirstLinkpathDest(`${viewName}/view.css`, this.currentFilePath); - if (!cssFile) - return; - let cssContents = await this.app.vault.read(cssFile); - this.container.createEl("style", { text: cssContents, attr: { scope: " " } }); - } - /** Render a dataview list of the given values. */ - list(values) { - return this.api.list(values, this.container, this.component, this.currentFilePath); - } - /** Render a dataview table with the given headers, and the 2D array of values. */ - table(headers, values) { - return this.api.table(headers, values, this.container, this.component, this.currentFilePath); - } - /** Render a dataview task view with the given tasks. */ - taskList(tasks, groupByFile = true) { - return this.api.taskList(tasks, groupByFile, this.container, this.component, this.currentFilePath); - } - //////////////////////// - // Markdown Rendering // - //////////////////////// - /** Render a table directly to markdown, returning the markdown. */ - markdownTable(headers, values, settings) { - return this.api.markdownTable(headers, values, settings); - } - /** Render a list directly to markdown, returning the markdown. */ - markdownList(values, settings) { - return this.api.markdownList(values, settings); - } - /** Render at ask list directly to markdown, returning the markdown. */ - markdownTaskList(values, settings) { - return this.api.markdownTaskList(values, settings); - } -} -/** - * Evaluate a script where 'this' for the script is set to the given context. Allows you to define global variables. - */ -function evalInContext(script, context) { - return function () { - return eval(script); - }.call(context); -} -/** - * Evaluate a script possibly asynchronously, if the script contains `async/await` blocks. - */ -async function asyncEvalInContext(script, context) { - if (script.includes("await")) { - return evalInContext("(async () => { " + script + " })()", context); - } - else { - return Promise.resolve(evalInContext(script, context)); - } -} - -class DataviewJSRenderer extends DataviewRefreshableRenderer { - constructor(api, script, container, origin) { - super(container, api.index, api.app, api.settings); - this.api = api; - this.script = script; - this.container = container; - this.origin = origin; - } - async render() { - this.container.innerHTML = ""; - if (!this.settings.enableDataviewJs) { - this.containerEl.innerHTML = ""; - renderErrorPre(this.container, "Dataview JS queries are disabled. You can enable them in the Dataview settings."); - return; - } - // Assume that the code is javascript, and try to eval it. - try { - await asyncEvalInContext(DataviewJSRenderer.PREAMBLE + this.script, new DataviewInlineApi(this.api, this, this.container, this.origin)); - } - catch (e) { - this.containerEl.innerHTML = ""; - renderErrorPre(this.container, "Evaluation Error: " + e.stack); - } - } -} -DataviewJSRenderer.PREAMBLE = "const dataview = this;const dv = this;"; -/** Inline JS renderer accessible using '=$' by default. */ -class DataviewInlineJSRenderer extends DataviewRefreshableRenderer { - constructor(api, script, container, target, origin) { - super(container, api.index, api.app, api.settings); - this.api = api; - this.script = script; - this.container = container; - this.target = target; - this.origin = origin; - } - async render() { - var _a; - (_a = this.errorbox) === null || _a === void 0 ? void 0 : _a.remove(); - if (!this.settings.enableDataviewJs || !this.settings.enableInlineDataviewJs) { - let temp = document.createElement("span"); - temp.innerText = "(disabled; enable in settings)"; - this.target.replaceWith(temp); - this.target = temp; - return; - } - // Assume that the code is javascript, and try to eval it. - try { - let temp = document.createElement("span"); - let result = await asyncEvalInContext(DataviewInlineJSRenderer.PREAMBLE + this.script, new DataviewInlineApi(this.api, this, temp, this.origin)); - this.target.replaceWith(temp); - this.target = temp; - if (result === undefined) - return; - renderValue(result, temp, this.origin, this, this.settings, false); - } - catch (e) { - this.errorbox = this.container.createEl("div"); - renderErrorPre(this.errorbox, "Dataview (for inline JS query '" + this.script + "'): " + e); - } - } -} -DataviewInlineJSRenderer.PREAMBLE = "const dataview = this;const dv=this;"; - -//////////// -// Tables // -//////////// -/** Render a table of literals to Markdown. */ -function markdownTable(headers, values, settings) { - if (values.length > 0 && headers.length != values[0].length) - throw new Error(`The number of headers (${headers.length}) must match the number of columns (${values[0].length})`); - settings = settings !== null && settings !== void 0 ? settings : DEFAULT_SETTINGS; - const mvalues = []; - const maxLengths = Array.from(headers, v => escapeTable(v).length); - // Pre-construct the table in memory so we can size columns. - for (let row = 0; row < values.length; row++) { - const current = []; - for (let col = 0; col < values[row].length; col++) { - const text = tableLiteral(values[row][col], settings.allowHtml, settings); - current.push(text); - maxLengths[col] = Math.max(maxLengths[col], text.length); - } - mvalues.push(current); - } - // Then construct the actual table... - // Append the header fields first. - let table = `| ${headers.map((v, i) => padright(escapeTable(v), " ", maxLengths[i])).join(" | ")} |\n`; - // Then the separating column. - table += `| ${maxLengths.map(i => padright("", "-", i)).join(" | ")} |\n`; - // Then the data colunns. - for (let row = 0; row < values.length; row++) { - table += `| ${mvalues[row].map((v, i) => padright(v, " ", maxLengths[i])).join(" | ")} |\n`; - } - return table; -} -/** Convert a value to a Markdown-friendly string. */ -function tableLiteral(value, allowHtml = true, settings) { - return escapeTable(rawTableLiteral(value, allowHtml, settings)); -} -/** Convert a value to a Markdown-friendly string; does not do escaping. */ -function rawTableLiteral(value, allowHtml = true, settings) { - if (!allowHtml) - return Values.toString(value, settings); - if (Values.isArray(value)) { - return `
    ${value.map(v => "
  • " + tableLiteral(v, allowHtml, settings) + "
  • ").join("")}
`; - } - else if (Values.isObject(value)) { - const inner = Object.entries(value) - .map(([k, v]) => { - return `
  • ${tableLiteral(k, allowHtml, settings)}: ${tableLiteral(v, allowHtml, settings)}
  • `; - }) - .join(""); - return `
      ${inner}
    `; - } - else { - return Values.toString(value, settings); - } -} -/** Don't need to import a library for this one... */ -function padright(text, padding, length) { - if (text.length >= length) - return text; - return text + padding.repeat(length - text.length); -} -/** Escape bars inside table content to prevent it from messing up table rows. */ -function escapeTable(text) { - return text.split(/(?!\\)\|/i).join("\\|"); -} -/////////// -// Lists // -/////////// -/** Render a list of literal elements to a markdown list. */ -function markdownList(values, settings) { - return markdownListRec(values, settings, 0); -} -/** Internal recursive function which renders markdown lists. */ -function markdownListRec(input, settings, depth = 0) { - if (Values.isArray(input)) { - let result = depth == 0 ? "" : "\n"; - for (let value of input) { - result += " ".repeat(depth) + "- "; - result += markdownListRec(value, settings, depth); - result += "\n"; - } - return result; - } - else if (Values.isObject(input)) { - let result = depth == 0 ? "" : "\n"; - for (let [key, value] of Object.entries(input)) { - result += " ".repeat(depth) + "- "; - result += Values.toString(key) + ": "; - result += markdownListRec(value, settings, depth); - result += "\n"; - } - return result; - } - else if (Values.isWidget(input) && Widgets.isListPair(input)) { - return `${Values.toString(input.key)}: ${markdownListRec(input.value, settings, depth + 1)}`; - } - return Values.toString(input); -} -/////////// -// Tasks // -/////////// -/** Render the result of a task query to markdown. */ -function markdownTaskList(tasks, settings, depth = 0) { - var _a, _b; - if (Groupings.isGrouping(tasks)) { - let result = ""; - for (let element of tasks) { - result += "#".repeat(depth + 1) + " " + Values.toString(element.key) + "\n\n"; - result += markdownTaskList(element.rows, settings, depth + 1); - } - return result; - } - else { - // Remove task line duplicates if present to match `taskList()` behavior. - const [dedupTasks, _] = nestItems(tasks); - let result = ""; - for (let element of dedupTasks) { - result += " ".repeat(depth) + "- "; - if (element.task) { - result += `[${element.status}] ${((_a = element.visual) !== null && _a !== void 0 ? _a : element.text).split("\n").join(" ")}\n`; - } - else { - result += `${((_b = element.visual) !== null && _b !== void 0 ? _b : element.text).split("\n").join(" ")}\n`; - } - result += markdownTaskList(element.children, settings, depth + 1); - } - return result; - } -} - -/** The general, externally accessible plugin API (available at `app.plugins.plugins.dataview.api` or as global `DataviewAPI`). */ -/** Asynchronous API calls related to file / system IO. */ -class DataviewIOApi { - constructor(api) { - this.api = api; - } - /** Load the contents of a CSV asynchronously, returning a data array of rows (or undefined if it does not exist). */ - async csv(path, originFile) { - if (!Values.isLink(path) && !Values.isString(path)) { - throw Error(`dv.io.csv only handles string or link paths; was provided type '${typeof path}'.`); - } - let data = await this.api.index.csv.get(this.normalize(path, originFile)); - if (data.successful) - return DataArray.from(data.value, this.api.settings); - else - throw Error(`Could not find CSV for path '${path}' (relative to origin '${originFile !== null && originFile !== void 0 ? originFile : "/"}')`); - } - /** Asynchronously load the contents of any link or path in an Obsidian vault. */ - async load(path, originFile) { - if (!Values.isLink(path) && !Values.isString(path)) { - throw Error(`dv.io.load only handles string or link paths; was provided type '${typeof path}'.`); - } - let existingFile = this.api.index.vault.getAbstractFileByPath(this.normalize(path, originFile)); - if (!existingFile || !(existingFile instanceof obsidian.TFile)) - return undefined; - return this.api.index.vault.cachedRead(existingFile); - } - /** Normalize a link or path relative to an optional origin file. Returns a textual fully-qualified-path. */ - normalize(path, originFile) { - let realPath; - if (Values.isLink(path)) - realPath = path.path; - else - realPath = path; - return this.api.index.prefix.resolveRelative(realPath, originFile); - } -} -/** Global API for accessing the Dataview API, executing dataview queries, and */ -class DataviewApi { - constructor(app, index, settings, verNum) { - this.app = app; - this.index = index; - this.settings = settings; - this.verNum = verNum; - /** Value utility functions for comparisons and type-checking. */ - this.value = Values; - /** Widget utility functions for creating built-in widgets. */ - this.widget = Widgets; - /** Re-exporting of luxon for people who can't easily require it. Sorry! */ - this.luxon = Luxon; - /** Utilities to check the current Dataview version and comapre it to SemVer version ranges. */ - this.version = (() => { - const { verNum: version } = this; - return { - get current() { - return version; - }, - compare: (op, ver) => compare(version, ver, op), - satisfies: (range) => satisfies(version, range), - }; - })(); - this.evaluationContext = new Context(defaultLinkHandler(index, ""), settings); - this.func = Functions.bindAll(DEFAULT_FUNCTIONS, this.evaluationContext); - this.io = new DataviewIOApi(this); - } - ///////////////////////////// - // Index + Data Collection // - ///////////////////////////// - /** Return an array of paths (as strings) corresponding to pages which match the query. */ - pagePaths(query, originFile) { - let source; - try { - if (!query || query.trim() === "") - source = Sources.folder(""); - else - source = EXPRESSION.source.tryParse(query); - } - catch (ex) { - throw new Error(`Failed to parse query in 'pagePaths': ${ex}`); - } - return matchingSourcePaths(source, this.index, originFile) - .map(s => DataArray.from(s, this.settings)) - .orElseThrow(); - } - /** Map a page path to the actual data contained within that page. */ - page(path, originFile) { - if (!(typeof path === "string") && !Values.isLink(path)) { - throw Error("dv.page only handles string and link paths; was provided type '" + typeof path + "'"); - } - let rawPath = path instanceof Link ? path.path : path; - let normPath = this.app.metadataCache.getFirstLinkpathDest(rawPath, originFile !== null && originFile !== void 0 ? originFile : ""); - if (!normPath) - return undefined; - let pageObject = this.index.pages.get(normPath.path); - if (!pageObject) - return undefined; - return this._addDataArrays(pageObject.serialize(this.index)); - } - /** Return an array of page objects corresponding to pages which match the source query. */ - pages(query, originFile) { - return this.pagePaths(query, originFile).flatMap(p => { - let res = this.page(p, originFile); - return res ? [res] : []; - }); - } - /** Remaps important metadata to add data arrays. */ - _addDataArrays(pageObject) { - // Remap the "file" metadata entries to be data arrays. - for (let [key, value] of Object.entries(pageObject.file)) { - if (Array.isArray(value)) - pageObject.file[key] = DataArray.wrap(value, this.settings); - } - return pageObject; - } - ///////////// - // Utility // - ///////////// - /** - * Convert an input element or array into a Dataview data-array. If the input is already a data array, - * it is returned unchanged. - */ - array(raw) { - if (DataArray.isDataArray(raw)) - return raw; - if (Array.isArray(raw)) - return DataArray.wrap(raw, this.settings); - return DataArray.wrap([raw], this.settings); - } - /** Return true if the given value is a javascript array OR a dataview data array. */ - isArray(raw) { - return DataArray.isDataArray(raw) || Array.isArray(raw); - } - /** Return true if the given value is a dataview data array; this returns FALSE for plain JS arrays. */ - isDataArray(raw) { - return DataArray.isDataArray(raw); - } - /** Create a dataview file link to the given path. */ - fileLink(path, embed = false, display) { - return Link.file(path, embed, display); - } - /** Create a dataview section link to the given path. */ - sectionLink(path, section, embed = false, display) { - return Link.header(path, section, embed, display); - } - /** Create a dataview block link to the given path. */ - blockLink(path, blockId, embed = false, display) { - return Link.block(path, blockId, embed, display); - } - /** Attempt to extract a date from a string, link or date. */ - date(pathlike) { - return this.func.date(pathlike); - } - /** Attempt to extract a duration from a string or duration. */ - duration(str) { - return this.func.dur(str); - } - /** Parse a raw textual value into a complex Dataview type, if possible. */ - parse(value) { - let raw = EXPRESSION.inlineField.parse(value); - if (raw.status) - return raw.value; - else - return value; - } - /** Convert a basic JS type into a Dataview type by parsing dates, links, durations, and so on. */ - literal(value) { - return parseFrontmatter(value); - } - /** Deep clone the given literal, returning a new literal which is independent of the original. */ - clone(value) { - return Values.deepCopy(value); - } - /** - * Compare two arbitrary JavaScript values using Dataview's default comparison rules. Returns a negative value if - * a < b, 0 if a = b, and a positive value if a > b. - */ - compare(a, b) { - return Values.compareValue(a, b, this.evaluationContext.linkHandler.normalize); - } - /** Return true if the two given JavaScript values are equal using Dataview's default comparison rules. */ - equal(a, b) { - return this.compare(a, b) == 0; - } - /////////////////////////////// - // Dataview Query Evaluation // - /////////////////////////////// - /** - * Execute an arbitrary Dataview query, returning a query result which: - * - * 1. Indicates the type of query, - * 2. Includes the raw AST of the parsed query. - * 3. Includes the output in the form relevant to that query type. - * - * List queries will return a list of objects ({ id, value }); table queries return a header array - * and a 2D array of values; and task arrays return a Grouping type which allows for recursive - * task nesting. - */ - async query(source, originFile, settings) { - const query = typeof source === "string" ? parseQuery(source) : Result.success(source); - if (!query.successful) - return query.cast(); - const header = query.value.header; - switch (header.type) { - case "calendar": - const cres = await executeCalendar(query.value, this.index, originFile !== null && originFile !== void 0 ? originFile : "", this.settings); - if (!cres.successful) - return cres.cast(); - return Result.success({ type: "calendar", values: cres.value.data }); - case "task": - const tasks = await executeTask(query.value, originFile !== null && originFile !== void 0 ? originFile : "", this.index, this.settings); - if (!tasks.successful) - return tasks.cast(); - return Result.success({ type: "task", values: tasks.value.tasks }); - case "list": - if ((settings === null || settings === void 0 ? void 0 : settings.forceId) !== undefined) - header.showId = settings.forceId; - const lres = await executeList(query.value, this.index, originFile !== null && originFile !== void 0 ? originFile : "", this.settings); - if (!lres.successful) - return lres.cast(); - // TODO: WITHOUT ID probably shouldn't exist, or should be moved to the engine itself. - // For now, until I fix it up in an upcoming refactor, we re-implement the behavior here. - return Result.success({ - type: "list", - values: lres.value.data, - primaryMeaning: lres.value.primaryMeaning, - }); - case "table": - if ((settings === null || settings === void 0 ? void 0 : settings.forceId) !== undefined) - header.showId = settings.forceId; - const tres = await executeTable(query.value, this.index, originFile !== null && originFile !== void 0 ? originFile : "", this.settings); - if (!tres.successful) - return tres.cast(); - return Result.success({ - type: "table", - values: tres.value.data, - headers: tres.value.names, - idMeaning: tres.value.idMeaning, - }); - } - } - /** Error-throwing version of {@link query}. */ - async tryQuery(source, originFile, settings) { - return (await this.query(source, originFile, settings)).orElseThrow(); - } - /** Execute an arbitrary dataview query, returning the results in well-formatted markdown. */ - async queryMarkdown(source, originFile, settings) { - const result = await this.query(source, originFile, settings); - if (!result.successful) - return result.cast(); - switch (result.value.type) { - case "list": - return Result.success(this.markdownList(result.value.values, settings)); - case "table": - return Result.success(this.markdownTable(result.value.headers, result.value.values, settings)); - case "task": - return Result.success(this.markdownTaskList(result.value.values, settings)); - case "calendar": - return Result.failure("Cannot render calendar queries to markdown."); - } - } - /** Error-throwing version of {@link queryMarkdown}. */ - async tryQueryMarkdown(source, originFile, settings) { - return (await this.queryMarkdown(source, originFile, settings)).orElseThrow(); - } - /** - * Evaluate a dataview expression (like '2 + 2' or 'link("hello")'), returning the evaluated result. - * This takes an optional second argument which provides definitions for variables, such as: - * - * ``` - * dv.evaluate("x + 6", { x: 2 }) = 8 - * dv.evaluate('link(target)', { target: "Okay" }) = [[Okay]] - * ``` - * - * This method returns a Result type instead of throwing an error; you can check the result of the - * execution via `result.successful` and obtain `result.value` or `result.error` resultingly. If - * you'd rather this method throw on an error, use `dv.tryEvaluate`. - */ - evaluate(expression, context) { - let field = EXPRESSION.field.parse(expression); - if (!field.status) - return Result.failure(`Failed to parse expression "${expression}"`); - return this.evaluationContext.evaluate(field.value, context); - } - /** Error-throwing version of `dv.evaluate`. */ - tryEvaluate(expression, context) { - return this.evaluate(expression, context).orElseThrow(); - } - /////////////// - // Rendering // - /////////////// - /** - * Execute the given query, rendering results into the given container using the components lifecycle. - * Your component should be a *real* component which calls onload() on it's child components at some point, - * or a MarkdownPostProcessorContext! - * - * Note that views made in this way are live updating and will automatically clean themselves up when - * the component is unloaded or the container is removed. - */ - async execute(source, container, component, filePath) { - if (isDataviewDisabled(filePath)) { - renderCodeBlock(container, source); - return; - } - let maybeQuery = tryOrPropogate(() => parseQuery(source)); - // In case of parse error, just render the error. - if (!maybeQuery.successful) { - renderErrorPre(container, "Dataview: " + maybeQuery.error); - return; - } - let query = maybeQuery.value; - let init = { app: this.app, settings: this.settings, index: this.index, container }; - let childComponent; - switch (query.header.type) { - case "task": - childComponent = createTaskView(init, query, filePath); - component.addChild(childComponent); - break; - case "list": - childComponent = createListView(init, query, filePath); - component.addChild(childComponent); - break; - case "table": - childComponent = createTableView(init, query, filePath); - component.addChild(childComponent); - break; - case "calendar": - childComponent = new DataviewCalendarRenderer(query, container, this.index, filePath, this.settings, this.app); - component.addChild(childComponent); - break; - } - childComponent.load(); - } - /** - * Execute the given DataviewJS query, rendering results into the given container using the components lifecycle. - * See {@link execute} for general rendering semantics. - */ - async executeJs(code, container, component, filePath) { - if (isDataviewDisabled(filePath)) { - renderCodeBlock(container, code, "javascript"); - return; - } - const renderer = new DataviewJSRenderer(this, code, container, filePath); - renderer.load(); - component.addChild(renderer); - } - /** Render a dataview list of the given values. */ - async list(values, container, component, filePath) { - if (!values) - return; - if (values !== undefined && values !== null && !Array.isArray(values) && !DataArray.isDataArray(values)) - values = Array.from(values); - // Append a child div, since React will keep re-rendering otherwise. - let subcontainer = container.createEl("div"); - component.addChild(createFixedListView({ app: this.app, settings: this.settings, index: this.index, container: subcontainer }, values, filePath)); - } - /** Render a dataview table with the given headers, and the 2D array of values. */ - async table(headers, values, container, component, filePath) { - if (!headers) - headers = []; - if (!values) - values = []; - if (!Array.isArray(headers) && !DataArray.isDataArray(headers)) - headers = Array.from(headers); - // Append a child div, since React will keep re-rendering otherwise. - let subcontainer = container.createEl("div"); - component.addChild(createFixedTableView({ app: this.app, settings: this.settings, index: this.index, container: subcontainer }, headers, values, filePath)); - } - /** Render a dataview task view with the given tasks. */ - async taskList(tasks, groupByFile = true, container, component, filePath = "") { - let groupedTasks = !Groupings.isGrouping(tasks) && groupByFile ? this.array(tasks).groupBy(t => Link.file(t.path)) : tasks; - // Append a child div, since React will override several task lists otherwise. - let taskContainer = container.createEl("div"); - component.addChild(createFixedTaskView({ app: this.app, settings: this.settings, index: this.index, container: taskContainer }, groupedTasks, filePath)); - } - /** Render an arbitrary value into a container. */ - async renderValue(value, container, component, filePath, inline = false) { - return renderValue(value, container, filePath, component, this.settings, inline); - } - ///////////////// - // Data Export // - ///////////////// - /** Render data to a markdown table. */ - markdownTable(headers, values, settings) { - if (!headers) - headers = []; - if (!values) - values = []; - const combined = Object.assign({}, this.settings, settings); - return markdownTable(headers, values, combined); - } - /** Render data to a markdown list. */ - markdownList(values, settings) { - if (!values) - values = []; - const combined = Object.assign({}, this.settings, settings); - return markdownList(values, combined); - } - /** Render tasks or list items to a markdown task list. */ - markdownTaskList(values, settings) { - if (!values) - values = []; - const sparse = nestGroups(values); - const combined = Object.assign({}, this.settings, settings); - return markdownTaskList(sparse, combined); - } -} -/** Determines if source-path has a `?no-dataview` annotation that disables dataview. */ -function isDataviewDisabled(sourcePath) { - let questionLocation = sourcePath.lastIndexOf("?"); - if (questionLocation == -1) - return false; - return sourcePath.substring(questionLocation).contains("no-dataview"); -} - -/** Refreshable renderer which renders inline instead of in a div. */ -class DataviewInlineRenderer extends DataviewRefreshableRenderer { - constructor(field, fieldText, container, target, index, origin, settings, app) { - super(container, index, app, settings); - this.field = field; - this.fieldText = fieldText; - this.container = container; - this.target = target; - this.index = index; - this.origin = origin; - this.settings = settings; - this.app = app; - } - async render() { - var _a; - (_a = this.errorbox) === null || _a === void 0 ? void 0 : _a.remove(); - let result = tryOrPropogate(() => executeInline(this.field, this.origin, this.index, this.settings)); - if (!result.successful) { - this.errorbox = this.container.createEl("div"); - renderErrorPre(this.errorbox, "Dataview (for inline query '" + this.fieldText + "'): " + result.error); - } - else { - let temp = document.createElement("span"); - temp.addClasses(["dataview", "dataview-inline-query"]); - await renderValue(result.value, temp, this.origin, this, this.settings, false); - this.target.replaceWith(temp); - } - } -} - -/** Replaces raw textual inline fields in text containers with pretty HTML equivalents. */ -async function replaceInlineFields(ctx, init) { - let inlineFields = extractInlineFields(init.container.innerHTML); - if (inlineFields.length == 0) - return; - let component = new obsidian.MarkdownRenderChild(init.container); - ctx.addChild(component); - // Iterate through the raw HTML and replace inline field matches with corresponding rendered values. - let result = init.container.innerHTML; - for (let x = inlineFields.length - 1; x >= 0; x--) { - let field = inlineFields[x]; - let renderContainer = document.createElement("span"); - renderContainer.addClasses(["dataview", "inline-field"]); - // Block inline fields render the key, parenthesis ones do not. - if (field.wrapping == "[") { - const key = renderContainer.createSpan({ - cls: ["dataview", "inline-field-key"], - attr: { - "data-dv-key": field.key, - "data-dv-norm-key": canonicalizeVarName(field.key), - }, - }); - // Explicitly set the inner HTML to respect any key formatting that we should carry over. - key.innerHTML = field.key; - renderContainer.createSpan({ - cls: ["dataview", "inline-field-value"], - attr: { id: "dataview-inline-field-" + x }, - }); - } - else { - renderContainer.createSpan({ - cls: ["dataview", "inline-field-standalone-value"], - attr: { id: "dataview-inline-field-" + x }, - }); - } - result = result.slice(0, field.start) + renderContainer.outerHTML + result.slice(field.end); - } - // Use a