mirror of
https://github.com/lynchaos/ashvale-station.git
synced 2026-10-28 18:08:04 +00:00
Six enhancements: recompute, markers, vendoring, tests, nerd stats, DS18B20
1. POST /api/recompute re-derives every compensated column from the untouched raw values, removing the step a calibration otherwise leaves through the history. Possible because temp_raw, cpu_temp and hum are never overwritten. Idempotent by construction and tested per row: 0 of 6051 rows change on a second run. 6069 rows in 0.25 s here, so a few seconds on the Pi. 2. Calibration now emits a 'discontinuity' event alongside the calibration log, so downstream views can find the boundary without parsing prose. 3. Vendored Tailwind, Chart.js, hammer, the zoom plugin, KaTeX with its 20 woff2 faces, and both Google fonts into ashvale/static, served by the station. 1.4 MB. Verified with every non-localhost request aborted in the browser: zero external requests, equations still render, fonts still load. The dashboard no longer needs internet. 4. 54 pytest cases over the pure numerics: physics closed forms and round trips, both compensator inverse properties, the Kalman covariance invariants and NIS consistency, the RLS trace cap under a deliberately unexcited regressor, conformal coverage, and the Zambretti ordering. Wired into CI after the seed step so the recompute cases have history. Writing them caught my own sign error on the conformal update: a hit raises alpha and narrows the band, which reads backwards until you follow it through. 5. Stats for Nerds gains the condition number of each head's covariance, a standardised innovation histogram per Kalman filter from a bounded 600 sample ring buffer, and a reliability strip of realised against nominal coverage. All arithmetic on data already in memory. 6. OutdoorProbe reads a DS18B20 over the kernel 1-Wire driver, no new dependency. Polled on its own slower cadence because the sensor blocks for up to 750 ms during conversion, which would eat a third of the 2 s sample budget. Rejects the 85000 power-on sentinel and out-of-range values, and reports age so a dead probe cannot masquerade as fresh.
This commit is contained in:
1 parent
9d2e884b74
commit
98210bff8f
49 files changed
+1437
-12
No files matched your search
@@ -27,7 +27,7 @@ jobs:
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pip install httpx
|
||||
pip install httpx pytest
|
||||
|
||||
- name: Lint
|
||||
run: |
|
||||
@@ -43,6 +43,13 @@ jobs:
|
||||
- name: Seed synthetic history
|
||||
run: python scripts/simulate.py --days 10 --wipe
|
||||
|
||||
# Unit tests over the pure numerics: physics closed forms, the compensator
|
||||
# inverse properties, the Kalman covariance invariants and the RLS trace
|
||||
# cap. Run after seeding so the recompute tests have history rather than skipping.
|
||||
- name: Unit tests
|
||||
run: python -m pytest tests/ -q
|
||||
|
||||
|
||||
# The backtest is the real test: it exercises features, the RLS heads,
|
||||
# climatology and conformal calibration end to end, and fails loudly if
|
||||
# any of them stop producing finite numbers.
|
||||
|
||||
@@ -25,11 +25,13 @@ import asyncio
|
||||
import json
|
||||
import time
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
import numpy as np
|
||||
from fastapi import FastAPI, HTTPException, Query, Request
|
||||
from fastapi.responses import HTMLResponse, StreamingResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from .config import CONFIG
|
||||
@@ -78,6 +80,14 @@ app = FastAPI(
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
# Vendored browser libraries. The dashboard used to pull Tailwind, Chart.js,
|
||||
# hammer, the zoom plugin, KaTeX and two Google fonts from CDNs at runtime,
|
||||
# which meant the Pi needed internet to render its own UI. Serving them from
|
||||
# disk costs about 1.4 MB and removes that dependency entirely.
|
||||
_STATIC = Path(__file__).resolve().parent / "static"
|
||||
if _STATIC.is_dir():
|
||||
app.mount("/static", StaticFiles(directory=str(_STATIC)), name="static")
|
||||
|
||||
|
||||
def _st() -> Station:
|
||||
if station is None:
|
||||
@@ -158,6 +168,7 @@ def telemetry() -> Dict:
|
||||
"cpu_offset": live.get("cpu_offset"),
|
||||
"compensator_k": live.get("compensator_k"),
|
||||
"hum_offset": live.get("hum_offset"),
|
||||
"outdoor_c": live.get("outdoor_c"),
|
||||
"hum_psychrometric": live.get("hum_psychrometric"),
|
||||
"rates": {
|
||||
"temperature_c_per_h": live.get("temp_rate"),
|
||||
@@ -361,6 +372,54 @@ def models() -> Dict:
|
||||
})
|
||||
|
||||
|
||||
def _innovation_histogram(st, bins: int = 21) -> Dict:
|
||||
"""Distribution of recent standardised Kalman innovations, per signal.
|
||||
|
||||
y/sqrt(S) should be standard normal when a filter is consistent. The single
|
||||
NIS number says whether the spread is right on average; this says whether
|
||||
the *shape* is right. Skew means systematic bias, excess kurtosis means the
|
||||
filter is surprised more often than it admits.
|
||||
"""
|
||||
out = {}
|
||||
for name, buf in st.tracker.innovations.items():
|
||||
z = np.array(buf, dtype=float)
|
||||
z = z[np.isfinite(z)]
|
||||
if z.size < 20:
|
||||
out[name] = {"counts": [], "n": int(z.size)}
|
||||
continue
|
||||
clipped = np.clip(z, -4.0, 4.0)
|
||||
counts, edges = np.histogram(clipped, bins=bins, range=(-4.0, 4.0))
|
||||
out[name] = {
|
||||
"counts": [int(c) for c in counts],
|
||||
"edges": [round(float(e), 2) for e in edges],
|
||||
"n": int(z.size),
|
||||
"mean": round(float(np.mean(z)), 4),
|
||||
"std": round(float(np.std(z)), 4),
|
||||
"skew": round(float(np.mean(((z - z.mean()) / (z.std() or 1.0)) ** 3)), 3),
|
||||
"kurtosis": round(float(np.mean(((z - z.mean()) / (z.std() or 1.0)) ** 4)), 3),
|
||||
}
|
||||
return out
|
||||
|
||||
|
||||
def _reliability_curve(st) -> Dict:
|
||||
"""Realised coverage against nominal, per horizon.
|
||||
|
||||
The scorecard reports one coverage number per head. This asks the sharper
|
||||
question: is the *shape* right. Points below the diagonal mean the intervals
|
||||
are lying, and by how much.
|
||||
"""
|
||||
out = []
|
||||
for (target, h), head in sorted(st.nowcast.heads.items()):
|
||||
cov = head.conformal.empirical_coverage
|
||||
if not np.isfinite(cov):
|
||||
continue
|
||||
out.append({"target": target, "horizon_s": h,
|
||||
"nominal": round(1.0 - head.conformal.alpha_target, 4),
|
||||
"realised": round(float(cov), 4),
|
||||
"n": int(head.n_scored)})
|
||||
return {"points": out}
|
||||
|
||||
|
||||
@app.get("/api/nerd")
|
||||
def nerd() -> Dict:
|
||||
"""Every internal number the estimator and the learners are carrying.
|
||||
@@ -393,10 +452,22 @@ def nerd() -> Dict:
|
||||
m = head.model
|
||||
P = np.asarray(m.P, dtype=float)
|
||||
theta = np.asarray(m.theta, dtype=float)
|
||||
# Condition number of P says whether the 33 directions are being excited
|
||||
# evenly. A huge value means some directions carry almost no information
|
||||
# and the fit there is effectively arbitrary, which is the quiet failure
|
||||
# the trace cap only partly protects against. eigvalsh because P is
|
||||
# symmetric by construction.
|
||||
try:
|
||||
ev = np.linalg.eigvalsh(P)
|
||||
lo, hi = float(np.min(ev)), float(np.max(ev))
|
||||
cond = float(hi / lo) if lo > 1e-12 else float("inf")
|
||||
except np.linalg.LinAlgError:
|
||||
cond = float("nan")
|
||||
heads.append({
|
||||
"target": target, "horizon_s": h,
|
||||
"n_updates": int(m.n_updates),
|
||||
"trace_p": float(np.trace(P)),
|
||||
"cond_p": cond,
|
||||
"theta_norm": float(np.linalg.norm(theta)),
|
||||
"rmse_ewma": float(np.sqrt(max(m.ewma_sq_error, 0.0))),
|
||||
"lam": float(m.lam), "p_max": float(m.p_max),
|
||||
@@ -459,6 +530,8 @@ def nerd() -> Dict:
|
||||
"logloss_ewma": st.precip.ewma_logloss,
|
||||
},
|
||||
"monitoring": monitoring,
|
||||
"innovation": _innovation_histogram(st),
|
||||
"reliability": _reliability_curve(st),
|
||||
})
|
||||
|
||||
|
||||
@@ -515,12 +588,25 @@ def calibrate_humidity(body: HumidityCalibrationIn) -> Dict:
|
||||
return _clean(result)
|
||||
|
||||
|
||||
@app.post("/api/recompute")
|
||||
def recompute() -> Dict:
|
||||
"""Re-derive every compensated column in the history from the raw values.
|
||||
|
||||
Run after a calibration to remove the step it leaves behind. Safe to repeat:
|
||||
it always starts from the untouched raw columns, never from a previous
|
||||
result, so it cannot compound.
|
||||
"""
|
||||
result = _st().recompute_history()
|
||||
return _clean(result)
|
||||
|
||||
|
||||
@app.get("/api/status")
|
||||
def status() -> Dict:
|
||||
st = _st()
|
||||
return _clean({
|
||||
**st.status(),
|
||||
"display_frame": display.frame_name if display else None,
|
||||
"outdoor_probe": (st.probe.status() if st.probe is not None else None),
|
||||
"events": st.store.recent_events(15),
|
||||
})
|
||||
|
||||
|
||||
@@ -66,6 +66,11 @@ class SensorConfig:
|
||||
# HIGH and this correction would push it higher still. The error is an
|
||||
# additive element bias, not a thermal gradient. Leave off unless your own
|
||||
# reference says otherwise.
|
||||
# Optional DS18B20 on the 1-Wire bus, outside the window. When present its
|
||||
# reading is logged as outdoor_c and surfaced in the API. It does not feed
|
||||
# the forecasting features yet: that needs history to train against.
|
||||
outdoor_probe: bool = True
|
||||
outdoor_probe_period_s: float = 20.0
|
||||
hum_psychrometric: bool = False
|
||||
hum_offset: float = 0.0
|
||||
hum_offset_min: float = -35.0
|
||||
|
||||
+49
-9
@@ -48,14 +48,15 @@ DASHBOARD_HTML = r"""
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Ashvale Station</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css">
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/hammer.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chartjs-plugin-zoom.min.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700&display=swap">
|
||||
<!-- Served from the station, not a CDN, so the dashboard renders on a LAN with
|
||||
no internet at all. See ashvale/static/. -->
|
||||
<script src="/static/tailwind.js"></script>
|
||||
<link rel="stylesheet" href="/static/katex.min.css">
|
||||
<script defer src="/static/katex.min.js"></script>
|
||||
<script src="/static/chart.umd.min.js"></script>
|
||||
<script src="/static/hammer.min.js"></script>
|
||||
<script src="/static/chartjs-plugin-zoom.min.js"></script>
|
||||
<link rel="stylesheet" href="/static/gfonts.css">
|
||||
<style>
|
||||
body { font-family:'Plus Jakarta Sans',sans-serif; }
|
||||
.font-mono { font-family:'JetBrains Mono',monospace; }
|
||||
@@ -404,7 +405,7 @@ DASHBOARD_HTML = r"""
|
||||
<!-- Everything the estimator and the 18 learners are actually carrying, read
|
||||
straight off the live objects. No internal scrollers: the head bank is a
|
||||
fixed 18 rows and the attribution list is capped at what fits. -->
|
||||
<section id="pane-nerd" class="pane h-full min-h-0 gap-3 grid-cols-1 lg:grid-cols-4 lg:grid-rows-[auto_1fr]">
|
||||
<section id="pane-nerd" class="pane h-full min-h-0 gap-3 grid-cols-1 lg:grid-cols-4 lg:grid-rows-[auto_1fr_auto]">
|
||||
|
||||
<div class="glass rounded-2xl p-3 lg:col-span-3">
|
||||
<div class="flex items-baseline justify-between mb-1.5">
|
||||
@@ -450,6 +451,14 @@ DASHBOARD_HTML = r"""
|
||||
<div id="n-precip" class="font-mono text-[10px] space-y-0.5"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="glass rounded-2xl p-3 lg:col-span-4 shrink-0">
|
||||
<div class="flex items-baseline justify-between mb-1.5">
|
||||
<h2 class="text-sm font-bold">Reliability</h2>
|
||||
<span class="text-[9px] font-mono text-slate-600 uppercase">realised coverage against the 90% nominal</span>
|
||||
</div>
|
||||
<div id="n-rel" class="grid grid-cols-3 sm:grid-cols-6 gap-x-3 gap-y-0.5 font-mono text-[9px]"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ---------------- METHODS ---------------- -->
|
||||
@@ -965,6 +974,15 @@ el('m-hcalrst').addEventListener('click', async () => {
|
||||
/* ---------------- STATS FOR NERDS ---------------- */
|
||||
let nerdDoc = null, nerdHead = null;
|
||||
const HL = (h) => h<3600 ? (h/60)+'m' : h<86400 ? (h/3600)+'h' : (h/86400)+'d';
|
||||
// A 21-bin histogram drawn as inline divs. No canvas: Chart.js instances cost
|
||||
// memory and this is three tiny plots that never need interaction.
|
||||
function histo(counts, colour, h) {
|
||||
if (!counts || !counts.length) return '<div class="text-slate-700 text-[9px]">warming up</div>';
|
||||
const mx = Math.max.apply(null, counts) || 1;
|
||||
return '<div class="flex items-end gap-px" style="height:'+h+'px">'+
|
||||
counts.map(c=>'<div style="flex:1;height:'+Math.max(1,(c/mx)*h)+'px;background:'+colour+
|
||||
';opacity:'+(0.35+0.65*(c/mx))+'"></div>').join('')+'</div>';
|
||||
}
|
||||
function bar(frac, colour) {
|
||||
const w = Math.max(0, Math.min(1, frac||0))*100;
|
||||
return '<div class="h-1 bg-slate-950 rounded-full overflow-hidden border border-slate-800/70">'+
|
||||
@@ -975,6 +993,7 @@ async function loadNerd() {
|
||||
nerdDoc = d;
|
||||
|
||||
const COL = {temperature:'#f59e0b', humidity:'#06b6d4', pressure:'#a78bfa'};
|
||||
const iv = d.innovation||{};
|
||||
el('n-filters').innerHTML = Object.keys(d.filters||{}).map(k=>{
|
||||
const f = d.filters[k];
|
||||
// NIS is chi-square(1) distributed when consistent, so 1 is the target and
|
||||
@@ -987,6 +1006,12 @@ async function loadNerd() {
|
||||
'<div class="flex justify-between text-slate-500 mt-1">σ level<span class="text-slate-300">'+fmt(f.sigma_level,4)+'</span></div>'+
|
||||
'<div class="flex justify-between text-slate-500">P rate<span class="text-slate-300">'+f.p_rate.toExponential(2)+'</span></div>'+
|
||||
'<div class="flex justify-between text-slate-600">q / r<span>'+f.q.toExponential(1)+' / '+fmt(f.r,3)+'</span></div>'+
|
||||
// innovation shape: should look standard normal if the filter is honest
|
||||
'<div class="mt-1 pt-1 border-t border-slate-800/70">'+
|
||||
histo((iv[k]||{}).counts, COL[k], 16)+
|
||||
'<div class="flex justify-between text-slate-600 mt-0.5 text-[9px]">'+
|
||||
'<span>innov μ='+fmt((iv[k]||{}).mean,2)+' σ='+fmt((iv[k]||{}).std,2)+'</span>'+
|
||||
'<span>skew '+fmt((iv[k]||{}).skew,2)+'</span></div></div>'+
|
||||
'</div>';
|
||||
}).join('');
|
||||
|
||||
@@ -1004,6 +1029,7 @@ async function loadNerd() {
|
||||
el('n-heads').innerHTML = heads.length ? '<table class="w-full font-mono text-[10px]">'+
|
||||
'<thead class="text-slate-600 uppercase text-[9px]"><tr class="border-b border-slate-800">'+
|
||||
'<th class="text-left py-0.5">head</th><th class="text-right">n</th><th class="text-right">tr P</th>'+
|
||||
'<th class="text-right">cond</th>'+
|
||||
'<th class="text-right">|θ|</th><th class="text-right">rmse</th><th class="text-right">α</th>'+
|
||||
'<th class="text-right">cov</th><th class="text-right">±</th><th class="text-right pl-2">p/c/l</th></tr></thead><tbody>'+
|
||||
heads.map(h=>{
|
||||
@@ -1015,6 +1041,10 @@ async function loadNerd() {
|
||||
'<td class="py-0.5 text-slate-400">'+h.target.slice(0,4)+' <span class="text-slate-600">'+HL(h.horizon_s)+'</span></td>'+
|
||||
'<td class="text-right text-slate-600">'+h.n_updates+'</td>'+
|
||||
'<td class="text-right '+(sat>0.95?'text-rose-300':'text-slate-400')+'">'+h.trace_p.toExponential(1)+'</td>'+
|
||||
// a huge condition number means some of the 33 directions are barely
|
||||
// excited, so their weights are close to arbitrary
|
||||
'<td class="text-right '+(h.cond_p>1e8?'text-amber-300':'text-slate-500')+'">'+
|
||||
(isFinite(h.cond_p)?h.cond_p.toExponential(0):'inf')+'</td>'+
|
||||
'<td class="text-right text-slate-300">'+fmt(h.theta_norm,1)+'</td>'+
|
||||
'<td class="text-right text-slate-300">'+fmt(h.rmse_ewma,3)+'</td>'+
|
||||
'<td class="text-right text-indigo-300">'+fmt(h.alpha,3)+'</td>'+
|
||||
@@ -1025,6 +1055,16 @@ async function loadNerd() {
|
||||
}).join('')+'</tbody></table>'
|
||||
: '<p class="text-[10px] text-slate-600 font-mono">No heads trained yet.</p>';
|
||||
|
||||
const rel = ((d.reliability||{}).points)||[];
|
||||
el('n-rel').innerHTML = rel.length ? rel.map(pt=>{
|
||||
const gap = pt.realised - pt.nominal;
|
||||
const cls = Math.abs(gap)<0.03 ? '#34d399' : Math.abs(gap)<0.06 ? '#fbbf24' : '#fb7185';
|
||||
return '<div class="flex items-center gap-1.5">'+
|
||||
'<span class="text-slate-600" style="width:42%">'+pt.target.slice(0,4)+' '+HL(pt.horizon_s)+'</span>'+
|
||||
'<span class="flex-1">'+bar(pt.realised, cls)+'</span>'+
|
||||
'<span style="width:26%;text-align:right;color:'+cls+'">'+(pt.realised*100).toFixed(0)+'%</span></div>';
|
||||
}).join('') : '<p class="text-slate-600">Nothing scored yet.</p>';
|
||||
|
||||
const sel = el('n-head-sel');
|
||||
if (sel.options.length !== heads.length) {
|
||||
sel.innerHTML = heads.map((h,i)=>'<option value="'+i+'">'+h.target.slice(0,4)+' '+HL(h.horizon_s)+'</option>').join('');
|
||||
|
||||
@@ -30,6 +30,7 @@ Two jobs here, both familiar from soft-sensor work:
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import deque
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, Optional
|
||||
|
||||
@@ -54,6 +55,7 @@ class KalmanCV:
|
||||
P: np.ndarray = field(default_factory=lambda: np.eye(2) * 1e3)
|
||||
initialised: bool = False
|
||||
nis: float = 0.0 # normalised innovation squared, for health monitoring
|
||||
innovation_z: float = 0.0
|
||||
|
||||
def update(self, z: float, dt: float) -> tuple[float, float]:
|
||||
if not np.isfinite(z):
|
||||
@@ -83,6 +85,11 @@ class KalmanCV:
|
||||
self.P = I_KH @ self.P @ I_KH.T + K @ K.T * self.r # Joseph form, stays PSD
|
||||
|
||||
self.nis = (y * y) / S
|
||||
# y/sqrt(S) is the innovation in units of its own predicted spread, so it
|
||||
# is comparable across signals and should look standard normal when the
|
||||
# filter is consistent. Cheap to keep, and the only honest way to see
|
||||
# skew or fat tails rather than inferring them from a single NIS value.
|
||||
self.innovation_z = float(y / np.sqrt(S)) if S > 0 else 0.0
|
||||
return float(self.x[0]), float(self.x[1])
|
||||
|
||||
@property
|
||||
@@ -265,6 +272,12 @@ class SignalTracker:
|
||||
"pressure": KalmanCV(cfg.sensor.kalman_q_press, cfg.sensor.kalman_r_press),
|
||||
}
|
||||
self.last_ts: Optional[float] = None
|
||||
# 600 samples per signal is 20 minutes at the live 2 s cadence, about
|
||||
# 14 kB total. Bounded on purpose: this board has 512 MB and an
|
||||
# unbounded diagnostic buffer is a slow memory leak with a nice name.
|
||||
self.innovations: Dict[str, deque] = {
|
||||
k: deque(maxlen=600) for k in self.filters
|
||||
}
|
||||
|
||||
def step(self, ts: float, temp_raw: float, hum: float, press: float,
|
||||
cpu_temp: float) -> Dict[str, float]:
|
||||
@@ -278,6 +291,9 @@ class SignalTracker:
|
||||
t_lvl, t_rate = self.filters["temperature"].update(temp_c, dt)
|
||||
h_lvl, h_rate = self.filters["humidity"].update(hum_c, dt)
|
||||
p_lvl, p_rate = self.filters["pressure"].update(press, dt)
|
||||
for name, kf in self.filters.items():
|
||||
if kf.initialised:
|
||||
self.innovations[name].append(kf.innovation_z)
|
||||
|
||||
return {
|
||||
"temp_c": temp_c,
|
||||
|
||||
@@ -24,14 +24,18 @@ same code to the Pi unchanged.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import math
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import numpy as np
|
||||
|
||||
from .physics import dew_point, sea_level_pressure, solar_position
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
TCS3400_ENABLE = 0x80
|
||||
TCS3400_ATIME = 0x81
|
||||
TCS3400_CONTROL = 0x8F
|
||||
@@ -105,6 +109,95 @@ class SimulatedBoard:
|
||||
pass
|
||||
|
||||
|
||||
class OutdoorProbe:
|
||||
"""Optional DS18B20 on the 1-Wire bus, read through the kernel's w1 driver.
|
||||
|
||||
Why this matters more than any model change: indoors the station forecasts
|
||||
a room. Pressure passes through walls, temperature and humidity do not. One
|
||||
three-pound sensor on a metre of cable outside the window removes the single
|
||||
largest caveat in the project.
|
||||
|
||||
No new dependency. The kernel exposes each probe as a text file under
|
||||
/sys/bus/w1/devices/28-*/w1_slave, so this is a file read and two string
|
||||
splits. Enable with `dtoverlay=w1-gpio` in /boot/firmware/config.txt.
|
||||
|
||||
How it fails: the DS18B20 takes up to 750 ms to convert, and the driver
|
||||
blocks for that whole time. Reading it on the 2 s sample loop would eat a
|
||||
third of the budget on a single-issue core, so it is polled on its own
|
||||
slower cadence and the last good value is reused in between. A probe that
|
||||
goes missing (cable pulled, bad CRC) returns None rather than a stale value
|
||||
forever: `age_s` lets the caller decide when to stop trusting it.
|
||||
"""
|
||||
|
||||
ROOT = "/sys/bus/w1/devices"
|
||||
|
||||
def __init__(self, min_period_s: float = 20.0) -> None:
|
||||
self.min_period_s = float(min_period_s)
|
||||
self.device: Optional[str] = None
|
||||
self.available = False
|
||||
self.last_value: Optional[float] = None
|
||||
self.last_ts: Optional[float] = None
|
||||
self.errors = 0
|
||||
self._discover()
|
||||
|
||||
def _discover(self) -> None:
|
||||
try:
|
||||
root = Path(self.ROOT)
|
||||
if not root.is_dir():
|
||||
return
|
||||
probes = sorted(p for p in root.glob("28-*") if (p / "w1_slave").exists())
|
||||
if probes:
|
||||
self.device = str(probes[0] / "w1_slave")
|
||||
self.available = True
|
||||
log.info("outdoor probe found at %s", self.device)
|
||||
except OSError as exc:
|
||||
log.warning("1-wire scan failed: %r", exc)
|
||||
|
||||
def read(self) -> Optional[float]:
|
||||
"""Celsius, or None. Cached between polls so the sample loop never blocks."""
|
||||
if not self.available or self.device is None:
|
||||
return None
|
||||
now = time.time()
|
||||
if self.last_ts is not None and (now - self.last_ts) < self.min_period_s:
|
||||
return self.last_value
|
||||
try:
|
||||
with open(self.device, "r") as fh:
|
||||
text = fh.read()
|
||||
except OSError as exc:
|
||||
self.errors += 1
|
||||
log.warning("outdoor probe read failed: %r", exc)
|
||||
return self.last_value
|
||||
# Two lines: the first ends in YES only when the CRC checked out.
|
||||
if "YES" not in text.split("\n")[0]:
|
||||
self.errors += 1
|
||||
return self.last_value
|
||||
marker = text.find("t=")
|
||||
if marker < 0:
|
||||
self.errors += 1
|
||||
return self.last_value
|
||||
try:
|
||||
milli = int(text[marker + 2:].strip())
|
||||
except ValueError:
|
||||
self.errors += 1
|
||||
return self.last_value
|
||||
# 85000 is the DS18B20 power-on default and means "never converted".
|
||||
if milli == 85000:
|
||||
self.errors += 1
|
||||
return self.last_value
|
||||
value = milli / 1000.0
|
||||
if not (-55.0 <= value <= 125.0):
|
||||
self.errors += 1
|
||||
return self.last_value
|
||||
self.last_value = value
|
||||
self.last_ts = now
|
||||
return value
|
||||
|
||||
def status(self) -> Dict[str, Any]:
|
||||
age = None if self.last_ts is None else round(time.time() - self.last_ts, 1)
|
||||
return {"available": self.available, "device": self.device,
|
||||
"value_c": self.last_value, "age_s": age, "errors": self.errors}
|
||||
|
||||
|
||||
class SenseBoard:
|
||||
"""Real hardware wrapper. Attribute `available` tells you which world
|
||||
you are in without try/except at every call site."""
|
||||
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Skipped minification because the original files appears to be already minified.
|
||||
* Original file: /npm/[email protected]/dist/chart.umd.js
|
||||
*
|
||||
* Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
|
||||
*/
|
||||
/*!
|
||||
* Chart.js v4.4.1
|
||||
* https://www.chartjs.org
|
||||
* (c) 2023 Chart.js Contributors
|
||||
* Released under the MIT License
|
||||
*/
|
||||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Chart=e()}(this,(function(){"use strict";var t=Object.freeze({__proto__:null,get Colors(){return Go},get Decimation(){return Qo},get Filler(){return ma},get Legend(){return ya},get SubTitle(){return ka},get Title(){return Ma},get Tooltip(){return Ba}});function e(){}const i=(()=>{let t=0;return()=>t++})();function s(t){return null==t}function n(t){if(Array.isArray&&Array.isArray(t))return!0;const e=Object.prototype.toString.call(t);return"[object"===e.slice(0,7)&&"Array]"===e.slice(-6)}function o(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)}function a(t){return("number"==typeof t||t instanceof Number)&&isFinite(+t)}function r(t,e){return a(t)?t:e}function l(t,e){return void 0===t?e:t}const h=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100:+t/e,c=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100*e:+t;function d(t,e,i){if(t&&"function"==typeof t.call)return t.apply(i,e)}function u(t,e,i,s){let a,r,l;if(n(t))if(r=t.length,s)for(a=r-1;a>=0;a--)e.call(i,t[a],a);else for(a=0;a<r;a++)e.call(i,t[a],a);else if(o(t))for(l=Object.keys(t),r=l.length,a=0;a<r;a++)e.call(i,t[l[a]],l[a])}function f(t,e){let i,s,n,o;if(!t||!e||t.length!==e.length)return!1;for(i=0,s=t.length;i<s;++i)if(n=t[i],o=e[i],n.datasetIndex!==o.datasetIndex||n.index!==o.index)return!1;return!0}function g(t){if(n(t))return t.map(g);if(o(t)){const e=Object.create(null),i=Object.keys(t),s=i.length;let n=0;for(;n<s;++n)e[i[n]]=g(t[i[n]]);return e}return t}function p(t){return-1===["__proto__","prototype","constructor"].indexOf(t)}function m(t,e,i,s){if(!p(t))return;const n=e[t],a=i[t];o(n)&&o(a)?b(n,a,s):e[t]=g(a)}function b(t,e,i){const s=n(e)?e:[e],a=s.length;if(!o(t))return t;const r=(i=i||{}).merger||m;let l;for(let e=0;e<a;++e){if(l=s[e],!o(l))continue;const n=Object.keys(l);for(let e=0,s=n.length;e<s;++e)r(n[e],t,l,i)}return t}function x(t,e){return b(t,e,{merger:_})}function _(t,e,i){if(!p(t))return;const s=e[t],n=i[t];o(s)&&o(n)?x(s,n):Object.prototype.hasOwnProperty.call(e,t)||(e[t]=g(n))}const y={"":t=>t,x:t=>t.x,y:t=>t.y};function v(t){const e=t.split("."),i=[];let s="";for(const t of e)s+=t,s.endsWith("\\")?s=s.slice(0,-1)+".":(i.push(s),s="");return i}function M(t,e){const i=y[e]||(y[e]=function(t){const e=v(t);return t=>{for(const i of e){if(""===i)break;t=t&&t[i]}return t}}(e));return i(t)}function w(t){return t.charAt(0).toUpperCase()+t.slice(1)}const k=t=>void 0!==t,S=t=>"function"==typeof t,P=(t,e)=>{if(t.size!==e.size)return!1;for(const i of t)if(!e.has(i))return!1;return!0};function D(t){return"mouseup"===t.type||"click"===t.type||"contextmenu"===t.type}const C=Math.PI,O=2*C,A=O+C,T=Number.POSITIVE_INFINITY,L=C/180,E=C/2,R=C/4,I=2*C/3,z=Math.log10,F=Math.sign;function V(t,e,i){return Math.abs(t-e)<i}function B(t){const e=Math.round(t);t=V(t,e,t/1e3)?e:t;const i=Math.pow(10,Math.floor(z(t))),s=t/i;return(s<=1?1:s<=2?2:s<=5?5:10)*i}function W(t){const e=[],i=Math.sqrt(t);let s;for(s=1;s<i;s++)t%s==0&&(e.push(s),e.push(t/s));return i===(0|i)&&e.push(i),e.sort(((t,e)=>t-e)).pop(),e}function N(t){return!isNaN(parseFloat(t))&&isFinite(t)}function H(t,e){const i=Math.round(t);return i-e<=t&&i+e>=t}function j(t,e,i){let s,n,o;for(s=0,n=t.length;s<n;s++)o=t[s][i],isNaN(o)||(e.min=Math.min(e.min,o),e.max=Math.max(e.max,o))}function $(t){return t*(C/180)}function Y(t){return t*(180/C)}function U(t){if(!a(t))return;let e=1,i=0;for(;Math.round(t*e)/e!==t;)e*=10,i++;return i}function X(t,e){const i=e.x-t.x,s=e.y-t.y,n=Math.sqrt(i*i+s*s);let o=Math.atan2(s,i);return o<-.5*C&&(o+=O),{angle:o,distance:n}}function q(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))}function K(t,e){return(t-e+A)%O-C}function G(t){return(t%O+O)%O}function Z(t,e,i,s){const n=G(t),o=G(e),a=G(i),r=G(o-n),l=G(a-n),h=G(n-o),c=G(n-a);return n===o||n===a||s&&o===a||r>l&&h<c}function J(t,e,i){return Math.max(e,Math.min(i,t))}function Q(t){return J(t,-32768,32767)}function tt(t,e,i,s=1e-6){return t>=Math.min(e,i)-s&&t<=Math.max(e,i)+s}function et(t,e,i){i=i||(i=>t[i]<e);let s,n=t.length-1,o=0;for(;n-o>1;)s=o+n>>1,i(s)?o=s:n=s;return{lo:o,hi:n}}const it=(t,e,i,s)=>et(t,i,s?s=>{const n=t[s][e];return n<i||n===i&&t[s+1][e]===i}:s=>t[s][e]<i),st=(t,e,i)=>et(t,i,(s=>t[s][e]>=i));function nt(t,e,i){let s=0,n=t.length;for(;s<n&&t[s]<e;)s++;for(;n>s&&t[n-1]>i;)n--;return s>0||n<t.length?t.slice(s,n):t}const ot=["push","pop","shift","splice","unshift"];function at(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),ot.forEach((e=>{const i="_onData"+w(e),s=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value(...e){const n=s.apply(this,e);return t._chartjs.listeners.forEach((t=>{"function"==typeof t[i]&&t[i](...e)})),n}})})))}function rt(t,e){Line truncated
|
||||
/*!
|
||||
* @kurkle/color v0.3.2
|
||||
* https://github.com/kurkle/color#readme
|
||||
* (c) 2023 Jukka Kurkela
|
||||
* Released under the MIT License
|
||||
*/function _t(t){return t+.5|0}const yt=(t,e,i)=>Math.max(Math.min(t,i),e);function vt(t){return yt(_t(2.55*t),0,255)}function Mt(t){return yt(_t(255*t),0,255)}function wt(t){return yt(_t(t/2.55)/100,0,1)}function kt(t){return yt(_t(100*t),0,100)}const St={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},Pt=[..."0123456789ABCDEF"],Dt=t=>Pt[15&t],Ct=t=>Pt[(240&t)>>4]+Pt[15&t],Ot=t=>(240&t)>>4==(15&t);function At(t){var e=(t=>Ot(t.r)&&Ot(t.g)&&Ot(t.b)&&Ot(t.a))(t)?Dt:Ct;return t?"#"+e(t.r)+e(t.g)+e(t.b)+((t,e)=>t<255?e(t):"")(t.a,e):void 0}const Tt=/^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;function Lt(t,e,i){const s=e*Math.min(i,1-i),n=(e,n=(e+t/30)%12)=>i-s*Math.max(Math.min(n-3,9-n,1),-1);return[n(0),n(8),n(4)]}function Et(t,e,i){const s=(s,n=(s+t/60)%6)=>i-i*e*Math.max(Math.min(n,4-n,1),0);return[s(5),s(3),s(1)]}function Rt(t,e,i){const s=Lt(t,1,.5);let n;for(e+i>1&&(n=1/(e+i),e*=n,i*=n),n=0;n<3;n++)s[n]*=1-e-i,s[n]+=e;return s}function It(t){const e=t.r/255,i=t.g/255,s=t.b/255,n=Math.max(e,i,s),o=Math.min(e,i,s),a=(n+o)/2;let r,l,h;return n!==o&&(h=n-o,l=a>.5?h/(2-n-o):h/(n+o),r=function(t,e,i,s,n){return t===n?(e-i)/s+(e<i?6:0):e===n?(i-t)/s+2:(t-e)/s+4}(e,i,s,h,n),r=60*r+.5),[0|r,l||0,a]}function zt(t,e,i,s){return(Array.isArray(e)?t(e[0],e[1],e[2]):t(e,i,s)).map(Mt)}function Ft(t,e,i){return zt(Lt,t,e,i)}function Vt(t){return(t%360+360)%360}function Bt(t){const e=Tt.exec(t);let i,s=255;if(!e)return;e[5]!==i&&(s=e[6]?vt(+e[5]):Mt(+e[5]));const n=Vt(+e[2]),o=+e[3]/100,a=+e[4]/100;return i="hwb"===e[1]?function(t,e,i){return zt(Rt,t,e,i)}(n,o,a):"hsv"===e[1]?function(t,e,i){return zt(Et,t,e,i)}(n,o,a):Ft(n,o,a),{r:i[0],g:i[1],b:i[2],a:s}}const Wt={x:"dark",Z:"light",Y:"re",X:"blu",W:"gr",V:"medium",U:"slate",A:"ee",T:"ol",S:"or",B:"ra",C:"lateg",D:"ights",R:"in",Q:"turquois",E:"hi",P:"ro",O:"al",N:"le",M:"de",L:"yello",F:"en",K:"ch",G:"arks",H:"ea",I:"ightg",J:"wh"},Nt={OiceXe:"f0f8ff",antiquewEte:"faebd7",aqua:"ffff",aquamarRe:"7fffd4",azuY:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"0",blanKedOmond:"ffebcd",Xe:"ff",XeviTet:"8a2be2",bPwn:"a52a2a",burlywood:"deb887",caMtXe:"5f9ea0",KartYuse:"7fff00",KocTate:"d2691e",cSO:"ff7f50",cSnflowerXe:"6495ed",cSnsilk:"fff8dc",crimson:"dc143c",cyan:"ffff",xXe:"8b",xcyan:"8b8b",xgTMnPd:"b8860b",xWay:"a9a9a9",xgYF:"6400",xgYy:"a9a9a9",xkhaki:"bdb76b",xmagFta:"8b008b",xTivegYF:"556b2f",xSange:"ff8c00",xScEd:"9932cc",xYd:"8b0000",xsOmon:"e9967a",xsHgYF:"8fbc8f",xUXe:"483d8b",xUWay:"2f4f4f",xUgYy:"2f4f4f",xQe:"ced1",xviTet:"9400d3",dAppRk:"ff1493",dApskyXe:"bfff",dimWay:"696969",dimgYy:"696969",dodgerXe:"1e90ff",fiYbrick:"b22222",flSOwEte:"fffaf0",foYstWAn:"228b22",fuKsia:"ff00ff",gaRsbSo:"dcdcdc",ghostwEte:"f8f8ff",gTd:"ffd700",gTMnPd:"daa520",Way:"808080",gYF:"8000",gYFLw:"adff2f",gYy:"808080",honeyMw:"f0fff0",hotpRk:"ff69b4",RdianYd:"cd5c5c",Rdigo:"4b0082",ivSy:"fffff0",khaki:"f0e68c",lavFMr:"e6e6fa",lavFMrXsh:"fff0f5",lawngYF:"7cfc00",NmoncEffon:"fffacd",ZXe:"add8e6",ZcSO:"f08080",Zcyan:"e0ffff",ZgTMnPdLw:"fafad2",ZWay:"d3d3d3",ZgYF:"90ee90",ZgYy:"d3d3d3",ZpRk:"ffb6c1",ZsOmon:"ffa07a",ZsHgYF:"20b2aa",ZskyXe:"87cefa",ZUWay:"778899",ZUgYy:"778899",ZstAlXe:"b0c4de",ZLw:"ffffe0",lime:"ff00",limegYF:"32cd32",lRF:"faf0e6",magFta:"ff00ff",maPon:"800000",VaquamarRe:"66cdaa",VXe:"cd",VScEd:"ba55d3",VpurpN:"9370db",VsHgYF:"3cb371",VUXe:"7b68ee",VsprRggYF:"fa9a",VQe:"48d1cc",VviTetYd:"c71585",midnightXe:"191970",mRtcYam:"f5fffa",mistyPse:"ffe4e1",moccasR:"ffe4b5",navajowEte:"ffdead",navy:"80",Tdlace:"fdf5e6",Tive:"808000",TivedBb:"6b8e23",Sange:"ffa500",SangeYd:"ff4500",ScEd:"da70d6",pOegTMnPd:"eee8aa",pOegYF:"98fb98",pOeQe:"afeeee",pOeviTetYd:"db7093",papayawEp:"ffefd5",pHKpuff:"ffdab9",peru:"cd853f",pRk:"ffc0cb",plum:"dda0dd",powMrXe:"b0e0e6",purpN:"800080",YbeccapurpN:"663399",Yd:"ff0000",Psybrown:"bc8f8f",PyOXe:"4169e1",saddNbPwn:"8b4513",sOmon:"fa8072",sandybPwn:"f4a460",sHgYF:"2e8b57",sHshell:"fff5ee",siFna:"a0522d",silver:"c0c0c0",skyXe:"87ceeb",UXe:"6a5acd",UWay:"708090",UgYy:"708090",snow:"fffafa",sprRggYF:"ff7f",stAlXe:"4682b4",tan:"d2b48c",teO:"8080",tEstN:"d8bfd8",tomato:"ff6347",Qe:"40e0d0",viTet:"ee82ee",JHt:"f5deb3",wEte:"ffffff",wEtesmoke:"f5f5f5",Lw:"ffff00",LwgYF:"9acd32"};let Ht;function jt(t){Ht||(Ht=function(){const t={},e=Object.keys(Nt),i=Object.keys(Wt);let s,n,o,a,r;for(s=0;s<e.length;s++){for(a=r=e[s],n=0;n<i.length;n++)o=i[n],r=r.replace(o,Wt[o]);o=parseInt(Nt[a],16),t[r]=[o>>16&255,o>>8&255,255&o]}return t}(),Ht.transparent=[0,0,0,0]);const e=Ht[t.toLowerCase()];return e&&{r:e[0],g:e[1],b:e[2],a:4===e.length?e[3]:255}}const $t=/^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;const Yt=t=>t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055,Ut=t=>t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4);function Xt(t,e,i){if(t){let s=It(t);s[e]=Math.max(0,Math.min(s[e]+s[e]*i,0===e?360:1)),Line truncated
|
||||
//# sourceMappingURL=chart.umd.js.map
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
/*!
|
||||
* chartjs-plugin-zoom v2.0.1
|
||||
* undefined
|
||||
* (c) 2016-2023 chartjs-plugin-zoom Contributors
|
||||
* Released under the MIT License
|
||||
*/
|
||||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("chart.js"),require("hammerjs"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["chart.js","hammerjs","chart.js/helpers"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).ChartZoom=t(e.Chart,e.Hammer,e.Chart.helpers)}(this,(function(e,t,n){"use strict";function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var a=o(t);const i=e=>e&&e.enabled&&e.modifierKey,c=(e,t)=>e&&t[e+"Key"],r=(e,t)=>e&&!t[e+"Key"];function s(e,t,n){return void 0===e||("string"==typeof e?-1!==e.indexOf(t):"function"==typeof e&&-1!==e({chart:n}).indexOf(t))}function l(e,t){return"function"==typeof e&&(e=e({chart:t})),"string"==typeof e?{x:-1!==e.indexOf("x"),y:-1!==e.indexOf("y")}:{x:!1,y:!1}}function u(e,t,o){const{mode:a="xy",scaleMode:i,overScaleMode:c}=e||{},r=function({x:e,y:t},n){const o=n.scales,a=Object.keys(o);for(let n=0;n<a.length;n++){const i=o[a[n]];if(t>=i.top&&t<=i.bottom&&e>=i.left&&e<=i.right)return i}return null}(t,o),s=l(a,o),u=l(i,o);if(c){const e=l(c,o);for(const t of["x","y"])e[t]&&(u[t]=s[t],s[t]=!1)}if(r&&u[r.axis])return[r];const m=[];return n.each(o.scales,(function(e){s[e.axis]&&m.push(e)})),m}const m=new WeakMap;function d(e){let t=m.get(e);return t||(t={originalScaleLimits:{},updatedScaleLimits:{},handlers:{},panDelta:{}},m.set(e,t)),t}function f(e,t,n){const o=e.max-e.min,a=o*(t-1),i=e.isHorizontal()?n.x:n.y,c=Math.max(0,Math.min(1,(e.getValueForPixel(i)-e.min)/o||0));return{min:a*c,max:a*(1-c)}}function p(e,t,o,a,i){let c=o[a];if("original"===c){const o=e.originalScaleLimits[t.id][a];c=n.valueOrDefault(o.options,o.scale)}return n.valueOrDefault(c,i)}function h(e,{min:t,max:n},o,a=!1){const i=d(e.chart),{id:c,axis:r,options:s}=e,l=o&&(o[c]||o[r])||{},{minRange:u=0}=l,m=p(i,e,l,"min",-1/0),f=p(i,e,l,"max",1/0),h=a?Math.max(n-t,u):e.max-e.min,x=(h-n+t)/2;return n+=x,(t-=x)<m?(t=m,n=Math.min(m+h,f)):n>f&&(n=f,t=Math.max(f-h,m)),s.min=t,s.max=n,i.updatedScaleLimits[e.id]={min:t,max:n},e.parse(t)!==e.min||e.parse(n)!==e.max}const x=e=>0===e||isNaN(e)?0:e<0?Math.min(Math.round(e),-1):Math.max(Math.round(e),1);const g={second:500,minute:3e4,hour:18e5,day:432e5,week:3024e5,month:1296e6,quarter:5184e6,year:157248e5};function y(e,t,n,o=!1){const{min:a,max:i,options:c}=e,r=c.time&&c.time.round,s=g[r]||0,l=e.getValueForPixel(e.getPixelForValue(a+s)-t),u=e.getValueForPixel(e.getPixelForValue(i+s)-t),{min:m=-1/0,max:d=1/0}=o&&n&&n[e.axis]||{};return!!(isNaN(l)||isNaN(u)||l<m||u>d)||h(e,{min:l,max:u},n,o)}function b(e,t,n){return y(e,t,n,!0)}const v={category:function(e,t,n,o){const a=f(e,t,n);return e.min===e.max&&t<1&&function(e){const t=e.getLabels().length-1;e.min>0&&(e.min-=1),e.max<t&&(e.max+=1)}(e),h(e,{min:e.min+x(a.min),max:e.max-x(a.max)},o,!0)},default:function(e,t,n,o){const a=f(e,t,n);return h(e,{min:e.min+a.min,max:e.max-a.max},o,!0)}},w={default:function(e,t,n,o){h(e,function(e,t,n){const o=e.getValueForPixel(t),a=e.getValueForPixel(n);return{min:Math.min(o,a),max:Math.max(o,a)}}(e,t,n),o,!0)}},z={category:function(e,t,n){const o=e.getLabels().length-1;let{min:a,max:i}=e;const c=Math.max(i-a,1),r=Math.round(function(e){return e.isHorizontal()?e.width:e.height}(e)/Math.max(c,10)),s=Math.round(Math.abs(t/r));let l;return t<-r?(i=Math.min(i+s,o),a=1===c?i:i-c,l=i===o):t>r&&(a=Math.max(0,a-s),i=1===c?a:a+c,l=0===a),h(e,{min:a,max:i},n)||l},default:y,logarithmic:b,timeseries:b};function M(e,t){n.each(e,((n,o)=>{t[o]||delete e[o]}))}function k(e,t){const{scales:o}=e,{originalScaleLimits:a,updatedScaleLimits:i}=t;return n.each(o,(function(e){(function(e,t,n){const{id:o,options:{min:a,max:i}}=e;if(!t[o]||!n[o])return!0;const c=n[o];return c.min!==a||c.max!==i})(e,a,i)&&(a[e.id]={min:{scale:e.min,options:e.options.min},max:{scale:e.max,options:e.options.max}})})),M(a,o),M(i,o),a}function S(e,t,o,a){const i=v[e.type]||v.default;n.callback(i,[e,t,o,a])}function P(e,t,o,a,i){const c=w[e.type]||w.default;n.callback(c,[e,t,o,a,i])}function D(e){const t=e.chartArea;return{x:(t.left+t.right)/2,y:(t.top+t.bottom)/2}}function j(e,t,o="none"){const{x:a=1,y:i=1,focalPoint:c=D(e)}="number"==typeof t?{x:t,y:t}:t,r=d(e),{options:{limits:s,zoom:l}}=r;k(e,r);const m=1!==a,f=1!==i,p=u(l,c,e);n.each(p||e.scales,(function(e){e.isHorizontal()&&m?S(e,a,c,s):!e.isHorizontal()&&f&&S(e,i,c,s)})),e.update(o),n.callback(l.onZoom,[{chart:e}])}function O(e,t,o,a="none"){const i=d(e),{options:{limits:c,zoom:r}}=i,{mode:l="xy"}=r;k(e,i);const u=s(l,"x",e),m=s(l,"y",e);n.each(e.scales,(function(e){e.isHorizontal()&&u?P(e,t.x,o.x,c):!e.isHorizontal()&&m&&P(e,t.y,o.y,c)})),e.update(a),n.callback(r.onZoom,[{chart:e}])}function C(e){const t=d(e);let o=1,a=1;return n.each(e.scales,(function(e){const i=function(e,t){const o=e.originalScaleLimits[t];if(!o)return;const{min:a,max:i}=o;return n.valueOrDefault(i.options,i.scale)-n.valueOrDefault(a.options,a.scale)}(t,e.id);if(i){const t=Math.round(i/(e.max-e.min)*10Line truncated
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,396 @@
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx3cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxTcwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxPcwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx_cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx7cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxDcwgknk-4.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx3cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxTcwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxPcwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx_cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx7cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxDcwgknk-4.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx3cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxTcwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxPcwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx_cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx7cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxDcwgknk-4.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx3cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxTcwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxPcwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx_cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPx7cwgknk-6nFg.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-tDbv2o-flEEny0FZhsfKu5WU4zr3E_BX0PnT8RD8yKwBNntkaToggR7BYRbKPxDcwgknk-4.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko70yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko50yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko40yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko20yygg_vb.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko70yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko50yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko40yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko20yygg_vb.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko70yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko50yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko40yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko20yygg_vb.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko70yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko50yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko40yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko20yygg_vb.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko70yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko50yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko40yygg_vbd-E.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Plus Jakarta Sans';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url(fonts/gf-LDIoaomQNQcsA88c7O9yZ4KMCoOg4Ko20yygg_vb.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
/*! Hammer.JS - v2.0.7 - 2016-04-22
|
||||
* http://hammerjs.github.io/
|
||||
*
|
||||
* Copyright (c) 2016 Jorik Tangelder;
|
||||
* Licensed under the MIT license */
|
||||
!function(a,b,c,d){"use strict";function e(a,b,c){return setTimeout(j(a,c),b)}function f(a,b,c){return Array.isArray(a)?(g(a,c[b],c),!0):!1}function g(a,b,c){var e;if(a)if(a.forEach)a.forEach(b,c);else if(a.length!==d)for(e=0;e<a.length;)b.call(c,a[e],e,a),e++;else for(e in a)a.hasOwnProperty(e)&&b.call(c,a[e],e,a)}function h(b,c,d){var e="DEPRECATED METHOD: "+c+"\n"+d+" AT \n";return function(){var c=new Error("get-stack-trace"),d=c&&c.stack?c.stack.replace(/^[^\(]+?[\n$]/gm,"").replace(/^\s+at\s+/gm,"").replace(/^Object.<anonymous>\s*\(/gm,"{anonymous}()@"):"Unknown Stack Trace",f=a.console&&(a.console.warn||a.console.log);return f&&f.call(a.console,e,d),b.apply(this,arguments)}}function i(a,b,c){var d,e=b.prototype;d=a.prototype=Object.create(e),d.constructor=a,d._super=e,c&&la(d,c)}function j(a,b){return function(){return a.apply(b,arguments)}}function k(a,b){return typeof a==oa?a.apply(b?b[0]||d:d,b):a}function l(a,b){return a===d?b:a}function m(a,b,c){g(q(b),function(b){a.addEventListener(b,c,!1)})}function n(a,b,c){g(q(b),function(b){a.removeEventListener(b,c,!1)})}function o(a,b){for(;a;){if(a==b)return!0;a=a.parentNode}return!1}function p(a,b){return a.indexOf(b)>-1}function q(a){return a.trim().split(/\s+/g)}function r(a,b,c){if(a.indexOf&&!c)return a.indexOf(b);for(var d=0;d<a.length;){if(c&&a[d][c]==b||!c&&a[d]===b)return d;d++}return-1}function s(a){return Array.prototype.slice.call(a,0)}function t(a,b,c){for(var d=[],e=[],f=0;f<a.length;){var g=b?a[f][b]:a[f];r(e,g)<0&&d.push(a[f]),e[f]=g,f++}return c&&(d=b?d.sort(function(a,c){return a[b]>c[b]}):d.sort()),d}function u(a,b){for(var c,e,f=b[0].toUpperCase()+b.slice(1),g=0;g<ma.length;){if(c=ma[g],e=c?c+f:b,e in a)return e;g++}return d}function v(){return ua++}function w(b){var c=b.ownerDocument||b;return c.defaultView||c.parentWindow||a}function x(a,b){var c=this;this.manager=a,this.callback=b,this.element=a.element,this.target=a.options.inputTarget,this.domHandler=function(b){k(a.options.enable,[a])&&c.handler(b)},this.init()}function y(a){var b,c=a.options.inputClass;return new(b=c?c:xa?M:ya?P:wa?R:L)(a,z)}function z(a,b,c){var d=c.pointers.length,e=c.changedPointers.length,f=b&Ea&&d-e===0,g=b&(Ga|Ha)&&d-e===0;c.isFirst=!!f,c.isFinal=!!g,f&&(a.session={}),c.eventType=b,A(a,c),a.emit("hammer.input",c),a.recognize(c),a.session.prevInput=c}function A(a,b){var c=a.session,d=b.pointers,e=d.length;c.firstInput||(c.firstInput=D(b)),e>1&&!c.firstMultiple?c.firstMultiple=D(b):1===e&&(c.firstMultiple=!1);var f=c.firstInput,g=c.firstMultiple,h=g?g.center:f.center,i=b.center=E(d);b.timeStamp=ra(),b.deltaTime=b.timeStamp-f.timeStamp,b.angle=I(h,i),b.distance=H(h,i),B(c,b),b.offsetDirection=G(b.deltaX,b.deltaY);var j=F(b.deltaTime,b.deltaX,b.deltaY);b.overallVelocityX=j.x,b.overallVelocityY=j.y,b.overallVelocity=qa(j.x)>qa(j.y)?j.x:j.y,b.scale=g?K(g.pointers,d):1,b.rotation=g?J(g.pointers,d):0,b.maxPointers=c.prevInput?b.pointers.length>c.prevInput.maxPointers?b.pointers.length:c.prevInput.maxPointers:b.pointers.length,C(c,b);var k=a.element;o(b.srcEvent.target,k)&&(k=b.srcEvent.target),b.target=k}function B(a,b){var c=b.center,d=a.offsetDelta||{},e=a.prevDelta||{},f=a.prevInput||{};b.eventType!==Ea&&f.eventType!==Ga||(e=a.prevDelta={x:f.deltaX||0,y:f.deltaY||0},d=a.offsetDelta={x:c.x,y:c.y}),b.deltaX=e.x+(c.x-d.x),b.deltaY=e.y+(c.y-d.y)}function C(a,b){var c,e,f,g,h=a.lastInterval||b,i=b.timeStamp-h.timeStamp;if(b.eventType!=Ha&&(i>Da||h.velocity===d)){var j=b.deltaX-h.deltaX,k=b.deltaY-h.deltaY,l=F(i,j,k);e=l.x,f=l.y,c=qa(l.x)>qa(l.y)?l.x:l.y,g=G(j,k),a.lastInterval=b}else c=h.velocity,e=h.velocityX,f=h.velocityY,g=h.direction;b.velocity=c,b.velocityX=e,b.velocityY=f,b.direction=g}function D(a){for(var b=[],c=0;c<a.pointers.length;)b[c]={clientX:pa(a.pointers[c].clientX),clientY:pa(a.pointers[c].clientY)},c++;return{timeStamp:ra(),pointers:b,center:E(b),deltaX:a.deltaX,deltaY:a.deltaY}}function E(a){var b=a.length;if(1===b)return{x:pa(a[0].clientX),y:pa(a[0].clientY)};for(var c=0,d=0,e=0;b>e;)c+=a[e].clientX,d+=a[e].clientY,e++;return{x:pa(c/b),y:pa(d/b)}}function F(a,b,c){return{x:b/a||0,y:c/a||0}}function G(a,b){return a===b?Ia:qa(a)>=qa(b)?0>a?Ja:Ka:0>b?La:Ma}function H(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return Math.sqrt(d*d+e*e)}function I(a,b,c){c||(c=Qa);var d=b[c[0]]-a[c[0]],e=b[c[1]]-a[c[1]];return 180*Math.atan2(e,d)/Math.PI}function J(a,b){return I(b[1],b[0],Ra)+I(a[1],a[0],Ra)}function K(a,b){return H(b[0],b[1],Ra)/H(a[0],a[1],Ra)}function L(){this.evEl=Ta,this.evWin=Ua,this.pressed=!1,x.apply(this,arguments)}function M(){this.evEl=Xa,this.evWin=Ya,x.apply(this,arguments),this.store=this.manager.session.pointerEvents=[]}function N(){this.evTarget=$a,this.evWin=_a,this.started=!1,x.apply(this,arguments)}function O(a,b){var c=s(a.touches),d=s(a.changedTouches);return b&(Ga|Ha)&&(c=t(c.concat(d),"identifier",!0)),[c,d]}function P(){this.evTarget=bb,this.targetIds={},x.apply(this,arguments)}function Q(a,b){var c=s(a.touches)Line truncated
|
||||
//# sourceMappingURL=hammer.min.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
@font-face{font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(fonts/KaTeX_AMS-Regular.woff2) format("woff2")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Caligraphic-Bold.woff2) format("woff2")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Caligraphic-Regular.woff2) format("woff2")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Fraktur-Bold.woff2) format("woff2")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Fraktur-Regular.woff2) format("woff2")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Main-Bold.woff2) format("woff2")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Main-BoldItalic.woff2) format("woff2")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Main-Italic.woff2) format("woff2")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Main-Regular.woff2) format("woff2")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Math-BoldItalic.woff2) format("woff2")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Math-Italic.woff2) format("woff2")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:700;src:url(fonts/KaTeX_SansSerif-Bold.woff2) format("woff2")}@font-face{font-family:"KaTeX_SansSerif";font-style:italic;font-weight:400;src:url(fonts/KaTeX_SansSerif-Italic.woff2) format("woff2")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:400;src:url(fonts/KaTeX_SansSerif-Regular.woff2) format("woff2")}@font-face{font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Script-Regular.woff2) format("woff2")}@font-face{font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size1-Regular.woff2) format("woff2")}@font-face{font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size2-Regular.woff2) format("woff2")}@font-face{font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size3-Regular.woff2) format("woff2")}@font-face{font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size4-Regular.woff2) format("woff2")}@font-face{font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Typewriter-Regular.woff2) format("woff2")}.katex{text-rendering:auto;font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;text-indent:0}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:"0.16.9"}.katex .katex-mathml{clip:rect(1px,1px,1px,1px);border:0;height:1px;overflow:hidden;padding:0;position:absolute;width:1px}.katex .katex-html>.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathboldfrak,.katex .textboldfrak{font-family:KaTeX_Fraktur;font-weight:700}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .vbox{align-items:baseline;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .fracLine truncated
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.katex=t():e.katex=t()}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={d:function(t,r){for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:r[n]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t={};e.d(t,{default:function(){return na}});var r=function e(t,r){this.name=void 0,this.position=void 0,this.length=void 0,this.rawMessage=void 0;var n,a,i="KaTeX parse error: "+t,o=r&&r.loc;if(o&&o.start<=o.end){var s=o.lexer.input;n=o.start,a=o.end,n===s.length?i+=" at end of input: ":i+=" at position "+(n+1)+": ";var l=s.slice(n,a).replace(/[^]/g,"$&\u0332");i+=(n>15?"\u2026"+s.slice(n-15,n):s.slice(0,n))+l+(a+15<s.length?s.slice(a,a+15)+"\u2026":s.slice(a))}var h=new Error(i);return h.name="ParseError",h.__proto__=e.prototype,h.position=n,null!=n&&null!=a&&(h.length=a-n),h.rawMessage=t,h};r.prototype.__proto__=Error.prototype;var n=r,a=/([A-Z])/g,i={"&":"&",">":">","<":"<",'"':""","'":"'"},o=/[&><"']/g;var s=function e(t){return"ordgroup"===t.type||"color"===t.type?1===t.body.length?e(t.body[0]):t:"font"===t.type?e(t.body):t},l={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(o,(function(e){return i[e]}))},hyphenate:function(e){return e.replace(a,"-$1").toLowerCase()},getBaseElem:s,isCharacterBox:function(e){var t=s(e);return"mathord"===t.type||"textord"===t.type||"atom"===t.type},protocolFromUrl:function(e){var t=/^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(e);return null!=t?t[1]:"_relative"}},h={displayMode:{type:"boolean",description:"Render math in display mode, which puts the math in display style (so \\int and \\sum are large, for example), and centers the math on the page on its own line.",cli:"-d, --display-mode"},output:{type:{enum:["htmlAndMathml","html","mathml"]},description:"Determines the markup language of the output.",cli:"-F, --format <type>"},leqno:{type:"boolean",description:"Render display math in leqno style (left-justified tags)."},fleqn:{type:"boolean",description:"Render display math flush left."},throwOnError:{type:"boolean",default:!0,cli:"-t, --no-throw-on-error",cliDescription:"Render errors (in the color given by --error-color) instead of throwing a ParseError exception when encountering an error."},errorColor:{type:"string",default:"#cc0000",cli:"-c, --error-color <color>",cliDescription:"A color string given in the format 'rgb' or 'rrggbb' (no #). This option determines the color of errors rendered by the -t option.",cliProcessor:function(e){return"#"+e}},macros:{type:"object",cli:"-m, --macro <def>",cliDescription:"Define custom macro of the form '\\foo:expansion' (use multiple -m arguments for multiple macros).",cliDefault:[],cliProcessor:function(e,t){return t.push(e),t}},minRuleThickness:{type:"number",description:"Specifies a minimum thickness, in ems, for fraction lines, `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, `\\hdashline`, `\\underline`, `\\overline`, and the borders of `\\fbox`, `\\boxed`, and `\\fcolorbox`.",processor:function(e){return Math.max(0,e)},cli:"--min-rule-thickness <size>",cliProcessor:parseFloat},colorIsTextColor:{type:"boolean",description:"Makes \\color behave like LaTeX's 2-argument \\textcolor, instead of LaTeX's one-argument \\color mode change.",cli:"-b, --color-is-text-color"},strict:{type:[{enum:["warn","ignore","error"]},"boolean","function"],description:"Turn on strict / LaTeX faithfulness mode, which throws an error if the input uses features that are not supported by LaTeX.",cli:"-S, --strict",cliDefault:!1},trust:{type:["boolean","function"],description:"Trust the input, enabling all HTML features such as \\url.",cli:"-T, --trust"},maxSize:{type:"number",default:1/0,description:"If non-zero, all user-specified sizes, e.g. in \\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, elements and spaces can be arbitrarily large",processor:function(e){return Math.max(0,e)},cli:"-s, --max-size <n>",cliProcessor:parseInt},maxExpand:{type:"number",default:1e3,description:"Limit the number of macro expansions to the specified number, to prevent e.g. infinite macro loops. If set to Infinity, the macro expander will try to fully expand as in LaTeX.",processor:function(e){return Math.max(0,e)},cli:"-e, --max-expand <n>",cliProcessor:function(e){return"Infinity"===e?1/0:parseInt(e)}},globalGroup:{type:"boolean",cli:!1}};function c(e){if(e.default)return e.default;var t=e.type,r=Array.isArray(t)?t[0]:t;if("string"!=typeof r)return r.enum[0];switch(r){case"boolean":return!1;case"string":return"";case"number":return 0;case"object":return{}}}var m=function(){function e(e){for(var t in this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void
Line truncated
|
||||
@@ -0,0 +1,83 @@
|
||||
(()=>{var qv=Object.create;var Hi=Object.defineProperty;var $v=Object.getOwnPropertyDescriptor;var Lv=Object.getOwnPropertyNames;var Mv=Object.getPrototypeOf,Nv=Object.prototype.hasOwnProperty;var df=r=>Hi(r,"__esModule",{value:!0});var hf=r=>{if(typeof require!="undefined")return require(r);throw new Error('Dynamic require of "'+r+'" is not supported')};var P=(r,e)=>()=>(r&&(e=r(r=0)),e);var x=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports),Ge=(r,e)=>{df(r);for(var t in e)Hi(r,t,{get:e[t],enumerable:!0})},Bv=(r,e,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Lv(e))!Nv.call(r,i)&&i!=="default"&&Hi(r,i,{get:()=>e[i],enumerable:!(t=$v(e,i))||t.enumerable});return r},pe=r=>Bv(df(Hi(r!=null?qv(Mv(r)):{},"default",r&&r.__esModule&&"default"in r?{get:()=>r.default,enumerable:!0}:{value:r,enumerable:!0})),r);var m,u=P(()=>{m={platform:"",env:{},versions:{node:"14.17.6"}}});var Fv,be,ft=P(()=>{u();Fv=0,be={readFileSync:r=>self[r]||"",statSync:()=>({mtimeMs:Fv++}),promises:{readFile:r=>Promise.resolve(self[r]||"")}}});var Fs=x((oP,gf)=>{u();"use strict";var mf=class{constructor(e={}){if(!(e.maxSize&&e.maxSize>0))throw new TypeError("`maxSize` must be a number greater than 0");if(typeof e.maxAge=="number"&&e.maxAge===0)throw new TypeError("`maxAge` must be a number greater than 0");this.maxSize=e.maxSize,this.maxAge=e.maxAge||1/0,this.onEviction=e.onEviction,this.cache=new Map,this.oldCache=new Map,this._size=0}_emitEvictions(e){if(typeof this.onEviction=="function")for(let[t,i]of e)this.onEviction(t,i.value)}_deleteIfExpired(e,t){return typeof t.expiry=="number"&&t.expiry<=Date.now()?(typeof this.onEviction=="function"&&this.onEviction(e,t.value),this.delete(e)):!1}_getOrDeleteIfExpired(e,t){if(this._deleteIfExpired(e,t)===!1)return t.value}_getItemValue(e,t){return t.expiry?this._getOrDeleteIfExpired(e,t):t.value}_peek(e,t){let i=t.get(e);return this._getItemValue(e,i)}_set(e,t){this.cache.set(e,t),this._size++,this._size>=this.maxSize&&(this._size=0,this._emitEvictions(this.oldCache),this.oldCache=this.cache,this.cache=new Map)}_moveToRecent(e,t){this.oldCache.delete(e),this._set(e,t)}*_entriesAscending(){for(let e of this.oldCache){let[t,i]=e;this.cache.has(t)||this._deleteIfExpired(t,i)===!1&&(yield e)}for(let e of this.cache){let[t,i]=e;this._deleteIfExpired(t,i)===!1&&(yield e)}}get(e){if(this.cache.has(e)){let t=this.cache.get(e);return this._getItemValue(e,t)}if(this.oldCache.has(e)){let t=this.oldCache.get(e);if(this._deleteIfExpired(e,t)===!1)return this._moveToRecent(e,t),t.value}}set(e,t,{maxAge:i=this.maxAge===1/0?void 0:Date.now()+this.maxAge}={}){this.cache.has(e)?this.cache.set(e,{value:t,maxAge:i}):this._set(e,{value:t,expiry:i})}has(e){return this.cache.has(e)?!this._deleteIfExpired(e,this.cache.get(e)):this.oldCache.has(e)?!this._deleteIfExpired(e,this.oldCache.get(e)):!1}peek(e){if(this.cache.has(e))return this._peek(e,this.cache);if(this.oldCache.has(e))return this._peek(e,this.oldCache)}delete(e){let t=this.cache.delete(e);return t&&this._size--,this.oldCache.delete(e)||t}clear(){this.cache.clear(),this.oldCache.clear(),this._size=0}resize(e){if(!(e&&e>0))throw new TypeError("`maxSize` must be a number greater than 0");let t=[...this._entriesAscending()],i=t.length-e;i<0?(this.cache=new Map(t),this.oldCache=new Map,this._size=t.length):(i>0&&this._emitEvictions(t.slice(0,i)),this.oldCache=new Map(t.slice(i)),this.cache=new Map,this._size=0),this.maxSize=e}*keys(){for(let[e]of this)yield e}*values(){for(let[,e]of this)yield e}*[Symbol.iterator](){for(let e of this.cache){let[t,i]=e;this._deleteIfExpired(t,i)===!1&&(yield[t,i.value])}for(let e of this.oldCache){let[t,i]=e;this.cache.has(t)||this._deleteIfExpired(t,i)===!1&&(yield[t,i.value])}}*entriesDescending(){let e=[...this.cache];for(let t=e.length-1;t>=0;--t){let i=e[t],[n,s]=i;this._deleteIfExpired(n,s)===!1&&(yield[n,s.value])}e=[...this.oldCache];for(let t=e.length-1;t>=0;--t){let i=e[t],[n,s]=i;this.cache.has(n)||this._deleteIfExpired(n,s)===!1&&(yield[n,s.value])}}*entriesAscending(){for(let[e,t]of this._entriesAscending())yield[e,t.value]}get size(){if(!this._size)return this.oldCache.size;let e=0;for(let t of this.oldCache.keys())this.cache.has(t)||e++;return Math.min(this._size+e,this.maxSize)}};gf.exports=mf});var yf,bf=P(()=>{u();yf=r=>r&&r._hash});function Wi(r){return yf(r,{ignoreUnknown:!0})}var wf=P(()=>{u();bf()});function xt(r){if(r=`${r}`,r==="0")return"0";if(/^[+-]?(\d+|\d*\.\d+)(e[+-]?\d+)?(%|\w+)?$/.test(r))return r.replace(/^[+-]?/,t=>t==="-"?"":"-");let e=["var","calc","min","max","clamp"];for(let t of e)if(r.includes(`${t}(`))return`calc(${r} * -1)`}var Gi=P(()=>{u()});var vf,xf=P(()=>{u();vf=["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","lineClamp","display","aspectRatio","size","height","maxHeight"Line truncated
|
||||
`+S+n("^")}let b=i(h.replace(/\d/g," "))+f.slice(0,this.column-1).replace(/[^\t]/g," ");return n(">")+i(h)+s(f)+`
|
||||
`+b+n("^")}return" "+i(h)+s(f)}).join(`
|
||||
`)}toString(){let e=this.showSourceCode();return e&&(e=`
|
||||
|
||||
`+e+`
|
||||
`),this.name+": "+this.message+e}};cc.exports=Jt;Jt.default=Jt});var fa=x((x3,dc)=>{u();"use strict";var pc={after:`
|
||||
`,beforeClose:`
|
||||
`,beforeComment:`
|
||||
`,beforeDecl:`
|
||||
`,beforeOpen:" ",beforeRule:`
|
||||
`,colon:": ",commentLeft:" ",commentRight:" ",emptyBody:"",indent:" ",semicolon:!1};function vx(r){return r[0].toUpperCase()+r.slice(1)}var on=class{constructor(e){this.builder=e}atrule(e,t){let i="@"+e.name,n=e.params?this.rawValue(e,"params"):"";if(typeof e.raws.afterName!="undefined"?i+=e.raws.afterName:n&&(i+=" "),e.nodes)this.block(e,i+n);else{let s=(e.raws.between||"")+(t?";":"");this.builder(i+n+s,e)}}beforeAfter(e,t){let i;e.type==="decl"?i=this.raw(e,null,"beforeDecl"):e.type==="comment"?i=this.raw(e,null,"beforeComment"):t==="before"?i=this.raw(e,null,"beforeRule"):i=this.raw(e,null,"beforeClose");let n=e.parent,s=0;for(;n&&n.type!=="root";)s+=1,n=n.parent;if(i.includes(`
|
||||
`)){let a=this.raw(e,null,"indent");if(a.length)for(let o=0;o<s;o++)i+=a}return i}block(e,t){let i=this.raw(e,"between","beforeOpen");this.builder(t+i+"{",e,"start");let n;e.nodes&&e.nodes.length?(this.body(e),n=this.raw(e,"after")):n=this.raw(e,"after","emptyBody"),n&&this.builder(n),this.builder("}",e,"end")}body(e){let t=e.nodes.length-1;for(;t>0&&e.nodes[t].type==="comment";)t-=1;let i=this.raw(e,"semicolon");for(let n=0;n<e.nodes.length;n++){let s=e.nodes[n],a=this.raw(s,"before");a&&this.builder(a),this.stringify(s,t!==n||i)}}comment(e){let t=this.raw(e,"left","commentLeft"),i=this.raw(e,"right","commentRight");this.builder("/*"+t+e.text+i+"*/",e)}decl(e,t){let i=this.raw(e,"between","colon"),n=e.prop+i+this.rawValue(e,"value");e.important&&(n+=e.raws.important||" !important"),t&&(n+=";"),this.builder(n,e)}document(e){this.body(e)}raw(e,t,i){let n;if(i||(i=t),t&&(n=e.raws[t],typeof n!="undefined"))return n;let s=e.parent;if(i==="before"&&(!s||s.type==="root"&&s.first===e||s&&s.type==="document"))return"";if(!s)return pc[i];let a=e.root();if(a.rawCache||(a.rawCache={}),typeof a.rawCache[i]!="undefined")return a.rawCache[i];if(i==="before"||i==="after")return this.beforeAfter(e,i);{let o="raw"+vx(i);this[o]?n=this[o](a,e):a.walk(l=>{if(n=l.raws[t],typeof n!="undefined")return!1})}return typeof n=="undefined"&&(n=pc[i]),a.rawCache[i]=n,n}rawBeforeClose(e){let t;return e.walk(i=>{if(i.nodes&&i.nodes.length>0&&typeof i.raws.after!="undefined")return t=i.raws.after,t.includes(`
|
||||
`)&&(t=t.replace(/[^\n]+$/,"")),!1}),t&&(t=t.replace(/\S/g,"")),t}rawBeforeComment(e,t){let i;return e.walkComments(n=>{if(typeof n.raws.before!="undefined")return i=n.raws.before,i.includes(`
|
||||
`)&&(i=i.replace(/[^\n]+$/,"")),!1}),typeof i=="undefined"?i=this.raw(t,null,"beforeDecl"):i&&(i=i.replace(/\S/g,"")),i}rawBeforeDecl(e,t){let i;return e.walkDecls(n=>{if(typeof n.raws.before!="undefined")return i=n.raws.before,i.includes(`
|
||||
`)&&(i=i.replace(/[^\n]+$/,"")),!1}),typeof i=="undefined"?i=this.raw(t,null,"beforeRule"):i&&(i=i.replace(/\S/g,"")),i}rawBeforeOpen(e){let t;return e.walk(i=>{if(i.type!=="decl"&&(t=i.raws.between,typeof t!="undefined"))return!1}),t}rawBeforeRule(e){let t;return e.walk(i=>{if(i.nodes&&(i.parent!==e||e.first!==i)&&typeof i.raws.before!="undefined")return t=i.raws.before,t.includes(`
|
||||
`)&&(t=t.replace(/[^\n]+$/,"")),!1}),t&&(t=t.replace(/\S/g,"")),t}rawColon(e){let t;return e.walkDecls(i=>{if(typeof i.raws.between!="undefined")return t=i.raws.between.replace(/[^\s:]/g,""),!1}),t}rawEmptyBody(e){let t;return e.walk(i=>{if(i.nodes&&i.nodes.length===0&&(t=i.raws.after,typeof t!="undefined"))return!1}),t}rawIndent(e){if(e.raws.indent)return e.raws.indent;let t;return e.walk(i=>{let n=i.parent;if(n&&n!==e&&n.parent&&n.parent===e&&typeof i.raws.before!="undefined"){let s=i.raws.before.split(`
|
||||
`);return t=s[s.length-1],t=t.replace(/\S/g,""),!1}}),t}rawSemicolon(e){let t;return e.walk(i=>{if(i.nodes&&i.nodes.length&&i.last.type==="decl"&&(t=i.raws.semicolon,typeof t!="undefined"))return!1}),t}rawValue(e,t){let i=e[t],n=e.raws[t];return n&&n.value===i?n.raw:i}root(e){this.body(e),e.raws.after&&this.builder(e.raws.after)}rule(e){this.block(e,this.rawValue(e,"selector")),e.raws.ownSemicolon&&this.builder(e.raws.ownSemicolon,e,"end")}stringify(e,t){if(!this[e.type])throw new Error("Unknown AST node type "+e.type+". Maybe you need to change PostCSS stringifier.");this[e.type](e,t)}};dc.exports=on;on.default=on});var Vr=x((k3,hc)=>{u();"use strict";var xx=fa();function ca(r,e){new xx(e).stringify(r)}hc.exports=ca;ca.default=ca});var ln=x((S3,pa)=>{u();"use strict";pa.exports.isClean=Symbol("isClean");pa.exports.my=Symbol("my")});var Gr=x((A3,mc)=>{u();"use strict";var kx=an(),Sx=fa(),Ax=Vr(),{isClean:Hr,my:Cx}=ln();function da(r,e){let t=new r.constructor;for(let i in r){if(!Object.prototype.hasOwnProperty.call(r,i)||i==="proxyCache")continue;let n=r[i],s=typeof n;i==="parent"&&s==="object"?e&&(t[i]=e):i==="source"?t[i]=n:Array.isArray(n)?t[i]=n.map(a=>da(a,t)):(s==="object"&&n!==null&&(n=da(n)),t[i]=n)}return t}function Wr(r,e){if(e&&typeof e.offset!="undefined")return e.offset;let t=1,i=1,n=0;for(let s=0;s<r.length;s++){if(i===e.line&&t===e.column){n=s;break}r[s]===`
|
||||
`?(t=1,i+=1):t+=1}return n}var un=class{constructor(e={}){this.raws={},this[Hr]=!1,this[Cx]=!0;for(let t in e)if(t==="nodes"){this.nodes=[];for(let i of e[t])typeof i.clone=="function"?this.append(i.clone()):this.append(i)}else this[t]=e[t]}addToError(e){if(e.postcssNode=this,e.stack&&this.source&&/\n\s{4}at /.test(e.stack)){let t=this.source;e.stack=e.stack.replace(/\n\s{4}at /,`$&${t.input.from}:${t.start.line}:${t.start.column}$&`)}return e}after(e){return this.parent.insertAfter(this,e),this}assign(e={}){for(let t in e)this[t]=e[t];return this}before(e){return this.parent.insertBefore(this,e),this}cleanRaws(e){delete this.raws.before,delete this.raws.after,e||delete this.raws.between}clone(e={}){let t=da(this);for(let i in e)t[i]=e[i];return t}cloneAfter(e={}){let t=this.clone(e);return this.parent.insertAfter(this,t),t}cloneBefore(e={}){let t=this.clone(e);return this.parent.insertBefore(this,t),t}error(e,t={}){if(this.source){let{end:i,start:n}=this.rangeBy(t);return this.source.input.error(e,{column:n.column,line:n.line},{column:i.column,line:i.line},t)}return new kx(e)}getProxyProcessor(){return{get(e,t){return t==="proxyOf"?e:t==="root"?()=>e.root().toProxy():e[t]},set(e,t,i){return e[t]===i||(e[t]=i,(t==="prop"||t==="value"||t==="name"||t==="params"||t==="important"||t==="text")&&e.markDirty()),!0}}}markClean(){this[Hr]=!0}markDirty(){if(this[Hr]){this[Hr]=!1;let e=this;for(;e=e.parent;)e[Hr]=!1}}next(){if(!this.parent)return;let e=this.parent.index(this);return this.parent.nodes[e+1]}positionBy(e){let t=this.source.start;if(e.index)t=this.positionInside(e.index);else if(e.word){let n=this.source.input.css.slice(Wr(this.source.input.css,this.source.start),Wr(this.source.input.css,this.source.end)).indexOf(e.word);n!==-1&&(t=this.positionInside(n))}return t}positionInside(e){let t=this.source.start.column,i=this.source.start.line,n=Wr(this.source.input.css,this.source.start),s=n+e;for(let a=n;a<s;a++)this.source.input.css[a]===`
|
||||
`?(t=1,i+=1):t+=1;return{column:t,line:i}}prev(){if(!this.parent)return;let e=this.parent.index(this);return this.parent.nodes[e-1]}rangeBy(e){let t={column:this.source.start.column,line:this.source.start.line},i=this.source.end?{column:this.source.end.column+1,line:this.source.end.line}:{column:t.column+1,line:t.line};if(e.word){let s=this.source.input.css.slice(Wr(this.source.input.css,this.source.start),Wr(this.source.input.css,this.source.end)).indexOf(e.word);s!==-1&&(t=this.positionInside(s),i=this.positionInside(s+e.word.length))}else e.start?t={column:e.start.column,line:e.start.line}:e.index&&(t=this.positionInside(e.index)),e.end?i={column:e.end.column,line:e.end.line}:typeof e.endIndex=="number"?i=this.positionInside(e.endIndex):e.index&&(i=this.positionInside(e.index+1));return(i.line<t.line||i.line===t.line&&i.column<=t.column)&&(i={column:t.column+1,line:t.line}),{end:i,start:t}}raw(e,t){return new Sx().raw(this,e,t)}remove(){return this.parent&&this.parent.removeChild(this),this.parent=void 0,this}replaceWith(...e){if(this.parent){let t=this,i=!1;for(let n of e)n===this?i=!0:i?(this.parent.insertAfter(t,n),t=n):this.parent.insertBefore(t,n);i||this.remove()}return this}root(){let e=this;for(;e.parent&&e.parent.type!=="document";)e=e.parent;return e}toJSON(e,t){let i={},n=t==null;t=t||new Map;let s=0;for(let a in this){if(!Object.prototype.hasOwnProperty.call(this,a)||a==="parent"||a==="proxyCache")continue;let o=this[a];if(Array.isArray(o))i[a]=o.map(l=>typeof l=="object"&&l.toJSON?l.toJSON(null,t):l);else if(typeof o=="object"&&o.toJSON)i[a]=o.toJSON(null,t);else if(a==="source"){let l=t.get(o.input);l==null&&(l=s,t.set(o.input,s),s++),i[a]={end:o.end,inputId:l,start:o.start}}else i[a]=o}return n&&(i.inputs=[...t.keys()].map(a=>a.toJSON())),i}toProxy(){return this.proxyCache||(this.proxyCache=new Proxy(this,this.getProxyProcessor())),this.proxyCache}toString(e=Ax){e.stringify&&(e=e.stringify);let t="";return e(this,i=>{t+=i}),t}warn(e,t,i){let n={node:this};for(let s in i)n[s]=i[s];return e.warn(t,n)}get proxyOf(){return this}};mc.exports=un;un.default=un});var Qr=x((C3,gc)=>{u();"use strict";var _x=Gr(),fn=class extends _x{constructor(e){super(e);this.type="comment"}};gc.exports=fn;fn.default=fn});var Yr=x((_3,yc)=>{u();"use strict";var Ex=Gr(),cn=class extends Ex{constructor(e){e&&typeof e.value!="undefined"&&typeof e.value!="string"&&(e={...e,value:String(e.value)});super(e);this.type="decl"}get variable(){return this.prop.startsWith("--")||this.prop[0]==="$"}};yc.exports=cn;cn.default=cn});var Et=x((E3,_c)=>{u();"use strict";var bc=Qr(),wc=Yr(),Ox=Gr(),{isClean:vc,my:xc}=ln(),ha,kc,Sc,ma;function Ac(r){return r.map(e=>(e.nodes&&(e.nodes=Ac(e.nodes)),delete e.source,e))}function Cc(r){if(r[vc]=!1,r.proxyOf.nodes)for(let e of r.proxyOf.nodes)Cc(e)}var Fe=class extends Ox{append(...e){for(let t of e){let i=this.normalize(t,this.last);for(let n of i)this.proxyOf.nodes.push(n)}return this.markDirty(),this}cleanRaws(e){if(super.cleanRaws(e),this.nodes)for(let t of this.nodes)t.cleanRaws(e)}each(e){if(!this.proxyOf.nodes)return;let t=this.getIterator(),i,n;for(;this.indexes[t]<this.proxyOf.nodes.length&&(i=this.indexes[t],n=e(this.proxyOf.nodes[i],i),n!==!1);)this.indexes[t]+=1;return delete this.indexes[t],n}every(e){return this.nodes.every(e)}getIterator(){this.lastEach||(this.lastEach=0),this.indexes||(this.indexes={}),this.lastEach+=1;let e=this.lastEach;return this.indexes[e]=0,e}getProxyProcessor(){return{get(e,t){return t==="proxyOf"?e:e[t]?t==="each"||typeof t=="string"&&t.startsWith("walk")?(...i)=>e[t](...i.map(n=>typeof n=="function"?(s,a)=>n(s.toProxy(),a):n)):t==="every"||t==="some"?i=>e[t]((n,...s)=>i(n.toProxy(),...s)):t==="root"?()=>e.root().toProxy():t==="nodes"?e.nodes.map(i=>i.toProxy()):t==="first"||t==="last"?e[t].toProxy():e[t]:e[t]},set(e,t,i){return e[t]===i||(e[t]=i,(t==="name"||t==="params"||t==="selector")&&e.markDirty()),!0}}}index(e){return typeof e=="number"?e:(e.proxyOf&&(e=e.proxyOf),this.proxyOf.nodes.indexOf(e))}insertAfter(e,t){let i=this.index(e),n=this.normalize(t,this.proxyOf.nodes[i]).reverse();i=this.index(e);for(let a of n)this.proxyOf.nodes.splice(i+1,0,a);let s;for(let a in this.indexes)s=this.indexes[a],i<s&&(this.indexes[a]=s+n.length);return this.markDirty(),this}insertBefore(e,t){let i=this.index(e),n=i===0?"prepend":!1,s=this.normalize(t,this.proxyOf.nodes[i],n).reverse();i=this.index(e);for(let o of s)this.proxyOf.nodes.splice(i,0,o);let a;for(let o in this.indexes)a=this.indexes[o],i<=a&&(this.indexes[o]=a+s.length);return this.markDirty(),this}normalize(e,t){if(typeof e=="string")e=Ac(kc(e).nodes);else if(typeof e=="undefined")e=[];else if(Array.isArray(e)){e=e.slice(0);for(let n of e)n.parent&&n.parent.removeChild(n,"ignore")}else if(e.type==="root"&&this.type!=="document"){e=e.nodes.slice(0);for(let n of e)n.parent&&n.parent.removeChild(n,"ignore")}else if(e.type)e=[e];else if(e.prop){if(typeof e.value=="undefined")throw new Error("Value fie
Line truncated
|
||||
`);i=new Array(s.length);let a=0;for(let o=0,l=s.length;o<l;o++)i[o]=a,a+=s[o].length+1;this[va]=i}t=i[i.length-1];let n=0;if(e>=t)n=i.length-1;else{let s=i.length-2,a;for(;n<s;)if(a=n+(s-n>>1),e<i[a])s=a-1;else if(e>=i[a+1])n=a+1;else{n=a;break}}return{col:e-i[n]+1,line:n+1}}mapResolve(e){return/^\w+:\/\//.test(e)?e:ba(this.map.consumer().sourceRoot||this.map.root||".",e)}origin(e,t,i,n){if(!this.map)return!1;let s=this.map.consumer(),a=s.originalPositionFor({column:t,line:e});if(!a.source)return!1;let o;typeof i=="number"&&(o=s.originalPositionFor({column:n,line:i}));let l;ya(a.source)?l=hn(a.source):l=new URL(a.source,this.map.consumer().sourceRoot||hn(this.map.mapFile));let c={column:a.column,endColumn:o&&o.column,endLine:o&&o.line,line:a.line,url:l.toString()};if(l.protocol==="file:")if(Lc)c.file=Lc(l);else throw new Error("file: protocol is not available in this PostCSS build");let f=s.sourceContentFor(a.source);return f&&(c.source=f),c}toJSON(){let e={};for(let t of["hasBOM","css","file","id"])this[t]!=null&&(e[t]=this[t]);return this.map&&(e.map={...this.map},e.map.consumerCache&&(e.map.consumerCache=void 0)),e}get from(){return this.file||this.id}};Bc.exports=Xr;Xr.default=Xr;wa&&wa.registerInput&&wa.registerInput(Xr)});var tr=x(($3,Uc)=>{u();"use strict";var Fc=Et(),jc,zc,Ut=class extends Fc{constructor(e){super(e);this.type="root",this.nodes||(this.nodes=[])}normalize(e,t,i){let n=super.normalize(e);if(t){if(i==="prepend")this.nodes.length>1?t.raws.before=this.nodes[1].raws.before:delete t.raws.before;else if(this.first!==t)for(let s of n)s.raws.before=t.raws.before}return n}removeChild(e,t){let i=this.index(e);return!t&&i===0&&this.nodes.length>1&&(this.nodes[1].raws.before=this.nodes[i].raws.before),super.removeChild(e)}toResult(e={}){return new jc(new zc,this,e).stringify()}};Ut.registerLazyResult=r=>{jc=r};Ut.registerProcessor=r=>{zc=r};Uc.exports=Ut;Ut.default=Ut;Fc.registerRoot(Ut)});var xa=x((L3,Vc)=>{u();"use strict";var Zr={comma(r){return Zr.split(r,[","],!0)},space(r){let e=[" ",`
|
||||
`," "];return Zr.split(r,e)},split(r,e,t){let i=[],n="",s=!1,a=0,o=!1,l="",c=!1;for(let f of r)c?c=!1:f==="\\"?c=!0:o?f===l&&(o=!1):f==='"'||f==="'"?(o=!0,l=f):f==="("?a+=1:f===")"?a>0&&(a-=1):a===0&&e.includes(f)&&(s=!0),s?(n!==""&&i.push(n.trim()),n="",s=!1):n+=f;return(t||n!=="")&&i.push(n.trim()),i}};Vc.exports=Zr;Zr.default=Zr});var gn=x((M3,Wc)=>{u();"use strict";var Hc=Et(),Nx=xa(),Jr=class extends Hc{constructor(e){super(e);this.type="rule",this.nodes||(this.nodes=[])}get selectors(){return Nx.comma(this.selector)}set selectors(e){let t=this.selector?this.selector.match(/,\s*/):null,i=t?t[0]:","+this.raw("between","beforeOpen");this.selector=e.join(i)}};Wc.exports=Jr;Jr.default=Jr;Hc.registerRule(Jr)});var Qc=x((N3,Gc)=>{u();"use strict";var Bx=pn(),Fx=Qr(),jx=Yr(),zx=mn(),Ux=ga(),Vx=tr(),Hx=gn();function ei(r,e){if(Array.isArray(r))return r.map(n=>ei(n));let{inputs:t,...i}=r;if(t){e=[];for(let n of t){let s={...n,__proto__:zx.prototype};s.map&&(s.map={...s.map,__proto__:Ux.prototype}),e.push(s)}}if(i.nodes&&(i.nodes=r.nodes.map(n=>ei(n,e))),i.source){let{inputId:n,...s}=i.source;i.source=s,n!=null&&(i.source.input=e[n])}if(i.type==="root")return new Vx(i);if(i.type==="decl")return new jx(i);if(i.type==="rule")return new Hx(i);if(i.type==="comment")return new Fx(i);if(i.type==="atrule")return new Bx(i);throw new Error("Unknown node type: "+r.type)}Gc.exports=ei;ei.default=ei});var ka=x((B3,Yc)=>{u();Yc.exports=function(r,e){return{generate:()=>{let t="";return r(e,i=>{t+=i}),[t]}}}});var ep=x((F3,Jc)=>{u();"use strict";var Sa="'".charCodeAt(0),Kc='"'.charCodeAt(0),yn="\\".charCodeAt(0),Xc="/".charCodeAt(0),bn=`
|
||||
`.charCodeAt(0),ti=" ".charCodeAt(0),wn="\f".charCodeAt(0),vn=" ".charCodeAt(0),xn="\r".charCodeAt(0),Wx="[".charCodeAt(0),Gx="]".charCodeAt(0),Qx="(".charCodeAt(0),Yx=")".charCodeAt(0),Kx="{".charCodeAt(0),Xx="}".charCodeAt(0),Zx=";".charCodeAt(0),Jx="*".charCodeAt(0),e1=":".charCodeAt(0),t1="@".charCodeAt(0),kn=/[\t\n\f\r "#'()/;[\\\]{}]/g,Sn=/[\t\n\f\r !"#'():;@[\\\]{}]|\/(?=\*)/g,r1=/.[\r\n"'(/\\]/,Zc=/[\da-f]/i;Jc.exports=function(e,t={}){let i=e.css.valueOf(),n=t.ignoreErrors,s,a,o,l,c,f,d,p,h,b,v=i.length,y=0,w=[],k=[];function S(){return y}function E(R){throw e.error("Unclosed "+R,y)}function T(){return k.length===0&&y>=v}function B(R){if(k.length)return k.pop();if(y>=v)return;let F=R?R.ignoreUnclosed:!1;switch(s=i.charCodeAt(y),s){case bn:case ti:case vn:case xn:case wn:{l=y;do l+=1,s=i.charCodeAt(l);while(s===ti||s===bn||s===vn||s===xn||s===wn);f=["space",i.slice(y,l)],y=l-1;break}case Wx:case Gx:case Kx:case Xx:case e1:case Zx:case Yx:{let Y=String.fromCharCode(s);f=[Y,Y,y];break}case Qx:{if(b=w.length?w.pop()[1]:"",h=i.charCodeAt(y+1),b==="url"&&h!==Sa&&h!==Kc&&h!==ti&&h!==bn&&h!==vn&&h!==wn&&h!==xn){l=y;do{if(d=!1,l=i.indexOf(")",l+1),l===-1)if(n||F){l=y;break}else E("bracket");for(p=l;i.charCodeAt(p-1)===yn;)p-=1,d=!d}while(d);f=["brackets",i.slice(y,l+1),y,l],y=l}else l=i.indexOf(")",y+1),a=i.slice(y,l+1),l===-1||r1.test(a)?f=["(","(",y]:(f=["brackets",a,y,l],y=l);break}case Sa:case Kc:{c=s===Sa?"'":'"',l=y;do{if(d=!1,l=i.indexOf(c,l+1),l===-1)if(n||F){l=y+1;break}else E("string");for(p=l;i.charCodeAt(p-1)===yn;)p-=1,d=!d}while(d);f=["string",i.slice(y,l+1),y,l],y=l;break}case t1:{kn.lastIndex=y+1,kn.test(i),kn.lastIndex===0?l=i.length-1:l=kn.lastIndex-2,f=["at-word",i.slice(y,l+1),y,l],y=l;break}case yn:{for(l=y,o=!0;i.charCodeAt(l+1)===yn;)l+=1,o=!o;if(s=i.charCodeAt(l+1),o&&s!==Xc&&s!==ti&&s!==bn&&s!==vn&&s!==xn&&s!==wn&&(l+=1,Zc.test(i.charAt(l)))){for(;Zc.test(i.charAt(l+1));)l+=1;i.charCodeAt(l+1)===ti&&(l+=1)}f=["word",i.slice(y,l+1),y,l],y=l;break}default:{s===Xc&&i.charCodeAt(y+1)===Jx?(l=i.indexOf("*/",y+2)+1,l===0&&(n||F?l=i.length:E("comment")),f=["comment",i.slice(y,l+1),y,l],y=l):(Sn.lastIndex=y+1,Sn.test(i),Sn.lastIndex===0?l=i.length-1:l=Sn.lastIndex-2,f=["word",i.slice(y,l+1),y,l],w.push(f),y=l);break}}return y++,f}function N(R){k.push(R)}return{back:N,endOfFile:T,nextToken:B,position:S}}});var sp=x((j3,np)=>{u();"use strict";var i1=pn(),n1=Qr(),s1=Yr(),a1=tr(),tp=gn(),o1=ep(),rp={empty:!0,space:!0};function l1(r){for(let e=r.length-1;e>=0;e--){let t=r[e],i=t[3]||t[2];if(i)return i}}var ip=class{constructor(e){this.input=e,this.root=new a1,this.current=this.root,this.spaces="",this.semicolon=!1,this.createTokenizer(),this.root.source={input:e,start:{column:1,line:1,offset:0}}}atrule(e){let t=new i1;t.name=e[1].slice(1),t.name===""&&this.unnamedAtrule(t,e),this.init(t,e[2]);let i,n,s,a=!1,o=!1,l=[],c=[];for(;!this.tokenizer.endOfFile();){if(e=this.tokenizer.nextToken(),i=e[0],i==="("||i==="["?c.push(i==="("?")":"]"):i==="{"&&c.length>0?c.push("}"):i===c[c.length-1]&&c.pop(),c.length===0)if(i===";"){t.source.end=this.getPosition(e[2]),t.source.end.offset++,this.semicolon=!0;break}else if(i==="{"){o=!0;break}else if(i==="}"){if(l.length>0){for(s=l.length-1,n=l[s];n&&n[0]==="space";)n=l[--s];n&&(t.source.end=this.getPosition(n[3]||n[2]),t.source.end.offset++)}this.end(e);break}else l.push(e);else l.push(e);if(this.tokenizer.endOfFile()){a=!0;break}}t.raws.between=this.spacesAndCommentsFromEnd(l),l.length?(t.raws.afterName=this.spacesAndCommentsFromStart(l),this.raw(t,"params",l),a&&(e=l[l.length-1],t.source.end=this.getPosition(e[3]||e[2]),t.source.end.offset++,this.spaces=t.raws.between,t.raws.between="")):(t.raws.afterName="",t.params=""),o&&(t.nodes=[],this.current=t)}checkMissedSemicolon(e){let t=this.colon(e);if(t===!1)return;let i=0,n;for(let s=t-1;s>=0&&(n=e[s],!(n[0]!=="space"&&(i+=1,i===2)));s--);throw this.input.error("Missed semicolon",n[0]==="word"?n[3]+1:n[2])}colon(e){let t=0,i,n,s;for(let[a,o]of e.entries()){if(n=o,s=n[0],s==="("&&(t+=1),s===")"&&(t-=1),t===0&&s===":")if(!i)this.doubleColon(n);else{if(i[0]==="word"&&i[1]==="progid")continue;return a}i=n}return!1}comment(e){let t=new n1;this.init(t,e[2]),t.source.end=this.getPosition(e[3]||e[2]),t.source.end.offset++;let i=e[1].slice(2,-2);if(/^\s*$/.test(i))t.text="",t.raws.left=i,t.raws.right="";else{let n=i.match(/^(\s*)([^]*\S)(\s*)$/);t.text=n[2],t.raws.left=n[1],t.raws.right=n[3]}}createTokenizer(){this.tokenizer=o1(this.input)}decl(e,t){let i=new s1;this.init(i,e[0][2]);let n=e[e.length-1];for(n[0]===";"&&(this.semicolon=!0,e.pop()),i.source.end=this.getPosition(n[3]||n[2]||l1(e)),i.source.end.offset++;e[0][0]!=="word";)e.length===1&&this.unknownWord(e),i.raws.before+=e.shift()[1];for(i.source.start=this.getPosition(e[0][2]),i.prop="";e.length;){let c=e[0][0];if(c===":"||c==="space"||c==="comment")break;i.prop+=e.shift()[1]}i.raws.between="";let s;for(;e.length;)if(s=e.shift(),s[0]===":"){i.raws.between+=s[1
Line truncated
|
||||
https://evilmartians.com/chronicles/postcss-8-plugin-migration`),m.env.LANG&&m.env.LANG.startsWith("cn")&&console.warn(e+`: \u91CC\u9762 postcss.plugin \u88AB\u5F03\u7528. \u8FC1\u79FB\u6307\u5357:
|
||||
https://www.w3ctech.com/topic/2226`));let o=t(...a);return o.postcssPlugin=e,o.postcssVersion=new Ta().version,o}let s;return Object.defineProperty(n,"postcss",{get(){return s||(s=n()),s}}),n.process=function(a,o,l){return J([n(l)]).process(a,o)},n};J.stringify=F1;J.parse=N1;J.fromJSON=D1;J.list=L1;J.comment=r=>new vp(r);J.atRule=r=>new wp(r);J.decl=r=>new xp(r);J.rule=r=>new Ap(r);J.root=r=>new Sp(r);J.document=r=>new kp(r);J.CssSyntaxError=I1;J.Declaration=xp;J.Container=P1;J.Processor=Ta;J.Document=kp;J.Comment=vp;J.Warning=j1;J.AtRule=wp;J.Result=B1;J.Input=q1;J.Rule=Ap;J.Root=Sp;J.Node=M1;$1.registerPostcss(J);Cp.exports=J;J.default=J});var re,ee,Z3,J3,eI,tI,rI,iI,nI,sI,aI,oI,lI,uI,fI,cI,pI,dI,hI,mI,gI,yI,bI,wI,vI,xI,Ot=P(()=>{u();re=pe($e()),ee=re.default,Z3=re.default.stringify,J3=re.default.fromJSON,eI=re.default.plugin,tI=re.default.parse,rI=re.default.list,iI=re.default.document,nI=re.default.comment,sI=re.default.atRule,aI=re.default.rule,oI=re.default.decl,lI=re.default.root,uI=re.default.CssSyntaxError,fI=re.default.Declaration,cI=re.default.Container,pI=re.default.Processor,dI=re.default.Document,hI=re.default.Comment,mI=re.default.Warning,gI=re.default.AtRule,yI=re.default.Result,bI=re.default.Input,wI=re.default.Rule,vI=re.default.Root,xI=re.default.Node});var Ra=x((SI,_p)=>{u();_p.exports=function(r,e,t,i,n){for(e=e.split?e.split("."):e,i=0;i<e.length;i++)r=r?r[e[i]]:n;return r===n?t:r}});var Pn=x((Rn,Ep)=>{u();"use strict";Rn.__esModule=!0;Rn.default=V1;function z1(r){for(var e=r.toLowerCase(),t="",i=!1,n=0;n<6&&e[n]!==void 0;n++){var s=e.charCodeAt(n),a=s>=97&&s<=102||s>=48&&s<=57;if(i=s===32,!a)break;t+=e[n]}if(t.length!==0){var o=parseInt(t,16),l=o>=55296&&o<=57343;return l||o===0||o>1114111?["\uFFFD",t.length+(i?1:0)]:[String.fromCodePoint(o),t.length+(i?1:0)]}}var U1=/\\/;function V1(r){var e=U1.test(r);if(!e)return r;for(var t="",i=0;i<r.length;i++){if(r[i]==="\\"){var n=z1(r.slice(i+1,i+7));if(n!==void 0){t+=n[0],i+=n[1];continue}if(r[i+1]==="\\"){t+="\\",i++;continue}r.length===i+1&&(t+=r[i]);continue}t+=r[i]}return t}Ep.exports=Rn.default});var Tp=x((In,Op)=>{u();"use strict";In.__esModule=!0;In.default=H1;function H1(r){for(var e=arguments.length,t=new Array(e>1?e-1:0),i=1;i<e;i++)t[i-1]=arguments[i];for(;t.length>0;){var n=t.shift();if(!r[n])return;r=r[n]}return r}Op.exports=In.default});var Pp=x((Dn,Rp)=>{u();"use strict";Dn.__esModule=!0;Dn.default=W1;function W1(r){for(var e=arguments.length,t=new Array(e>1?e-1:0),i=1;i<e;i++)t[i-1]=arguments[i];for(;t.length>0;){var n=t.shift();r[n]||(r[n]={}),r=r[n]}}Rp.exports=Dn.default});var Dp=x((qn,Ip)=>{u();"use strict";qn.__esModule=!0;qn.default=G1;function G1(r){for(var e="",t=r.indexOf("/*"),i=0;t>=0;){e=e+r.slice(i,t);var n=r.indexOf("*/",t+2);if(n<0)return e;i=n+2,t=r.indexOf("/*",i)}return e=e+r.slice(i),e}Ip.exports=qn.default});var ii=x(rt=>{u();"use strict";rt.__esModule=!0;rt.unesc=rt.stripComments=rt.getProp=rt.ensureObject=void 0;var Q1=$n(Pn());rt.unesc=Q1.default;var Y1=$n(Tp());rt.getProp=Y1.default;var K1=$n(Pp());rt.ensureObject=K1.default;var X1=$n(Dp());rt.stripComments=X1.default;function $n(r){return r&&r.__esModule?r:{default:r}}});var dt=x((ni,Lp)=>{u();"use strict";ni.__esModule=!0;ni.default=void 0;var qp=ii();function $p(r,e){for(var t=0;t<e.length;t++){var i=e[t];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(r,i.key,i)}}function Z1(r,e,t){return e&&$p(r.prototype,e),t&&$p(r,t),Object.defineProperty(r,"prototype",{writable:!1}),r}var J1=function r(e,t){if(typeof e!="object"||e===null)return e;var i=new e.constructor;for(var n in e)if(!!e.hasOwnProperty(n)){var s=e[n],a=typeof s;n==="parent"&&a==="object"?t&&(i[n]=t):s instanceof Array?i[n]=s.map(function(o){return r(o,i)}):i[n]=r(s,i)}return i},ek=function(){function r(t){t===void 0&&(t={}),Object.assign(this,t),this.spaces=this.spaces||{},this.spaces.before=this.spaces.before||"",this.spaces.after=this.spaces.after||""}var e=r.prototype;return e.remove=function(){return this.parent&&this.parent.removeChild(this),this.parent=void 0,this},e.replaceWith=function(){if(this.parent){for(var i in arguments)this.parent.insertBefore(this,arguments[i]);this.remove()}return this},e.next=function(){return this.parent.at(this.parent.index(this)+1)},e.prev=function(){return this.parent.at(this.parent.index(this)-1)},e.clone=function(i){i===void 0&&(i={});var n=J1(this);for(var s in i)n[s]=i[s];return n},e.appendToPropertyAndEscape=function(i,n,s){this.raws||(this.raws={});var a=this[i],o=this.raws[i];this[i]=a+n,o||s!==n?this.raws[i]=(o||a)+s:delete this.raws[i]},e.setPropertyAndEscape=function(i,n,s){this.raws||(this.raws={}),this[i]=n,this.raws[i]=s},e.setPropertyWithoutEscape=function(i,n){this[i]=n,this.raws&&delete this.raws[i]},e.isAtPosition=function(i,n){if(this.source&&this.source.start&&this.source.end)return!(this.source.start.line>i||this.source.end.line<i||this.source.start.line===i&&this.source.start.col
Line truncated
|
||||
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function yk(r,e){if(!!r){if(typeof r=="string")return Np(r,e);var t=Object.prototype.toString.call(r).slice(8,-1);if(t==="Object"&&r.constructor&&(t=r.constructor.name),t==="Map"||t==="Set")return Array.from(r);if(t==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return Np(r,e)}}function Np(r,e){(e==null||e>r.length)&&(e=r.length);for(var t=0,i=new Array(e);t<e;t++)i[t]=r[t];return i}function Bp(r,e){for(var t=0;t<e.length;t++){var i=e[t];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(r,i.key,i)}}function bk(r,e,t){return e&&Bp(r.prototype,e),t&&Bp(r,t),Object.defineProperty(r,"prototype",{writable:!1}),r}function wk(r,e){r.prototype=Object.create(e.prototype),r.prototype.constructor=r,Pa(r,e)}function Pa(r,e){return Pa=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(i,n){return i.__proto__=n,i},Pa(r,e)}var vk=function(r){wk(e,r);function e(i){var n;return n=r.call(this,i)||this,n.nodes||(n.nodes=[]),n}var t=e.prototype;return t.append=function(n){return n.parent=this,this.nodes.push(n),this},t.prepend=function(n){return n.parent=this,this.nodes.unshift(n),this},t.at=function(n){return this.nodes[n]},t.index=function(n){return typeof n=="number"?n:this.nodes.indexOf(n)},t.removeChild=function(n){n=this.index(n),this.at(n).parent=void 0,this.nodes.splice(n,1);var s;for(var a in this.indexes)s=this.indexes[a],s>=n&&(this.indexes[a]=s-1);return this},t.removeAll=function(){for(var n=gk(this.nodes),s;!(s=n()).done;){var a=s.value;a.parent=void 0}return this.nodes=[],this},t.empty=function(){return this.removeAll()},t.insertAfter=function(n,s){s.parent=this;var a=this.index(n);this.nodes.splice(a+1,0,s),s.parent=this;var o;for(var l in this.indexes)o=this.indexes[l],a<=o&&(this.indexes[l]=o+1);return this},t.insertBefore=function(n,s){s.parent=this;var a=this.index(n);this.nodes.splice(a,0,s),s.parent=this;var o;for(var l in this.indexes)o=this.indexes[l],o<=a&&(this.indexes[l]=o+1);return this},t._findChildAtPosition=function(n,s){var a=void 0;return this.each(function(o){if(o.atPosition){var l=o.atPosition(n,s);if(l)return a=l,!1}else if(o.isAtPosition(n,s))return a=o,!1}),a},t.atPosition=function(n,s){if(this.isAtPosition(n,s))return this._findChildAtPosition(n,s)||this},t._inferEndPosition=function(){this.last&&this.last.source&&this.last.source.end&&(this.source=this.source||{},this.source.end=this.source.end||{},Object.assign(this.source.end,this.last.source.end))},t.each=function(n){this.lastEach||(this.lastEach=0),this.indexes||(this.indexes={}),this.lastEach++;var s=this.lastEach;if(this.indexes[s]=0,!!this.length){for(var a,o;this.indexes[s]<this.length&&(a=this.indexes[s],o=n(this.at(a),a),o!==!1);)this.indexes[s]+=1;if(delete this.indexes[s],o===!1)return!1}},t.walk=function(n){return this.each(function(s,a){var o=n(s,a);if(o!==!1&&s.length&&(o=s.walk(n)),o===!1)return!1})},t.walkAttributes=function(n){var s=this;return this.walk(function(a){if(a.type===ht.ATTRIBUTE)return n.call(s,a)})},t.walkClasses=function(n){var s=this;return this.walk(function(a){if(a.type===ht.CLASS)return n.call(s,a)})},t.walkCombinators=function(n){var s=this;return this.walk(function(a){if(a.type===ht.COMBINATOR)return n.call(s,a)})},t.walkComments=function(n){var s=this;return this.walk(function(a){if(a.type===ht.COMMENT)return n.call(s,a)})},t.walkIds=function(n){var s=this;return this.walk(function(a){if(a.type===ht.ID)return n.call(s,a)})},t.walkNesting=function(n){var s=this;return this.walk(function(a){if(a.type===ht.NESTING)return n.call(s,a)})},t.walkPseudos=function(n){var s=this;return this.walk(function(a){if(a.type===ht.PSEUDO)return n.call(s,a)})},t.walkTags=function(n){var s=this;return this.walk(function(a){if(a.type===ht.TAG)return n.call(s,a)})},t.walkUniversals=function(n){var s=this;return this.walk(function(a){if(a.type===ht.UNIVERSAL)return n.call(s,a)})},t.split=function(n){var s=this,a=[];return this.reduce(function(o,l,c){var f=n.call(s,l);return a.push(l),f?(o.push(a),a=[]):c===s.length-1&&o.push(a),o},[])},t.map=function(n){return this.nodes.map(n)},t.reduce=function(n,s){return this.nodes.reduce(n,s)},t.every=function(n){return this.nodes.every(n)},t.some=function(n){return this.nodes.some(n)},t.filter=function(n){return this.nodes.filter(n)},t.sort=function(n){return this.nodes.sort(n)},t.toString=function(){return this.map(String).join("")},bk(e,[{key:"first",get:function(){return this.at(0)}},{key:"last",get:function(){return this.at(this.length-1)}},{key:"length",get:function(){return this.nodes.length}}]),e}(dk.default);si.default=vk;Fp.exports=si.default});var Da=x((ai,zp)=>{u();"use strict";ai.__esModule=!0;ai.default=void 0;var xk=Sk(Ln()),kk=Se();function Sk(r){return r&&r.__esModule?r:{default:r}}function jp(r,e){for(var t=0;t<e.length;t++){var i=e[t];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable
Line truncated
|
||||
`),v=y.length-1,v>0?(k=a+v,S=w-y[v].length):(k=a,S=s),T=D.comment,a=k,p=k,d=w-S):c===D.slash?(w=o,T=c,p=a,d=o-s,l=w+1):(w=OA(t,o),T=D.word,p=a,d=w-s),l=w+1;break}e.push([T,a,o-s,p,d,o,l]),S&&(s=S,S=null),o=l}return e}});var kd=x((ki,xd)=>{u();"use strict";ki.__esModule=!0;ki.default=void 0;var IA=je(Da()),fo=je($a()),DA=je(Na()),md=je(Fa()),qA=je(za()),$A=je(Ha()),co=je(Ga()),LA=je(Ya()),gd=Vn(to()),MA=je(io()),po=je(so()),NA=je(oo()),BA=je(fd()),O=Vn(hd()),q=Vn(lo()),FA=Vn(Se()),ue=ii(),Vt,ho;function yd(r){if(typeof WeakMap!="function")return null;var e=new WeakMap,t=new WeakMap;return(yd=function(n){return n?t:e})(r)}function Vn(r,e){if(!e&&r&&r.__esModule)return r;if(r===null||typeof r!="object"&&typeof r!="function")return{default:r};var t=yd(e);if(t&&t.has(r))return t.get(r);var i={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var s in r)if(s!=="default"&&Object.prototype.hasOwnProperty.call(r,s)){var a=n?Object.getOwnPropertyDescriptor(r,s):null;a&&(a.get||a.set)?Object.defineProperty(i,s,a):i[s]=r[s]}return i.default=r,t&&t.set(r,i),i}function je(r){return r&&r.__esModule?r:{default:r}}function bd(r,e){for(var t=0;t<e.length;t++){var i=e[t];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(r,i.key,i)}}function jA(r,e,t){return e&&bd(r.prototype,e),t&&bd(r,t),Object.defineProperty(r,"prototype",{writable:!1}),r}var mo=(Vt={},Vt[q.space]=!0,Vt[q.cr]=!0,Vt[q.feed]=!0,Vt[q.newline]=!0,Vt[q.tab]=!0,Vt),zA=Object.assign({},mo,(ho={},ho[q.comment]=!0,ho));function wd(r){return{line:r[O.FIELDS.START_LINE],column:r[O.FIELDS.START_COL]}}function vd(r){return{line:r[O.FIELDS.END_LINE],column:r[O.FIELDS.END_COL]}}function Ht(r,e,t,i){return{start:{line:r,column:e},end:{line:t,column:i}}}function sr(r){return Ht(r[O.FIELDS.START_LINE],r[O.FIELDS.START_COL],r[O.FIELDS.END_LINE],r[O.FIELDS.END_COL])}function go(r,e){if(!!r)return Ht(r[O.FIELDS.START_LINE],r[O.FIELDS.START_COL],e[O.FIELDS.END_LINE],e[O.FIELDS.END_COL])}function ar(r,e){var t=r[e];if(typeof t=="string")return t.indexOf("\\")!==-1&&((0,ue.ensureObject)(r,"raws"),r[e]=(0,ue.unesc)(t),r.raws[e]===void 0&&(r.raws[e]=t)),r}function yo(r,e){for(var t=-1,i=[];(t=r.indexOf(e,t+1))!==-1;)i.push(t);return i}function UA(){var r=Array.prototype.concat.apply([],arguments);return r.filter(function(e,t){return t===r.indexOf(e)})}var VA=function(){function r(t,i){i===void 0&&(i={}),this.rule=t,this.options=Object.assign({lossy:!1,safe:!1},i),this.position=0,this.css=typeof this.rule=="string"?this.rule:this.rule.selector,this.tokens=(0,O.default)({css:this.css,error:this._errorGenerator(),safe:this.options.safe});var n=go(this.tokens[0],this.tokens[this.tokens.length-1]);this.root=new IA.default({source:n}),this.root.errorGenerator=this._errorGenerator();var s=new fo.default({source:{start:{line:1,column:1}},sourceIndex:0});this.root.append(s),this.current=s,this.loop()}var e=r.prototype;return e._errorGenerator=function(){var i=this;return function(n,s){return typeof i.rule=="string"?new Error(n):i.rule.error(n,s)}},e.attribute=function(){var i=[],n=this.currToken;for(this.position++;this.position<this.tokens.length&&this.currToken[O.FIELDS.TYPE]!==q.closeSquare;)i.push(this.currToken),this.position++;if(this.currToken[O.FIELDS.TYPE]!==q.closeSquare)return this.expected("closing square bracket",this.currToken[O.FIELDS.START_POS]);var s=i.length,a={source:Ht(n[1],n[2],this.currToken[3],this.currToken[4]),sourceIndex:n[O.FIELDS.START_POS]};if(s===1&&!~[q.word].indexOf(i[0][O.FIELDS.TYPE]))return this.expected("attribute",i[0][O.FIELDS.START_POS]);for(var o=0,l="",c="",f=null,d=!1;o<s;){var p=i[o],h=this.content(p),b=i[o+1];switch(p[O.FIELDS.TYPE]){case q.space:if(d=!0,this.options.lossy)break;if(f){(0,ue.ensureObject)(a,"spaces",f);var v=a.spaces[f].after||"";a.spaces[f].after=v+h;var y=(0,ue.getProp)(a,"raws","spaces",f,"after")||null;y&&(a.raws.spaces[f].after=y+h)}else l=l+h,c=c+h;break;case q.asterisk:if(b[O.FIELDS.TYPE]===q.equals)a.operator=h,f="operator";else if((!a.namespace||f==="namespace"&&!d)&&b){l&&((0,ue.ensureObject)(a,"spaces","attribute"),a.spaces.attribute.before=l,l=""),c&&((0,ue.ensureObject)(a,"raws","spaces","attribute"),a.raws.spaces.attribute.before=l,c=""),a.namespace=(a.namespace||"")+h;var w=(0,ue.getProp)(a,"raws","namespace")||null;w&&(a.raws.namespace+=h),f="namespace"}d=!1;break;case q.dollar:if(f==="value"){var k=(0,ue.getProp)(a,"raws","value");a.value+="$",k&&(a.raws.value=k+"$");break}case q.caret:b[O.FIELDS.TYPE]===q.equals&&(a.operator=h,f="operator"),d=!1;break;case q.combinator:if(h==="~"&&b[O.FIELDS.TYPE]===q.equals&&(a.operator=h,f="operator"),h!=="|"){d=!1;break}b[O.FIELDS.TYPE]===q.equals?(a.operator=h,f="operator"):!a.namespace&&!a.attribute&&(a.namespace=!0),d=!1;break;case q.word:if(b&&this.content(b)==="|"&&i[o+2]&&i[o+2][O.FIELDS.TYPE]!==q.equals&&!a.operator&&!a.namespace)a.namespace=h,f="namespace";else if(!a.attribute||f==="attribute"&&!d){l&&((0,ue.
Line truncated
|
||||
`).slice(1,-1).map(N=>N.trim()).map(N=>` ${N}`).join(`
|
||||
`)).join(`
|
||||
|
||||
`);w.push(` Use \`${r.replace("[",`[${E}:`)}\` for \`${T.trim()}\``);break}G.warn([`The class \`${r}\` is ambiguous and matches multiple utilities.`,...w,`If this is content and not a class, replace it with \`${r.replace("[","[").replace("]","]")}\` to silence this warning.`]);continue}}o=o.map(p=>p.filter(h=>Eh(h[1])))}o=o.flat(),o=Array.from(P_(o,i)),o=k_(o,e),s&&(o=S_(o,i));for(let p of n)o=A_(p,o,e);for(let p of o)p[1].raws.tailwind={...p[1].raws.tailwind,candidate:r},p=I_(p,{context:e,candidate:r}),p!==null&&(yield p)}}function I_(r,{context:e,candidate:t}){if(!r[0].collectedFormats)return r;let i=!0,n;try{n=dr(r[0].collectedFormats,{context:e,candidate:t})}catch{return null}let s=ee.root({nodes:[r[1].clone()]});return s.walkRules(a=>{if(!ss(a))try{let o=rs(a.selector,n,{candidate:t,context:e});if(o===null){a.remove();return}a.selector=o}catch{return i=!1,!1}}),!i||s.nodes.length===0?null:(r[1]=s.nodes[0],r)}function ss(r){return r.parent&&r.parent.type==="atrule"&&r.parent.name==="keyframes"}function D_(r){if(r===!0)return e=>{ss(e)||e.walkDecls(t=>{t.parent.type==="rule"&&!ss(t.parent)&&(t.important=!0)})};if(typeof r=="string")return e=>{ss(e)||(e.selectors=e.selectors.map(t=>is(t,r)))}}function as(r,e,t=!1){let i=[],n=D_(e.tailwindConfig.important);for(let s of r){if(e.notClassCache.has(s))continue;if(e.candidateRuleCache.has(s)){i=i.concat(Array.from(e.candidateRuleCache.get(s)));continue}let a=Array.from(Yo(s,e));if(a.length===0){e.notClassCache.add(s);continue}e.classCache.set(s,a);let o=e.candidateRuleCache.get(s)??new Set;e.candidateRuleCache.set(s,o);for(let l of a){let[{sort:c,options:f},d]=l;if(f.respectImportant&&n){let h=ee.root({nodes:[d.clone()]});h.walkRules(n),d=h.nodes[0]}let p=[c,t?d.clone():d];o.add(p),e.ruleCache.add(p),i.push(p)}}return i}function Ko(r){return r.startsWith("[")&&r.endsWith("]")}var ns,v_,C_,os=P(()=>{u();Ot();ns=pe(it());qo();Kt();Gn();Fr();Be();It();Vo();Lo();Br();Oi();Bo();zt();ct();Wo();v_=(0,ns.default)(r=>r.first.filter(({type:e})=>e==="class").pop().value);C_=/^[a-z_-]/});var Th,Rh=P(()=>{u();Th={}});function q_(r){try{return Th.createHash("md5").update(r,"utf-8").digest("binary")}catch(e){return""}}function Ph(r,e){let t=e.toString();if(!t.includes("@tailwind"))return!1;let i=No.get(r),n=q_(t),s=i!==n;return No.set(r,n),s}var Ih=P(()=>{u();Rh();It()});function us(r){return(r>0n)-(r<0n)}var Dh=P(()=>{u()});function qh(r,e){let t=0n,i=0n;for(let[n,s]of e)r&n&&(t=t|n,i=i|s);return r&~t|i}var $h=P(()=>{u()});function Lh(r){let e=null;for(let t of r)e=e??t,e=e>t?e:t;return e}function $_(r,e){let t=r.length,i=e.length,n=t<i?t:i;for(let s=0;s<n;s++){let a=r.charCodeAt(s)-e.charCodeAt(s);if(a!==0)return a}return t-i}var Xo,Mh=P(()=>{u();Dh();$h();Xo=class{constructor(){this.offsets={defaults:0n,base:0n,components:0n,utilities:0n,variants:0n,user:0n},this.layerPositions={defaults:0n,base:1n,components:2n,utilities:3n,user:4n,variants:5n},this.reservedVariantBits=0n,this.variantOffsets=new Map}create(e){return{layer:e,parentLayer:e,arbitrary:0n,variants:0n,parallelIndex:0n,index:this.offsets[e]++,propertyOffset:0n,property:"",options:[]}}arbitraryProperty(e){return{...this.create("utilities"),arbitrary:1n,property:e}}forVariant(e,t=0){let i=this.variantOffsets.get(e);if(i===void 0)throw new Error(`Cannot find offset for unknown variant ${e}`);return{...this.create("variants"),variants:i<<BigInt(t)}}applyVariantOffset(e,t,i){return i.variant=t.variants,{...e,layer:"variants",parentLayer:e.layer==="variants"?e.parentLayer:e.layer,variants:e.variants|t.variants,options:i.sort?[].concat(i,e.options):e.options,parallelIndex:Lh([e.parallelIndex,t.parallelIndex])}}applyParallelOffset(e,t){return{...e,parallelIndex:BigInt(t)}}recordVariants(e,t){for(let i of e)this.recordVariant(i,t(i))}recordVariant(e,t=1){return this.variantOffsets.set(e,1n<<this.reservedVariantBits),this.reservedVariantBits+=BigInt(t),{...this.create("variants"),variants:this.variantOffsets.get(e)}}compare(e,t){if(e.layer!==t.layer)return this.layerPositions[e.layer]-this.layerPositions[t.layer];if(e.parentLayer!==t.parentLayer)return this.layerPositions[e.parentLayer]-this.layerPositions[t.parentLayer];for(let i of e.options)for(let n of t.options){if(i.id!==n.id||!i.sort||!n.sort)continue;let s=Lh([i.variant,n.variant])??0n,a=~(s|s-1n),o=e.variants&a,l=t.variants&a;if(o!==l)continue;let c=i.sort({value:i.value,modifier:i.modifier},{value:n.value,modifier:n.modifier});if(c!==0)return c}return e.variants!==t.variants?e.variants-t.variants:e.parallelIndex!==t.parallelIndex?e.parallelIndex-t.parallelIndex:e.arbitrary!==t.arbitrary?e.arbitrary-t.arbitrary:e.propertyOffset!==t.propertyOffset?e.propertyOffset-t.propertyOffset:e.index-t.index}recalculateVariantOffsets(){let e=Array.from(this.variantOffsets.entries()).filter(([n])=>n.startsWith("[")).sort(([n],[s])=>$_(n,s)),t=e.map(([,n])=>n).sort((n,s)=>us(n-s));return e.map(([,n],s)=>[n,t[s]]).filter(([n,s])=>n!==s)}remapArbitraryVariantOffsets(eLine truncated
|
||||
`,CHAR_NO_BREAK_SPACE:"\xA0",CHAR_PERCENT:"%",CHAR_PLUS:"+",CHAR_QUESTION_MARK:"?",CHAR_RIGHT_ANGLE_BRACKET:">",CHAR_RIGHT_CURLY_BRACE:"}",CHAR_RIGHT_SQUARE_BRACKET:"]",CHAR_SEMICOLON:";",CHAR_SINGLE_QUOTE:"'",CHAR_SPACE:" ",CHAR_TAB:" ",CHAR_UNDERSCORE:"_",CHAR_VERTICAL_LINE:"|",CHAR_ZERO_WIDTH_NOBREAK_SPACE:"\uFEFF"}});var Nm=x((s6,Mm)=>{u();"use strict";var mE=hs(),{MAX_LENGTH:qm,CHAR_BACKSLASH:dl,CHAR_BACKTICK:gE,CHAR_COMMA:yE,CHAR_DOT:bE,CHAR_LEFT_PARENTHESES:wE,CHAR_RIGHT_PARENTHESES:vE,CHAR_LEFT_CURLY_BRACE:xE,CHAR_RIGHT_CURLY_BRACE:kE,CHAR_LEFT_SQUARE_BRACKET:$m,CHAR_RIGHT_SQUARE_BRACKET:Lm,CHAR_DOUBLE_QUOTE:SE,CHAR_SINGLE_QUOTE:AE,CHAR_NO_BREAK_SPACE:CE,CHAR_ZERO_WIDTH_NOBREAK_SPACE:_E}=Dm(),EE=(r,e={})=>{if(typeof r!="string")throw new TypeError("Expected a string");let t=e||{},i=typeof t.maxLength=="number"?Math.min(qm,t.maxLength):qm;if(r.length>i)throw new SyntaxError(`Input length (${r.length}), exceeds max characters (${i})`);let n={type:"root",input:r,nodes:[]},s=[n],a=n,o=n,l=0,c=r.length,f=0,d=0,p,h=()=>r[f++],b=v=>{if(v.type==="text"&&o.type==="dot"&&(o.type="text"),o&&o.type==="text"&&v.type==="text"){o.value+=v.value;return}return a.nodes.push(v),v.parent=a,v.prev=o,o=v,v};for(b({type:"bos"});f<c;)if(a=s[s.length-1],p=h(),!(p===_E||p===CE)){if(p===dl){b({type:"text",value:(e.keepEscaping?p:"")+h()});continue}if(p===Lm){b({type:"text",value:"\\"+p});continue}if(p===$m){l++;let v;for(;f<c&&(v=h());){if(p+=v,v===$m){l++;continue}if(v===dl){p+=h();continue}if(v===Lm&&(l--,l===0))break}b({type:"text",value:p});continue}if(p===wE){a=b({type:"paren",nodes:[]}),s.push(a),b({type:"text",value:p});continue}if(p===vE){if(a.type!=="paren"){b({type:"text",value:p});continue}a=s.pop(),b({type:"text",value:p}),a=s[s.length-1];continue}if(p===SE||p===AE||p===gE){let v=p,y;for(e.keepQuotes!==!0&&(p="");f<c&&(y=h());){if(y===dl){p+=y+h();continue}if(y===v){e.keepQuotes===!0&&(p+=y);break}p+=y}b({type:"text",value:p});continue}if(p===xE){d++;let v=o.value&&o.value.slice(-1)==="$"||a.dollar===!0;a=b({type:"brace",open:!0,close:!1,dollar:v,depth:d,commas:0,ranges:0,nodes:[]}),s.push(a),b({type:"open",value:p});continue}if(p===kE){if(a.type!=="brace"){b({type:"text",value:p});continue}let v="close";a=s.pop(),a.close=!0,b({type:v,value:p}),d--,a=s[s.length-1];continue}if(p===yE&&d>0){if(a.ranges>0){a.ranges=0;let v=a.nodes.shift();a.nodes=[v,{type:"text",value:mE(a)}]}b({type:"comma",value:p}),a.commas++;continue}if(p===bE&&d>0&&a.commas===0){let v=a.nodes;if(d===0||v.length===0){b({type:"text",value:p});continue}if(o.type==="dot"){if(a.range=[],o.value+=p,o.type="range",a.nodes.length!==3&&a.nodes.length!==5){a.invalid=!0,a.ranges=0,o.type="text";continue}a.ranges++,a.args=[];continue}if(o.type==="range"){v.pop();let y=v[v.length-1];y.value+=o.value+p,o=y,a.ranges--;continue}b({type:"dot",value:p});continue}b({type:"text",value:p})}do if(a=s.pop(),a.type!=="root"){a.nodes.forEach(w=>{w.nodes||(w.type==="open"&&(w.isOpen=!0),w.type==="close"&&(w.isClose=!0),w.nodes||(w.type="text"),w.invalid=!0)});let v=s[s.length-1],y=v.nodes.indexOf(a);v.nodes.splice(y,1,...a.nodes)}while(s.length>0);return b({type:"eos"}),n};Mm.exports=EE});var jm=x((a6,Fm)=>{u();"use strict";var Bm=hs(),OE=Om(),TE=Pm(),RE=Nm(),Le=(r,e={})=>{let t=[];if(Array.isArray(r))for(let i of r){let n=Le.create(i,e);Array.isArray(n)?t.push(...n):t.push(n)}else t=[].concat(Le.create(r,e));return e&&e.expand===!0&&e.nodupes===!0&&(t=[...new Set(t)]),t};Le.parse=(r,e={})=>RE(r,e);Le.stringify=(r,e={})=>typeof r=="string"?Bm(Le.parse(r,e),e):Bm(r,e);Le.compile=(r,e={})=>(typeof r=="string"&&(r=Le.parse(r,e)),OE(r,e));Le.expand=(r,e={})=>{typeof r=="string"&&(r=Le.parse(r,e));let t=TE(r,e);return e.noempty===!0&&(t=t.filter(Boolean)),e.nodupes===!0&&(t=[...new Set(t)]),t};Le.create=(r,e={})=>r===""||r.length<3?[r]:e.expand!==!0?Le.compile(r,e):Le.expand(r,e);Fm.exports=Le});var Di=x((o6,Wm)=>{u();"use strict";var PE=(et(),Ur),at="\\\\/",zm=`[^${at}]`,yt="\\.",IE="\\+",DE="\\?",ys="\\/",qE="(?=.)",Um="[^/]",hl=`(?:${ys}|$)`,Vm=`(?:^|${ys})`,ml=`${yt}{1,2}${hl}`,$E=`(?!${yt})`,LE=`(?!${Vm}${ml})`,ME=`(?!${yt}{0,1}${hl})`,NE=`(?!${ml})`,BE=`[^.${ys}]`,FE=`${Um}*?`,Hm={DOT_LITERAL:yt,PLUS_LITERAL:IE,QMARK_LITERAL:DE,SLASH_LITERAL:ys,ONE_CHAR:qE,QMARK:Um,END_ANCHOR:hl,DOTS_SLASH:ml,NO_DOT:$E,NO_DOTS:LE,NO_DOT_SLASH:ME,NO_DOTS_SLASH:NE,QMARK_NO_DOT:BE,STAR:FE,START_ANCHOR:Vm},jE={...Hm,SLASH_LITERAL:`[${at}]`,QMARK:zm,STAR:`${zm}*?`,DOTS_SLASH:`${yt}{1,2}(?:[${at}]|$)`,NO_DOT:`(?!${yt})`,NO_DOTS:`(?!(?:^|[${at}])${yt}{1,2}(?:[${at}]|$))`,NO_DOT_SLASH:`(?!${yt}{0,1}(?:[${at}]|$))`,NO_DOTS_SLASH:`(?!${yt}{1,2}(?:[${at}]|$))`,QMARK_NO_DOT:`[^.${at}]`,START_ANCHOR:`(?:^|[${at}])`,END_ANCHOR:`(?:[${at}]|$)`},zE={alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_Line truncated
|
||||
`))if(n=n.trim(),!i.has(n))if(i.add(n),Li.get(e).has(n))for(let s of Li.get(e).get(n))t.add(s);else{let s=e(n).filter(o=>o!=="!*"),a=new Set(s);for(let o of a)t.add(o);Li.get(e).set(n,a)}}function T2(r,e){let t=e.offsets.sort(r),i={base:new Set,defaults:new Set,components:new Set,utilities:new Set,variants:new Set};for(let[n,s]of t)i[n.layer].add(s);return i}function Pl(r){return async e=>{let t={base:null,components:null,utilities:null,variants:null};if(e.walkAtRules(y=>{y.name==="tailwind"&&Object.keys(t).includes(y.params)&&(t[y.params]=y)}),Object.values(t).every(y=>y===null))return e;let i=new Set([...r.candidates??[],gt]),n=new Set;bt.DEBUG&&console.time("Reading changed files");let s=[];for(let y of r.changedContent){let w=E2(r.tailwindConfig,y.extension),k=_2(r,y.extension);s.push([y,{transformer:w,extractor:k}])}let a=500;for(let y=0;y<s.length;y+=a){let w=s.slice(y,y+a);await Promise.all(w.map(async([{file:k,content:S},{transformer:E,extractor:T}])=>{S=k?await be.promises.readFile(k,"utf8"):S,O2(E(S),T,i,n)}))}bt.DEBUG&&console.timeEnd("Reading changed files");let o=r.classCache.size;bt.DEBUG&&console.time("Generate rules"),bt.DEBUG&&console.time("Sorting candidates");let l=new Set([...i].sort((y,w)=>y===w?0:y<w?-1:1));bt.DEBUG&&console.timeEnd("Sorting candidates"),as(l,r),bt.DEBUG&&console.timeEnd("Generate rules"),bt.DEBUG&&console.time("Build stylesheet"),(r.stylesheetCache===null||r.classCache.size!==o)&&(r.stylesheetCache=T2([...r.ruleCache],r)),bt.DEBUG&&console.timeEnd("Build stylesheet");let{defaults:c,base:f,components:d,utilities:p,variants:h}=r.stylesheetCache;t.base&&(t.base.before(Qt([...c,...f],t.base.source,{layer:"base"})),t.base.remove()),t.components&&(t.components.before(Qt([...d],t.components.source,{layer:"components"})),t.components.remove()),t.utilities&&(t.utilities.before(Qt([...p],t.utilities.source,{layer:"utilities"})),t.utilities.remove());let b=Array.from(h).filter(y=>{let w=y.raws.tailwind?.parentLayer;return w==="components"?t.components!==null:w==="utilities"?t.utilities!==null:!0});t.variants?(t.variants.before(Qt(b,t.variants.source,{layer:"variants"})),t.variants.remove()):b.length>0&&e.append(Qt(b,e.source,{layer:"variants"})),e.source.end=e.source.end??e.source.start;let v=b.some(y=>y.raws.tailwind?.parentLayer==="utilities");t.utilities&&p.size===0&&!v&&G.warn("content-problems",["No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.","https://tailwindcss.com/docs/content-configuration"]),bt.DEBUG&&(console.log("Potential classes: ",i.size),console.log("Active contexts: ",es.size)),r.changedContent=[],e.walkAtRules("layer",y=>{Object.keys(t).includes(y.params)&&y.remove()})}}var Lg,bt,Mg,Ng,Li,Bg=P(()=>{u();ft();Lg=pe(Fs());It();os();Be();Rg();$g();bt=Ze,Mg={DEFAULT:qg},Ng={DEFAULT:r=>r,svelte:r=>r.replace(/(?:^|\s)class:/g," ")};Li=new WeakMap});function xs(r){let e=new Map;ee.root({nodes:[r.clone()]}).walkRules(s=>{(0,vs.default)(a=>{a.walkClasses(o=>{let l=o.parent.toString(),c=e.get(l);c||e.set(l,c=new Set),c.add(o.value)})}).processSync(s.selector)});let i=Array.from(e.values(),s=>Array.from(s)),n=i.flat();return Object.assign(n,{groups:i})}function Il(r){return R2.astSync(r)}function Fg(r,e){let t=new Set;for(let i of r)t.add(i.split(e).pop());return Array.from(t)}function jg(r,e){let t=r.tailwindConfig.prefix;return typeof t=="function"?t(e):t+e}function*zg(r){for(yield r;r.parent;)yield r.parent,r=r.parent}function P2(r,e={}){let t=r.nodes;r.nodes=[];let i=r.clone(e);return r.nodes=t,i}function I2(r){for(let e of zg(r))if(r!==e){if(e.type==="root")break;r=P2(e,{nodes:[r]})}return r}function D2(r,e){let t=new Map;return r.walkRules(i=>{for(let a of zg(i))if(a.raws.tailwind?.layer!==void 0)return;let n=I2(i),s=e.offsets.create("user");for(let a of xs(i)){let o=t.get(a)||[];t.set(a,o),o.push([{layer:"user",sort:s,important:!1},n])}}),t}function q2(r,e){for(let t of r){if(e.notClassCache.has(t)||e.applyClassCache.has(t))continue;if(e.classCache.has(t)){e.applyClassCache.set(t,e.classCache.get(t).map(([n,s])=>[n,s.clone()]));continue}let i=Array.from(Yo(t,e));if(i.length===0){e.notClassCache.add(t);continue}e.applyClassCache.set(t,i)}return e.applyClassCache}function $2(r){let e=null;return{get:t=>(e=e||r(),e.get(t)),has:t=>(e=e||r(),e.has(t))}}function L2(r){return{get:e=>r.flatMap(t=>t.get(e)||[]),has:e=>r.some(t=>t.has(e))}}function Ug(r){let e=r.split(/[\s\t\n]+/g);return e[e.length-1]==="!important"?[e.slice(0,-1),!0]:[e,!1]}function Vg(r,e,t){let i=new Set,n=[];if(r.walkAtRules("apply",l=>{let[c]=Ug(l.params);for(let f of c)i.add(f);n.push(l)}),n.length===0)return;let s=L2([t,q2(i,e)]);function a(l,c,f){let d=Il(l),p=Il(c),b=Il(`.${Te(f)}`).nodes[0].nodes[0];return d.each(v=>{let y=new Set;p.each(w=>{let k=!1;w=w.clone(),w.walkClasses(S=>{S.value===b.value&&(k||(S.replaceWith(...v.nodes.map(E=>E.clone())),y.add(w),k=!0))})});for(let w of y){let k=[[]];for(
Line truncated
|
||||
`))});c.push([p,d,h])}}for(let[l,[c,f]]of o){let d=[];for(let[h,b,v]of c){let y=[h,...Fg([h],e.tailwindConfig.separator)];for(let[w,k]of v){let S=xs(l),E=xs(k);if(E=E.groups.filter(R=>R.some(F=>y.includes(F))).flat(),E=E.concat(Fg(E,e.tailwindConfig.separator)),S.some(R=>E.includes(R)))throw k.error(`You cannot \`@apply\` the \`${h}\` utility here because it creates a circular dependency.`);let B=ee.root({nodes:[k.clone()]});B.walk(R=>{R.source=f}),(k.type!=="atrule"||k.type==="atrule"&&k.name!=="keyframes")&&B.walkRules(R=>{if(!xs(R).some(U=>U===h)){R.remove();return}let F=typeof e.tailwindConfig.important=="string"?e.tailwindConfig.important:null,_=l.raws.tailwind!==void 0&&F&&l.selector.indexOf(F)===0?l.selector.slice(F.length):l.selector;_===""&&(_=l.selector),R.selector=a(_,R.selector,h),F&&_!==l.selector&&(R.selector=is(R.selector,F)),R.walkDecls(U=>{U.important=w.important||b});let Q=(0,vs.default)().astSync(R.selector);Q.each(U=>pr(U)),R.selector=Q.toString()}),!!B.nodes[0]&&d.push([w.sort,B.nodes[0]])}}let p=e.offsets.sort(d).map(h=>h[1]);l.after(p)}for(let l of n)l.parent.nodes.length>1?l.remove():l.parent.remove();Vg(r,e,t)}function Dl(r){return e=>{let t=$2(()=>D2(e,r));Vg(e,r,t)}}var vs,R2,Hg=P(()=>{u();Ot();vs=pe(it());os();fr();Wo();ts();R2=(0,vs.default)()});var Wg=x((nq,ks)=>{u();(function(){"use strict";function r(i,n,s){if(!i)return null;r.caseSensitive||(i=i.toLowerCase());var a=r.threshold===null?null:r.threshold*i.length,o=r.thresholdAbsolute,l;a!==null&&o!==null?l=Math.min(a,o):a!==null?l=a:o!==null?l=o:l=null;var c,f,d,p,h,b=n.length;for(h=0;h<b;h++)if(f=n[h],s&&(f=f[s]),!!f&&(r.caseSensitive?d=f:d=f.toLowerCase(),p=t(i,d,l),(l===null||p<l)&&(l=p,s&&r.returnWinningObject?c=n[h]:c=f,r.returnFirstMatch)))return c;return c||r.nullResultValue}r.threshold=.4,r.thresholdAbsolute=20,r.caseSensitive=!1,r.nullResultValue=null,r.returnWinningObject=null,r.returnFirstMatch=!1,typeof ks!="undefined"&&ks.exports?ks.exports=r:window.didYouMean=r;var e=Math.pow(2,32)-1;function t(i,n,s){s=s||s===0?s:e;var a=i.length,o=n.length;if(a===0)return Math.min(s+1,o);if(o===0)return Math.min(s+1,a);if(Math.abs(a-o)>s)return s+1;var l=[],c,f,d,p,h;for(c=0;c<=o;c++)l[c]=[c];for(f=0;f<=a;f++)l[0][f]=f;for(c=1;c<=o;c++){for(d=e,p=1,c>s&&(p=c-s),h=o+1,h>s+c&&(h=s+c),f=1;f<=a;f++)f<p||f>h?l[c][f]=s+1:n.charAt(c-1)===i.charAt(f-1)?l[c][f]=l[c-1][f-1]:l[c][f]=Math.min(l[c-1][f-1]+1,Math.min(l[c][f-1]+1,l[c-1][f]+1)),l[c][f]<d&&(d=l[c][f]);if(d>s)return s+1}return l[o][a]}})()});var Qg=x((sq,Gg)=>{u();var ql="(".charCodeAt(0),$l=")".charCodeAt(0),Ss="'".charCodeAt(0),Ll='"'.charCodeAt(0),Ml="\\".charCodeAt(0),yr="/".charCodeAt(0),Nl=",".charCodeAt(0),Bl=":".charCodeAt(0),As="*".charCodeAt(0),M2="u".charCodeAt(0),N2="U".charCodeAt(0),B2="+".charCodeAt(0),F2=/^[a-f0-9?-]+$/i;Gg.exports=function(r){for(var e=[],t=r,i,n,s,a,o,l,c,f,d=0,p=t.charCodeAt(d),h=t.length,b=[{nodes:e}],v=0,y,w="",k="",S="";d<h;)if(p<=32){i=d;do i+=1,p=t.charCodeAt(i);while(p<=32);a=t.slice(d,i),s=e[e.length-1],p===$l&&v?S=a:s&&s.type==="div"?(s.after=a,s.sourceEndIndex+=a.length):p===Nl||p===Bl||p===yr&&t.charCodeAt(i+1)!==As&&(!y||y&&y.type==="function"&&!1)?k=a:e.push({type:"space",sourceIndex:d,sourceEndIndex:i,value:a}),d=i}else if(p===Ss||p===Ll){i=d,n=p===Ss?"'":'"',a={type:"string",sourceIndex:d,quote:n};do if(o=!1,i=t.indexOf(n,i+1),~i)for(l=i;t.charCodeAt(l-1)===Ml;)l-=1,o=!o;else t+=n,i=t.length-1,a.unclosed=!0;while(o);a.value=t.slice(d+1,i),a.sourceEndIndex=a.unclosed?i:i+1,e.push(a),d=i+1,p=t.charCodeAt(d)}else if(p===yr&&t.charCodeAt(d+1)===As)i=t.indexOf("*/",d),a={type:"comment",sourceIndex:d,sourceEndIndex:i+2},i===-1&&(a.unclosed=!0,i=t.length,a.sourceEndIndex=i),a.value=t.slice(d+2,i),e.push(a),d=i+2,p=t.charCodeAt(d);else if((p===yr||p===As)&&y&&y.type==="function")a=t[d],e.push({type:"word",sourceIndex:d-k.length,sourceEndIndex:d+a.length,value:a}),d+=1,p=t.charCodeAt(d);else if(p===yr||p===Nl||p===Bl)a=t[d],e.push({type:"div",sourceIndex:d-k.length,sourceEndIndex:d+a.length,value:a,before:k,after:""}),k="",d+=1,p=t.charCodeAt(d);else if(ql===p){i=d;do i+=1,p=t.charCodeAt(i);while(p<=32);if(f=d,a={type:"function",sourceIndex:d-w.length,value:w,before:t.slice(f+1,i)},d=i,w==="url"&&p!==Ss&&p!==Ll){i-=1;do if(o=!1,i=t.indexOf(")",i+1),~i)for(l=i;t.charCodeAt(l-1)===Ml;)l-=1,o=!o;else t+=")",i=t.length-1,a.unclosed=!0;while(o);c=i;do c-=1,p=t.charCodeAt(c);while(p<=32);f<c?(d!==c+1?a.nodes=[{type:"word",sourceIndex:d,sourceEndIndex:c+1,value:t.slice(d,c+1)}]:a.nodes=[],a.unclosed&&c+1!==i?(a.after="",a.nodes.push({type:"space",sourceIndex:c+1,sourceEndIndex:i,value:t.slice(c+1,i)})):(a.after=t.slice(c+1,i),a.sourceEndIndex=i)):(a.after="",a.nodes=[]),d=i+1,a.sourceEndIndex=a.unclosed?i:d,p=t.charCodeAt(d),e.push(a)}else v+=1,a.after="",a.sourceEndIndex=d+1,e.push(a),b.push(a),e=a.nodes=[],y=a;w=""}else if($l===p&&v)d+=1,p=t.charCodeAt(d),y.after=S,y.sourceEndIndex+=S.length,S="",v-=1,b[b.length-1].sourceEndIndex=d,b.pop(),y=bLine truncated
|
||||
`),console.time("JIT TOTAL"),t},async function(t,i){e=ky(t,i)??e;let n=El(e);if(t.type==="document"){let s=t.nodes.filter(a=>a.type==="root");for(let a of s)a.type==="root"&&await Ts(n)(a,i);return}await Ts(n)(t,i)},Ze.DEBUG&&function(t){return console.timeEnd("JIT TOTAL"),console.log(`
|
||||
`),t}].filter(Boolean)}};Ql.exports.postcss=!0});var _y=x((Gq,Cy)=>{u();Cy.exports=Ay()});var Yl=x((Qq,Ey)=>{u();Ey.exports=()=>["and_chr 114","and_uc 15.5","chrome 114","chrome 113","chrome 109","edge 114","firefox 114","ios_saf 16.5","ios_saf 16.4","ios_saf 16.3","ios_saf 16.1","opera 99","safari 16.5","samsung 21"]});var Rs={};Ge(Rs,{agents:()=>nO,feature:()=>sO});function sO(){return{status:"cr",title:"CSS Feature Queries",stats:{ie:{"6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","5.5":"n"},edge:{"12":"y","13":"y","14":"y","15":"y","16":"y","17":"y","18":"y","79":"y","80":"y","81":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","101":"y","102":"y","103":"y","104":"y","105":"y","106":"y","107":"y","108":"y","109":"y","110":"y","111":"y","112":"y","113":"y","114":"y"},firefox:{"2":"n","3":"n","4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y","40":"y","41":"y","42":"y","43":"y","44":"y","45":"y","46":"y","47":"y","48":"y","49":"y","50":"y","51":"y","52":"y","53":"y","54":"y","55":"y","56":"y","57":"y","58":"y","59":"y","60":"y","61":"y","62":"y","63":"y","64":"y","65":"y","66":"y","67":"y","68":"y","69":"y","70":"y","71":"y","72":"y","73":"y","74":"y","75":"y","76":"y","77":"y","78":"y","79":"y","80":"y","81":"y","82":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","101":"y","102":"y","103":"y","104":"y","105":"y","106":"y","107":"y","108":"y","109":"y","110":"y","111":"y","112":"y","113":"y","114":"y","115":"y","116":"y","117":"y","3.5":"n","3.6":"n"},chrome:{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"n","10":"n","11":"n","12":"n","13":"n","14":"n","15":"n","16":"n","17":"n","18":"n","19":"n","20":"n","21":"n","22":"n","23":"n","24":"n","25":"n","26":"n","27":"n","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y","40":"y","41":"y","42":"y","43":"y","44":"y","45":"y","46":"y","47":"y","48":"y","49":"y","50":"y","51":"y","52":"y","53":"y","54":"y","55":"y","56":"y","57":"y","58":"y","59":"y","60":"y","61":"y","62":"y","63":"y","64":"y","65":"y","66":"y","67":"y","68":"y","69":"y","70":"y","71":"y","72":"y","73":"y","74":"y","75":"y","76":"y","77":"y","78":"y","79":"y","80":"y","81":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","101":"y","102":"y","103":"y","104":"y","105":"y","106":"y","107":"y","108":"y","109":"y","110":"y","111":"y","112":"y","113":"y","114":"y","115":"y","116":"y","117":"y"},safari:{"4":"n","5":"n","6":"n","7":"n","8":"n","9":"y","10":"y","11":"y","12":"y","13":"y","14":"y","15":"y","17":"y","9.1":"y","10.1":"y","11.1":"y","12.1":"y","13.1":"y","14.1":"y","15.1":"y","15.2-15.3":"y","15.4":"y","15.5":"y","15.6":"y","16.0":"y","16.1":"y","16.2":"y","16.3":"y","16.4":"y","16.5":"y","16.6":"y",TP:"y","3.1":"n","3.2":"n","5.1":"n","6.1":"n","7.1":"n"},opera:{"9":"n","11":"n","12":"n","15":"y","16":"y","17":"y","18":"y","19":"y","20":"y","21":"y","22":"y","23":"y","24":"y","25":"y","26":"y","27":"y","28":"y","29":"y","30":"y","31":"y","32":"y","33":"y","34":"y","35":"y","36":"y","37":"y","38":"y","39":"y","40":"y","41":"y","42":"y","43":"y","44":"y","45":"y","46":"y","47":"y","48":"y","49":"y","50":"y","51":"y","52":"y","53":"y","54":"y","55":"y","56":"y","57":"y","58":"y","60":"y","62":"y","63":"y","64":"y","65":"y","66":"y","67":"y","68":"y","69":"y","70":"y","71":"y","72":"y","73":"y","74":"y","75":"y","76":"y","77":"y","78":"y","79":"y","80":"y","81":"y","82":"y","83":"y","84":"y","85":"y","86":"y","87":"y","88":"y","89":"y","90":"y","91":"y","92":"y","93":"y","94":"y","95":"y","96":"y","97":"y","98":"y","99":"y","100":"y","12.1":"y","9.5-9.6":"n","10.0-10.1":"n","10.5":"n","10.6":"n","11.1":"n","11.5":"n","11.6":"n"},ios_saf:{"8":"n","17":"y","9.0-9.2":"y","9.3":"y","10.0-10.2":"y","10.3":"y","11.0-11.2":"y","11.3-11.4":"y","12.0-12.1":"y","12.2-12.5":"y","13.0-13.1":"y","13.2":"y","13.3":"y","13.4-13.7":"y","14.0-14.4":"y","14.5-14.8":"y","15.0-15.1":"y","15.2-15.3":"y","15.4":"y","15.5":"y","15.6":"y","16.0":"y","16.1":"y","16.2":"y","16.3":"y","16.4":"y","16.5":"y","16.6":"y","3.2":"n","4.0-4.1":"n","4.2-4.3":"n","5.0-5.1":"n","6.0-6.1":"n","7.0-7.1":"n","8.1-8.4":"n"},op_mini:{all:"y"},android:{"3":"n","4":"n","114":"y","4.4":"y","4.4.3-4.4.4":"y","2.1":"n","2.2":"n","2.3":"n","4.1":"n","4.2-4.3":"n"},bb:{"7":"n","10":"n"},op_mob:{"10":"n","11":"n","12":"n","73":"y","11.1":"n","11.5":"n","12.1":"n"},and_chr:
Line truncated
|
||||
`)),e._autoprefixerCascade}maxPrefixed(e,t){if(t._autoprefixerMax)return t._autoprefixerMax;let i=0;for(let n of e)n=$y.removeNote(n),n.length>i&&(i=n.length);return t._autoprefixerMax=i,t._autoprefixerMax}calcBefore(e,t,i=""){let s=this.maxPrefixed(e,t)-$y.removeNote(i).length,a=t.raw("before");return s>0&&(a+=Array(s).fill(" ").join("")),a}restoreBefore(e){let t=e.raw("before").split(`
|
||||
`),i=t[t.length-1];this.all.group(e).up(n=>{let s=n.raw("before").split(`
|
||||
`),a=s[s.length-1];a.length<i.length&&(i=a)}),t[t.length-1]=i,e.raws.before=t.join(`
|
||||
`)}insert(e,t,i){let n=this.set(this.clone(e),t);if(!(!n||e.parent.some(a=>a.prop===n.prop&&a.value===n.value)))return this.needCascade(e)&&(n.raws.before=this.calcBefore(i,e,t)),e.parent.insertBefore(e,n)}isAlready(e,t){let i=this.all.group(e).up(n=>n.prop===t);return i||(i=this.all.group(e).down(n=>n.prop===t)),i}add(e,t,i,n){let s=this.prefixed(e.prop,t);if(!(this.isAlready(e,s)||this.otherPrefixes(e.value,t)))return this.insert(e,t,i,n)}process(e,t){if(!this.needCascade(e)){super.process(e,t);return}let i=super.process(e,t);!i||!i.length||(this.restoreBefore(e),e.raws.before=this.calcBefore(i,e))}old(e,t){return[this.prefixed(e,t)]}};My.exports=Ly});var By=x((r$,Ny)=>{u();Ny.exports=function r(e){return{mul:t=>new r(e*t),div:t=>new r(e/t),simplify:()=>new r(e),toString:()=>e.toString()}}});var zy=x((i$,jy)=>{u();var pO=By(),dO=wr(),Zl=_e(),hO=/(min|max)-resolution\s*:\s*\d*\.?\d+(dppx|dpcm|dpi|x)/gi,mO=/(min|max)-resolution(\s*:\s*)(\d*\.?\d+)(dppx|dpcm|dpi|x)/i,Fy=class extends dO{prefixName(e,t){return e==="-moz-"?t+"--moz-device-pixel-ratio":e+t+"-device-pixel-ratio"}prefixQuery(e,t,i,n,s){return n=new pO(n),s==="dpi"?n=n.div(96):s==="dpcm"&&(n=n.mul(2.54).div(96)),n=n.simplify(),e==="-o-"&&(n=n.n+"/"+n.d),this.prefixName(e,t)+i+n}clean(e){if(!this.bad){this.bad=[];for(let t of this.prefixes)this.bad.push(this.prefixName(t,"min")),this.bad.push(this.prefixName(t,"max"))}e.params=Zl.editList(e.params,t=>t.filter(i=>this.bad.every(n=>!i.includes(n))))}process(e){let t=this.parentPrefix(e),i=t?[t]:this.prefixes;e.params=Zl.editList(e.params,(n,s)=>{for(let a of n){if(!a.includes("min-resolution")&&!a.includes("max-resolution")){s.push(a);continue}for(let o of i){let l=a.replace(hO,c=>{let f=c.match(mO);return this.prefixQuery(o,f[1],f[2],f[3],f[4])});s.push(l)}s.push(a)}return Zl.uniq(s)})}};jy.exports=Fy});var Vy=x((n$,Uy)=>{u();var Jl="(".charCodeAt(0),eu=")".charCodeAt(0),Ds="'".charCodeAt(0),tu='"'.charCodeAt(0),ru="\\".charCodeAt(0),vr="/".charCodeAt(0),iu=",".charCodeAt(0),nu=":".charCodeAt(0),qs="*".charCodeAt(0),gO="u".charCodeAt(0),yO="U".charCodeAt(0),bO="+".charCodeAt(0),wO=/^[a-f0-9?-]+$/i;Uy.exports=function(r){for(var e=[],t=r,i,n,s,a,o,l,c,f,d=0,p=t.charCodeAt(d),h=t.length,b=[{nodes:e}],v=0,y,w="",k="",S="";d<h;)if(p<=32){i=d;do i+=1,p=t.charCodeAt(i);while(p<=32);a=t.slice(d,i),s=e[e.length-1],p===eu&&v?S=a:s&&s.type==="div"?(s.after=a,s.sourceEndIndex+=a.length):p===iu||p===nu||p===vr&&t.charCodeAt(i+1)!==qs&&(!y||y&&y.type==="function"&&y.value!=="calc")?k=a:e.push({type:"space",sourceIndex:d,sourceEndIndex:i,value:a}),d=i}else if(p===Ds||p===tu){i=d,n=p===Ds?"'":'"',a={type:"string",sourceIndex:d,quote:n};do if(o=!1,i=t.indexOf(n,i+1),~i)for(l=i;t.charCodeAt(l-1)===ru;)l-=1,o=!o;else t+=n,i=t.length-1,a.unclosed=!0;while(o);a.value=t.slice(d+1,i),a.sourceEndIndex=a.unclosed?i:i+1,e.push(a),d=i+1,p=t.charCodeAt(d)}else if(p===vr&&t.charCodeAt(d+1)===qs)i=t.indexOf("*/",d),a={type:"comment",sourceIndex:d,sourceEndIndex:i+2},i===-1&&(a.unclosed=!0,i=t.length,a.sourceEndIndex=i),a.value=t.slice(d+2,i),e.push(a),d=i+2,p=t.charCodeAt(d);else if((p===vr||p===qs)&&y&&y.type==="function"&&y.value==="calc")a=t[d],e.push({type:"word",sourceIndex:d-k.length,sourceEndIndex:d+a.length,value:a}),d+=1,p=t.charCodeAt(d);else if(p===vr||p===iu||p===nu)a=t[d],e.push({type:"div",sourceIndex:d-k.length,sourceEndIndex:d+a.length,value:a,before:k,after:""}),k="",d+=1,p=t.charCodeAt(d);else if(Jl===p){i=d;do i+=1,p=t.charCodeAt(i);while(p<=32);if(f=d,a={type:"function",sourceIndex:d-w.length,value:w,before:t.slice(f+1,i)},d=i,w==="url"&&p!==Ds&&p!==tu){i-=1;do if(o=!1,i=t.indexOf(")",i+1),~i)for(l=i;t.charCodeAt(l-1)===ru;)l-=1,o=!o;else t+=")",i=t.length-1,a.unclosed=!0;while(o);c=i;do c-=1,p=t.charCodeAt(c);while(p<=32);f<c?(d!==c+1?a.nodes=[{type:"word",sourceIndex:d,sourceEndIndex:c+1,value:t.slice(d,c+1)}]:a.nodes=[],a.unclosed&&c+1!==i?(a.after="",a.nodes.push({type:"space",sourceIndex:c+1,sourceEndIndex:i,value:t.slice(c+1,i)})):(a.after=t.slice(c+1,i),a.sourceEndIndex=i)):(a.after="",a.nodes=[]),d=i+1,a.sourceEndIndex=a.unclosed?i:d,p=t.charCodeAt(d),e.push(a)}else v+=1,a.after="",a.sourceEndIndex=d+1,e.push(a),b.push(a),e=a.nodes=[],y=a;w=""}else if(eu===p&&v)d+=1,p=t.charCodeAt(d),y.after=S,y.sourceEndIndex+=S.length,S="",v-=1,b[b.length-1].sourceEndIndex=d,b.pop(),y=b[v],e=y.nodes;else{i=d;do p===ru&&(i+=1),i+=1,p=t.charCodeAt(i);while(i<h&&!(p<=32||p===Ds||p===tu||p===iu||p===nu||p===vr||p===Jl||p===qs&&y&&y.type==="function"&&y.value==="calc"||p===vr&&y.type==="function"&&y.value==="calc"||p===eu&&v));a=t.slice(d,i),Jl===p?w=a:(gO===a.charCodeAt(0)||yO===a.charCodeAt(0))&&bO===a.charCodeAt(1)&&wO.test(a.slice(2))?e.push({type:"unicode-range",sourceIndex:d,sourceEndIndex:i,value:a}):e.push({type:"word",sourceIndex:d,sourceEndIndex:i,value:a}),d=i}for(d=b.length-1;d;d-=1)b[d].unclosed=!0,b[d].sourceEndIndex=t.length;return b[0].nodes}});var Wy=x((s$,Hy)=>{u();Hy.exports=function r(e,t,i){var n,s
Line truncated
|
||||
`)&&this.reduceSpaces(n),a.removeChild(s);return}}for(let l of this.prefixes.values("remove",o)){if(!l.check||!l.check(n.value))continue;if(o=l.unprefixed,this.prefixes.group(n).down(f=>f.value.includes(o))){a.removeChild(s);return}}})}withHackValue(e){return e.prop==="-webkit-background-clip"&&e.value==="text"}disabledValue(e,t){return this.gridStatus(e,t)===!1&&e.type==="decl"&&e.prop==="display"&&e.value.includes("grid")||this.prefixes.options.flexbox===!1&&e.type==="decl"&&e.prop==="display"&&e.value.includes("flex")||e.type==="decl"&&e.prop==="content"?!0:this.disabled(e,t)}disabledDecl(e,t){if(this.gridStatus(e,t)===!1&&e.type==="decl"&&(e.prop.includes("grid")||e.prop==="justify-items"))return!0;if(this.prefixes.options.flexbox===!1&&e.type==="decl"){let i=["order","justify-content","align-items","align-content"];if(e.prop.includes("flex")||i.includes(e.prop))return!0}return this.disabled(e,t)}disabled(e,t){if(!e)return!1;if(e._autoprefixerDisabled!==void 0)return e._autoprefixerDisabled;if(e.parent){let n=e.prev();if(n&&n.type==="comment"&&$O.test(n.text))return e._autoprefixerDisabled=!0,e._autoprefixerSelfDisabled=!0,!0}let i=null;if(e.nodes){let n;e.each(s=>{s.type==="comment"&&/(!\s*)?autoprefixer:\s*(off|on)/i.test(s.text)&&(typeof n!="undefined"?t.warn("Second Autoprefixer control comment was ignored. Autoprefixer applies control comment to whole block, not to next rules.",{node:s}):n=/on/i.test(s.text))}),n!==void 0&&(i=!n)}if(!e.nodes||i===null)if(e.parent){let n=this.disabled(e.parent,t);e.parent._autoprefixerSelfDisabled===!0?i=!1:i=n}else i=!1;return e._autoprefixerDisabled=i,i}reduceSpaces(e){let t=!1;if(this.prefixes.group(e).up(()=>(t=!0,!0)),t)return;let i=e.raw("before").split(`
|
||||
`),n=i[i.length-1].length,s=!1;this.prefixes.group(e).down(a=>{i=a.raw("before").split(`
|
||||
`);let o=i.length-1;i[o].length>n&&(s===!1&&(s=i[o].length-n),i[o]=i[o].slice(0,-s),a.raws.before=i.join(`
|
||||
`))})}displayType(e){for(let t of e.parent.nodes)if(t.prop==="display"){if(t.value.includes("flex"))return"flex";if(t.value.includes("grid"))return"grid"}return!1}gridStatus(e,t){if(!e)return!1;if(e._autoprefixerGridStatus!==void 0)return e._autoprefixerGridStatus;let i=null;if(e.nodes){let n;e.each(s=>{if(s.type==="comment"&&LO.test(s.text)){let a=/:\s*autoplace/i.test(s.text),o=/no-autoplace/i.test(s.text);typeof n!="undefined"?t.warn("Second Autoprefixer grid control comment was ignored. Autoprefixer applies control comments to the whole block, not to the next rules.",{node:s}):a?n="autoplace":o?n=!0:n=/on/i.test(s.text)}}),n!==void 0&&(i=n)}if(e.type==="atrule"&&e.name==="supports"){let n=e.params;n.includes("grid")&&n.includes("auto")&&(i=!1)}if(!e.nodes||i===null)if(e.parent){let n=this.gridStatus(e.parent,t);e.parent._autoprefixerSelfDisabled===!0?i=!1:i=n}else typeof this.prefixes.options.grid!="undefined"?i=this.prefixes.options.grid:typeof m.env.AUTOPREFIXER_GRID!="undefined"?m.env.AUTOPREFIXER_GRID==="autoplace"?i="autoplace":i=!0:i=!1;return e._autoprefixerGridStatus=i,i}};hb.exports=db});var gb=x((h$,mb)=>{u();mb.exports={A:{A:{"2":"K E F G A B JC"},B:{"1":"C L M H N D O P Q R S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I"},C:{"1":"2 3 4 5 6 7 8 9 AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB 0B dB 1B eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R 2B S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I uB 3B 4B","2":"0 1 KC zB J K E F G A B C L M H N D O k l LC MC"},D:{"1":"8 9 AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB 0B dB 1B eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R S T U V W X Y Z a b c d e f g h i j n o p q r s t u v w x y z I uB 3B 4B","2":"0 1 2 3 4 5 6 7 J K E F G A B C L M H N D O k l"},E:{"1":"G A B C L M H D RC 6B vB wB 7B SC TC 8B 9B xB AC yB BC CC DC EC FC GC UC","2":"0 J K E F NC 5B OC PC QC"},F:{"1":"1 2 3 4 5 6 7 8 9 H N D O k l AB BB CB DB EB FB GB HB IB JB KB LB MB NB OB PB QB RB SB TB UB VB WB XB YB ZB aB bB cB dB eB fB gB hB iB jB kB lB mB nB oB m pB qB rB sB tB P Q R 2B S T U V W X Y Z a b c d e f g h i j wB","2":"G B C VC WC XC YC vB HC ZC"},G:{"1":"D fC gC hC iC jC kC lC mC nC oC pC qC rC sC tC 8B 9B xB AC yB BC CC DC EC FC GC","2":"F 5B aC IC bC cC dC eC"},H:{"1":"uC"},I:{"1":"I zC 0C","2":"zB J vC wC xC yC IC"},J:{"2":"E A"},K:{"1":"m","2":"A B C vB HC wB"},L:{"1":"I"},M:{"1":"uB"},N:{"2":"A B"},O:{"1":"xB"},P:{"1":"J k l 1C 2C 3C 4C 5C 6B 6C 7C 8C 9C AD yB BD CD DD"},Q:{"1":"7B"},R:{"1":"ED"},S:{"1":"FD GD"}},B:4,C:"CSS Feature Queries"}});var vb=x((m$,wb)=>{u();function yb(r){return r[r.length-1]}var bb={parse(r){let e=[""],t=[e];for(let i of r){if(i==="("){e=[""],yb(t).push(e),t.push(e);continue}if(i===")"){t.pop(),e=yb(t),e.push("");continue}e[e.length-1]+=i}return t[0]},stringify(r){let e="";for(let t of r){if(typeof t=="object"){e+=`(${bb.stringify(t)})`;continue}e+=t}return e}};wb.exports=bb});var Cb=x((g$,Ab)=>{u();var BO=gb(),{feature:FO}=(Ps(),Rs),{parse:jO}=$e(),zO=Mt(),lu=vb(),UO=He(),VO=_e(),xb=FO(BO),kb=[];for(let r in xb.stats){let e=xb.stats[r];for(let t in e){let i=e[t];/y/.test(i)&&kb.push(r+" "+t)}}var Sb=class{constructor(e,t){this.Prefixes=e,this.all=t}prefixer(){if(this.prefixerCache)return this.prefixerCache;let e=this.all.browsers.selected.filter(i=>kb.includes(i)),t=new zO(this.all.browsers.data,e,this.all.options);return this.prefixerCache=new this.Prefixes(this.all.data,t,this.all.options),this.prefixerCache}parse(e){let t=e.split(":"),i=t[0],n=t[1];return n||(n=""),[i.trim(),n.trim()]}virtual(e){let[t,i]=this.parse(e),n=jO("a{}").first;return n.append({prop:t,value:i,raws:{before:""}}),n}prefixed(e){let t=this.virtual(e);if(this.disabled(t.first))return t.nodes;let i={warn:()=>null},n=this.prefixer().add[t.first.prop];n&&n.process&&n.process(t.first,i);for(let s of t.nodes){for(let a of this.prefixer().values("add",t.first.prop))a.process(s);UO.save(this.all,s)}return t.nodes}isNot(e){return typeof e=="string"&&/not\s*/i.test(e)}isOr(e){return typeof e=="string"&&/\s*or\s*/i.test(e)}isProp(e){return typeof e=="object"&&e.length===1&&typeof e[0]=="string"}isHack(e,t){return!new RegExp(`(\\(|\\s)${VO.escapeRegexp(t)}:`).test(e)}toRemove(e,t){let[i,n]=this.parse(e),s=this.all.unprefixed(i),a=this.all.cleaner();if(a.remove[i]&&a.remove[i].remove&&!this.isHack(t,s))return!0;for(let o of a.values("remove",s))if(o.check(n))return!0;return!1}remove(e,t){let i=0;for(;i<e.length;){if(!this.isNot(e[i-1])&&this.isProp(e[i])&&this.isOr(e[i+1])){if(this.toRemove(e[i][0],t)){e.splice(i,2);continue}i+=2;continue}typeof e[i]=="object"&&(e[i]=this.remove(e[i],t)),i+=1}return e}cleanBrackets(e){return e.map(t=>typeof t!="object"?t:t.length===1&&typeof t[0]=="object"?this.cleanBrackets(t[0]):this.cleanBrackets(t))}convert(e){let t=[""];for(let i of e)t.push([`${i.prop}: ${i.value}`]),t.push(" or ");return t[t.length-1]="",t}n
Line truncated
|
||||
Replace Autoprefixer \`browsers\` option to Browserslist config.
|
||||
Use \`browserslist\` key in \`package.json\` or \`.browserslistrc\` file.
|
||||
|
||||
Using \`browsers\` option can cause errors. Browserslist config can
|
||||
be used for Babel, Autoprefixer, postcss-normalize and other tools.
|
||||
|
||||
If you really need to use option, rename it to \`overrideBrowserslist\`.
|
||||
|
||||
Learn more at:
|
||||
https://github.com/browserslist/browserslist#readme
|
||||
https://twitter.com/browserslist
|
||||
|
||||
`;function V5(r){return Object.prototype.toString.apply(r)==="[object Object]"}var lf=new Map;function H5(r,e){e.browsers.selected.length!==0&&(e.add.selectors.length>0||Object.keys(e.add).length>2||r.warn(`Autoprefixer target browsers do not need any prefixes.You do not need Autoprefixer anymore.
|
||||
Check your Browserslist config to be sure that your targets are set up correctly.
|
||||
|
||||
Learn more at:
|
||||
https://github.com/postcss/autoprefixer#readme
|
||||
https://github.com/browserslist/browserslist#readme
|
||||
|
||||
`))}gv.exports=Dr;function Dr(...r){let e;if(r.length===1&&V5(r[0])?(e=r[0],r=void 0):r.length===0||r.length===1&&!r[0]?r=void 0:r.length<=2&&(Array.isArray(r[0])||!r[0])?(e=r[1],r=r[0]):typeof r[r.length-1]=="object"&&(e=r.pop()),e||(e={}),e.browser)throw new Error("Change `browser` option to `overrideBrowserslist` in Autoprefixer");if(e.browserslist)throw new Error("Change `browserslist` option to `overrideBrowserslist` in Autoprefixer");e.overrideBrowserslist?r=e.overrideBrowserslist:e.browsers&&(typeof console!="undefined"&&console.warn&&(of.red?console.warn(of.red(mv.replace(/`[^`]+`/g,n=>of.yellow(n.slice(1,-1))))):console.warn(mv)),r=e.browsers);let t={ignoreUnknownVersions:e.ignoreUnknownVersions,stats:e.stats,env:e.env};function i(n){let s=hv,a=new F5(s.browsers,r,n,t),o=a.selected.join(", ")+JSON.stringify(e);return lf.has(o)||lf.set(o,new j5(s.prefixes,a,e)),lf.get(o)}return{postcssPlugin:"autoprefixer",prepare(n){let s=i({from:n.opts.from,env:e.env});return{OnceExit(a){H5(n,s),e.remove!==!1&&s.processor.remove(a,n),e.add!==!1&&s.processor.add(a,n)}}},info(n){return n=n||{},n.from=n.from||m.cwd(),U5(i(n))},options:e,browsers:r}}Dr.postcss=!0;Dr.data=hv;Dr.defaults=N5.defaults;Dr.info=()=>Dr().info()});var bv={};Ge(bv,{default:()=>W5});var W5,wv=P(()=>{u();W5=[]});var xv={};Ge(xv,{default:()=>G5});var vv,G5,kv=P(()=>{u();Xi();vv=pe(rn()),G5=St(vv.default.theme)});var Av={};Ge(Av,{default:()=>Q5});var Sv,Q5,Cv=P(()=>{u();Xi();Sv=pe(rn()),Q5=St(Sv.default)});u();"use strict";var Y5=vt(_y()),K5=vt($e()),X5=vt(yv()),Z5=vt((wv(),bv)),J5=vt((kv(),xv)),eP=vt((Cv(),Av)),tP=vt((Vs(),_f)),rP=vt((al(),sl)),iP=vt((sa(),sc));function vt(r){return r&&r.__esModule?r:{default:r}}console.warn("cdn.tailwindcss.com should not be used in production. To use Tailwind CSS in production, install it as a PostCSS plugin or use the Tailwind CLI: https://tailwindcss.com/docs/installation");var Ns="tailwind",uf="text/tailwindcss",_v="/template.html",Yt,Ev=!0,Ov=0,ff=new Set,cf,Tv="",Rv=(r=!1)=>({get(e,t){return(!r||t==="config")&&typeof e[t]=="object"&&e[t]!==null?new Proxy(e[t],Rv()):e[t]},set(e,t,i){return e[t]=i,(!r||t==="config")&&pf(!0),!0}});window[Ns]=new Proxy({config:{},defaultTheme:J5.default,defaultConfig:eP.default,colors:tP.default,plugin:rP.default,resolveConfig:iP.default},Rv(!0));function Pv(r){cf.observe(r,{attributes:!0,attributeFilter:["type"],characterData:!0,subtree:!0,childList:!0})}new MutationObserver(async r=>{let e=!1;if(!cf){cf=new MutationObserver(async()=>await pf(!0));for(let t of document.querySelectorAll(`style[type="${uf}"]`))Pv(t)}for(let t of r)for(let i of t.addedNodes)i.nodeType===1&&i.tagName==="STYLE"&&i.getAttribute("type")===uf&&(Pv(i),e=!0);await pf(e)}).observe(document.documentElement,{attributes:!0,attributeFilter:["class"],childList:!0,subtree:!0});async function pf(r=!1){r&&(Ov++,ff.clear());let e="";for(let i of document.querySelectorAll(`style[type="${uf}"]`))e+=i.textContent;let t=new Set;for(let i of document.querySelectorAll("[class]"))for(let n of i.classList)ff.has(n)||t.add(n);if(document.body&&(Ev||t.size>0||e!==Tv||!Yt||!Yt.isConnected)){for(let n of t)ff.add(n);Ev=!1,Tv=e,self[_v]=Array.from(t).join(" ");let{css:i}=await(0,K5.default)([(0,Y5.default)({...window[Ns].config,_hash:Ov,content:{files:[_v],extract:{html:n=>n.split(" ")}},plugins:[...Z5.default,...Array.isArray(window[Ns].config.plugins)?window[Ns].config.plugins:[]]}),(0,X5.default)({remove:!1})]).process(`@tailwind base;@tailwind components;@tailwind utilities;${e}`);(!Yt||!Yt.isConnected)&&(Yt=document.createElement("style"),document.head.append(Yt)),Yt.textContent=i}}})();
|
||||
/*!
|
||||
* fill-range <https://github.com/jonschlinkert/fill-range>
|
||||
*
|
||||
* Copyright (c) 2014-present, Jon Schlinkert.
|
||||
* Licensed under the MIT License.
|
||||
*/
|
||||
/*!
|
||||
* is-number <https://github.com/jonschlinkert/is-number>
|
||||
*
|
||||
* Copyright (c) 2014-present, Jon Schlinkert.
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
/*!
|
||||
* to-regex-range <https://github.com/micromatch/to-regex-range>
|
||||
*
|
||||
* Copyright (c) 2015-present, Jon Schlinkert.
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
/*! https://mths.be/cssesc v3.0.0 by @mathias */
|
||||
+79
-2
@@ -42,13 +42,13 @@ import numpy as np
|
||||
|
||||
from . import physics
|
||||
from .config import Config
|
||||
from .estimation import SignalTracker
|
||||
from .estimation import KalmanCV, SignalTracker
|
||||
from .features import build_features
|
||||
from .models.anomaly import AnomalyMonitor
|
||||
from .models.climatology import HarmonicClimatology
|
||||
from .models.nowcast import NowcastEnsemble
|
||||
from .models.precip import PrecipitationModel, proxy_wet_label, zambretti
|
||||
from .sensors import SenseBoard, enrich
|
||||
from .sensors import OutdoorProbe, SenseBoard, enrich
|
||||
from .storage import Store, resample
|
||||
|
||||
STATE_VERSION = 1
|
||||
@@ -65,6 +65,9 @@ class Station:
|
||||
latitude=cfg.site.latitude,
|
||||
longitude=cfg.site.longitude,
|
||||
)
|
||||
# Optional and entirely absent on a board without one wired up.
|
||||
self.probe = (OutdoorProbe(cfg.sensor.outdoor_probe_period_s)
|
||||
if cfg.sensor.outdoor_probe else None)
|
||||
self.tracker = SignalTracker(cfg)
|
||||
self.nowcast = NowcastEnsemble(cfg.model.targets, cfg.model.horizons_s, cfg.model)
|
||||
self.climatology = HarmonicClimatology(
|
||||
@@ -191,6 +194,7 @@ class Station:
|
||||
"cpu_offset": (raw.get("cpu_temp") or float("nan")) - (raw.get("temp_raw") or float("nan")),
|
||||
"compensator_k": self.tracker.compensator.k,
|
||||
"hum_offset": self.tracker.hum_compensator.offset,
|
||||
"outdoor_c": (self.probe.read() if self.probe is not None else None),
|
||||
"hum_psychrometric": float(est["hum_c"]) - float(raw.get("hum") or float("nan")),
|
||||
"health": anomaly["health_overall"],
|
||||
"novelty_d2": anomaly["novelty"].get("d2", 0.0),
|
||||
@@ -265,6 +269,11 @@ class Station:
|
||||
result = self.tracker.compensator.calibrate(float(raw), float(cpu), float(reference_c))
|
||||
self.store.log_event("calibration", "info",
|
||||
f"k -> {result['k']:.3f} (residual {result['residual']:+.2f} C)")
|
||||
# Discontinuity marker: everything logged before this instant used a
|
||||
# different coefficient. Kept as its own event kind so the scorecard and
|
||||
# the records view can find it without parsing prose.
|
||||
self.store.log_event("discontinuity", "warn",
|
||||
f"temperature k {result['k']:.4f}")
|
||||
return result
|
||||
|
||||
def calibrate_humidity(self, reference_pct: float) -> Dict:
|
||||
@@ -279,6 +288,8 @@ class Station:
|
||||
self.store.log_event("calibration", "info",
|
||||
f"rh offset -> {result['offset']:+.2f}% "
|
||||
f"(residual {result['residual']:+.2f}%)")
|
||||
self.store.log_event("discontinuity", "warn",
|
||||
f"humidity offset {result['offset']:+.4f}")
|
||||
return result
|
||||
|
||||
def reset_humidity_calibration(self) -> Dict:
|
||||
@@ -293,6 +304,72 @@ class Station:
|
||||
f"rh offset reset to prior {self.cfg.sensor.hum_offset}")
|
||||
return {"offset": self.tracker.hum_compensator.offset, "reset": True, "n": 0}
|
||||
|
||||
def recompute_history(self) -> Dict:
|
||||
"""Re-derive every compensated column from the stored raw values.
|
||||
|
||||
Why this exists: calibration only changes readings from that moment on,
|
||||
so a correction of any size leaves a step in the record. Measured on this
|
||||
station, one humidity calibration put a 25-point discontinuity through
|
||||
the middle of the day. That contaminates the all-time records with values
|
||||
that were never real weather, and makes the learners train across a jump.
|
||||
|
||||
It is possible at all because the raw columns are never overwritten:
|
||||
`temp_raw`, `cpu_temp` and `hum` are exactly what the sensor reported, so
|
||||
the current coefficients can be applied to the whole history.
|
||||
|
||||
The Kalman levels are re-run rather than shifted, because the filter is
|
||||
not a constant offset. That means the smoothing is *re-derived*, not bit
|
||||
identical to what was logged live: the replay sees the stored cadence,
|
||||
which for tiered rows is coarser than the 2 s the filter runs at. The
|
||||
levels are right, the fine texture of old raw rows is not recoverable.
|
||||
"""
|
||||
data = self.store.all_for_recompute()
|
||||
ts = data["ts"]
|
||||
if ts.size == 0:
|
||||
return {"rows": 0, "reason": "no history"}
|
||||
|
||||
t0 = time.time()
|
||||
comp, hcomp = self.tracker.compensator, self.tracker.hum_compensator
|
||||
n = ts.size
|
||||
temp_c = np.empty(n)
|
||||
hum_c = np.empty(n)
|
||||
for i in range(n):
|
||||
tr, cp, hu = data["temp_raw"][i], data["cpu_temp"][i], data["hum"][i]
|
||||
temp_c[i] = comp.compensate(tr, cp) if np.isfinite(tr) and np.isfinite(cp) else tr
|
||||
hum_c[i] = (hcomp.compensate(hu, tr, temp_c[i])
|
||||
if np.isfinite(hu) and np.isfinite(tr) else hu)
|
||||
|
||||
# Replay the filters over the corrected series. Fresh instances, so an
|
||||
# old contaminated state cannot leak into the re-derivation.
|
||||
kt = KalmanCV(self.cfg.sensor.kalman_q_temp, self.cfg.sensor.kalman_r_temp)
|
||||
kh = KalmanCV(self.cfg.sensor.kalman_q_hum, self.cfg.sensor.kalman_r_hum)
|
||||
temp_s = np.empty(n)
|
||||
temp_r = np.empty(n)
|
||||
hum_s = np.empty(n)
|
||||
prev = None
|
||||
for i in range(n):
|
||||
dt = 1.0 if prev is None else max(ts[i] - prev, 1e-3)
|
||||
prev = ts[i]
|
||||
lvl, rate = kt.update(temp_c[i], dt)
|
||||
temp_s[i], temp_r[i] = lvl, rate * 3600.0
|
||||
hum_s[i], _ = kh.update(hum_c[i], dt)
|
||||
|
||||
dew = np.asarray(physics.dew_point(temp_s, hum_s), dtype=float)
|
||||
slp = np.asarray(physics.sea_level_pressure(
|
||||
data["press"], temp_s, self.cfg.site.altitude_m), dtype=float)
|
||||
|
||||
written = self.store.apply_recompute(ts, {
|
||||
"temp_c": temp_c, "temp_smooth": temp_s, "temp_rate": temp_r,
|
||||
"hum_smooth": hum_s, "dew_c": dew, "press_slp": slp,
|
||||
})
|
||||
secs = time.time() - t0
|
||||
self.store.log_event(
|
||||
"recompute", "info",
|
||||
f"re-derived {written} rows from raw with k={comp.k:.4f}, "
|
||||
f"rh offset={hcomp.offset:+.2f}% in {secs:.1f}s")
|
||||
return {"rows": written, "seconds": round(secs, 2),
|
||||
"k": comp.k, "hum_offset": hcomp.offset}
|
||||
|
||||
def reset_calibration(self) -> Dict:
|
||||
"""Return the self-heating coefficient to its configured prior.
|
||||
|
||||
|
||||
@@ -154,6 +154,52 @@ class Store:
|
||||
|
||||
# ------------------------------------------------------------- reads
|
||||
|
||||
def all_for_recompute(self) -> Dict[str, np.ndarray]:
|
||||
"""Every stored row's *raw* inputs, oldest first.
|
||||
|
||||
Only the columns a re-derivation actually needs. The raw sensor values
|
||||
are never overwritten, which is precisely what makes recomputation
|
||||
possible after a calibration changes k or the humidity offset.
|
||||
"""
|
||||
cols = ["ts", "temp_raw", "cpu_temp", "hum", "press"]
|
||||
with self._conn() as conn:
|
||||
rows = conn.execute(
|
||||
f"SELECT {', '.join(cols)} FROM telemetry ORDER BY ts ASC").fetchall()
|
||||
if not rows:
|
||||
return {c: np.empty(0) for c in cols}
|
||||
arr = np.array(rows, dtype=object)
|
||||
out = {}
|
||||
for i, c in enumerate(cols):
|
||||
out[c] = np.array([np.nan if v is None else float(v) for v in arr[:, i]],
|
||||
dtype=float)
|
||||
return out
|
||||
|
||||
def apply_recompute(self, ts: np.ndarray, updates: Dict[str, np.ndarray],
|
||||
chunk: int = 2000) -> int:
|
||||
"""Write recomputed derived columns back, in chunks.
|
||||
|
||||
Chunked because a year of tiered history is a six-figure row count and a
|
||||
single statement would hold the whole parameter list in memory on a
|
||||
512 MB board.
|
||||
"""
|
||||
names = list(updates.keys())
|
||||
sql = (f"UPDATE telemetry SET {', '.join(n + ' = ?' for n in names)} "
|
||||
f"WHERE ts = ?")
|
||||
n_written = 0
|
||||
with self._conn() as conn:
|
||||
for start in range(0, ts.size, chunk):
|
||||
stop = min(start + chunk, ts.size)
|
||||
batch = [
|
||||
tuple(
|
||||
[None if not np.isfinite(updates[n][i]) else float(updates[n][i])
|
||||
for n in names] + [float(ts[i])]
|
||||
)
|
||||
for i in range(start, stop)
|
||||
]
|
||||
conn.executemany(sql, batch)
|
||||
n_written += len(batch)
|
||||
return n_written
|
||||
|
||||
def window(self, hours: float, columns: Optional[Iterable[str]] = None) -> Dict[str, np.ndarray]:
|
||||
"""Return the last `hours` of telemetry as column arrays, oldest first."""
|
||||
cols = list(columns) if columns else COLUMNS
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
# Copyright 2026 Kemal Yaylali
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Compensators and the Kalman bank.
|
||||
|
||||
The inverse-property tests here exist because getting that algebra wrong has
|
||||
already cost this project twice: once on temperature, where a mismatched
|
||||
simulator injected 1.2 C of phantom noise floor, and once on humidity, where
|
||||
the correction ran the wrong way against a reference hygrometer.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from ashvale.estimation import HumidityCompensator, KalmanCV, ThermalCompensator
|
||||
from ashvale.physics import dew_point, saturation_vapour_pressure
|
||||
|
||||
# ---------------------------------------------------------------- thermal
|
||||
|
||||
def test_thermal_forward_model_is_the_exact_inverse_of_the_compensator():
|
||||
"""T_raw = (T + k*T_cpu)/(1+k) must invert T = T_raw - k(T_cpu - T_raw)."""
|
||||
for k, t_true, t_cpu in [(0.55, 19.0, 40.0), (0.26, 24.4, 40.2), (1.0, 5.0, 30.0)]:
|
||||
c = ThermalCompensator(k0=k, k_min=0.0, k_max=2.0)
|
||||
t_raw = (t_true + k * t_cpu) / (1.0 + k)
|
||||
assert c.compensate(t_raw, t_cpu) == pytest.approx(t_true, abs=1e-9)
|
||||
|
||||
|
||||
def test_thermal_calibration_moves_k_toward_the_truth():
|
||||
c = ThermalCompensator(k0=0.30, k_min=0.05, k_max=1.5)
|
||||
k_true, t_true, t_cpu = 0.62, 19.0, 41.0
|
||||
t_raw = (t_true + k_true * t_cpu) / (1.0 + k_true)
|
||||
before = abs(c.k - k_true)
|
||||
c.calibrate(t_raw, t_cpu, t_true)
|
||||
assert abs(c.k - k_true) < before
|
||||
|
||||
|
||||
def test_thermal_clamp_survives_a_mistyped_reference():
|
||||
c = ThermalCompensator(k0=0.55, k_min=0.15, k_max=1.20)
|
||||
for _ in range(50):
|
||||
c.calibrate(25.0, 40.0, -300.0) # absurd reference
|
||||
assert c.k_min <= c.k <= c.k_max
|
||||
|
||||
|
||||
def test_thermal_compensation_is_a_noop_without_a_gradient():
|
||||
c = ThermalCompensator(k0=0.8)
|
||||
assert c.compensate(21.0, 21.0) == pytest.approx(21.0)
|
||||
# and never amplifies when the CPU is cooler than the sensor
|
||||
assert c.compensate(21.0, 15.0) == pytest.approx(21.0)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- humidity
|
||||
|
||||
def test_humidity_psychrometric_round_trip():
|
||||
"""The simulator's forward model must invert the compensator exactly."""
|
||||
rh_true, t_true, t_raw = 62.0, 19.0, 25.6
|
||||
rh_sensor = rh_true * float(saturation_vapour_pressure(t_true) /
|
||||
saturation_vapour_pressure(t_raw))
|
||||
hc = HumidityCompensator(psychrometric=True)
|
||||
assert hc.compensate(rh_sensor, t_raw, t_true) == pytest.approx(rh_true, abs=1e-6)
|
||||
|
||||
|
||||
def test_humidity_psychrometric_preserves_dew_point():
|
||||
"""Vapour pressure is the conserved quantity, so dew point must not move."""
|
||||
rh_sensor, t_raw, t_true = 60.0, 25.6, 19.0
|
||||
hc = HumidityCompensator(psychrometric=True)
|
||||
out = hc.compensate(rh_sensor, t_raw, t_true)
|
||||
assert float(dew_point(t_true, out)) == pytest.approx(float(dew_point(t_raw, rh_sensor)),
|
||||
abs=1e-6)
|
||||
|
||||
|
||||
def test_humidity_psychrometric_disabled_by_default():
|
||||
hc = HumidityCompensator()
|
||||
assert hc.compensate(60.0, 25.6, 19.0) == pytest.approx(60.0)
|
||||
|
||||
|
||||
def test_humidity_offset_converges_on_a_reference():
|
||||
"""The measured case: board reads 75.35% where the truth is 50.4%."""
|
||||
hc = HumidityCompensator()
|
||||
errors = []
|
||||
for _ in range(6):
|
||||
hc.calibrate(75.35, 27.94, 24.86, 50.4)
|
||||
errors.append(abs(hc.compensate(75.35, 27.94, 24.86) - 50.4))
|
||||
assert errors[-1] < errors[0]
|
||||
assert errors[-1] < 0.5
|
||||
|
||||
|
||||
def test_humidity_offset_is_clamped():
|
||||
hc = HumidityCompensator()
|
||||
for _ in range(50):
|
||||
hc.calibrate(50.0, 20.0, 20.0, 100.0)
|
||||
assert hc.off_min <= hc.offset <= hc.off_max
|
||||
|
||||
|
||||
def test_humidity_output_stays_in_range():
|
||||
hc = HumidityCompensator(offset=30.0)
|
||||
assert 0.0 <= hc.compensate(95.0, 20.0, 20.0) <= 100.0
|
||||
hc2 = HumidityCompensator(offset=-30.0)
|
||||
assert 0.0 <= hc2.compensate(5.0, 20.0, 20.0) <= 100.0
|
||||
|
||||
|
||||
def test_humidity_state_round_trips_through_dict():
|
||||
hc = HumidityCompensator(offset=-24.2, psychrometric=True)
|
||||
hc.calibrate(70.0, 25.0, 21.0, 50.0)
|
||||
back = HumidityCompensator.from_dict(hc.to_dict())
|
||||
assert back.offset == pytest.approx(hc.offset)
|
||||
assert back.psychrometric is hc.psychrometric
|
||||
assert back.n_calibrations == hc.n_calibrations
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- kalman
|
||||
|
||||
def test_kalman_covariance_stays_symmetric_and_psd():
|
||||
"""Joseph form exists precisely so this holds over a long run."""
|
||||
kf = KalmanCV(q=1e-6, r=0.05)
|
||||
rng = np.random.default_rng(7)
|
||||
for _ in range(20000):
|
||||
kf.update(20.0 + 0.05 * rng.normal(), 2.0)
|
||||
P = np.asarray(kf.P, dtype=float)
|
||||
assert np.allclose(P, P.T, atol=1e-12)
|
||||
assert np.all(np.linalg.eigvalsh(P) > -1e-12)
|
||||
|
||||
|
||||
def test_kalman_tracks_a_constant_and_reports_zero_rate():
|
||||
kf = KalmanCV(q=1e-8, r=0.01)
|
||||
for _ in range(2000):
|
||||
kf.update(15.0, 2.0)
|
||||
assert kf.level == pytest.approx(15.0, abs=1e-3)
|
||||
assert kf.rate == pytest.approx(0.0, abs=1e-5)
|
||||
|
||||
|
||||
def test_kalman_recovers_a_known_ramp_rate():
|
||||
kf = KalmanCV(q=1e-4, r=0.01)
|
||||
true_rate = 0.5 / 3600.0 # 0.5 units per hour
|
||||
for i in range(6000):
|
||||
kf.update(10.0 + true_rate * i * 2.0, 2.0)
|
||||
assert kf.rate * 3600.0 == pytest.approx(0.5, rel=0.05)
|
||||
|
||||
|
||||
def test_kalman_ignores_non_finite_measurements():
|
||||
kf = KalmanCV(q=1e-6, r=0.05)
|
||||
kf.update(20.0, 2.0)
|
||||
lvl_before = kf.level
|
||||
kf.update(float("nan"), 2.0)
|
||||
assert kf.level == pytest.approx(lvl_before)
|
||||
|
||||
|
||||
def test_kalman_nis_is_near_one_when_noise_matches_the_model():
|
||||
"""NIS is the honest self-check: consistent filter, NIS about 1."""
|
||||
r = 0.04
|
||||
kf = KalmanCV(q=1e-7, r=r)
|
||||
rng = np.random.default_rng(11)
|
||||
nis = []
|
||||
for i in range(4000):
|
||||
kf.update(18.0 + np.sqrt(r) * rng.normal(), 2.0)
|
||||
if i > 500:
|
||||
nis.append(kf.nis)
|
||||
assert 0.5 < float(np.mean(nis)) < 2.0
|
||||
|
||||
|
||||
def test_kalman_state_round_trips_through_dict():
|
||||
kf = KalmanCV(q=1e-6, r=0.05)
|
||||
for _ in range(50):
|
||||
kf.update(12.0, 2.0)
|
||||
back = KalmanCV.from_dict(kf.to_dict())
|
||||
assert back.level == pytest.approx(kf.level)
|
||||
assert back.rate == pytest.approx(kf.rate)
|
||||
@@ -0,0 +1,151 @@
|
||||
# Copyright 2026 Kemal Yaylali
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""The learners: RLS, adaptive conformal, and the Zambretti prior.
|
||||
|
||||
The covariance-cap test is the important one in this file. Unbounded P growth
|
||||
through an unexcited subspace is the most common way a field RLS deployment
|
||||
dies, and it dies silently until the first excited sample.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from ashvale.models.precip import zambretti
|
||||
from ashvale.models.rls import AdaptiveConformal, RecursiveLeastSquares
|
||||
|
||||
# ---------------------------------------------------------------- RLS
|
||||
|
||||
def test_rls_recovers_known_coefficients():
|
||||
rng = np.random.default_rng(3)
|
||||
truth = np.array([0.5, -1.25, 2.0, 0.0])
|
||||
m = RecursiveLeastSquares(n_features=4, forgetting=0.999)
|
||||
for _ in range(4000):
|
||||
x = rng.normal(size=4)
|
||||
m.update(x, float(truth @ x))
|
||||
assert np.allclose(m.theta, truth, atol=0.02)
|
||||
|
||||
|
||||
def test_rls_covariance_trace_never_exceeds_the_cap():
|
||||
"""A quiet regressor is exactly what inflates P. It must not run away."""
|
||||
m = RecursiveLeastSquares(n_features=8, forgetting=0.99, p_max=1e4)
|
||||
quiet = np.zeros(8)
|
||||
quiet[0] = 1.0 # only one direction ever excited
|
||||
for _ in range(50000):
|
||||
m.update(quiet, 1.0)
|
||||
tr = float(np.trace(np.asarray(m.P, dtype=float)))
|
||||
assert np.isfinite(tr)
|
||||
assert tr <= 1e4 * (1.0 + 1e-6)
|
||||
|
||||
|
||||
def test_rls_covariance_stays_symmetric():
|
||||
rng = np.random.default_rng(5)
|
||||
m = RecursiveLeastSquares(n_features=6, forgetting=0.995)
|
||||
for _ in range(5000):
|
||||
m.update(rng.normal(size=6), float(rng.normal()))
|
||||
P = np.asarray(m.P, dtype=float)
|
||||
assert np.allclose(P, P.T, atol=1e-9)
|
||||
|
||||
|
||||
def test_rls_survives_a_non_finite_sample_without_poisoning_theta():
|
||||
m = RecursiveLeastSquares(n_features=3, forgetting=0.99)
|
||||
for _ in range(100):
|
||||
m.update(np.array([1.0, 0.5, -0.2]), 1.0)
|
||||
good = m.theta.copy()
|
||||
m.update(np.array([np.nan, 1.0, 1.0]), 1.0)
|
||||
assert np.all(np.isfinite(m.theta)), "a NaN sample must not poison the weights"
|
||||
m.update(np.array([1.0, 1.0, 1.0]), float("inf"))
|
||||
assert np.all(np.isfinite(m.theta))
|
||||
assert good.shape == m.theta.shape
|
||||
|
||||
|
||||
def test_rls_forgetting_gives_the_documented_effective_memory():
|
||||
m = RecursiveLeastSquares(n_features=2, forgetting=0.9985)
|
||||
assert 1.0 / (1.0 - m.lam) == pytest.approx(666.67, rel=1e-3)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- conformal
|
||||
|
||||
def test_conformal_coverage_tracks_the_target_on_stationary_noise():
|
||||
ac = AdaptiveConformal(alpha=0.1, gamma=0.02)
|
||||
rng = np.random.default_rng(17)
|
||||
inside = 0
|
||||
n = 4000
|
||||
for i in range(n):
|
||||
err = float(rng.normal())
|
||||
q = float(ac.quantile())
|
||||
covered = bool(np.isfinite(q) and abs(err) <= q)
|
||||
if i > 400 and covered:
|
||||
inside += 1
|
||||
ac.observe(err, covered)
|
||||
assert 0.84 <= inside / (n - 400) <= 0.96
|
||||
|
||||
|
||||
def test_conformal_alpha_is_clamped():
|
||||
ac = AdaptiveConformal(alpha=0.1, gamma=0.2)
|
||||
for _ in range(5000):
|
||||
ac.observe(1e9, False) # always a miss, alpha should rise then stop
|
||||
assert 0.005 <= ac.alpha <= 0.75
|
||||
|
||||
|
||||
def test_conformal_widens_after_misses_and_narrows_after_hits():
|
||||
"""Mind the sign. The update is
|
||||
|
||||
alpha <- alpha + gamma * (alpha_target - 1[miss])
|
||||
|
||||
so a hit adds +gamma*alpha_target and a miss subtracts gamma*(1-alpha_target).
|
||||
Since the band is the (1-alpha) quantile, a *rising* alpha is a *narrowing*
|
||||
band. Hits therefore push alpha up and misses push it down, which reads
|
||||
backwards until you follow it through.
|
||||
"""
|
||||
ac = AdaptiveConformal(alpha=0.1, gamma=0.05)
|
||||
for _ in range(200):
|
||||
ac.observe(0.1, True)
|
||||
a_hits = ac.alpha
|
||||
assert a_hits > 0.1, "a run of hits should raise alpha, narrowing the band"
|
||||
|
||||
for _ in range(200):
|
||||
ac.observe(1e6, False)
|
||||
assert ac.alpha < a_hits, "a run of misses should lower alpha, widening the band"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- zambretti
|
||||
|
||||
def test_zambretti_ordering_rising_is_never_worse_than_falling():
|
||||
"""Z increases toward bad weather, so falling must not score below rising."""
|
||||
for p in [980.0, 1000.0, 1013.0, 1030.0]:
|
||||
rising = zambretti(p, +1.2, 6)["z"]
|
||||
steady = zambretti(p, 0.0, 6)["z"]
|
||||
falling = zambretti(p, -1.2, 6)["z"]
|
||||
assert rising <= steady <= falling, f"ordering broken at {p} hPa"
|
||||
|
||||
|
||||
def test_zambretti_z_decreases_with_pressure_within_a_branch():
|
||||
for tend in (-1.2, 0.0, 1.2):
|
||||
zs = [zambretti(p, tend, 6)["z"] for p in (985.0, 1000.0, 1015.0, 1030.0)]
|
||||
assert all(a >= b for a, b in zip(zs, zs[1:])), f"not monotonic for tend={tend}"
|
||||
|
||||
|
||||
def test_zambretti_stays_on_the_26_point_scale():
|
||||
for p in (940.0, 1050.0):
|
||||
for tend in (-5.0, 0.0, 5.0):
|
||||
assert 1 <= zambretti(p, tend, 6)["z"] <= 26
|
||||
|
||||
|
||||
def test_zambretti_rain_prior_rises_with_z():
|
||||
settled = zambretti(1035.0, 1.5, 6)
|
||||
stormy = zambretti(960.0, -2.5, 6)
|
||||
assert stormy["prior_rain_prob"] > settled["prior_rain_prob"]
|
||||
@@ -0,0 +1,95 @@
|
||||
# Copyright 2026 Kemal Yaylali
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Physics closed forms.
|
||||
|
||||
These are properties, not golden numbers. A golden number test tells you the
|
||||
output changed; a property test tells you the output became unphysical, which
|
||||
is the failure that actually matters here.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from ashvale import physics
|
||||
|
||||
|
||||
@pytest.mark.parametrize("t", [-20.0, -5.0, 0.0, 12.3, 25.0, 40.0])
|
||||
def test_dew_point_at_saturation_equals_temperature(t):
|
||||
"""100% RH means the air is already at its dew point."""
|
||||
assert float(physics.dew_point(t, 100.0)) == pytest.approx(t, abs=1e-6)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("t,rh", [(20.0, 50.0), (5.0, 80.0), (30.0, 20.0), (-3.0, 95.0)])
|
||||
def test_dew_point_never_exceeds_temperature(t, rh):
|
||||
assert float(physics.dew_point(t, rh)) <= t + 1e-9
|
||||
|
||||
|
||||
def test_dew_point_round_trip_through_vapour_pressure():
|
||||
"""e(T, RH) evaluated at the dew point must be the saturation pressure."""
|
||||
for t, rh in [(20.0, 50.0), (25.6, 72.9), (0.5, 90.0)]:
|
||||
td = float(physics.dew_point(t, rh))
|
||||
assert float(physics.vapour_pressure(t, rh)) == pytest.approx(
|
||||
float(physics.saturation_vapour_pressure(td)), rel=1e-6)
|
||||
|
||||
|
||||
def test_saturation_vapour_pressure_is_monotonic_in_temperature():
|
||||
t = np.linspace(-30.0, 50.0, 400)
|
||||
es = np.asarray(physics.saturation_vapour_pressure(t), dtype=float)
|
||||
assert np.all(np.diff(es) > 0.0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("t,rh", [(20.0, 50.0), (30.0, 30.0), (10.0, 95.0)])
|
||||
def test_wet_bulb_between_dew_point_and_temperature(t, rh):
|
||||
"""The psychrometric ordering Td <= Tw <= T is not optional."""
|
||||
td = float(physics.dew_point(t, rh))
|
||||
tw = float(physics.wet_bulb(t, rh))
|
||||
assert td - 1e-6 <= tw <= t + 1e-6
|
||||
|
||||
|
||||
def test_vpd_is_zero_at_saturation_and_positive_below():
|
||||
assert float(physics.vapour_pressure_deficit(20.0, 100.0)) == pytest.approx(0.0, abs=1e-9)
|
||||
assert float(physics.vapour_pressure_deficit(20.0, 40.0)) > 0.0
|
||||
|
||||
|
||||
def test_sea_level_pressure_round_trips_with_station_pressure():
|
||||
for p, t, alt in [(1000.0, 15.0, 11.0), (1024.5, -2.0, 250.0), (985.0, 28.0, 0.0)]:
|
||||
slp = float(physics.sea_level_pressure(p, t, alt))
|
||||
back = float(physics.station_pressure(slp, t, alt))
|
||||
assert back == pytest.approx(p, rel=1e-9)
|
||||
|
||||
|
||||
def test_sea_level_pressure_is_above_station_pressure_when_elevated():
|
||||
assert float(physics.sea_level_pressure(1000.0, 15.0, 100.0)) > 1000.0
|
||||
assert float(physics.sea_level_pressure(1000.0, 15.0, 0.0)) == pytest.approx(1000.0, rel=1e-12)
|
||||
|
||||
|
||||
def test_solar_elevation_is_higher_at_local_noon_than_midnight():
|
||||
# 21 June 2026, Cambridge. Noon UTC against midnight UTC.
|
||||
noon, _ = physics.solar_position(np.array([1781784000.0]), 52.2053, 0.1218)
|
||||
midnight, _ = physics.solar_position(np.array([1781740800.0]), 52.2053, 0.1218)
|
||||
assert float(np.atleast_1d(noon)[0]) > float(np.atleast_1d(midnight)[0])
|
||||
|
||||
|
||||
def test_clear_sky_irradiance_is_zero_below_the_horizon():
|
||||
assert float(np.atleast_1d(physics.clear_sky_irradiance(np.array([-10.0])))[0]) == 0.0
|
||||
assert float(np.atleast_1d(physics.clear_sky_irradiance(np.array([45.0])))[0]) > 0.0
|
||||
|
||||
|
||||
def test_absolute_humidity_rises_with_temperature_at_fixed_rh():
|
||||
a = float(physics.absolute_humidity(10.0, 60.0))
|
||||
b = float(physics.absolute_humidity(25.0, 60.0))
|
||||
assert b > a
|
||||
@@ -0,0 +1,115 @@
|
||||
# Copyright 2026 Kemal Yaylali
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""History re-derivation after a calibration.
|
||||
|
||||
The property that matters is idempotence. Recompute always starts from the
|
||||
untouched raw columns, so running it twice must land in exactly the same place.
|
||||
If it ever compounds, a user who clicks the button twice silently corrupts
|
||||
their entire record.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlite3
|
||||
|
||||
import pytest
|
||||
|
||||
pytest.importorskip("fastapi")
|
||||
|
||||
from fastapi.testclient import TestClient # noqa: E402
|
||||
|
||||
import ashvale.api as api # noqa: E402
|
||||
from ashvale.config import CONFIG # noqa: E402
|
||||
|
||||
|
||||
def _avg(col: str) -> float:
|
||||
with sqlite3.connect(CONFIG.storage.db_path) as c:
|
||||
return c.execute(f"SELECT round(avg({col}), 6) FROM telemetry").fetchone()[0]
|
||||
|
||||
|
||||
def _snapshot() -> dict:
|
||||
"""Per-row values keyed by timestamp.
|
||||
|
||||
Deliberately not an aggregate. The station's sample loop is live under
|
||||
TestClient, so rows arrive between calls and any average over the whole
|
||||
table is a moving target. Comparing the rows present in both snapshots
|
||||
tests the property that actually matters.
|
||||
"""
|
||||
with sqlite3.connect(CONFIG.storage.db_path) as c:
|
||||
return {r[0]: (r[1], r[2]) for r in
|
||||
c.execute("SELECT ts, hum_smooth, temp_smooth FROM telemetry")}
|
||||
|
||||
|
||||
def _rows() -> int:
|
||||
with sqlite3.connect(CONFIG.storage.db_path) as c:
|
||||
return c.execute("SELECT count(*) FROM telemetry").fetchone()[0]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def client():
|
||||
with TestClient(api.app) as c:
|
||||
yield c
|
||||
|
||||
|
||||
def test_recompute_is_idempotent(client):
|
||||
"""Running it twice must land in exactly the same place, row for row.
|
||||
|
||||
It always starts from the untouched raw columns, so it cannot compound. If
|
||||
that ever breaks, a user clicking the button twice silently corrupts their
|
||||
whole record, which is why this is tested per row rather than on an average.
|
||||
"""
|
||||
if _rows() == 0:
|
||||
pytest.skip("no history in the database")
|
||||
client.post("/api/recompute")
|
||||
first = _snapshot()
|
||||
client.post("/api/recompute")
|
||||
second = _snapshot()
|
||||
common = set(first) & set(second)
|
||||
assert common, "no overlapping rows to compare"
|
||||
differing = [ts for ts in common if first[ts] != second[ts]]
|
||||
assert not differing, f"{len(differing)} of {len(common)} rows changed on re-run"
|
||||
|
||||
|
||||
def test_recompute_preserves_row_count(client):
|
||||
if _rows() == 0:
|
||||
pytest.skip("no history in the database")
|
||||
before = _rows()
|
||||
client.post("/api/recompute")
|
||||
assert _rows() == before
|
||||
|
||||
|
||||
def test_recompute_tracks_the_current_offset(client):
|
||||
"""Changing the calibration must move the whole history, not just new rows."""
|
||||
if _rows() == 0:
|
||||
pytest.skip("no history in the database")
|
||||
client.post("/api/calibrate/humidity", json={"reset": True})
|
||||
client.post("/api/recompute")
|
||||
base = _avg("hum_smooth")
|
||||
|
||||
client.post("/api/calibrate/humidity", json={"reference_pct": 30.0})
|
||||
client.post("/api/recompute")
|
||||
shifted = _avg("hum_smooth")
|
||||
assert shifted != pytest.approx(base), "history did not follow the new offset"
|
||||
|
||||
client.post("/api/calibrate/humidity", json={"reset": True})
|
||||
client.post("/api/recompute")
|
||||
assert _avg("hum_smooth") == pytest.approx(base, abs=0.5), "reset did not restore"
|
||||
|
||||
|
||||
def test_calibration_logs_a_discontinuity_marker(client):
|
||||
client.post("/api/calibrate/humidity", json={"reference_pct": 55.0})
|
||||
kinds = [e["kind"] for e in client.get("/api/status").json()["events"]]
|
||||
assert "discontinuity" in kinds
|
||||
client.post("/api/calibrate/humidity", json={"reset": True})
|
||||
Reference in new issue
Block a user