Complete residential site build with Docker Compose & Gitea Actions deployment
This commit is contained in:
Vendored
+154
@@ -0,0 +1,154 @@
|
|||||||
|
declare module 'astro:content' {
|
||||||
|
export interface RenderResult {
|
||||||
|
Content: import('astro/runtime/server/index.js').AstroComponentFactory;
|
||||||
|
headings: import('astro').MarkdownHeading[];
|
||||||
|
remarkPluginFrontmatter: Record<string, any>;
|
||||||
|
}
|
||||||
|
interface Render {
|
||||||
|
'.md': Promise<RenderResult>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RenderedContent {
|
||||||
|
html: string;
|
||||||
|
metadata?: {
|
||||||
|
imagePaths: Array<string>;
|
||||||
|
[key: string]: unknown;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type Flatten<T> = T extends { [K: string]: infer U } ? U : never;
|
||||||
|
|
||||||
|
export type CollectionKey = keyof DataEntryMap;
|
||||||
|
export type CollectionEntry<C extends CollectionKey> = Flatten<DataEntryMap[C]>;
|
||||||
|
|
||||||
|
type AllValuesOf<T> = T extends any ? T[keyof T] : never;
|
||||||
|
|
||||||
|
export type ReferenceDataEntry<
|
||||||
|
C extends CollectionKey,
|
||||||
|
E extends keyof DataEntryMap[C] = string,
|
||||||
|
> = {
|
||||||
|
collection: C;
|
||||||
|
id: E;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ReferenceLiveEntry<C extends keyof LiveContentConfig['collections']> = {
|
||||||
|
collection: C;
|
||||||
|
id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getCollection<C extends keyof DataEntryMap, E extends CollectionEntry<C>>(
|
||||||
|
collection: C,
|
||||||
|
filter?: (entry: CollectionEntry<C>) => entry is E,
|
||||||
|
): Promise<E[]>;
|
||||||
|
export function getCollection<C extends keyof DataEntryMap>(
|
||||||
|
collection: C,
|
||||||
|
filter?: (entry: CollectionEntry<C>) => unknown,
|
||||||
|
): Promise<CollectionEntry<C>[]>;
|
||||||
|
|
||||||
|
export function getLiveCollection<C extends keyof LiveContentConfig['collections']>(
|
||||||
|
collection: C,
|
||||||
|
filter?: LiveLoaderCollectionFilterType<C>,
|
||||||
|
): Promise<
|
||||||
|
import('astro').LiveDataCollectionResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>
|
||||||
|
>;
|
||||||
|
|
||||||
|
export function getEntry<
|
||||||
|
C extends keyof DataEntryMap,
|
||||||
|
E extends keyof DataEntryMap[C] | (string & {}),
|
||||||
|
>(
|
||||||
|
entry: ReferenceDataEntry<C, E>,
|
||||||
|
): E extends keyof DataEntryMap[C]
|
||||||
|
? Promise<DataEntryMap[C][E]>
|
||||||
|
: Promise<CollectionEntry<C> | undefined>;
|
||||||
|
export function getEntry<
|
||||||
|
C extends keyof DataEntryMap,
|
||||||
|
E extends keyof DataEntryMap[C] | (string & {}),
|
||||||
|
>(
|
||||||
|
collection: C,
|
||||||
|
id: E,
|
||||||
|
): E extends keyof DataEntryMap[C]
|
||||||
|
? string extends keyof DataEntryMap[C]
|
||||||
|
? Promise<DataEntryMap[C][E]> | undefined
|
||||||
|
: Promise<DataEntryMap[C][E]>
|
||||||
|
: Promise<CollectionEntry<C> | undefined>;
|
||||||
|
export function getLiveEntry<C extends keyof LiveContentConfig['collections']>(
|
||||||
|
collection: C,
|
||||||
|
filter: string | LiveLoaderEntryFilterType<C>,
|
||||||
|
): Promise<import('astro').LiveDataEntryResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>>;
|
||||||
|
|
||||||
|
/** Resolve an array of entry references from the same collection */
|
||||||
|
export function getEntries<C extends keyof DataEntryMap>(
|
||||||
|
entries: ReferenceDataEntry<C, keyof DataEntryMap[C]>[],
|
||||||
|
): Promise<CollectionEntry<C>[]>;
|
||||||
|
|
||||||
|
export function render<C extends keyof DataEntryMap>(
|
||||||
|
entry: DataEntryMap[C][string],
|
||||||
|
): Promise<RenderResult>;
|
||||||
|
|
||||||
|
export function reference<
|
||||||
|
C extends
|
||||||
|
| keyof DataEntryMap
|
||||||
|
// Allow generic `string` to avoid excessive type errors in the config
|
||||||
|
// if `dev` is not running to update as you edit.
|
||||||
|
// Invalid collection names will be caught at build time.
|
||||||
|
| (string & {}),
|
||||||
|
>(
|
||||||
|
collection: C,
|
||||||
|
): import('astro/zod').ZodPipe<
|
||||||
|
import('astro/zod').ZodString,
|
||||||
|
import('astro/zod').ZodTransform<
|
||||||
|
C extends keyof DataEntryMap
|
||||||
|
? {
|
||||||
|
collection: C;
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
: never,
|
||||||
|
string
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
|
||||||
|
type ReturnTypeOrOriginal<T> = T extends (...args: any[]) => infer R ? R : T;
|
||||||
|
type InferEntrySchema<C extends keyof DataEntryMap> = import('astro/zod').infer<
|
||||||
|
ReturnTypeOrOriginal<Required<ContentConfig['collections'][C]>['schema']>
|
||||||
|
>;
|
||||||
|
type ExtractLoaderConfig<T> = T extends { loader: infer L } ? L : never;
|
||||||
|
type InferLoaderSchema<
|
||||||
|
C extends keyof DataEntryMap,
|
||||||
|
L = ExtractLoaderConfig<ContentConfig['collections'][C]>,
|
||||||
|
> = L extends { schema: import('astro/zod').ZodSchema }
|
||||||
|
? import('astro/zod').infer<L['schema']>
|
||||||
|
: any;
|
||||||
|
|
||||||
|
type DataEntryMap = {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
type ExtractLoaderTypes<T> = T extends import('astro/loaders').LiveLoader<
|
||||||
|
infer TData,
|
||||||
|
infer TEntryFilter,
|
||||||
|
infer TCollectionFilter,
|
||||||
|
infer TError
|
||||||
|
>
|
||||||
|
? { data: TData; entryFilter: TEntryFilter; collectionFilter: TCollectionFilter; error: TError }
|
||||||
|
: { data: never; entryFilter: never; collectionFilter: never; error: never };
|
||||||
|
type ExtractEntryFilterType<T> = ExtractLoaderTypes<T>['entryFilter'];
|
||||||
|
type ExtractCollectionFilterType<T> = ExtractLoaderTypes<T>['collectionFilter'];
|
||||||
|
type ExtractErrorType<T> = ExtractLoaderTypes<T>['error'];
|
||||||
|
|
||||||
|
type LiveLoaderDataType<C extends keyof LiveContentConfig['collections']> =
|
||||||
|
LiveContentConfig['collections'][C]['schema'] extends undefined
|
||||||
|
? ExtractDataType<LiveContentConfig['collections'][C]['loader']>
|
||||||
|
: import('astro/zod').infer<
|
||||||
|
Exclude<LiveContentConfig['collections'][C]['schema'], undefined>
|
||||||
|
>;
|
||||||
|
type LiveLoaderEntryFilterType<C extends keyof LiveContentConfig['collections']> =
|
||||||
|
ExtractEntryFilterType<LiveContentConfig['collections'][C]['loader']>;
|
||||||
|
type LiveLoaderCollectionFilterType<C extends keyof LiveContentConfig['collections']> =
|
||||||
|
ExtractCollectionFilterType<LiveContentConfig['collections'][C]['loader']>;
|
||||||
|
type LiveLoaderErrorType<C extends keyof LiveContentConfig['collections']> = ExtractErrorType<
|
||||||
|
LiveContentConfig['collections'][C]['loader']
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type ContentConfig = never;
|
||||||
|
export type LiveContentConfig = never;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"_variables": {
|
||||||
|
"lastUpdateCheck": 1778706332057
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+2
@@ -0,0 +1,2 @@
|
|||||||
|
/// <reference types="astro/client" />
|
||||||
|
/// <reference path="content.d.ts" />
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
name: Build and Deploy
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Build Docker Image
|
||||||
|
run: |
|
||||||
|
docker build -t chesco-site:latest -f docker/Dockerfile .
|
||||||
|
|
||||||
|
- name: Sync to Host Directory
|
||||||
|
run: |
|
||||||
|
# Create the directory if it doesn't exist
|
||||||
|
mkdir -p ~/chesco
|
||||||
|
|
||||||
|
# Copy the compose file to the host directory
|
||||||
|
cp docker/docker-compose.yaml ~/chesco/docker-compose.yaml
|
||||||
|
|
||||||
|
- name: Deploy with Compose
|
||||||
|
run: |
|
||||||
|
# Move into the dedicated directory and restart the service
|
||||||
|
cd ~/chesco
|
||||||
|
docker compose up -d --force-recreate
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
name: Bold Industrial
|
||||||
|
description: A high-impact, industrial-grade design system built for reliability and professional grit. It balances a clean light-mode foundation with heavy typography and bold navy and orange accents.
|
||||||
|
|
||||||
|
colors:
|
||||||
|
surface:
|
||||||
|
primary: '#ffffff'
|
||||||
|
secondary: '#f1f1f1'
|
||||||
|
contrast: '#0a162b'
|
||||||
|
brand:
|
||||||
|
primary: '#0a162b' # Deep Navy
|
||||||
|
secondary: '#f9a825' # Industrial Orange
|
||||||
|
accent: '#f39c12'
|
||||||
|
text:
|
||||||
|
primary: '#000000'
|
||||||
|
secondary: '#4b5563'
|
||||||
|
on-dark: '#ffffff'
|
||||||
|
border:
|
||||||
|
subtle: '#e5e7eb'
|
||||||
|
strong: '#0a162b'
|
||||||
|
|
||||||
|
typography:
|
||||||
|
font-family: 'Metropolis, sans-serif'
|
||||||
|
headings:
|
||||||
|
style: 'Heavy, Uppercase'
|
||||||
|
h1: '64px / 1.1'
|
||||||
|
h2: '48px / 1.2'
|
||||||
|
h3: '24px / 1.3'
|
||||||
|
body:
|
||||||
|
style: 'Normal'
|
||||||
|
size: '16px / 1.6'
|
||||||
|
|
||||||
|
layout:
|
||||||
|
spacing-unit: 8px
|
||||||
|
container-max-width: 1200px
|
||||||
|
border-radius: 4px # Industrial/Geometric sharp corners
|
||||||
|
|
||||||
|
principles:
|
||||||
|
- High Impact: Use large, bold typography to communicate strength.
|
||||||
|
- Functional Clarity: Clear service grids and high-contrast call-to-actions.
|
||||||
|
- Regional Pride: Large watermark typography for location-based identity.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Bold Industrial Design System
|
||||||
|
|
||||||
|
This document outlines the visual identity for Chester Valley Home Services.
|
||||||
|
|
||||||
|
## Visual Tone
|
||||||
|
The "Bold Industrial" style is designed to look tough, reliable, and established. It moves away from generic corporate aesthetics in favor of a specialized, high-performance look that resonates with homeowners looking for professional grade work.
|
||||||
|
|
||||||
|
## Color Usage
|
||||||
|
- **Deep Navy (#0a162b)**: Used for headers, footers, and primary buttons to establish authority.
|
||||||
|
- **Industrial Orange (#f9a825)**: Used for primary CTAs and status highlights.
|
||||||
|
- **White (#ffffff)**: The primary background for maximum legibility in light mode.
|
||||||
|
|
||||||
|
## Components
|
||||||
|
### Buttons
|
||||||
|
- **Primary**: Solid Deep Navy with White text, minimal 4px radius.
|
||||||
|
- **Secondary**: Solid Industrial Orange with Black text.
|
||||||
|
- **Ghost**: Deep Navy border with Navy text.
|
||||||
|
|
||||||
|
### Cards
|
||||||
|
- Service cards should use thin borders (#e5e7eb) and generous internal padding (32px).
|
||||||
|
- Iconography should be simple, single-color glyphs.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from 'astro/config';
|
||||||
|
import tailwind from '@astrojs/tailwind';
|
||||||
|
import sitemap from '@astrojs/sitemap';
|
||||||
|
|
||||||
|
// https://astro.build/config
|
||||||
|
export default defineConfig({
|
||||||
|
site: 'https://chesteryvalleyservices.com', // Placeholder URL
|
||||||
|
integrations: [
|
||||||
|
tailwind(),
|
||||||
|
sitemap(),
|
||||||
|
],
|
||||||
|
});
|
||||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 655 B |
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#f9a825" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 322 B |
Vendored
+23
@@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width"><link rel="icon" type="image/svg+xml" href="/favicon.svg"><meta name="generator" content="Astro v6.3.2"><title>Chester Valley Home Services | Professional & Reliable</title><link rel="canonical" href="https://chesteryvalleyservices.com/"><meta name="description" content="Locally owned. Professionally done. One call covers it all for Electrical, Plumbing, HVAC, and Home Services in Chester County."><meta name="robots" content="index, follow"><meta property="og:title" content="Chester Valley Home Services | Professional & Reliable"><meta property="og:type" content="website"><meta property="og:image" content="/og-image.jpg"><meta property="og:url" content="https://chesteryvalleyservices.com/"><meta name="twitter:creator" content="@chescoservices"><link rel="icon" href="/favicon.ico"><meta name="twitter:image" content="/og-image.jpg"><meta name="twitter:title" content="Chester Valley Home Services | Professional & Reliable"><meta name="twitter:description" content="Locally owned. Professionally done. One call covers it all for Electrical, Plumbing, HVAC, and Home Services in Chester County."><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;900&family=Oswald:wght@500;700&display=swap" rel="stylesheet"><script type="application/ld+json">{"@context":"https://schema.org","@type":"HomeAndConstructionBusiness","name":"Chester Valley Home Services","description":"Locally owned. Professionally done. One call covers it all for Electrical, Plumbing, HVAC, and Home Services in Chester County.","address":{"@type":"PostalAddress","addressLocality":"West Chester","addressRegion":"PA","addressCountry":"US"},"url":"https://chesteryvalleyservices.com","telephone":"+14843015834","email":"info@chescohome.com","openingHoursSpecification":[{"@type":"OpeningHoursSpecification","dayOfWeek":["Monday","Tuesday","Wednesday","Thursday","Friday"],"opens":"07:00","closes":"18:00"},{"@type":"OpeningHoursSpecification","dayOfWeek":["Saturday"],"opens":"08:00","closes":"14:00"}],"areaServed":"Chester County, PA","hasOfferCatalog":{"@type":"OfferCatalog","name":"Home Services","itemListElement":[{"@type":"Offer","itemOffered":{"@type":"Service","name":"Electrical Services"}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Plumbing Services"}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"HVAC Services"}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Appliance Repair"}},{"@type":"Offer","itemOffered":{"@type":"Service","name":"Home Improvements"}}]}}</script><meta name="llm-info" content="Chester Valley Home Services provides professional Electrical, Plumbing, HVAC, Appliance Repair, and Home Improvements for residential properties in Chester County, PA. Locally owned. Professionally done. One call covers it all. Contact: (484) 301-5834."><link rel="stylesheet" href="/_astro/index.Bz_moLIJ.css"></head> <body class="bg-surface-primary text-text-primary font-sans antialiased"> <header class="sticky top-0 z-50 bg-white/95 backdrop-blur-md border-b border-border-subtle"> <nav class="max-w-7xl mx-auto px-4 h-20 flex items-center justify-between"> <div class="flex items-center gap-2"> <div class="bg-brand-orange p-1.5 rounded-brand"> <svg class="w-8 h-8 text-brand-navy" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"></path> </svg> </div> <div class="flex flex-col leading-tight"> <span class="font-industrial text-xl font-bold tracking-tighter uppercase text-brand-navy">Chester Valley</span> <span class="text-[10px] tracking-[0.2em] uppercase font-bold text-brand-orange">Home Services</span> </div> </div> <div class="hidden md:flex items-center gap-8 text-sm font-bold uppercase tracking-widest text-text-secondary"> <a href="/" class="hover:text-brand-orange transition-colors">Home</a> <a href="#services" class="hover:text-brand-orange transition-colors">Services</a> <a href="#about" class="hover:text-brand-orange transition-colors">About</a> <a href="#area" class="hover:text-brand-orange transition-colors">Service Area</a> </div> <div> <a href="#contact" class="bg-brand-navy text-white px-6 py-2.5 rounded-brand font-industrial font-bold uppercase tracking-wider hover:bg-brand-orange hover:text-brand-navy transition-all">
|
||||||
|
Request Service
|
||||||
|
</a> </div> </nav> </header> <main> <section class="relative min-h-[85vh] flex items-center overflow-hidden border-b border-border-subtle bg-surface-primary"> <!-- Background Watermark --> <div class="absolute inset-0 pointer-events-none select-none flex items-center justify-center overflow-hidden opacity-[0.03]"> <span class="font-industrial text-[30vw] font-black uppercase text-brand-navy leading-none text-center">WE LIVE HERE<br>WE WORK HERE</span> </div> <div class="relative z-10 max-w-7xl mx-auto px-4 py-20"> <div class="max-w-4xl"> <div class="flex items-center gap-4 mb-6"> <span class="h-1 w-12 bg-brand-orange"></span> <span class="uppercase tracking-[0.4em] text-brand-orange font-black text-sm">Locally Owned. Professionally Done.</span> </div> <h1 class="font-industrial text-6xl md:text-8xl font-bold uppercase leading-[0.9] mb-8 text-brand-navy">
|
||||||
|
Professional <br> <span class="text-brand-orange">Home Services</span> <br>
|
||||||
|
for Chester County
|
||||||
|
</h1> <p class="text-xl md:text-2xl text-text-secondary font-medium mb-12 max-w-2xl leading-relaxed">
|
||||||
|
We're not a call center. We're your neighbors. One call covers it all—from electrical and plumbing to HVAC and appliance repair.
|
||||||
|
</p> <div class="flex flex-wrap gap-4 mb-16"> <a href="#contact" class="group flex items-center gap-4 bg-brand-navy text-white px-8 py-5 rounded-brand font-industrial font-bold uppercase text-xl tracking-wider hover:bg-brand-orange hover:text-brand-navy transition-all shadow-xl">
|
||||||
|
Schedule A Free Estimate
|
||||||
|
<svg class="w-6 h-6 group-hover:translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path d="M17 8l4 4m0 0l-4 4m4-4H3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"></path> </svg> </a> </div> <div class="grid grid-cols-2 md:grid-cols-4 gap-8 border-t border-border-subtle pt-10"> <div class="flex flex-col gap-1"> <span class="text-brand-orange font-black text-xs uppercase tracking-widest">Transparent</span> <span class="text-sm font-bold text-text-secondary">Upfront Pricing</span> </div> <div class="flex flex-col gap-1"> <span class="text-brand-orange font-black text-xs uppercase tracking-widest">Neighborly</span> <span class="text-sm font-bold text-text-secondary">We Live & Work Here</span> </div> <div class="flex flex-col gap-1"> <span class="text-brand-orange font-black text-xs uppercase tracking-widest">Accountable</span> <span class="text-sm font-bold text-text-secondary">Done Right First Time</span> </div> <div class="flex flex-col gap-1"> <span class="text-brand-orange font-black text-xs uppercase tracking-widest">Respectful</span> <span class="text-sm font-bold text-text-secondary">Clean Work Policy</span> </div> </div> </div> </div> </section> <section id="services" class="py-24 bg-surface-secondary"> <div class="max-w-7xl mx-auto px-4"> <div class="flex flex-col md:flex-row md:items-end justify-between gap-8 mb-16"> <div class="max-w-2xl"> <h2 class="font-industrial text-5xl font-bold uppercase tracking-tight mb-4 text-brand-navy">What We Do</h2> <p class="text-text-secondary text-lg">One call covers it all. We're your trusted partner for professional home maintenance and repair throughout the county.</p> </div> <div class="hidden md:block"> <span class="font-industrial text-7xl font-black opacity-10 text-brand-navy select-none">SERVICES</span> </div> </div> <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div class="group p-10 border border-border-subtle bg-white hover:border-brand-orange transition-all relative overflow-hidden rounded-brand"> <div class="relative z-10"> <div class="w-14 h-14 bg-surface-secondary flex items-center justify-center mb-8 border border-border-subtle group-hover:border-brand-orange group-hover:bg-brand-orange transition-all"> <svg class="w-8 h-8 text-brand-orange group-hover:text-brand-navy" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path d="M13 10V3L4 14h7v7l9-11h-7z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path> </svg> </div> <h3 class="font-industrial text-2xl font-bold uppercase mb-4 tracking-wider text-brand-navy">Electrical</h3> <p class="text-text-secondary mb-8 leading-relaxed">Outlets, smart lighting, EV chargers, and critical troubleshooting. Professional wiring done right.</p> <a href="#" class="inline-flex items-center gap-2 font-bold uppercase text-xs tracking-widest text-brand-orange hover:text-brand-navy transition-colors">
|
||||||
|
Learn More <span class="text-lg">→</span> </a> </div> </div><div class="group p-10 border border-border-subtle bg-white hover:border-brand-orange transition-all relative overflow-hidden rounded-brand"> <div class="relative z-10"> <div class="w-14 h-14 bg-surface-secondary flex items-center justify-center mb-8 border border-border-subtle group-hover:border-brand-orange group-hover:bg-brand-orange transition-all"> <svg class="w-8 h-8 text-brand-orange group-hover:text-brand-navy" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path> </svg> </div> <h3 class="font-industrial text-2xl font-bold uppercase mb-4 tracking-wider text-brand-navy">Plumbing</h3> <p class="text-text-secondary mb-8 leading-relaxed">Fixtures, leaks, high-flow water heaters, garbage disposals, and drain solutions for your home.</p> <a href="#" class="inline-flex items-center gap-2 font-bold uppercase text-xs tracking-widest text-brand-orange hover:text-brand-navy transition-colors">
|
||||||
|
Learn More <span class="text-lg">→</span> </a> </div> </div><div class="group p-10 border border-border-subtle bg-white hover:border-brand-orange transition-all relative overflow-hidden rounded-brand"> <div class="relative z-10"> <div class="w-14 h-14 bg-surface-secondary flex items-center justify-center mb-8 border border-border-subtle group-hover:border-brand-orange group-hover:bg-brand-orange transition-all"> <svg class="w-8 h-8 text-brand-orange group-hover:text-brand-navy" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path> </svg> </div> <h3 class="font-industrial text-2xl font-bold uppercase mb-4 tracking-wider text-brand-navy">HVAC</h3> <p class="text-text-secondary mb-8 leading-relaxed">Maintenance, troubleshooting, thermostats, and mini-split system installation to keep you comfortable.</p> <a href="#" class="inline-flex items-center gap-2 font-bold uppercase text-xs tracking-widest text-brand-orange hover:text-brand-navy transition-colors">
|
||||||
|
Learn More <span class="text-lg">→</span> </a> </div> </div><div class="group p-10 border border-border-subtle bg-white hover:border-brand-orange transition-all relative overflow-hidden rounded-brand"> <div class="relative z-10"> <div class="w-14 h-14 bg-surface-secondary flex items-center justify-center mb-8 border border-border-subtle group-hover:border-brand-orange group-hover:bg-brand-orange transition-all"> <svg class="w-8 h-8 text-brand-orange group-hover:text-brand-navy" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path> </svg> </div> <h3 class="font-industrial text-2xl font-bold uppercase mb-4 tracking-wider text-brand-navy">Appliance Repair</h3> <p class="text-text-secondary mb-8 leading-relaxed">Restoration for ovens, refrigerators, dishwashers, washers, and dryers. Extending the life of your appliances.</p> <a href="#" class="inline-flex items-center gap-2 font-bold uppercase text-xs tracking-widest text-brand-orange hover:text-brand-navy transition-colors">
|
||||||
|
Learn More <span class="text-lg">→</span> </a> </div> </div><div class="group p-10 border border-border-subtle bg-white hover:border-brand-orange transition-all relative overflow-hidden rounded-brand"> <div class="relative z-10"> <div class="w-14 h-14 bg-surface-secondary flex items-center justify-center mb-8 border border-border-subtle group-hover:border-brand-orange group-hover:bg-brand-orange transition-all"> <svg class="w-8 h-8 text-brand-orange group-hover:text-brand-navy" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"></path> </svg> </div> <h3 class="font-industrial text-2xl font-bold uppercase mb-4 tracking-wider text-brand-navy">Home Improvements</h3> <p class="text-text-secondary mb-8 leading-relaxed">Custom built-ins, precision trim work, decks, patios, and general mechanical repairs for homeowners.</p> <a href="#" class="inline-flex items-center gap-2 font-bold uppercase text-xs tracking-widest text-brand-orange hover:text-brand-navy transition-colors">
|
||||||
|
Learn More <span class="text-lg">→</span> </a> </div> </div> <!-- Emergency CTA Card --> <div class="group p-10 bg-brand-orange transition-all relative overflow-hidden rounded-brand flex flex-col justify-center items-start"> <div class="relative z-10"> <span class="font-black text-brand-navy uppercase tracking-widest text-sm mb-4 block">Urgent Need?</span> <h3 class="font-industrial text-3xl font-black uppercase text-brand-navy mb-6 leading-none">5-Star <br> Dispatch</h3> <p class="text-brand-navy text-xs font-bold mb-6 opacity-80 uppercase tracking-widest">Real people answering the phone.</p> <a href="tel:4843015834" class="bg-brand-navy text-white px-6 py-3 font-industrial font-bold uppercase tracking-widest hover:bg-black transition-colors rounded-brand">
|
||||||
|
(484) 301-5834
|
||||||
|
</a> </div> <div class="absolute -bottom-8 -right-8 opacity-10 transform -rotate-12"> <svg class="w-48 h-48 text-brand-navy" fill="currentColor" viewBox="0 0 24 24"> <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path> </svg> </div> </div> </div> </div> </section> <section id="area" class="py-24 border-t border-border-subtle bg-white"> <div class="max-w-7xl mx-auto px-4"> <div class="grid grid-cols-1 lg:grid-cols-2 gap-16 items-center"> <div class="order-2 lg:order-1"> <div class="relative aspect-square bg-surface-secondary flex items-center justify-center p-8 overflow-hidden border border-border-subtle rounded-brand"> <div class="absolute inset-0 opacity-10 pointer-events-none"> <div class="w-full h-full" style="background-image: linear-gradient(#000 1px, transparent 1px), linear-gradient(90deg, #000 1px, transparent 1px); background-size: 40px 40px;"></div> </div> <div class="relative z-10 text-center"> <div class="bg-white border-2 border-brand-orange p-12 inline-block shadow-2xl rounded-brand"> <span class="font-industrial text-4xl font-bold uppercase tracking-widest text-brand-navy">Chester County</span> <p class="mt-4 font-bold tracking-tighter text-text-secondary">MAXIMUM COVERAGE AREA</p> </div> </div> <div class="absolute bottom-8 right-8 flex gap-4"> <div class="w-3 h-3 bg-brand-orange animate-pulse"></div> <span class="text-[10px] uppercase font-bold tracking-widest text-text-secondary">Live Response Tracking</span> </div> </div> </div> <div class="order-1 lg:order-2"> <span class="text-brand-orange font-black uppercase tracking-[0.3em] text-sm mb-6 block">Our Territory</span> <h2 class="font-industrial text-5xl md:text-6xl font-bold uppercase leading-tight mb-8 text-brand-navy">Serving the Heart <br> of Pennsylvania</h2> <p class="text-xl text-text-secondary mb-8 leading-relaxed">We live here and we work here. We provide rapid-response maintenance to residential properties throughout the county. Our technicians are local, giving us the edge in speed and regional knowledge.</p> <ul class="grid grid-cols-2 gap-y-4 gap-x-8 mb-10"> <li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> West Chester </li><li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> Exton </li><li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> Downingtown </li><li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> Coatesville </li><li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> Phoenixville </li><li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> Malvern </li><li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> Paoli </li><li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> Wayne </li><li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> Berwyn </li><li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> Devon </li><li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> Kennett Square </li><li class="flex items-center gap-3 font-bold uppercase tracking-wider text-sm border-l-2 border-brand-orange pl-4 text-brand-navy"> Oxford </li> </ul> <div class="flex flex-col gap-4"> <div class="flex gap-2"> <input type="text" placeholder="Enter Zip Code" class="flex-1 px-4 py-4 border border-border-subtle rounded-brand focus:outline-none focus:border-brand-orange"> <button class="bg-brand-navy text-white px-8 py-4 font-industrial font-bold uppercase tracking-wider hover:bg-brand-orange hover:text-brand-navy transition-all rounded-brand">
|
||||||
|
Check
|
||||||
|
</button> </div> <p class="text-[10px] uppercase font-bold tracking-widest text-text-secondary opacity-60 text-center">Placeholder: Functional Zip validation coming soon</p> </div> </div> </div> </div> </section> </main> <footer class="bg-surface-secondary py-20 border-t border-border-subtle"> <div class="max-w-7xl mx-auto px-4"> <div class="flex flex-col md:flex-row justify-between items-start gap-12 pb-16 border-b border-border-subtle"> <div class="max-w-xs"> <div class="flex items-center gap-2 mb-6"> <div class="bg-brand-orange p-1 rounded-sm"> <svg class="w-6 h-6 text-brand-navy" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.5"></path> </svg> </div> <span class="font-industrial text-xl font-bold uppercase tracking-tighter text-brand-navy">Chester Valley</span> </div> <p class="text-text-secondary text-sm leading-relaxed mb-6">Built on reliability and hard work. Locally owned and operated since 2024. One call covers it all.</p> <div class="flex gap-4"> <a href="#" class="w-10 h-10 border border-border-subtle flex items-center justify-center hover:border-brand-orange transition-colors text-brand-navy rounded-brand"> <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"> <path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"></path> </svg> </a> <a href="#" class="w-10 h-10 border border-border-subtle flex items-center justify-center hover:border-brand-orange transition-colors text-brand-navy rounded-brand"> <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"> <path d="M12.315 2c2.43 0 2.784.01 3.71.054 1.14.051 1.918.24 2.594.504.7.273 1.29.636 1.884 1.23.596.593.96 1.184 1.23 1.884.265.676.453 1.454.504 2.594.045.927.054 1.28.054 3.71s-.01 2.784-.054 3.71c-.051 1.14-.24 1.918-.504 2.594-.273.7-.636 1.29-1.23 1.884-.593.596-1.184.96-1.884 1.23-.676.265-1.454.453-2.594.504-.927.045-1.28.054-3.71.054s-2.784-.01-3.71-.054c-1.14-.051-1.918-.24-2.594-.504-.7-.273-1.29-.636-1.884-1.23-.596-.593-.96-1.184-1.23-1.884-.265-.676-.453-1.454-.504-2.594C2.01 14.784 2 14.43 2 12s.01-2.784.054-3.71c.051-1.14.24-1.918.504-2.594.273-.7.636-1.29 1.23-1.884.593-.596 1.184-.96 1.884-1.23.676-.265 1.454-.453 2.594-.504.927-.045 1.28-.054 3.71-.054zM12 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.162 6.162 6.162 6.162-2.759 6.162-6.162S15.403 5.838 12 5.838zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"></path> </svg> </a> </div> </div> <div class="grid grid-cols-2 gap-12"> <div class="flex flex-col gap-4"> <span class="font-industrial font-bold uppercase text-brand-orange text-xs tracking-widest">Navigation</span> <a href="#services" class="text-sm font-bold text-text-secondary hover:text-brand-orange transition-colors uppercase tracking-widest">Services</a> <a href="#about" class="text-sm font-bold text-text-secondary hover:text-brand-orange transition-colors uppercase tracking-widest">About Us</a> <a href="#area" class="text-sm font-bold text-text-secondary hover:text-brand-orange transition-colors uppercase tracking-widest">Area</a> <a href="#contact" class="text-sm font-bold text-text-secondary hover:text-brand-orange transition-colors uppercase tracking-widest">Contact</a> </div> <div class="flex flex-col gap-4"> <span class="font-industrial font-bold uppercase text-brand-orange text-xs tracking-widest">Capabilities</span> <span class="text-sm font-bold text-text-secondary uppercase tracking-widest">Electrical</span> <span class="text-sm font-bold text-text-secondary uppercase tracking-widest">HVAC Ops</span> <span class="text-sm font-bold text-text-secondary uppercase tracking-widest">Plumbing</span> <span class="text-sm font-bold text-text-secondary uppercase tracking-widest">Renovations</span> </div> </div> <div class="flex flex-col gap-6"> <span class="font-industrial font-bold uppercase text-brand-orange text-xs tracking-widest">Contact Info</span> <div class="text-sm font-bold tracking-widest leading-relaxed text-brand-navy">
|
||||||
|
CHESTER COUNTY, PA<br> <a href="tel:4843015834" class="hover:text-brand-orange transition-colors">(484) 301-5834</a><br> <a href="mailto:info@chescohome.com" class="hover:text-brand-orange transition-colors lowercase">info@chescohome.com</a> </div> <div class="text-[10px] uppercase font-bold tracking-widest text-text-secondary opacity-80">
|
||||||
|
MON–FRI 7AM–6PM<br>
|
||||||
|
SAT 8AM–2PM
|
||||||
|
</div> </div> </div> <div class="pt-10 flex flex-col md:flex-row justify-between items-center gap-4 text-[10px] font-black uppercase tracking-[0.2em] text-text-secondary"> <span class="opacity-60">© 2024 Chester Valley Home Services. All rights reserved.</span> <div class="flex gap-8"> <a href="#" class="hover:text-brand-orange transition-colors">Privacy Policy</a> <a href="#" class="hover:text-brand-orange transition-colors">Terms of Operation</a> <a href="#" class="hover:text-brand-orange transition-colors">Licensed & Insured</a> </div> </div> </div> </footer> </body></html>
|
||||||
Vendored
+28
@@ -0,0 +1,28 @@
|
|||||||
|
# Chester Valley Home Services
|
||||||
|
|
||||||
|
Professional Home Services for Chester County Homes. Locally owned. Professionally done.
|
||||||
|
|
||||||
|
## Business Information
|
||||||
|
- **Name:** Chester Valley Home Services
|
||||||
|
- **Phone:** (484) 301-5834
|
||||||
|
- **Email:** info@chescohome.com
|
||||||
|
- **Hours:** Mon–Fri 7am–6pm, Sat 8am–2pm
|
||||||
|
- **Service Area:** West Chester, Exton, Downingtown, Coatesville, Phoenixville, Malvern, Paoli, Wayne, Berwyn, Devon, Kennett Square, and surrounding Chester County.
|
||||||
|
- **License:** Fully Licensed & Insured
|
||||||
|
|
||||||
|
## Services Offered
|
||||||
|
1. **Electrical:** Outlets, lighting, EV chargers, troubleshooting.
|
||||||
|
2. **Plumbing:** Fixtures, leaks, water heaters, garbage disposals, drains.
|
||||||
|
3. **HVAC:** Maintenance, troubleshooting, thermostats, mini-splits.
|
||||||
|
4. **Appliance Repair:** Ovens, refrigerators, dishwashers, washers, dryers.
|
||||||
|
5. **Home Improvements:** Built-ins, trim, decks, patios, general repairs.
|
||||||
|
|
||||||
|
## Why Homeowners Choose Us
|
||||||
|
- **We Live Here. We Work Here.** We’re your neighbors, not a call center.
|
||||||
|
- **One Call Covers It All.** A single partner for electrical, plumbing, HVAC, and more.
|
||||||
|
- **Transparent Pricing.** Upfront quotes with no jargon or hidden fees.
|
||||||
|
- **Clean Work Policy.** We respect your home; cleanup is part of the job.
|
||||||
|
- **Reliability.** Done right the first time by licensed professionals.
|
||||||
|
|
||||||
|
## Emergency Service
|
||||||
|
Real people answering the phone for your urgent home service needs.
|
||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
User-agent: *
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
Sitemap: https://chesteryvalleyservices.com/sitemap-index.xml
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:news="http://www.google.com/schemas/sitemap-news/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"><url><loc>https://chesteryvalleyservices.com/</loc></url></urlset>
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><sitemap><loc>https://chesteryvalleyservices.com/sitemap-0.xml</loc></sitemap></sitemapindex>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
# Stage 1: Build
|
||||||
|
FROM node:22-alpine AS build
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Note: Context will be the project root, so paths are relative to root
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm install
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Stage 2: Serve
|
||||||
|
FROM nginx:alpine
|
||||||
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
EXPOSE 80
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
version: '3.8'
|
||||||
|
services:
|
||||||
|
chesco-site:
|
||||||
|
image: chesco-site:latest
|
||||||
|
container_name: chesco-site
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "8081:80"
|
||||||
|
# If you ever want to see logs or add custom configs,
|
||||||
|
# they will be managed here.
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../astro/bin/astro.mjs
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../@astrojs/check/bin/astro-check.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../@astrojs/language-server/bin/nodeServer.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../autoprefixer/bin/autoprefixer
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../baseline-browser-mapping/dist/cli.cjs
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../browserslist/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../cssesc/bin/cssesc
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../esbuild/bin/esbuild
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../vscode-languageserver/bin/installServerIntoExtension
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../is-docker/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../is-inside-container/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../jiti/bin/jiti.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../js-yaml/bin/js-yaml.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../nanoid/bin/nanoid.cjs
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../@babel/parser/bin/babel-parser.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../prettier/bin/prettier.cjs
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../resolve/bin/resolve
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../rollup/dist/bin/rollup
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../semver/bin/semver.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../sitemap/dist/esm/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../sucrase/bin/sucrase
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../sucrase/bin/sucrase-node
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../svgo/bin/svgo.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../tailwindcss/lib/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../tailwindcss/lib/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../update-browserslist-db/cli.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../vite/bin/vite.js
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../yaml/bin.mjs
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../yaml-language-server/bin/yaml-language-server
|
||||||
+5533
File diff suppressed because it is too large
Load Diff
+79
@@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"hash": "c15b83df",
|
||||||
|
"configHash": "677a254a",
|
||||||
|
"lockfileHash": "f6213e62",
|
||||||
|
"browserHash": "c61a65f7",
|
||||||
|
"optimized": {
|
||||||
|
"astro > aria-query": {
|
||||||
|
"src": "../../aria-query/lib/index.js",
|
||||||
|
"file": "astro___aria-query.js",
|
||||||
|
"fileHash": "9e40d2d3",
|
||||||
|
"needsInterop": true
|
||||||
|
},
|
||||||
|
"astro > axobject-query": {
|
||||||
|
"src": "../../axobject-query/lib/index.js",
|
||||||
|
"file": "astro___axobject-query.js",
|
||||||
|
"fileHash": "242cc81a",
|
||||||
|
"needsInterop": true
|
||||||
|
},
|
||||||
|
"astro > html-escaper": {
|
||||||
|
"src": "../../html-escaper/esm/index.js",
|
||||||
|
"file": "astro___html-escaper.js",
|
||||||
|
"fileHash": "a4c81b5c",
|
||||||
|
"needsInterop": false
|
||||||
|
},
|
||||||
|
"astro/runtime/client/dev-toolbar/entrypoint.js": {
|
||||||
|
"src": "../../astro/dist/runtime/client/dev-toolbar/entrypoint.js",
|
||||||
|
"file": "astro_runtime_client_dev-toolbar_entrypoint__js.js",
|
||||||
|
"fileHash": "f79f87b9",
|
||||||
|
"needsInterop": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chunks": {
|
||||||
|
"toolbar-2H5PSQQU": {
|
||||||
|
"file": "toolbar-2H5PSQQU.js"
|
||||||
|
},
|
||||||
|
"ui-library-EVFCBMCE": {
|
||||||
|
"file": "ui-library-EVFCBMCE.js"
|
||||||
|
},
|
||||||
|
"chunk-HNT3PLDI": {
|
||||||
|
"file": "chunk-HNT3PLDI.js"
|
||||||
|
},
|
||||||
|
"astro-IQQQXCO3": {
|
||||||
|
"file": "astro-IQQQXCO3.js"
|
||||||
|
},
|
||||||
|
"chunk-ZUETELRC": {
|
||||||
|
"file": "chunk-ZUETELRC.js"
|
||||||
|
},
|
||||||
|
"audit-XFDIA4TR": {
|
||||||
|
"file": "audit-XFDIA4TR.js"
|
||||||
|
},
|
||||||
|
"chunk-WTIA47ZU": {
|
||||||
|
"file": "chunk-WTIA47ZU.js"
|
||||||
|
},
|
||||||
|
"chunk-WDCEFGHP": {
|
||||||
|
"file": "chunk-WDCEFGHP.js"
|
||||||
|
},
|
||||||
|
"xray-XH6VIXDC": {
|
||||||
|
"file": "xray-XH6VIXDC.js"
|
||||||
|
},
|
||||||
|
"chunk-LEAOZWS7": {
|
||||||
|
"file": "chunk-LEAOZWS7.js"
|
||||||
|
},
|
||||||
|
"chunk-PXGSXSC7": {
|
||||||
|
"file": "chunk-PXGSXSC7.js"
|
||||||
|
},
|
||||||
|
"settings-K4OHAGC2": {
|
||||||
|
"file": "settings-K4OHAGC2.js"
|
||||||
|
},
|
||||||
|
"chunk-WM2KMMIK": {
|
||||||
|
"file": "chunk-WM2KMMIK.js"
|
||||||
|
},
|
||||||
|
"chunk-LEX3GG7N": {
|
||||||
|
"file": "chunk-LEX3GG7N.js"
|
||||||
|
},
|
||||||
|
"chunk-5WRI5ZAA": {
|
||||||
|
"file": "chunk-5WRI5ZAA.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+433
@@ -0,0 +1,433 @@
|
|||||||
|
import {
|
||||||
|
isDefinedIcon
|
||||||
|
} from "./chunk-ZUETELRC.js";
|
||||||
|
import {
|
||||||
|
closeOnOutsideClick,
|
||||||
|
createWindowElement,
|
||||||
|
synchronizePlacementOnUpdate
|
||||||
|
} from "./chunk-WM2KMMIK.js";
|
||||||
|
import "./chunk-LEX3GG7N.js";
|
||||||
|
import "./chunk-5WRI5ZAA.js";
|
||||||
|
|
||||||
|
// node_modules/astro/dist/runtime/client/dev-toolbar/apps/utils/icons.js
|
||||||
|
function randomFromArray(list) {
|
||||||
|
return list[Math.floor(Math.random() * list.length)];
|
||||||
|
}
|
||||||
|
var categoryIcons = new Map(
|
||||||
|
Object.entries({
|
||||||
|
frameworks: ["puzzle", "grid"],
|
||||||
|
adapters: ["puzzle", "grid", "compress"],
|
||||||
|
"css+ui": ["compress", "grid", "image", "resizeImage", "puzzle"],
|
||||||
|
"performance+seo": ["approveUser", "checkCircle", "compress", "robot", "searchFile", "sitemap"],
|
||||||
|
analytics: ["checkCircle", "compress", "searchFile"],
|
||||||
|
accessibility: ["approveUser", "checkCircle"],
|
||||||
|
other: ["checkCircle", "grid", "puzzle", "sitemap"]
|
||||||
|
})
|
||||||
|
);
|
||||||
|
function iconForIntegration(integration) {
|
||||||
|
const icons = integration.categories.filter((category) => categoryIcons.has(category)).flatMap((category) => categoryIcons.get(category));
|
||||||
|
return randomFromArray(icons);
|
||||||
|
}
|
||||||
|
var iconColors = [
|
||||||
|
"#BC52EE",
|
||||||
|
"#6D6AF0",
|
||||||
|
"#52EEBD",
|
||||||
|
"#52B7EE",
|
||||||
|
"#52EE55",
|
||||||
|
"#B7EE52",
|
||||||
|
"#EEBD52",
|
||||||
|
"#EE5552",
|
||||||
|
"#EE52B7",
|
||||||
|
"#858B98"
|
||||||
|
];
|
||||||
|
function colorForIntegration() {
|
||||||
|
return randomFromArray(iconColors);
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/astro/dist/runtime/client/dev-toolbar/apps/astro.js
|
||||||
|
var astroLogo = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 99 26" width="100"><path fill="#fff" d="M6.70402 22.1453c-1.17459-1.0737-1.51748-3.3297-1.02811-4.9641.84853 1.0304 2.02424 1.3569 3.24204 1.5411 1.88005.2844 3.72635.178 5.47285-.6813.1998-.0984.3844-.2292.6027-.3617.1639.4755.2065.9554.1493 1.4439-.1392 1.1898-.7313 2.1088-1.673 2.8054-.3765.2787-.775.5278-1.1639.7905-1.1948.8075-1.518 1.7544-1.0691 3.1318.0107.0336.0202.0671.0444.149-.6101-.273-1.0557-.6705-1.39518-1.1931-.3586-.5517-.52921-1.1619-.53819-1.8221-.00449-.3213-.00449-.6455-.0477-.9623-.10551-.7722-.46804-1.118-1.15102-1.1379-.70094-.0205-1.2554.4129-1.40244 1.0953-.01122.0523-.02749.1041-.04377.1649l.00112.0006Z"/><path fill="url(#paint0_linear_386_2739)" d="M6.70402 22.1453c-1.17459-1.0737-1.51748-3.3297-1.02811-4.9641.84853 1.0304 2.02424 1.3569 3.24204 1.5411 1.88005.2844 3.72635.178 5.47285-.6813.1998-.0984.3844-.2292.6027-.3617.1639.4755.2065.9554.1493 1.4439-.1392 1.1898-.7313 2.1088-1.673 2.8054-.3765.2787-.775.5278-1.1639.7905-1.1948.8075-1.518 1.7544-1.0691 3.1318.0107.0336.0202.0671.0444.149-.6101-.273-1.0557-.6705-1.39518-1.1931-.3586-.5517-.52921-1.1619-.53819-1.8221-.00449-.3213-.00449-.6455-.0477-.9623-.10551-.7722-.46804-1.118-1.15102-1.1379-.70094-.0205-1.2554.4129-1.40244 1.0953-.01122.0523-.02749.1041-.04377.1649l.00112.0006Z"/><path fill="#fff" d="M0 16.909s3.47815-1.6944 6.96603-1.6944l2.62973-8.13858c.09846-.39359.38592-.66106.71044-.66106.3246 0 .612.26747.7105.66106l2.6297 8.13858c4.1309 0 6.966 1.6944 6.966 1.6944S14.7045.814589 14.693.782298C14.5234.306461 14.2371 0 13.8512 0H6.76183c-.38593 0-.66063.306461-.84174.782298C5.90733.81398 0 16.909 0 16.909ZM36.671 11.7318c0 1.4262-1.7739 2.2779-4.2302 2.2779-1.5985 0-2.1638-.3962-2.1638-1.2281 0-.8715.7018-1.2875 2.3003-1.2875 1.4426 0 2.6707.0198 4.0937.1981v.0396Zm.0195-1.7629c-.8772-.19808-2.2028-.31693-3.7818-.31693-4.6006 0-6.7644 1.08943-6.7644 3.62483 0 2.6344 1.4815 3.6446 4.9125 3.6446 2.9046 0 4.8735-.7328 5.5947-2.5354h.117c-.0195.4358-.039.8716-.039 1.2083 0 .931.156 1.0102.9162 1.0102h3.5869c-.1949-.5546-.3119-2.1194-.3119-3.4663 0-1.446.0585-2.5355.0585-4.00123 0-2.99098-1.7934-4.89253-7.4077-4.89253-2.4173 0-5.1074.41596-7.1543 1.03.1949.81213.4679 2.45617.6043 3.5258 1.774-.83193 4.2887-1.18847 6.2381-1.18847 2.6902 0 3.4309.61404 3.4309 1.86193v.4952ZM46.5325 12.5637c-.4874.0594-1.1502.0594-1.8325.0594-.7213 0-1.3841-.0198-1.8324-.0792 0 .1585-.0195.3367-.0195.4952 0 2.476 1.618 3.922 7.3102 3.922 5.3609 0 7.0958-1.4262 7.0958-3.9418 0-2.3769-1.1501-3.5456-6.238-3.8031-3.9573-.17827-4.3082-.61404-4.3082-1.10924 0-.57442.5068-.87154 3.158-.87154 2.7487 0 3.4894.37635 3.4894 1.16866v.17827c.3899-.01981 1.0917-.03961 1.813-.03961.6823 0 1.423.0198 1.8519.05942 0-.17827.0195-.33674.0195-.47539 0-2.91175-2.4172-3.86252-7.0958-3.86252-5.2634 0-7.0373 1.2875-7.0373 3.8031 0 2.25805 1.423 3.66445 6.472 3.88235 3.7233.1188 4.1327.5348 4.1327 1.1092 0 .6141-.6043.8914-3.2165.8914-3.0021 0-3.7623-.416-3.7623-1.2677v-.1189ZM63.6883 2.125c-1.423 1.32712-3.9768 2.65425-5.3998 3.01079.0195.73289.0195 2.07982.0195 2.81271l1.3061.01981c-.0195 1.40635-.039 3.10979-.039 4.23889 0 2.6344 1.3841 4.6152 5.6922 4.6152 1.813 0 3.0216-.1981 4.5226-.515-.1559-.9706-.3314-2.4562-.3898-3.5852-.8968.2971-2.0274.4556-3.275.4556-1.735 0-2.4368-.4754-2.4368-1.8422 0-1.1884 0-2.29767.0195-3.32768 2.2223.01981 4.4446.05943 5.7507.09904-.0195-1.03.0195-2.51559.078-3.50598-1.8909.03961-4.0157.05942-5.7702.05942.0195-.87154.039-1.70347.0585-2.5354h-.1365ZM75.3313 7.35427c.0195-1.03001.039-1.90156.0585-2.75329h-3.9183c.0585 1.70347.0585 3.44656.0585 6.00172 0 2.5553-.0195 4.3182-.0585 6.0018h4.4836c-.078-1.1885-.0975-3.189-.0975-4.8925 0-2.69388 1.0917-3.46638 3.5674-3.46638 1.1502 0 1.9689.13865 2.6902.39615.0195-1.01019.2144-2.97117.3314-3.84271-.7408-.21789-1.5595-.35655-2.5537-.35655-2.1249-.0198-3.6844.85174-4.4056 2.93156l-.156-.0198ZM94.8501 10.5235c0 2.1591-1.5595 3.1693-4.0157 3.1693-2.4368 0-3.9963-.9508-3.9963-3.1693 0-2.21846 1.579-3.05039 3.9963-3.05039 2.4367 0 4.0157.89135 4.0157 3.05039Zm4.0743-.099c0-4.29832-3.353-6.21968-8.09-6.21968-4.7566 0-7.9926 1.92136-7.9926 6.21968 0 4.2785 3.0216 6.5762 7.9731 6.5762 4.9904 0 8.1095-2.2977 8.1095-6.5762Z"/><defs><linearGradient id="paint0_linear_386_2739" x1="5.46011" x2="16.8017" y1="25.9999" y2="20.6412" gradientUnits="userSpaceOnUse"><stop stop-color="#D83333"/><stop offset="1" stop-color="#F041FF"/></linearGradient></defs></svg>';
|
||||||
|
var integrationData;
|
||||||
|
var astro_default = {
|
||||||
|
id: "astro:home",
|
||||||
|
name: "Menu",
|
||||||
|
icon: "astro:logo",
|
||||||
|
async init(canvas, eventTarget) {
|
||||||
|
createCanvas();
|
||||||
|
document.addEventListener("astro:after-swap", createCanvas);
|
||||||
|
eventTarget.addEventListener("app-toggled", async (event) => {
|
||||||
|
resetDebugButton();
|
||||||
|
if (!(event instanceof CustomEvent)) return;
|
||||||
|
if (event.detail.state === true) {
|
||||||
|
if (!integrationData) fetchIntegrationData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
closeOnOutsideClick(eventTarget);
|
||||||
|
synchronizePlacementOnUpdate(eventTarget, canvas);
|
||||||
|
function fetchIntegrationData() {
|
||||||
|
fetch("https://astro.build/api/v1/dev-overlay/", {
|
||||||
|
cache: "no-cache"
|
||||||
|
}).then((res) => res.json()).then((data) => {
|
||||||
|
integrationData = data;
|
||||||
|
integrationData.data = integrationData.data.map((integration) => {
|
||||||
|
return integration;
|
||||||
|
});
|
||||||
|
refreshIntegrationList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function createCanvas() {
|
||||||
|
const links = [
|
||||||
|
{
|
||||||
|
icon: "bug",
|
||||||
|
name: "Report a Bug",
|
||||||
|
link: "https://github.com/withastro/astro/issues/new/choose"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "lightbulb",
|
||||||
|
name: "Feedback",
|
||||||
|
link: "https://github.com/withastro/roadmap/discussions/new/choose"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "file-search",
|
||||||
|
name: "Documentation",
|
||||||
|
link: "https://docs.astro.build"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 17 14"><path fill="currentColor" d="M14.3451 1.9072c-1.0375-.47613-2.1323-.81595-3.257-1.010998-.0102-.001716-.0207-.000234-.03.004243s-.017.011728-.022.020757c-.141.249998-.297.576998-.406.832998-1.2124-.18399-2.44561-.18399-3.658 0-.12159-.28518-.25914-.56328-.412-.832998-.00513-.00893-.01285-.016098-.02213-.02056-.00928-.004462-.0197-.00601-.02987-.00444-1.125.193998-2.22.533998-3.257 1.010998-.00888.00339-.0163.00975-.021.018-2.074 3.099-2.643004 6.122-2.364004 9.107.001.014.01.028.021.037 1.207724.8946 2.558594 1.5777 3.995004 2.02.01014.0032.02103.0031.03111-.0003.01007-.0034.01878-.01.02489-.0187.308-.42.582-.863.818-1.329.00491-.0096.0066-.0205.0048-.0312-.00181-.0106-.007-.0204-.0148-.0278-.00517-.0049-.0113-.0086-.018-.011-.43084-.1656-.84811-.3645-1.248-.595-.01117-.0063-.01948-.0167-.0232-.029-.00373-.0123-.00258-.0255.0032-.037.0034-.0074.00854-.014.015-.019.084-.063.168-.129.248-.195.00706-.0057.01554-.0093.02453-.0106.00898-.0012.01813 0 .02647.0036 2.619 1.196 5.454 1.196 8.041 0 .0086-.0037.0181-.0051.0275-.0038.0093.0012.0181.0049.0255.0108.08.066.164.132.248.195.0068.005.0123.0116.0159.0192.0036.0076.0053.016.0049.0244-.0003.0084-.0028.0166-.0072.0238-.0043.0072-.0104.0133-.0176.0176-.399.2326-.8168.4313-1.249.594-.0069.0025-.0132.0065-.0183.0117-.0052.0051-.0092.0114-.0117.0183-.0023.0067-.0032.0138-.0027.0208.0005.0071.0024.0139.0057.0202.24.465.515.909.817 1.329.0061.0087.0148.0153.0249.0187.0101.0034.021.0035.0311.0003 1.4388-.441 2.7919-1.1241 4.001-2.02.0061-.0042.0111-.0097.0147-.0161.0037-.0064.0058-.0135.0063-.0209.334-3.451-.559-6.449-2.366-9.106-.0018-.00439-.0045-.00834-.008-.01162-.0034-.00327-.0075-.00578-.012-.00738Zm-8.198 7.307c-.789 0-1.438-.724-1.438-1.612 0-.889.637-1.613 1.438-1.613.807 0 1.45.73 1.438 1.613 0 .888-.637 1.612-1.438 1.612Zm5.316 0c-.788 0-1.438-.724-1.438-1.612 0-.889.637-1.613 1.438-1.613.807 0 1.451.73 1.438 1.613 0 .888-.631 1.612-1.438 1.612Z"/></svg>',
|
||||||
|
name: "Community",
|
||||||
|
link: "https://astro.build/chat"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const { latestAstroVersion, version, debugInfo } = window.__astro_dev_toolbar__ ?? {};
|
||||||
|
const windowComponent = createWindowElement(
|
||||||
|
`<style>
|
||||||
|
#buttons-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#buttons-container astro-dev-toolbar-card {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a {
|
||||||
|
color: rgba(145, 152, 173, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a:hover {
|
||||||
|
color: rgba(204, 206, 216, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header section {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: white;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: rgba(224, 204, 250, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #f4ecfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list-wrapper {
|
||||||
|
position: relative;
|
||||||
|
--offset: 24px;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
margin-left: calc(var(--offset) * -1);
|
||||||
|
margin-right: calc(var(--offset) * -1);
|
||||||
|
padding-left: var(--offset);
|
||||||
|
padding-right: var(--offset);
|
||||||
|
height: 210px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pseudo-elements to fade cards as they scroll out of viewport */
|
||||||
|
#integration-list-wrapper::before,
|
||||||
|
#integration-list-wrapper::after {
|
||||||
|
content: '';
|
||||||
|
height: 192px;
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
width: var(--offset);
|
||||||
|
top: 106px;
|
||||||
|
background: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list-wrapper::before {
|
||||||
|
left: -1px;
|
||||||
|
border-left: 1px solid rgba(52, 56, 65, 1);
|
||||||
|
background: linear-gradient(to right, rgba(19, 21, 26, 1), rgba(19, 21, 26, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list-wrapper::after {
|
||||||
|
right: -1px;
|
||||||
|
border-right: 1px solid rgba(52, 56, 65, 1);
|
||||||
|
background: linear-gradient(to left, rgba(19, 21, 26, 1), rgba(19, 21, 26, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list-wrapper::-webkit-scrollbar {
|
||||||
|
width: 5px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.08); /* or add it to the track */
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is wild but gives us a gap on either side of the container */
|
||||||
|
#integration-list-wrapper::-webkit-scrollbar-button:start:decrement,
|
||||||
|
#integration-list-wrapper::-webkit-scrollbar-button:end:increment {
|
||||||
|
display: block;
|
||||||
|
width: 24px;
|
||||||
|
background-color: #13151A;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Removes arrows on both sides */
|
||||||
|
#integration-list-wrapper::-webkit-scrollbar-button:horizontal:start:increment,
|
||||||
|
#integration-list-wrapper::-webkit-scrollbar-button:horizontal:end:decrement {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list-wrapper::-webkit-scrollbar-track-piece {
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list-wrapper::-webkit-scrollbar-thumb {
|
||||||
|
background-color: rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list {
|
||||||
|
margin-top: 1em;
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list::after {
|
||||||
|
content: " ";
|
||||||
|
display: inline-block;
|
||||||
|
white-space: pre;
|
||||||
|
width: 1px;
|
||||||
|
height: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list astro-dev-toolbar-card, .integration-skeleton {
|
||||||
|
min-width: 240px;
|
||||||
|
height: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.integration-skeleton {
|
||||||
|
animation: pulse 2s calc(var(--i, 0) * 250ms) cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||||
|
background-color: rgba(35, 38, 45, 1);
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list astro-dev-toolbar-card .integration-image {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background-color: var(--integration-image-background, white);
|
||||||
|
border-radius: 9999px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list astro-dev-toolbar-card img {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list astro-dev-toolbar-card astro-dev-toolbar-icon {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
#links {
|
||||||
|
margin: auto 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#links a {
|
||||||
|
text-decoration: none;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.7em;
|
||||||
|
flex: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-weight: 600;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#links a:hover {
|
||||||
|
color: rgba(145, 152, 173, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#links astro-dev-toolbar-icon {
|
||||||
|
width: 1.5em;
|
||||||
|
height: 1.5em;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list astro-dev-toolbar-card svg {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list astro-dev-toolbar-card h3 {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
color: white;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
#integration-list astro-dev-toolbar-card p {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
svg path[fill="#fff"] {
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<section>
|
||||||
|
${astroLogo}
|
||||||
|
<astro-dev-toolbar-badge badge-style="gray" size="large">${version}</astro-dev-toolbar-badge>
|
||||||
|
${latestAstroVersion ? `<astro-dev-toolbar-badge badge-style="green" size="large">${latestAstroVersion} available!</astro-dev-toolbar-badge>
|
||||||
|
` : ""}
|
||||||
|
</section>
|
||||||
|
<astro-dev-toolbar-button id="copy-debug-button">Copy debug info <astro-dev-toolbar-icon icon="copy" /></astro-dev-toolbar-button>
|
||||||
|
</header>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div id="main-container">
|
||||||
|
<div>
|
||||||
|
<header><h2>Featured integrations</h2><a href="https://astro.build/integrations/" target="_blank">View all</a></header>
|
||||||
|
<div id="integration-list-wrapper">
|
||||||
|
<section id="integration-list">
|
||||||
|
<div class="integration-skeleton" style="--i:0;"></div>
|
||||||
|
<div class="integration-skeleton" style="--i:1;"></div>
|
||||||
|
<div class="integration-skeleton" style="--i:2;"></div>
|
||||||
|
<div class="integration-skeleton" style="--i:3;"></div>
|
||||||
|
<div class="integration-skeleton" style="--i:4;"></div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<section id="links">
|
||||||
|
${links.map(
|
||||||
|
(link) => `<a href="${link.link}" target="_blank"><astro-dev-toolbar-icon ${isDefinedIcon(link.icon) ? `icon="${link.icon}">` : `>${link.icon}`}</astro-dev-toolbar-icon>${link.name}</a>`
|
||||||
|
).join("")}
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
);
|
||||||
|
const copyDebugButton = windowComponent.querySelector("#copy-debug-button");
|
||||||
|
copyDebugButton?.addEventListener("click", () => {
|
||||||
|
navigator.clipboard.writeText("```\n" + debugInfo + "\n```");
|
||||||
|
copyDebugButton.textContent = "Copied to clipboard!";
|
||||||
|
setTimeout(() => {
|
||||||
|
resetDebugButton();
|
||||||
|
}, 3500);
|
||||||
|
});
|
||||||
|
canvas.append(windowComponent);
|
||||||
|
if (integrationData) refreshIntegrationList();
|
||||||
|
}
|
||||||
|
function resetDebugButton() {
|
||||||
|
const copyDebugButton = canvas.querySelector("#copy-debug-button");
|
||||||
|
if (!copyDebugButton) return;
|
||||||
|
copyDebugButton.innerHTML = 'Copy debug info <astro-dev-toolbar-icon icon="copy" />';
|
||||||
|
}
|
||||||
|
function refreshIntegrationList() {
|
||||||
|
const integrationList = canvas.querySelector("#integration-list");
|
||||||
|
if (!integrationList) return;
|
||||||
|
integrationList.innerHTML = "";
|
||||||
|
const fragment = document.createDocumentFragment();
|
||||||
|
for (const integration of integrationData.data) {
|
||||||
|
const integrationComponent = document.createElement("astro-dev-toolbar-card");
|
||||||
|
integrationComponent.link = integration.homepageUrl;
|
||||||
|
const integrationContainer = document.createElement("div");
|
||||||
|
integrationContainer.className = "integration-container";
|
||||||
|
const integrationImage = document.createElement("div");
|
||||||
|
integrationImage.className = "integration-image";
|
||||||
|
if (integration.image) {
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.src = integration.image;
|
||||||
|
img.alt = integration.title;
|
||||||
|
integrationImage.append(img);
|
||||||
|
} else {
|
||||||
|
const icon = document.createElement("astro-dev-toolbar-icon");
|
||||||
|
icon.icon = iconForIntegration(integration);
|
||||||
|
integrationImage.append(icon);
|
||||||
|
integrationImage.style.setProperty(
|
||||||
|
"--integration-image-background",
|
||||||
|
colorForIntegration()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
integrationContainer.append(integrationImage);
|
||||||
|
let integrationTitle = document.createElement("h3");
|
||||||
|
integrationTitle.textContent = integration.title;
|
||||||
|
if (integration.official || integration.categories.includes("official")) {
|
||||||
|
integrationTitle.innerHTML += ' <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 21 20"><rect width="19" height="19" x="1.16602" y=".5" fill="url(#paint0_linear_917_1096)" fill-opacity=".33" rx="9.5"/><path fill="#fff" d="M15.139 6.80657c-.062-.06248-.1357-.11208-.217-.14592-.0812-.03385-.1683-.05127-.2563-.05127-.0881 0-.1752.01742-.2564.05127-.0813.03384-.155.08344-.217.14592L9.22566 11.7799 7.13899 9.68657c-.06435-.06216-.14031-.11103-.22355-.14383-.08323-.03281-.17211-.04889-.26157-.04735-.08945.00155-.17773.0207-.25978.05637a.68120694.68120694 0 0 0-.21843.15148c-.06216.06435-.11104.14031-.14384.22355-.0328.08321-.04889.17211-.04734.26161.00154.0894.0207.1777.05636.2597.03566.0821.08714.1563.15148.2185l2.56 2.56c.06198.0625.13571.1121.21695.1459s.16838.0513.25639.0513c.088 0 .17514-.0175.25638-.0513s.15497-.0834.21695-.1459L15.139 7.78657c.0677-.06242.1217-.13819.1586-.22253.0369-.08433.056-.1754.056-.26747 0-.09206-.0191-.18313-.056-.26747-.0369-.08433-.0909-.1601-.1586-.22253Z"/><rect width="19" height="19" x="1.16602" y=".5" stroke="url(#paint1_linear_917_1096)" rx="9.5"/><defs><linearGradient id="paint0_linear_917_1096" x1="20.666" x2="-3.47548" y1=".00000136" y2="10.1345" gradientUnits="userSpaceOnUse"><stop stop-color="#4AF2C8"/><stop offset="1" stop-color="#2F4CB3"/></linearGradient><linearGradient id="paint1_linear_917_1096" x1="20.666" x2="-3.47548" y1=".00000136" y2="10.1345" gradientUnits="userSpaceOnUse"><stop stop-color="#4AF2C8"/><stop offset="1" stop-color="#2F4CB3"/></linearGradient></defs></svg>';
|
||||||
|
}
|
||||||
|
integrationContainer.append(integrationTitle);
|
||||||
|
const integrationDescription = document.createElement("p");
|
||||||
|
integrationDescription.textContent = integration.description.length > 90 ? integration.description.slice(0, 90) + "…" : integration.description;
|
||||||
|
integrationContainer.append(integrationDescription);
|
||||||
|
integrationComponent.append(integrationContainer);
|
||||||
|
fragment.append(integrationComponent);
|
||||||
|
}
|
||||||
|
integrationList.append(fragment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export {
|
||||||
|
astro_default as default
|
||||||
|
};
|
||||||
|
//# sourceMappingURL=astro-IQQQXCO3.js.map
|
||||||
+7
File diff suppressed because one or more lines are too long
+5
@@ -0,0 +1,5 @@
|
|||||||
|
import {
|
||||||
|
require_lib
|
||||||
|
} from "./chunk-WDCEFGHP.js";
|
||||||
|
import "./chunk-5WRI5ZAA.js";
|
||||||
|
export default require_lib();
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"sources": [],
|
||||||
|
"sourcesContent": [],
|
||||||
|
"mappings": "",
|
||||||
|
"names": []
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
import {
|
||||||
|
require_lib
|
||||||
|
} from "./chunk-WTIA47ZU.js";
|
||||||
|
import "./chunk-5WRI5ZAA.js";
|
||||||
|
export default require_lib();
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"sources": [],
|
||||||
|
"sourcesContent": [],
|
||||||
|
"mappings": "",
|
||||||
|
"names": []
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
import {
|
||||||
|
escape,
|
||||||
|
unescape
|
||||||
|
} from "./chunk-PXGSXSC7.js";
|
||||||
|
import "./chunk-5WRI5ZAA.js";
|
||||||
|
export {
|
||||||
|
escape,
|
||||||
|
unescape
|
||||||
|
};
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"sources": [],
|
||||||
|
"sourcesContent": [],
|
||||||
|
"mappings": "",
|
||||||
|
"names": []
|
||||||
|
}
|
||||||
+241
@@ -0,0 +1,241 @@
|
|||||||
|
import {
|
||||||
|
ToolbarAppEventTarget
|
||||||
|
} from "./chunk-HNT3PLDI.js";
|
||||||
|
import {
|
||||||
|
settings
|
||||||
|
} from "./chunk-LEX3GG7N.js";
|
||||||
|
import "./chunk-5WRI5ZAA.js";
|
||||||
|
|
||||||
|
// node_modules/astro/dist/runtime/client/dev-toolbar/entrypoint.js
|
||||||
|
import { loadDevToolbarApps } from "astro:toolbar:internal";
|
||||||
|
var overlay;
|
||||||
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
|
const [
|
||||||
|
customAppsDefinitions,
|
||||||
|
{ default: astroDevToolApp },
|
||||||
|
{ default: astroAuditApp },
|
||||||
|
{ default: astroXrayApp },
|
||||||
|
{ default: astroSettingsApp },
|
||||||
|
{ AstroDevToolbar, DevToolbarCanvas, getAppIcon },
|
||||||
|
{
|
||||||
|
DevToolbarCard,
|
||||||
|
DevToolbarHighlight,
|
||||||
|
DevToolbarTooltip,
|
||||||
|
DevToolbarWindow,
|
||||||
|
DevToolbarToggle,
|
||||||
|
DevToolbarButton,
|
||||||
|
DevToolbarBadge,
|
||||||
|
DevToolbarIcon,
|
||||||
|
DevToolbarSelect,
|
||||||
|
DevToolbarRadioCheckbox
|
||||||
|
}
|
||||||
|
] = await Promise.all([
|
||||||
|
loadDevToolbarApps(),
|
||||||
|
import("./astro-IQQQXCO3.js"),
|
||||||
|
import("./audit-XFDIA4TR.js"),
|
||||||
|
import("./xray-XH6VIXDC.js"),
|
||||||
|
import("./settings-K4OHAGC2.js"),
|
||||||
|
import("./toolbar-2H5PSQQU.js"),
|
||||||
|
import("./ui-library-EVFCBMCE.js")
|
||||||
|
]);
|
||||||
|
customElements.define("astro-dev-toolbar", AstroDevToolbar);
|
||||||
|
customElements.define("astro-dev-toolbar-window", DevToolbarWindow);
|
||||||
|
customElements.define("astro-dev-toolbar-app-canvas", DevToolbarCanvas);
|
||||||
|
customElements.define("astro-dev-toolbar-tooltip", DevToolbarTooltip);
|
||||||
|
customElements.define("astro-dev-toolbar-highlight", DevToolbarHighlight);
|
||||||
|
customElements.define("astro-dev-toolbar-card", DevToolbarCard);
|
||||||
|
customElements.define("astro-dev-toolbar-toggle", DevToolbarToggle);
|
||||||
|
customElements.define("astro-dev-toolbar-button", DevToolbarButton);
|
||||||
|
customElements.define("astro-dev-toolbar-badge", DevToolbarBadge);
|
||||||
|
customElements.define("astro-dev-toolbar-icon", DevToolbarIcon);
|
||||||
|
customElements.define("astro-dev-toolbar-select", DevToolbarSelect);
|
||||||
|
customElements.define("astro-dev-toolbar-radio-checkbox", DevToolbarRadioCheckbox);
|
||||||
|
overlay = document.createElement("astro-dev-toolbar");
|
||||||
|
const notificationLevels = ["error", "warning", "info"];
|
||||||
|
const notificationSVGs = {
|
||||||
|
error: '<svg viewBox="0 0 10 10" style="--fill:var(--fill-default);--fill-default:#B33E66;--fill-hover:#E3AFC1;"><rect width="9" height="9" x=".5" y=".5" fill="var(--fill)" stroke="#13151A" stroke-width="2" rx="4.5"/></svg>',
|
||||||
|
warning: '<svg width="12" height="10" fill="none" style="--fill:var(--fill-default);--fill-default:#B58A2D;--fill-hover:#D5B776;"><path fill="var(--fill)" stroke="#13151A" stroke-width="2" d="M7.29904 1.25c-.57735-1-2.02073-1-2.59808 0l-3.4641 6C.65951 8.25 1.3812 9.5 2.5359 9.5h6.9282c1.1547 0 1.8764-1.25 1.299-2.25l-3.46406-6Z"/></svg>',
|
||||||
|
info: '<svg viewBox="0 0 10 10" style="--fill:var(--fill-default);--fill-default:#3645D9;--fill-hover:#BDC3FF;"><rect width="9" height="9" x=".5" y=".5" fill="var(--fill)" stroke="#13151A" stroke-width="2" rx="1.5"/></svg>'
|
||||||
|
};
|
||||||
|
const prepareApp = (appDefinition, builtIn) => {
|
||||||
|
const eventTarget = new ToolbarAppEventTarget();
|
||||||
|
const app = {
|
||||||
|
...appDefinition,
|
||||||
|
builtIn,
|
||||||
|
active: false,
|
||||||
|
status: "loading",
|
||||||
|
notification: { state: false, level: void 0 },
|
||||||
|
eventTarget
|
||||||
|
};
|
||||||
|
eventTarget.addEventListener("toggle-notification", (evt) => {
|
||||||
|
if (!(evt instanceof CustomEvent)) return;
|
||||||
|
const target = overlay.shadowRoot?.querySelector(`[data-app-id="${app.id}"]`);
|
||||||
|
if (!target) return;
|
||||||
|
const notificationElement = target.querySelector(".notification");
|
||||||
|
if (!notificationElement) return;
|
||||||
|
let newState = evt.detail.state ?? true;
|
||||||
|
let level = notificationLevels.includes(evt?.detail?.level) ? evt.detail.level : "error";
|
||||||
|
app.notification.state = newState;
|
||||||
|
if (newState) app.notification.level = level;
|
||||||
|
notificationElement.toggleAttribute("data-active", newState);
|
||||||
|
if (newState) {
|
||||||
|
notificationElement.setAttribute("data-level", level);
|
||||||
|
notificationElement.innerHTML = notificationSVGs[level];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const onToggleApp = async (evt) => {
|
||||||
|
let newState = void 0;
|
||||||
|
if (evt instanceof CustomEvent) {
|
||||||
|
newState = evt.detail.state ?? true;
|
||||||
|
}
|
||||||
|
await overlay.setAppStatus(app, newState);
|
||||||
|
};
|
||||||
|
eventTarget.addEventListener("toggle-app", onToggleApp);
|
||||||
|
return app;
|
||||||
|
};
|
||||||
|
const astroMoreApp = {
|
||||||
|
id: "astro:more",
|
||||||
|
name: "More",
|
||||||
|
icon: "dots-three",
|
||||||
|
init(canvas, eventTarget) {
|
||||||
|
const hiddenApps = apps.filter((p) => !p.builtIn).slice(overlay.customAppsToShow);
|
||||||
|
createDropdown();
|
||||||
|
document.addEventListener("astro:after-swap", createDropdown);
|
||||||
|
function createDropdown() {
|
||||||
|
const style = document.createElement("style");
|
||||||
|
style.innerHTML = `
|
||||||
|
#dropdown {
|
||||||
|
background: rgba(19, 21, 26, 1);
|
||||||
|
border: 1px solid rgba(52, 56, 65, 1);
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0px 0px 0px 0px rgba(19, 21, 26, 0.30), 0px 1px 2px 0px rgba(19, 21, 26, 0.29), 0px 4px 4px 0px rgba(19, 21, 26, 0.26), 0px 10px 6px 0px rgba(19, 21, 26, 0.15), 0px 17px 7px 0px rgba(19, 21, 26, 0.04), 0px 26px 7px 0px rgba(19, 21, 26, 0.01);
|
||||||
|
width: 192px;
|
||||||
|
padding: 8px;
|
||||||
|
z-index: 2000000010;
|
||||||
|
transform: translate(-50%, 0%);
|
||||||
|
position: fixed;
|
||||||
|
bottom: 72px;
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: -4px;
|
||||||
|
right: -5px;
|
||||||
|
width: 12px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification svg {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dropdown:not([data-no-notification]) .notification[data-active] {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dropdown button {
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: white;
|
||||||
|
font-family: system-ui, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-decoration: none;
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dropdown button:hover, #dropdown button:focus-visible {
|
||||||
|
background: #FFFFFF20;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dropdown button.active {
|
||||||
|
background: rgba(71, 78, 94, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#dropdown .icon {
|
||||||
|
position: relative;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
padding: 1px;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dropdown .icon svg {
|
||||||
|
max-height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
canvas.append(style);
|
||||||
|
const dropdown = document.createElement("div");
|
||||||
|
dropdown.id = "dropdown";
|
||||||
|
dropdown.toggleAttribute("data-no-notification", settings.config.disableAppNotification);
|
||||||
|
for (const app of hiddenApps) {
|
||||||
|
const buttonContainer = document.createElement("div");
|
||||||
|
buttonContainer.classList.add("item");
|
||||||
|
const button = document.createElement("button");
|
||||||
|
button.setAttribute("data-app-id", app.id);
|
||||||
|
const iconContainer = document.createElement("div");
|
||||||
|
const iconElement = document.createElement("template");
|
||||||
|
iconElement.innerHTML = app.icon ? getAppIcon(app.icon) : "?";
|
||||||
|
iconContainer.append(iconElement.content.cloneNode(true));
|
||||||
|
const notification = document.createElement("div");
|
||||||
|
notification.classList.add("notification");
|
||||||
|
iconContainer.append(notification);
|
||||||
|
iconContainer.classList.add("icon");
|
||||||
|
button.append(iconContainer);
|
||||||
|
button.append(document.createTextNode(app.name));
|
||||||
|
button.addEventListener("click", () => {
|
||||||
|
overlay.toggleAppStatus(app);
|
||||||
|
});
|
||||||
|
buttonContainer.append(button);
|
||||||
|
dropdown.append(buttonContainer);
|
||||||
|
app.eventTarget.addEventListener("toggle-notification", (evt) => {
|
||||||
|
if (!(evt instanceof CustomEvent)) return;
|
||||||
|
let newState = evt.detail.state ?? true;
|
||||||
|
let level = notificationLevels.includes(evt?.detail?.level) ? evt.detail.level : "error";
|
||||||
|
notification.toggleAttribute("data-active", newState);
|
||||||
|
if (newState) {
|
||||||
|
notification.setAttribute("data-level", level);
|
||||||
|
notification.innerHTML = notificationSVGs[level];
|
||||||
|
}
|
||||||
|
app.notification.state = newState;
|
||||||
|
if (newState) app.notification.level = level;
|
||||||
|
eventTarget.dispatchEvent(
|
||||||
|
new CustomEvent("toggle-notification", {
|
||||||
|
detail: {
|
||||||
|
state: hiddenApps.some((p) => p.notification.state === true),
|
||||||
|
level: ["error", "warning", "info"].find(
|
||||||
|
(notificationLevel) => hiddenApps.some(
|
||||||
|
(p) => p.notification.state === true && p.notification.level === notificationLevel
|
||||||
|
)
|
||||||
|
) ?? "error"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
canvas.append(dropdown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const apps = [
|
||||||
|
...[astroDevToolApp, astroXrayApp, astroAuditApp, astroSettingsApp, astroMoreApp].map(
|
||||||
|
(appDef) => prepareApp(appDef, true)
|
||||||
|
),
|
||||||
|
...customAppsDefinitions.map((appDef) => prepareApp(appDef, false))
|
||||||
|
];
|
||||||
|
overlay.apps = apps;
|
||||||
|
document.body.append(overlay);
|
||||||
|
document.addEventListener("astro:after-swap", () => {
|
||||||
|
document.body.append(overlay);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
+7
File diff suppressed because one or more lines are too long
+1583
File diff suppressed because it is too large
Load Diff
+7
File diff suppressed because one or more lines are too long
+30
@@ -0,0 +1,30 @@
|
|||||||
|
var __create = Object.create;
|
||||||
|
var __defProp = Object.defineProperty;
|
||||||
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
||||||
|
var __getProtoOf = Object.getPrototypeOf;
|
||||||
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
var __commonJS = (cb, mod) => function __require() {
|
||||||
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
||||||
|
};
|
||||||
|
var __copyProps = (to, from, except, desc) => {
|
||||||
|
if (from && typeof from === "object" || typeof from === "function") {
|
||||||
|
for (let key of __getOwnPropNames(from))
|
||||||
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
||||||
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
};
|
||||||
|
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
||||||
|
// If the importer is in node compatibility mode or this is not an ESM
|
||||||
|
// file that has been converted to a CommonJS file using a Babel-
|
||||||
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
||||||
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
||||||
|
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||||
|
mod
|
||||||
|
));
|
||||||
|
|
||||||
|
export {
|
||||||
|
__commonJS,
|
||||||
|
__toESM
|
||||||
|
};
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"sources": [],
|
||||||
|
"sourcesContent": [],
|
||||||
|
"mappings": "",
|
||||||
|
"names": []
|
||||||
|
}
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
// node_modules/astro/dist/runtime/client/dev-toolbar/helpers.js
|
||||||
|
var ToolbarAppEventTarget = class extends EventTarget {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Toggle the notification state of the toolbar
|
||||||
|
* @param options - The notification options
|
||||||
|
* @param options.state - The state of the notification
|
||||||
|
* @param options.level - The level of the notification, optional when state is false
|
||||||
|
*/
|
||||||
|
toggleNotification(options) {
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent("toggle-notification", {
|
||||||
|
detail: {
|
||||||
|
state: options.state,
|
||||||
|
level: options.state === true ? options.level : void 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Toggle the app state on or off
|
||||||
|
* @param options - The app state options
|
||||||
|
* @param options.state - The new state of the app
|
||||||
|
*/
|
||||||
|
toggleState(options) {
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent("toggle-app", {
|
||||||
|
detail: {
|
||||||
|
state: options.state
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Fired when the app is toggled on or off
|
||||||
|
* @param callback - The callback to run when the event is fired, takes an object with the new state
|
||||||
|
*/
|
||||||
|
onToggled(callback) {
|
||||||
|
this.addEventListener("app-toggled", (evt) => {
|
||||||
|
if (!(evt instanceof CustomEvent)) return;
|
||||||
|
callback(evt.detail);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Fired when the toolbar placement is updated by the user
|
||||||
|
* @param callback - The callback to run when the event is fired, takes an object with the new placement
|
||||||
|
*/
|
||||||
|
onToolbarPlacementUpdated(callback) {
|
||||||
|
this.addEventListener("placement-updated", (evt) => {
|
||||||
|
if (!(evt instanceof CustomEvent)) return;
|
||||||
|
callback(evt.detail);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var serverHelpers = {
|
||||||
|
/**
|
||||||
|
* Send a message to the server, the payload can be any serializable data.
|
||||||
|
*
|
||||||
|
* The server can listen for this message in the `astro:server:config` hook of an Astro integration, using the `toolbar.on` method.
|
||||||
|
*
|
||||||
|
* @param event - The event name
|
||||||
|
* @param payload - The payload to send
|
||||||
|
*/
|
||||||
|
send: (event, payload) => {
|
||||||
|
if (import.meta.hot) {
|
||||||
|
import.meta.hot.send(event, payload);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Receive a message from the server.
|
||||||
|
* @param event - The event name
|
||||||
|
* @param callback - The callback to run when the event is received.
|
||||||
|
* The payload's content will be passed to the callback as an argument
|
||||||
|
*/
|
||||||
|
on: (event, callback) => {
|
||||||
|
if (import.meta.hot) {
|
||||||
|
import.meta.hot.on(event, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
ToolbarAppEventTarget,
|
||||||
|
serverHelpers
|
||||||
|
};
|
||||||
|
//# sourceMappingURL=chunk-HNT3PLDI.js.map
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"sources": ["../../astro/dist/runtime/client/dev-toolbar/helpers.js"],
|
||||||
|
"sourcesContent": ["class ToolbarAppEventTarget extends EventTarget {\n constructor() {\n super();\n }\n /**\n * Toggle the notification state of the toolbar\n * @param options - The notification options\n * @param options.state - The state of the notification\n * @param options.level - The level of the notification, optional when state is false\n */\n toggleNotification(options) {\n this.dispatchEvent(\n new CustomEvent(\"toggle-notification\", {\n detail: {\n state: options.state,\n level: options.state === true ? options.level : void 0\n }\n })\n );\n }\n /**\n * Toggle the app state on or off\n * @param options - The app state options\n * @param options.state - The new state of the app\n */\n toggleState(options) {\n this.dispatchEvent(\n new CustomEvent(\"toggle-app\", {\n detail: {\n state: options.state\n }\n })\n );\n }\n /**\n * Fired when the app is toggled on or off\n * @param callback - The callback to run when the event is fired, takes an object with the new state\n */\n onToggled(callback) {\n this.addEventListener(\"app-toggled\", (evt) => {\n if (!(evt instanceof CustomEvent)) return;\n callback(evt.detail);\n });\n }\n /**\n * Fired when the toolbar placement is updated by the user\n * @param callback - The callback to run when the event is fired, takes an object with the new placement\n */\n onToolbarPlacementUpdated(callback) {\n this.addEventListener(\"placement-updated\", (evt) => {\n if (!(evt instanceof CustomEvent)) return;\n callback(evt.detail);\n });\n }\n}\nconst serverHelpers = {\n /**\n * Send a message to the server, the payload can be any serializable data.\n *\n * The server can listen for this message in the `astro:server:config` hook of an Astro integration, using the `toolbar.on` method.\n *\n * @param event - The event name\n * @param payload - The payload to send\n */\n send: (event, payload) => {\n if (import.meta.hot) {\n import.meta.hot.send(event, payload);\n }\n },\n /**\n * Receive a message from the server.\n * @param event - The event name\n * @param callback - The callback to run when the event is received.\n * The payload's content will be passed to the callback as an argument\n */\n on: (event, callback) => {\n if (import.meta.hot) {\n import.meta.hot.on(event, callback);\n }\n }\n};\nexport {\n ToolbarAppEventTarget,\n serverHelpers\n};\n"],
|
||||||
|
"mappings": ";AAAA,IAAM,wBAAN,cAAoC,YAAY;AAAA,EAC9C,cAAc;AACZ,UAAM;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAmB,SAAS;AAC1B,SAAK;AAAA,MACH,IAAI,YAAY,uBAAuB;AAAA,QACrC,QAAQ;AAAA,UACN,OAAO,QAAQ;AAAA,UACf,OAAO,QAAQ,UAAU,OAAO,QAAQ,QAAQ;AAAA,QAClD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,SAAS;AACnB,SAAK;AAAA,MACH,IAAI,YAAY,cAAc;AAAA,QAC5B,QAAQ;AAAA,UACN,OAAO,QAAQ;AAAA,QACjB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,UAAU;AAClB,SAAK,iBAAiB,eAAe,CAAC,QAAQ;AAC5C,UAAI,EAAE,eAAe,aAAc;AACnC,eAAS,IAAI,MAAM;AAAA,IACrB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA,0BAA0B,UAAU;AAClC,SAAK,iBAAiB,qBAAqB,CAAC,QAAQ;AAClD,UAAI,EAAE,eAAe,aAAc;AACnC,eAAS,IAAI,MAAM;AAAA,IACrB,CAAC;AAAA,EACH;AACF;AACA,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASpB,MAAM,CAAC,OAAO,YAAY;AACxB,QAAI,YAAY,KAAK;AACnB,kBAAY,IAAI,KAAK,OAAO,OAAO;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,CAAC,OAAO,aAAa;AACvB,QAAI,YAAY,KAAK;AACnB,kBAAY,IAAI,GAAG,OAAO,QAAQ;AAAA,IACpC;AAAA,EACF;AACF;",
|
||||||
|
"names": []
|
||||||
|
}
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
// node_modules/astro/dist/runtime/client/dev-toolbar/apps/utils/highlight.js
|
||||||
|
function createHighlight(rect, icon, additionalAttributes) {
|
||||||
|
const highlight = document.createElement("astro-dev-toolbar-highlight");
|
||||||
|
if (icon) highlight.icon = icon;
|
||||||
|
if (additionalAttributes) {
|
||||||
|
for (const [key, value] of Object.entries(additionalAttributes)) {
|
||||||
|
highlight.setAttribute(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
highlight.tabIndex = 0;
|
||||||
|
if (rect.width === 0 || rect.height === 0) {
|
||||||
|
highlight.style.display = "none";
|
||||||
|
} else {
|
||||||
|
positionHighlight(highlight, rect);
|
||||||
|
}
|
||||||
|
return highlight;
|
||||||
|
}
|
||||||
|
function getElementsPositionInDocument(el) {
|
||||||
|
let isFixed = false;
|
||||||
|
let current = el;
|
||||||
|
while (current instanceof Element) {
|
||||||
|
let style = getComputedStyle(current);
|
||||||
|
if (style.position === "fixed") {
|
||||||
|
isFixed = true;
|
||||||
|
}
|
||||||
|
current = current.parentNode;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
isFixed
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function positionHighlight(highlight, rect) {
|
||||||
|
highlight.style.display = "block";
|
||||||
|
const scrollY = highlight.style.position === "fixed" ? 0 : window.scrollY;
|
||||||
|
highlight.style.top = `${Math.max(rect.top + scrollY - 10, 0)}px`;
|
||||||
|
highlight.style.left = `${Math.max(rect.left + window.scrollX - 10, 0)}px`;
|
||||||
|
highlight.style.width = `${rect.width + 15}px`;
|
||||||
|
highlight.style.height = `${rect.height + 15}px`;
|
||||||
|
}
|
||||||
|
function attachTooltipToHighlight(highlight, tooltip, originalElement) {
|
||||||
|
highlight.shadowRoot.append(tooltip);
|
||||||
|
["mouseover", "focus"].forEach((event) => {
|
||||||
|
highlight.addEventListener(event, () => {
|
||||||
|
tooltip.dataset.show = "true";
|
||||||
|
const originalRect = originalElement.getBoundingClientRect();
|
||||||
|
const dialogRect = tooltip.getBoundingClientRect();
|
||||||
|
if (originalRect.top < dialogRect.height) {
|
||||||
|
tooltip.style.top = `${originalRect.height + 15}px`;
|
||||||
|
} else {
|
||||||
|
tooltip.style.top = `-${tooltip.offsetHeight}px`;
|
||||||
|
}
|
||||||
|
if (dialogRect.right > document.documentElement.clientWidth) {
|
||||||
|
tooltip.style.right = "0px";
|
||||||
|
} else if (dialogRect.left < 0) {
|
||||||
|
tooltip.style.left = "0px";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
["mouseout", "blur"].forEach((event) => {
|
||||||
|
highlight.addEventListener(event, () => {
|
||||||
|
tooltip.dataset.show = "false";
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
createHighlight,
|
||||||
|
getElementsPositionInDocument,
|
||||||
|
positionHighlight,
|
||||||
|
attachTooltipToHighlight
|
||||||
|
};
|
||||||
|
//# sourceMappingURL=chunk-LEAOZWS7.js.map
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"sources": ["../../astro/dist/runtime/client/dev-toolbar/apps/utils/highlight.js"],
|
||||||
|
"sourcesContent": ["function createHighlight(rect, icon, additionalAttributes) {\n const highlight = document.createElement(\"astro-dev-toolbar-highlight\");\n if (icon) highlight.icon = icon;\n if (additionalAttributes) {\n for (const [key, value] of Object.entries(additionalAttributes)) {\n highlight.setAttribute(key, value);\n }\n }\n highlight.tabIndex = 0;\n if (rect.width === 0 || rect.height === 0) {\n highlight.style.display = \"none\";\n } else {\n positionHighlight(highlight, rect);\n }\n return highlight;\n}\nfunction getElementsPositionInDocument(el) {\n let isFixed = false;\n let current = el;\n while (current instanceof Element) {\n let style = getComputedStyle(current);\n if (style.position === \"fixed\") {\n isFixed = true;\n }\n current = current.parentNode;\n }\n return {\n isFixed\n };\n}\nfunction positionHighlight(highlight, rect) {\n highlight.style.display = \"block\";\n const scrollY = highlight.style.position === \"fixed\" ? 0 : window.scrollY;\n highlight.style.top = `${Math.max(rect.top + scrollY - 10, 0)}px`;\n highlight.style.left = `${Math.max(rect.left + window.scrollX - 10, 0)}px`;\n highlight.style.width = `${rect.width + 15}px`;\n highlight.style.height = `${rect.height + 15}px`;\n}\nfunction attachTooltipToHighlight(highlight, tooltip, originalElement) {\n highlight.shadowRoot.append(tooltip);\n [\"mouseover\", \"focus\"].forEach((event) => {\n highlight.addEventListener(event, () => {\n tooltip.dataset.show = \"true\";\n const originalRect = originalElement.getBoundingClientRect();\n const dialogRect = tooltip.getBoundingClientRect();\n if (originalRect.top < dialogRect.height) {\n tooltip.style.top = `${originalRect.height + 15}px`;\n } else {\n tooltip.style.top = `-${tooltip.offsetHeight}px`;\n }\n if (dialogRect.right > document.documentElement.clientWidth) {\n tooltip.style.right = \"0px\";\n } else if (dialogRect.left < 0) {\n tooltip.style.left = \"0px\";\n }\n });\n });\n [\"mouseout\", \"blur\"].forEach((event) => {\n highlight.addEventListener(event, () => {\n tooltip.dataset.show = \"false\";\n });\n });\n}\nexport {\n attachTooltipToHighlight,\n createHighlight,\n getElementsPositionInDocument,\n positionHighlight\n};\n"],
|
||||||
|
"mappings": ";AAAA,SAAS,gBAAgB,MAAM,MAAM,sBAAsB;AACzD,QAAM,YAAY,SAAS,cAAc,6BAA6B;AACtE,MAAI,KAAM,WAAU,OAAO;AAC3B,MAAI,sBAAsB;AACxB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,oBAAoB,GAAG;AAC/D,gBAAU,aAAa,KAAK,KAAK;AAAA,IACnC;AAAA,EACF;AACA,YAAU,WAAW;AACrB,MAAI,KAAK,UAAU,KAAK,KAAK,WAAW,GAAG;AACzC,cAAU,MAAM,UAAU;AAAA,EAC5B,OAAO;AACL,sBAAkB,WAAW,IAAI;AAAA,EACnC;AACA,SAAO;AACT;AACA,SAAS,8BAA8B,IAAI;AACzC,MAAI,UAAU;AACd,MAAI,UAAU;AACd,SAAO,mBAAmB,SAAS;AACjC,QAAI,QAAQ,iBAAiB,OAAO;AACpC,QAAI,MAAM,aAAa,SAAS;AAC9B,gBAAU;AAAA,IACZ;AACA,cAAU,QAAQ;AAAA,EACpB;AACA,SAAO;AAAA,IACL;AAAA,EACF;AACF;AACA,SAAS,kBAAkB,WAAW,MAAM;AAC1C,YAAU,MAAM,UAAU;AAC1B,QAAM,UAAU,UAAU,MAAM,aAAa,UAAU,IAAI,OAAO;AAClE,YAAU,MAAM,MAAM,GAAG,KAAK,IAAI,KAAK,MAAM,UAAU,IAAI,CAAC,CAAC;AAC7D,YAAU,MAAM,OAAO,GAAG,KAAK,IAAI,KAAK,OAAO,OAAO,UAAU,IAAI,CAAC,CAAC;AACtE,YAAU,MAAM,QAAQ,GAAG,KAAK,QAAQ,EAAE;AAC1C,YAAU,MAAM,SAAS,GAAG,KAAK,SAAS,EAAE;AAC9C;AACA,SAAS,yBAAyB,WAAW,SAAS,iBAAiB;AACrE,YAAU,WAAW,OAAO,OAAO;AACnC,GAAC,aAAa,OAAO,EAAE,QAAQ,CAAC,UAAU;AACxC,cAAU,iBAAiB,OAAO,MAAM;AACtC,cAAQ,QAAQ,OAAO;AACvB,YAAM,eAAe,gBAAgB,sBAAsB;AAC3D,YAAM,aAAa,QAAQ,sBAAsB;AACjD,UAAI,aAAa,MAAM,WAAW,QAAQ;AACxC,gBAAQ,MAAM,MAAM,GAAG,aAAa,SAAS,EAAE;AAAA,MACjD,OAAO;AACL,gBAAQ,MAAM,MAAM,IAAI,QAAQ,YAAY;AAAA,MAC9C;AACA,UAAI,WAAW,QAAQ,SAAS,gBAAgB,aAAa;AAC3D,gBAAQ,MAAM,QAAQ;AAAA,MACxB,WAAW,WAAW,OAAO,GAAG;AAC9B,gBAAQ,MAAM,OAAO;AAAA,MACvB;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACD,GAAC,YAAY,MAAM,EAAE,QAAQ,CAAC,UAAU;AACtC,cAAU,iBAAiB,OAAO,MAAM;AACtC,cAAQ,QAAQ,OAAO;AAAA,IACzB,CAAC;AAAA,EACH,CAAC;AACH;",
|
||||||
|
"names": []
|
||||||
|
}
|
||||||
+186
@@ -0,0 +1,186 @@
|
|||||||
|
// node_modules/astro/dist/runtime/client/dev-toolbar/settings.js
|
||||||
|
var defaultSettings = {
|
||||||
|
disableAppNotification: false,
|
||||||
|
verbose: false,
|
||||||
|
placement: "bottom-center"
|
||||||
|
};
|
||||||
|
var settings = getSettings();
|
||||||
|
function getSettings() {
|
||||||
|
let _settings = { ...defaultSettings };
|
||||||
|
const configPlacement = globalThis.__astro_dev_toolbar__?.placement;
|
||||||
|
if (configPlacement && isValidPlacement(configPlacement)) {
|
||||||
|
_settings.placement = configPlacement;
|
||||||
|
}
|
||||||
|
const toolbarSettings = localStorage.getItem("astro:dev-toolbar:settings");
|
||||||
|
if (toolbarSettings) {
|
||||||
|
_settings = { ..._settings, ...JSON.parse(toolbarSettings) };
|
||||||
|
}
|
||||||
|
function updateSetting(key, value) {
|
||||||
|
_settings[key] = value;
|
||||||
|
localStorage.setItem("astro:dev-toolbar:settings", JSON.stringify(_settings));
|
||||||
|
}
|
||||||
|
function log(message, level = "log") {
|
||||||
|
console[level](
|
||||||
|
`%cAstro`,
|
||||||
|
"background: linear-gradient(66.77deg, #D83333 0%, #F041FF 100%); color: white; padding-inline: 4px; border-radius: 2px; font-family: monospace;",
|
||||||
|
message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
get config() {
|
||||||
|
return _settings;
|
||||||
|
},
|
||||||
|
updateSetting,
|
||||||
|
logger: {
|
||||||
|
log,
|
||||||
|
warn: (message) => {
|
||||||
|
log(message, "warn");
|
||||||
|
},
|
||||||
|
error: (message) => {
|
||||||
|
log(message, "error");
|
||||||
|
},
|
||||||
|
verboseLog: (message) => {
|
||||||
|
if (_settings.verbose) {
|
||||||
|
log(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// node_modules/astro/dist/runtime/client/dev-toolbar/ui-library/window.js
|
||||||
|
var placements = ["bottom-left", "bottom-center", "bottom-right"];
|
||||||
|
function isValidPlacement(value) {
|
||||||
|
return placements.map(String).includes(value);
|
||||||
|
}
|
||||||
|
var DevToolbarWindow = class extends HTMLElement {
|
||||||
|
shadowRoot;
|
||||||
|
_placement = defaultSettings.placement;
|
||||||
|
get placement() {
|
||||||
|
return this._placement;
|
||||||
|
}
|
||||||
|
set placement(value) {
|
||||||
|
if (!isValidPlacement(value)) {
|
||||||
|
settings.logger.error(
|
||||||
|
`Invalid placement: ${value}, expected one of ${placements.join(", ")}, got ${value}.`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._placement = value;
|
||||||
|
this.updateStyle();
|
||||||
|
}
|
||||||
|
static observedAttributes = ["placement"];
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.shadowRoot = this.attachShadow({ mode: "open" });
|
||||||
|
}
|
||||||
|
async connectedCallback() {
|
||||||
|
this.shadowRoot.innerHTML = `
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: linear-gradient(0deg, #13151A, #13151A), linear-gradient(0deg, #343841, #343841);
|
||||||
|
border: 1px solid rgba(52, 56, 65, 1);
|
||||||
|
width: min(640px, 100%);
|
||||||
|
max-height: 480px;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
|
color: rgba(191, 193, 201, 1);
|
||||||
|
position: fixed;
|
||||||
|
z-index: 999999999;
|
||||||
|
bottom: 72px;
|
||||||
|
box-shadow: 0px 0px 0px 0px rgba(19, 21, 26, 0.30), 0px 1px 2px 0px rgba(19, 21, 26, 0.29), 0px 4px 4px 0px rgba(19, 21, 26, 0.26), 0px 10px 6px 0px rgba(19, 21, 26, 0.15), 0px 17px 7px 0px rgba(19, 21, 26, 0.04), 0px 26px 7px 0px rgba(19, 21, 26, 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
:host {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
:host {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::slotted(h1), ::slotted(h2), ::slotted(h3), ::slotted(h4), ::slotted(h5) {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
::slotted(h1) {
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::slotted(h2) {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::slotted(h3) {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::slotted(h4) {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::slotted(h5) {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr, ::slotted(hr) {
|
||||||
|
border: 1px solid rgba(27, 30, 36, 1);
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, ::slotted(p) {
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style id="selected-style"></style>
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
`;
|
||||||
|
this.updateStyle();
|
||||||
|
}
|
||||||
|
attributeChangedCallback() {
|
||||||
|
if (this.hasAttribute("placement"))
|
||||||
|
this.placement = this.getAttribute("placement");
|
||||||
|
}
|
||||||
|
updateStyle() {
|
||||||
|
const style = this.shadowRoot.querySelector("#selected-style");
|
||||||
|
if (style) {
|
||||||
|
const styleMap = {
|
||||||
|
"bottom-left": `
|
||||||
|
:host {
|
||||||
|
left: 16px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
"bottom-center": `
|
||||||
|
:host {
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
"bottom-right": `
|
||||||
|
:host {
|
||||||
|
right: 16px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
};
|
||||||
|
style.innerHTML = styleMap[this.placement];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export {
|
||||||
|
placements,
|
||||||
|
isValidPlacement,
|
||||||
|
DevToolbarWindow,
|
||||||
|
settings
|
||||||
|
};
|
||||||
|
//# sourceMappingURL=chunk-LEX3GG7N.js.map
|
||||||
+7
File diff suppressed because one or more lines are too long
+33
@@ -0,0 +1,33 @@
|
|||||||
|
// node_modules/html-escaper/esm/index.js
|
||||||
|
var { replace } = "";
|
||||||
|
var es = /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34);/g;
|
||||||
|
var ca = /[&<>'"]/g;
|
||||||
|
var esca = {
|
||||||
|
"&": "&",
|
||||||
|
"<": "<",
|
||||||
|
">": ">",
|
||||||
|
"'": "'",
|
||||||
|
'"': """
|
||||||
|
};
|
||||||
|
var pe = (m) => esca[m];
|
||||||
|
var escape = (es2) => replace.call(es2, ca, pe);
|
||||||
|
var unes = {
|
||||||
|
"&": "&",
|
||||||
|
"&": "&",
|
||||||
|
"<": "<",
|
||||||
|
"<": "<",
|
||||||
|
">": ">",
|
||||||
|
">": ">",
|
||||||
|
"'": "'",
|
||||||
|
"'": "'",
|
||||||
|
""": '"',
|
||||||
|
""": '"'
|
||||||
|
};
|
||||||
|
var cape = (m) => unes[m];
|
||||||
|
var unescape = (un) => replace.call(un, es, cape);
|
||||||
|
|
||||||
|
export {
|
||||||
|
escape,
|
||||||
|
unescape
|
||||||
|
};
|
||||||
|
//# sourceMappingURL=chunk-PXGSXSC7.js.map
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"sources": ["../../html-escaper/esm/index.js"],
|
||||||
|
"sourcesContent": ["/**\n * Copyright (C) 2017-present by Andrea Giammarchi - @WebReflection\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n\nconst {replace} = '';\n\n// escape\nconst es = /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34);/g;\nconst ca = /[&<>'\"]/g;\n\nconst esca = {\n '&': '&',\n '<': '<',\n '>': '>',\n \"'\": ''',\n '\"': '"'\n};\nconst pe = m => esca[m];\n\n/**\n * Safely escape HTML entities such as `&`, `<`, `>`, `\"`, and `'`.\n * @param {string} es the input to safely escape\n * @returns {string} the escaped input, and it **throws** an error if\n * the input type is unexpected, except for boolean and numbers,\n * converted as string.\n */\nexport const escape = es => replace.call(es, ca, pe);\n\n\n// unescape\nconst unes = {\n '&': '&',\n '&': '&',\n '<': '<',\n '<': '<',\n '>': '>',\n '>': '>',\n ''': \"'\",\n ''': \"'\",\n '"': '\"',\n '"': '\"'\n};\nconst cape = m => unes[m];\n\n/**\n * Safely unescape previously escaped entities such as `&`, `<`, `>`, `\"`,\n * and `'`.\n * @param {string} un a previously escaped string\n * @returns {string} the unescaped input, and it **throws** an error if\n * the input type is unexpected, except for boolean and numbers,\n * converted as string.\n */\nexport const unescape = un => replace.call(un, es, cape);\n"],
|
||||||
|
"mappings": ";AAsBA,IAAM,EAAC,QAAO,IAAI;AAGlB,IAAM,KAAK;AACX,IAAM,KAAK;AAEX,IAAM,OAAO;AAAA,EACX,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AACA,IAAM,KAAK,OAAK,KAAK,CAAC;AASf,IAAM,SAAS,CAAAA,QAAM,QAAQ,KAAKA,KAAI,IAAI,EAAE;AAInD,IAAM,OAAO;AAAA,EACX,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,SAAS;AACX;AACA,IAAM,OAAO,OAAK,KAAK,CAAC;AAUjB,IAAM,WAAW,QAAM,QAAQ,KAAK,IAAI,IAAI,IAAI;",
|
||||||
|
"names": ["es"]
|
||||||
|
}
|
||||||
+6779
File diff suppressed because it is too large
Load Diff
+7
File diff suppressed because one or more lines are too long
+54
@@ -0,0 +1,54 @@
|
|||||||
|
import {
|
||||||
|
settings
|
||||||
|
} from "./chunk-LEX3GG7N.js";
|
||||||
|
|
||||||
|
// node_modules/astro/dist/runtime/client/dev-toolbar/apps/utils/window.js
|
||||||
|
function createWindowElement(content, placement = settings.config.placement) {
|
||||||
|
const windowElement = document.createElement("astro-dev-toolbar-window");
|
||||||
|
windowElement.innerHTML = content;
|
||||||
|
windowElement.placement = placement;
|
||||||
|
return windowElement;
|
||||||
|
}
|
||||||
|
function closeOnOutsideClick(eventTarget, additionalCheck) {
|
||||||
|
function onPageClick(event) {
|
||||||
|
const target = event.target;
|
||||||
|
if (!target) return;
|
||||||
|
if (!target.closest) return;
|
||||||
|
if (target.closest("astro-dev-toolbar")) return;
|
||||||
|
if (additionalCheck && additionalCheck(target)) return;
|
||||||
|
eventTarget.dispatchEvent(
|
||||||
|
new CustomEvent("toggle-app", {
|
||||||
|
detail: {
|
||||||
|
state: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
eventTarget.addEventListener("app-toggled", (event) => {
|
||||||
|
if (event.detail.state === true) {
|
||||||
|
document.addEventListener("click", onPageClick, true);
|
||||||
|
} else {
|
||||||
|
document.removeEventListener("click", onPageClick, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function synchronizePlacementOnUpdate(eventTarget, canvas) {
|
||||||
|
eventTarget.addEventListener("placement-updated", (evt) => {
|
||||||
|
if (!(evt instanceof CustomEvent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const windowElement = canvas.querySelector("astro-dev-toolbar-window");
|
||||||
|
if (!windowElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const event = evt;
|
||||||
|
windowElement.placement = event.detail.placement;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
createWindowElement,
|
||||||
|
closeOnOutsideClick,
|
||||||
|
synchronizePlacementOnUpdate
|
||||||
|
};
|
||||||
|
//# sourceMappingURL=chunk-WM2KMMIK.js.map
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"sources": ["../../astro/dist/runtime/client/dev-toolbar/apps/utils/window.js"],
|
||||||
|
"sourcesContent": ["import { settings } from \"../../settings.js\";\nfunction createWindowElement(content, placement = settings.config.placement) {\n const windowElement = document.createElement(\"astro-dev-toolbar-window\");\n windowElement.innerHTML = content;\n windowElement.placement = placement;\n return windowElement;\n}\nfunction closeOnOutsideClick(eventTarget, additionalCheck) {\n function onPageClick(event) {\n const target = event.target;\n if (!target) return;\n if (!target.closest) return;\n if (target.closest(\"astro-dev-toolbar\")) return;\n if (additionalCheck && additionalCheck(target)) return;\n eventTarget.dispatchEvent(\n new CustomEvent(\"toggle-app\", {\n detail: {\n state: false\n }\n })\n );\n }\n eventTarget.addEventListener(\"app-toggled\", (event) => {\n if (event.detail.state === true) {\n document.addEventListener(\"click\", onPageClick, true);\n } else {\n document.removeEventListener(\"click\", onPageClick, true);\n }\n });\n}\nfunction synchronizePlacementOnUpdate(eventTarget, canvas) {\n eventTarget.addEventListener(\"placement-updated\", (evt) => {\n if (!(evt instanceof CustomEvent)) {\n return;\n }\n const windowElement = canvas.querySelector(\"astro-dev-toolbar-window\");\n if (!windowElement) {\n return;\n }\n const event = evt;\n windowElement.placement = event.detail.placement;\n });\n}\nexport {\n closeOnOutsideClick,\n createWindowElement,\n synchronizePlacementOnUpdate\n};\n"],
|
||||||
|
"mappings": ";;;;;AACA,SAAS,oBAAoB,SAAS,YAAY,SAAS,OAAO,WAAW;AAC3E,QAAM,gBAAgB,SAAS,cAAc,0BAA0B;AACvE,gBAAc,YAAY;AAC1B,gBAAc,YAAY;AAC1B,SAAO;AACT;AACA,SAAS,oBAAoB,aAAa,iBAAiB;AACzD,WAAS,YAAY,OAAO;AAC1B,UAAM,SAAS,MAAM;AACrB,QAAI,CAAC,OAAQ;AACb,QAAI,CAAC,OAAO,QAAS;AACrB,QAAI,OAAO,QAAQ,mBAAmB,EAAG;AACzC,QAAI,mBAAmB,gBAAgB,MAAM,EAAG;AAChD,gBAAY;AAAA,MACV,IAAI,YAAY,cAAc;AAAA,QAC5B,QAAQ;AAAA,UACN,OAAO;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACA,cAAY,iBAAiB,eAAe,CAAC,UAAU;AACrD,QAAI,MAAM,OAAO,UAAU,MAAM;AAC/B,eAAS,iBAAiB,SAAS,aAAa,IAAI;AAAA,IACtD,OAAO;AACL,eAAS,oBAAoB,SAAS,aAAa,IAAI;AAAA,IACzD;AAAA,EACF,CAAC;AACH;AACA,SAAS,6BAA6B,aAAa,QAAQ;AACzD,cAAY,iBAAiB,qBAAqB,CAAC,QAAQ;AACzD,QAAI,EAAE,eAAe,cAAc;AACjC;AAAA,IACF;AACA,UAAM,gBAAgB,OAAO,cAAc,0BAA0B;AACrE,QAAI,CAAC,eAAe;AAClB;AAAA,IACF;AACA,UAAM,QAAQ;AACd,kBAAc,YAAY,MAAM,OAAO;AAAA,EACzC,CAAC;AACH;",
|
||||||
|
"names": []
|
||||||
|
}
|
||||||
+3757
File diff suppressed because one or more lines are too long
+7
File diff suppressed because one or more lines are too long
+48
File diff suppressed because one or more lines are too long
+7
File diff suppressed because one or more lines are too long
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"type": "module"
|
||||||
|
}
|
||||||
+213
@@ -0,0 +1,213 @@
|
|||||||
|
import {
|
||||||
|
closeOnOutsideClick,
|
||||||
|
createWindowElement,
|
||||||
|
synchronizePlacementOnUpdate
|
||||||
|
} from "./chunk-WM2KMMIK.js";
|
||||||
|
import {
|
||||||
|
isValidPlacement,
|
||||||
|
placements,
|
||||||
|
settings
|
||||||
|
} from "./chunk-LEX3GG7N.js";
|
||||||
|
import "./chunk-5WRI5ZAA.js";
|
||||||
|
|
||||||
|
// node_modules/astro/dist/runtime/client/dev-toolbar/apps/settings.js
|
||||||
|
var settingsRows = [
|
||||||
|
{
|
||||||
|
name: "Disable notifications",
|
||||||
|
description: "Hide notification badges in the toolbar.",
|
||||||
|
input: "checkbox",
|
||||||
|
settingKey: "disableAppNotification",
|
||||||
|
changeEvent: (evt) => {
|
||||||
|
if (evt.currentTarget instanceof HTMLInputElement) {
|
||||||
|
const devToolbar = document.querySelector("astro-dev-toolbar");
|
||||||
|
if (devToolbar) {
|
||||||
|
devToolbar.setNotificationVisible(!evt.currentTarget.checked);
|
||||||
|
}
|
||||||
|
settings.updateSetting("disableAppNotification", evt.currentTarget.checked);
|
||||||
|
const action = evt.currentTarget.checked ? "disabled" : "enabled";
|
||||||
|
settings.logger.verboseLog(`App notification badges ${action}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Verbose logging",
|
||||||
|
description: "Logs dev toolbar events in the browser console.",
|
||||||
|
input: "checkbox",
|
||||||
|
settingKey: "verbose",
|
||||||
|
changeEvent: (evt) => {
|
||||||
|
if (evt.currentTarget instanceof HTMLInputElement) {
|
||||||
|
settings.updateSetting("verbose", evt.currentTarget.checked);
|
||||||
|
const action = evt.currentTarget.checked ? "enabled" : "disabled";
|
||||||
|
settings.logger.verboseLog(`Verbose logging ${action}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Placement",
|
||||||
|
description: "Adjust the placement of the dev toolbar.",
|
||||||
|
input: "select",
|
||||||
|
settingKey: "placement",
|
||||||
|
changeEvent: (evt) => {
|
||||||
|
if (evt.currentTarget instanceof HTMLSelectElement) {
|
||||||
|
const placement = evt.currentTarget.value;
|
||||||
|
if (isValidPlacement(placement)) {
|
||||||
|
document.querySelector("astro-dev-toolbar")?.setToolbarPlacement(placement);
|
||||||
|
settings.updateSetting("placement", placement);
|
||||||
|
settings.logger.verboseLog(`Placement set to ${placement}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
var settings_default = {
|
||||||
|
id: "astro:settings",
|
||||||
|
name: "Settings",
|
||||||
|
icon: "gear",
|
||||||
|
init(canvas, eventTarget) {
|
||||||
|
createSettingsWindow();
|
||||||
|
document.addEventListener("astro:after-swap", createSettingsWindow);
|
||||||
|
closeOnOutsideClick(eventTarget);
|
||||||
|
synchronizePlacementOnUpdate(eventTarget, canvas);
|
||||||
|
function createSettingsWindow() {
|
||||||
|
const windowElement = createWindowElement(
|
||||||
|
`<style>
|
||||||
|
:host astro-dev-toolbar-window {
|
||||||
|
height: 480px;
|
||||||
|
overflow-y: auto;
|
||||||
|
color-scheme: dark;
|
||||||
|
|
||||||
|
--color-purple: rgba(224, 204, 250, 1);
|
||||||
|
}
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2, h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: white;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fff;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
astro-dev-toolbar-icon {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
color: var(--color-purple);
|
||||||
|
border-color: #343841;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: .4em;
|
||||||
|
background-color: #24262D;
|
||||||
|
padding: .3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
label > section {
|
||||||
|
max-width: 67%;
|
||||||
|
}
|
||||||
|
label > section.full-width {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
a, a:visited {
|
||||||
|
color: var(--color-purple);
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #f4ecfd;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<header>
|
||||||
|
<h1><astro-dev-toolbar-icon icon="gear"></astro-dev-toolbar-icon> Settings</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<hr id="general"/>
|
||||||
|
|
||||||
|
<label class="setting-row">
|
||||||
|
<section class="full-width">
|
||||||
|
<h3>Hide toolbar</h3>
|
||||||
|
Run <code>astro preferences disable devToolbar</code> in your terminal to disable the toolbar. <a href="https://docs.astro.build/en/reference/cli-reference/#astro-preferences" target="_blank">Learn more</a>.
|
||||||
|
</section>
|
||||||
|
</label>
|
||||||
|
`
|
||||||
|
);
|
||||||
|
const general = windowElement.querySelector("#general");
|
||||||
|
for (const settingsRow of settingsRows) {
|
||||||
|
general.after(document.createElement("hr"));
|
||||||
|
general.after(getElementForSettingAsString(settingsRow));
|
||||||
|
}
|
||||||
|
canvas.append(windowElement);
|
||||||
|
function getElementForSettingAsString(setting) {
|
||||||
|
const label = document.createElement("label");
|
||||||
|
label.classList.add("setting-row");
|
||||||
|
const section = document.createElement("section");
|
||||||
|
section.innerHTML = `<h3>${setting.name}</h3>${setting.description}`;
|
||||||
|
label.append(section);
|
||||||
|
switch (setting.input) {
|
||||||
|
case "checkbox": {
|
||||||
|
const astroToggle = document.createElement("astro-dev-toolbar-toggle");
|
||||||
|
astroToggle.input.addEventListener("change", setting.changeEvent);
|
||||||
|
astroToggle.input.checked = settings.config[setting.settingKey];
|
||||||
|
label.append(astroToggle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "select": {
|
||||||
|
const astroSelect = document.createElement("astro-dev-toolbar-select");
|
||||||
|
placements.forEach((placement) => {
|
||||||
|
const option = document.createElement("option");
|
||||||
|
option.setAttribute("value", placement);
|
||||||
|
if (placement === settings.config[setting.settingKey]) {
|
||||||
|
option.selected = true;
|
||||||
|
}
|
||||||
|
option.textContent = `${placement.slice(0, 1).toUpperCase()}${placement.slice(
|
||||||
|
1
|
||||||
|
)}`.replace("-", " ");
|
||||||
|
astroSelect.append(option);
|
||||||
|
});
|
||||||
|
astroSelect.element.addEventListener("change", setting.changeEvent);
|
||||||
|
label.append(astroSelect);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "number":
|
||||||
|
case "text":
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export {
|
||||||
|
settings_default as default
|
||||||
|
};
|
||||||
|
//# sourceMappingURL=settings-K4OHAGC2.js.map
|
||||||
+7
File diff suppressed because one or more lines are too long
+525
@@ -0,0 +1,525 @@
|
|||||||
|
import {
|
||||||
|
serverHelpers
|
||||||
|
} from "./chunk-HNT3PLDI.js";
|
||||||
|
import {
|
||||||
|
getIconElement,
|
||||||
|
isDefinedIcon
|
||||||
|
} from "./chunk-ZUETELRC.js";
|
||||||
|
import {
|
||||||
|
settings
|
||||||
|
} from "./chunk-LEX3GG7N.js";
|
||||||
|
import "./chunk-5WRI5ZAA.js";
|
||||||
|
|
||||||
|
// node_modules/astro/dist/runtime/client/dev-toolbar/toolbar.js
|
||||||
|
var WS_EVENT_NAME = "astro-dev-toolbar";
|
||||||
|
var HOVER_DELAY = 2 * 1e3;
|
||||||
|
var DEVBAR_HITBOX_ABOVE = 42;
|
||||||
|
var AstroDevToolbar = class extends HTMLElement {
|
||||||
|
shadowRoot;
|
||||||
|
delayedHideTimeout;
|
||||||
|
devToolbarContainer;
|
||||||
|
apps = [];
|
||||||
|
hasBeenInitialized = false;
|
||||||
|
// TODO: This should be dynamic based on the screen size or at least configurable, erika - 2023-11-29
|
||||||
|
customAppsToShow = 3;
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.shadowRoot = this.attachShadow({ mode: "open" });
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* All one-time DOM setup runs through here. Only ever call this once,
|
||||||
|
* in connectedCallback(), and protect it from being called again.
|
||||||
|
*/
|
||||||
|
init() {
|
||||||
|
this.shadowRoot.innerHTML = `
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
/* Important! Reset all inherited styles to initial */
|
||||||
|
all: initial;
|
||||||
|
z-index: 999999;
|
||||||
|
view-transition-name: astro-dev-toolbar;
|
||||||
|
display: contents;
|
||||||
|
|
||||||
|
/* Hide the dev toolbar on window.print() (CTRL + P) */
|
||||||
|
@media print {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-old(astro-dev-toolbar),
|
||||||
|
::view-transition-new(astro-dev-toolbar) {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-toolbar-root {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0px;
|
||||||
|
z-index: 2000000010;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
transition: bottom 0.35s cubic-bezier(0.485, -0.050, 0.285, 1.505);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-toolbar-root[data-hidden] {
|
||||||
|
bottom: -40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-toolbar-root[data-hidden] #dev-bar .item {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-toolbar-root[data-placement="bottom-left"] {
|
||||||
|
left: 16px;
|
||||||
|
}
|
||||||
|
#dev-toolbar-root[data-placement="bottom-center"] {
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
#dev-toolbar-root[data-placement="bottom-right"] {
|
||||||
|
right: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar-hitbox-above,
|
||||||
|
#dev-bar-hitbox-below {
|
||||||
|
width: 100%;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
#dev-bar-hitbox-above {
|
||||||
|
height: ${DEVBAR_HITBOX_ABOVE}px;
|
||||||
|
}
|
||||||
|
#dev-bar-hitbox-below {
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
#dev-bar {
|
||||||
|
height: 40px;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: auto;
|
||||||
|
background: linear-gradient(180deg, #13151A 0%, rgba(19, 21, 26, 0.88) 100%);
|
||||||
|
border: 1px solid #343841;
|
||||||
|
border-radius: 9999px;
|
||||||
|
box-shadow: 0px 0px 0px 0px rgba(19, 21, 26, 0.30), 0px 1px 2px 0px rgba(19, 21, 26, 0.29), 0px 4px 4px 0px rgba(19, 21, 26, 0.26), 0px 10px 6px 0px rgba(19, 21, 26, 0.15), 0px 17px 7px 0px rgba(19, 21, 26, 0.04), 0px 26px 7px 0px rgba(19, 21, 26, 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
#dev-bar {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 44px;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: white;
|
||||||
|
font-family: system-ui, sans-serif;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.2;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: opacity 0.2s ease-out 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar #bar-container .item:hover, #dev-bar #bar-container .item:focus-visible {
|
||||||
|
background: #FFFFFF20;
|
||||||
|
cursor: pointer;
|
||||||
|
outline-offset: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar #bar-container .item[data-app-error]:hover, #dev-bar #bar-container .item[data-app-error]:focus-visible {
|
||||||
|
cursor: not-allowed;
|
||||||
|
background: #ff252520;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .item:first-of-type {
|
||||||
|
border-top-left-radius: 9999px;
|
||||||
|
border-bottom-left-radius: 9999px;
|
||||||
|
width: 42px;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .item:last-of-type {
|
||||||
|
border-top-right-radius: 9999px;
|
||||||
|
border-bottom-right-radius: 9999px;
|
||||||
|
width: 42px;
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
#dev-bar #bar-container .item.active {
|
||||||
|
background: rgba(71, 78, 94, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .item-tooltip {
|
||||||
|
background: linear-gradient(0deg, #13151A, #13151A), linear-gradient(0deg, #343841, #343841);
|
||||||
|
border: 1px solid rgba(52, 56, 65, 1);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
position: absolute;
|
||||||
|
top: ${4 - DEVBAR_HITBOX_ABOVE}px;
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s ease-in-out 0s;
|
||||||
|
pointer-events: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .item-tooltip::after{
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: calc(50% - 5px);
|
||||||
|
bottom: -6px;
|
||||||
|
border-left: 5px solid transparent;
|
||||||
|
border-right: 5px solid transparent;
|
||||||
|
border-top: 5px solid #343841;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .item[data-app-error] .icon {
|
||||||
|
opacity: 0.35;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .item:hover .item-tooltip, #dev-bar .item:not(.active):focus-visible .item-tooltip {
|
||||||
|
transition: opacity 0.2s ease-in-out 200ms;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
#dev-bar .item:hover .item-tooltip,
|
||||||
|
#dev-bar .item:not(.active):focus-visible .item-tooltip {
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar #bar-container .item:hover .notification rect, #dev-bar #bar-container .item:hover .notification path {
|
||||||
|
stroke: #38393D;
|
||||||
|
--fill: var(--fill-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar #bar-container .item.active .notification rect, #dev-bar #bar-container .item.active .notification path {
|
||||||
|
stroke: #454C5C;
|
||||||
|
--fill: var(--fill-hover);
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .item .icon {
|
||||||
|
position: relative;
|
||||||
|
max-width: 20px;
|
||||||
|
max-height: 20px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .item .icon>svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (forced-colors: active) {
|
||||||
|
#dev-bar .item svg path[fill="#fff"] {
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .item .notification {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: -4px;
|
||||||
|
right: -6px;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .item .notification svg {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-toolbar-root:not([data-no-notification]) #dev-bar .item .notification[data-active] {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar #bar-container {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dev-bar .separator {
|
||||||
|
background: rgba(52, 56, 65, 1);
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div id="dev-toolbar-root" data-hidden ${settings.config.disableAppNotification ? "data-no-notification" : ""} data-placement="${settings.config.placement}">
|
||||||
|
<div id="dev-bar-hitbox-above"></div>
|
||||||
|
<div id="dev-bar">
|
||||||
|
<div id="bar-container">
|
||||||
|
${this.apps.filter((app) => app.builtIn && !["astro:settings", "astro:more"].includes(app.id)).map((app) => this.getAppTemplate(app)).join("")}
|
||||||
|
${this.apps.filter((app) => !app.builtIn).length > 0 ? `<div class="separator"></div>${this.apps.filter((app) => !app.builtIn).slice(0, this.customAppsToShow).map((app) => this.getAppTemplate(app)).join("")}` : ""}
|
||||||
|
${this.apps.filter((app) => !app.builtIn).length > this.customAppsToShow ? this.getAppTemplate(
|
||||||
|
this.apps.find((app) => app.builtIn && app.id === "astro:more")
|
||||||
|
) : ""}
|
||||||
|
<div class="separator"></div>
|
||||||
|
${this.getAppTemplate(
|
||||||
|
this.apps.find((app) => app.builtIn && app.id === "astro:settings")
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="dev-bar-hitbox-below"></div>
|
||||||
|
</div>`;
|
||||||
|
this.devToolbarContainer = this.shadowRoot.querySelector("#dev-toolbar-root");
|
||||||
|
this.attachEvents();
|
||||||
|
this.apps.forEach(async (app) => {
|
||||||
|
settings.logger.verboseLog(`Creating app canvas for ${app.id}`);
|
||||||
|
const appCanvas = document.createElement("astro-dev-toolbar-app-canvas");
|
||||||
|
appCanvas.dataset.appId = app.id;
|
||||||
|
this.shadowRoot?.append(appCanvas);
|
||||||
|
});
|
||||||
|
if ("requestIdleCallback" in window) {
|
||||||
|
window.requestIdleCallback(
|
||||||
|
async () => {
|
||||||
|
this.apps.map((app) => this.initApp(app));
|
||||||
|
},
|
||||||
|
{ timeout: 300 }
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setTimeout(async () => {
|
||||||
|
this.apps.map((app) => this.initApp(app));
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// This is called whenever the component is connected to the DOM.
|
||||||
|
// This happens on first page load, and on each page change when
|
||||||
|
// view transitions are used.
|
||||||
|
connectedCallback() {
|
||||||
|
if (!this.hasBeenInitialized) {
|
||||||
|
this.init();
|
||||||
|
this.hasBeenInitialized = true;
|
||||||
|
}
|
||||||
|
this.apps.forEach(async (app) => {
|
||||||
|
await this.setAppStatus(app, app.active);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
attachEvents() {
|
||||||
|
const items = this.shadowRoot.querySelectorAll(".item");
|
||||||
|
items.forEach((item) => {
|
||||||
|
item.addEventListener("click", async (event) => {
|
||||||
|
const target = event.currentTarget;
|
||||||
|
if (!target || !(target instanceof HTMLElement)) return;
|
||||||
|
const id = target.dataset.appId;
|
||||||
|
if (!id) return;
|
||||||
|
const app = this.getAppById(id);
|
||||||
|
if (!app) return;
|
||||||
|
event.stopPropagation();
|
||||||
|
await this.toggleAppStatus(app);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
["mouseenter", "focusin"].forEach((event) => {
|
||||||
|
this.devToolbarContainer.addEventListener(event, () => {
|
||||||
|
this.clearDelayedHide();
|
||||||
|
if (this.isHidden()) {
|
||||||
|
this.setToolbarVisible(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
["mouseleave", "focusout"].forEach((event) => {
|
||||||
|
this.devToolbarContainer.addEventListener(event, () => {
|
||||||
|
this.clearDelayedHide();
|
||||||
|
if (this.getActiveApp() || this.isHidden()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.triggerDelayedHide();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
document.addEventListener("keyup", (event) => {
|
||||||
|
if (event.key !== "Escape") return;
|
||||||
|
if (this.isHidden()) return;
|
||||||
|
const activeApp = this.getActiveApp();
|
||||||
|
if (activeApp) {
|
||||||
|
this.toggleAppStatus(activeApp);
|
||||||
|
} else {
|
||||||
|
this.setToolbarVisible(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async initApp(app) {
|
||||||
|
const shadowRoot = this.getAppCanvasById(app.id).shadowRoot;
|
||||||
|
app.status = "loading";
|
||||||
|
try {
|
||||||
|
settings.logger.verboseLog(`Initializing app ${app.id}`);
|
||||||
|
await app.init?.(shadowRoot, app.eventTarget, serverHelpers);
|
||||||
|
app.status = "ready";
|
||||||
|
if (import.meta.hot) {
|
||||||
|
import.meta.hot.send(`${WS_EVENT_NAME}:${app.id}:initialized`);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Failed to init app ${app.id}, error: ${e}`);
|
||||||
|
app.status = "error";
|
||||||
|
if (import.meta.hot) {
|
||||||
|
import.meta.hot.send("astro:devtoolbar:error:init", {
|
||||||
|
app,
|
||||||
|
error: e instanceof Error ? e.stack : e
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const appButton = this.getAppButtonById(app.id);
|
||||||
|
const appTooltip = appButton?.querySelector(".item-tooltip");
|
||||||
|
if (appButton && appTooltip) {
|
||||||
|
appButton.toggleAttribute("data-app-error", true);
|
||||||
|
appTooltip.innerText = `Error initializing ${app.name}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getAppTemplate(app) {
|
||||||
|
return `<button class="item" data-app-id="${app.id}">
|
||||||
|
<div class="icon">${app.icon ? getAppIcon(app.icon) : "?"}<div class="notification"></div></div>
|
||||||
|
<span class="item-tooltip">${app.name}</span>
|
||||||
|
</button>`;
|
||||||
|
}
|
||||||
|
getAppById(id) {
|
||||||
|
return this.apps.find((app) => app.id === id);
|
||||||
|
}
|
||||||
|
getAppCanvasById(id) {
|
||||||
|
return this.shadowRoot.querySelector(
|
||||||
|
`astro-dev-toolbar-app-canvas[data-app-id="${id}"]`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
getAppButtonById(id) {
|
||||||
|
return this.shadowRoot.querySelector(`[data-app-id="${id}"]`);
|
||||||
|
}
|
||||||
|
async toggleAppStatus(app) {
|
||||||
|
const activeApp = this.getActiveApp();
|
||||||
|
if (activeApp) {
|
||||||
|
const closeApp = await this.setAppStatus(activeApp, false);
|
||||||
|
if (!closeApp) return;
|
||||||
|
}
|
||||||
|
if (app.status !== "ready") return;
|
||||||
|
if (app !== activeApp) {
|
||||||
|
await this.setAppStatus(app, true);
|
||||||
|
if (import.meta.hot && app.id !== "astro:more") {
|
||||||
|
import.meta.hot.send("astro:devtoolbar:app:toggled", {
|
||||||
|
app
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async setAppStatus(app, newStatus) {
|
||||||
|
const appCanvas = this.getAppCanvasById(app.id);
|
||||||
|
if (!appCanvas) return false;
|
||||||
|
if (app.active && !newStatus && app.beforeTogglingOff) {
|
||||||
|
const shouldToggleOff = await app.beforeTogglingOff(appCanvas.shadowRoot);
|
||||||
|
if (!shouldToggleOff) return false;
|
||||||
|
}
|
||||||
|
app.active = newStatus ?? !app.active;
|
||||||
|
const mainBarButton = this.getAppButtonById(app.id);
|
||||||
|
const moreBarButton = this.getAppCanvasById("astro:more")?.shadowRoot?.querySelector(
|
||||||
|
`[data-app-id="${app.id}"]`
|
||||||
|
);
|
||||||
|
if (mainBarButton) {
|
||||||
|
mainBarButton.classList.toggle("active", app.active);
|
||||||
|
}
|
||||||
|
if (moreBarButton) {
|
||||||
|
moreBarButton.classList.toggle("active", app.active);
|
||||||
|
}
|
||||||
|
if (app.active) {
|
||||||
|
appCanvas.style.display = "block";
|
||||||
|
appCanvas.setAttribute("data-active", "");
|
||||||
|
} else {
|
||||||
|
appCanvas.style.display = "none";
|
||||||
|
appCanvas.removeAttribute("data-active");
|
||||||
|
}
|
||||||
|
app.eventTarget.dispatchEvent(
|
||||||
|
new CustomEvent("app-toggled", {
|
||||||
|
detail: {
|
||||||
|
state: app.active,
|
||||||
|
app
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
import.meta.hot?.send(`${WS_EVENT_NAME}:${app.id}:toggled`, { state: app.active });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
isHidden() {
|
||||||
|
return this.devToolbarContainer?.hasAttribute("data-hidden") ?? true;
|
||||||
|
}
|
||||||
|
getActiveApp() {
|
||||||
|
return this.apps.find((app) => app.active);
|
||||||
|
}
|
||||||
|
clearDelayedHide() {
|
||||||
|
window.clearTimeout(this.delayedHideTimeout);
|
||||||
|
this.delayedHideTimeout = void 0;
|
||||||
|
}
|
||||||
|
triggerDelayedHide() {
|
||||||
|
this.clearDelayedHide();
|
||||||
|
this.delayedHideTimeout = window.setTimeout(() => {
|
||||||
|
this.setToolbarVisible(false);
|
||||||
|
this.delayedHideTimeout = void 0;
|
||||||
|
}, HOVER_DELAY);
|
||||||
|
}
|
||||||
|
setToolbarVisible(newStatus) {
|
||||||
|
const barContainer = this.shadowRoot.querySelector("#bar-container");
|
||||||
|
const devBar = this.shadowRoot.querySelector("#dev-bar");
|
||||||
|
const devBarHitboxAbove = this.shadowRoot.querySelector("#dev-bar-hitbox-above");
|
||||||
|
if (newStatus === true) {
|
||||||
|
this.devToolbarContainer?.removeAttribute("data-hidden");
|
||||||
|
barContainer?.removeAttribute("inert");
|
||||||
|
devBar?.removeAttribute("tabindex");
|
||||||
|
if (devBarHitboxAbove) devBarHitboxAbove.style.height = "0";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (newStatus === false) {
|
||||||
|
this.devToolbarContainer?.setAttribute("data-hidden", "");
|
||||||
|
barContainer?.setAttribute("inert", "");
|
||||||
|
devBar?.setAttribute("tabindex", "0");
|
||||||
|
if (devBarHitboxAbove) devBarHitboxAbove.style.height = `${DEVBAR_HITBOX_ABOVE}px`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setNotificationVisible(newStatus) {
|
||||||
|
this.devToolbarContainer?.toggleAttribute("data-no-notification", !newStatus);
|
||||||
|
const moreCanvas = this.getAppCanvasById("astro:more");
|
||||||
|
moreCanvas?.shadowRoot?.querySelector("#dropdown")?.toggleAttribute("data-no-notification", !newStatus);
|
||||||
|
}
|
||||||
|
setToolbarPlacement(newPlacement) {
|
||||||
|
this.devToolbarContainer?.setAttribute("data-placement", newPlacement);
|
||||||
|
this.apps.forEach((app) => {
|
||||||
|
app.eventTarget.dispatchEvent(
|
||||||
|
new CustomEvent("placement-updated", {
|
||||||
|
detail: {
|
||||||
|
placement: newPlacement
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var DevToolbarCanvas = class extends HTMLElement {
|
||||||
|
shadowRoot;
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.shadowRoot = this.attachShadow({ mode: "open" });
|
||||||
|
}
|
||||||
|
connectedCallback() {
|
||||||
|
this.shadowRoot.innerHTML = `
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
</style>`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
function getAppIcon(icon) {
|
||||||
|
if (isDefinedIcon(icon)) {
|
||||||
|
return getIconElement(icon).outerHTML;
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
export {
|
||||||
|
AstroDevToolbar,
|
||||||
|
DevToolbarCanvas,
|
||||||
|
getAppIcon
|
||||||
|
};
|
||||||
|
//# sourceMappingURL=toolbar-2H5PSQQU.js.map
|
||||||
+7
File diff suppressed because one or more lines are too long
+1020
File diff suppressed because it is too large
Load Diff
+7
File diff suppressed because one or more lines are too long
+147
@@ -0,0 +1,147 @@
|
|||||||
|
import {
|
||||||
|
attachTooltipToHighlight,
|
||||||
|
createHighlight,
|
||||||
|
getElementsPositionInDocument,
|
||||||
|
positionHighlight
|
||||||
|
} from "./chunk-LEAOZWS7.js";
|
||||||
|
import {
|
||||||
|
escape
|
||||||
|
} from "./chunk-PXGSXSC7.js";
|
||||||
|
import {
|
||||||
|
closeOnOutsideClick,
|
||||||
|
createWindowElement,
|
||||||
|
synchronizePlacementOnUpdate
|
||||||
|
} from "./chunk-WM2KMMIK.js";
|
||||||
|
import "./chunk-LEX3GG7N.js";
|
||||||
|
import "./chunk-5WRI5ZAA.js";
|
||||||
|
|
||||||
|
// node_modules/astro/dist/runtime/client/dev-toolbar/apps/xray.js
|
||||||
|
var icon = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" aria-hidden="true"><path fill="#fff" d="M7.9 1.5v-.4a1.1 1.1 0 0 1 2.2 0v.4a1.1 1.1 0 1 1-2.2 0Zm-6.4 8.6a1.1 1.1 0 1 0 0-2.2h-.4a1.1 1.1 0 0 0 0 2.2h.4ZM12 3.7a1.1 1.1 0 0 0 1.4-.7l.4-1.1a1.1 1.1 0 0 0-2.1-.8l-.4 1.2a1.1 1.1 0 0 0 .7 1.4Zm-9.7 7.6-1.2.4a1.1 1.1 0 1 0 .8 2.1l1-.4a1.1 1.1 0 1 0-.6-2ZM20.8 17a1.9 1.9 0 0 1 0 2.6l-1.2 1.2a1.9 1.9 0 0 1-2.6 0l-4.3-4.2-1.6 3.6a1.9 1.9 0 0 1-1.7 1.2A1.9 1.9 0 0 1 7.5 20L2.7 5a1.9 1.9 0 0 1 2.4-2.4l15 5a1.9 1.9 0 0 1 .2 3.4l-3.7 1.6 4.2 4.3ZM19 18.3 14.6 14a1.9 1.9 0 0 1 .6-3l3.2-1.5L5.1 5.1l4.3 13.3 1.5-3.2a1.9 1.9 0 0 1 3-.6l4.4 4.4.7-.7Z"/></svg>';
|
||||||
|
var xray_default = {
|
||||||
|
id: "astro:xray",
|
||||||
|
name: "Inspect",
|
||||||
|
icon,
|
||||||
|
init(canvas, eventTarget) {
|
||||||
|
let islandsOverlays = [];
|
||||||
|
addIslandsOverlay();
|
||||||
|
document.addEventListener("astro:after-swap", addIslandsOverlay);
|
||||||
|
document.addEventListener("astro:page-load", refreshIslandsOverlayPositions);
|
||||||
|
closeOnOutsideClick(eventTarget);
|
||||||
|
synchronizePlacementOnUpdate(eventTarget, canvas);
|
||||||
|
function addIslandsOverlay() {
|
||||||
|
islandsOverlays.forEach(({ highlightElement }) => {
|
||||||
|
highlightElement.remove();
|
||||||
|
});
|
||||||
|
islandsOverlays = [];
|
||||||
|
const islands = document.querySelectorAll("astro-island");
|
||||||
|
if (islands.length === 0) {
|
||||||
|
const window2 = createWindowElement(
|
||||||
|
`<style>
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #fff;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
astro-dev-toolbar-icon {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
padding: 8px;
|
||||||
|
display: block;
|
||||||
|
background: #5f9ea0;
|
||||||
|
border-radius: 9999px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<header>
|
||||||
|
<h1><astro-dev-toolbar-icon icon="lightbulb"></astro-dev-toolbar-icon>No islands detected.</h1>
|
||||||
|
</header>
|
||||||
|
<p>
|
||||||
|
It looks like there are no interactive component islands on this page. Did you forget to add a client directive to your interactive UI component?
|
||||||
|
</p>
|
||||||
|
`
|
||||||
|
);
|
||||||
|
canvas.append(window2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
islands.forEach((island) => {
|
||||||
|
const computedStyle = window.getComputedStyle(island);
|
||||||
|
const islandElement = island.children[0] || island;
|
||||||
|
if (islandElement.offsetParent === null || computedStyle.display === "none") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const rect = islandElement.getBoundingClientRect();
|
||||||
|
const highlight = createHighlight(rect);
|
||||||
|
const tooltip = buildIslandTooltip(island);
|
||||||
|
const { isFixed } = getElementsPositionInDocument(islandElement);
|
||||||
|
if (isFixed) {
|
||||||
|
tooltip.style.position = highlight.style.position = "fixed";
|
||||||
|
}
|
||||||
|
attachTooltipToHighlight(highlight, tooltip, islandElement);
|
||||||
|
canvas.append(highlight);
|
||||||
|
islandsOverlays.push({ highlightElement: highlight, island: islandElement });
|
||||||
|
});
|
||||||
|
["scroll", "resize"].forEach((event) => {
|
||||||
|
window.addEventListener(event, refreshIslandsOverlayPositions);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function refreshIslandsOverlayPositions() {
|
||||||
|
islandsOverlays.forEach(({ highlightElement, island: islandElement }) => {
|
||||||
|
const rect = islandElement.getBoundingClientRect();
|
||||||
|
positionHighlight(highlightElement, rect);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function buildIslandTooltip(island) {
|
||||||
|
const tooltip = document.createElement("astro-dev-toolbar-tooltip");
|
||||||
|
tooltip.sections = [];
|
||||||
|
const islandProps = island.getAttribute("props") ? JSON.parse(island.getAttribute("props")) : {};
|
||||||
|
const islandClientDirective = island.getAttribute("client");
|
||||||
|
if (islandClientDirective) {
|
||||||
|
tooltip.sections.push({
|
||||||
|
title: "Client directive",
|
||||||
|
inlineTitle: `<code>client:${islandClientDirective}</code>`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const islandPropsEntries = Object.entries(islandProps).filter(
|
||||||
|
(prop) => !prop[0].startsWith("data-astro-cid-")
|
||||||
|
);
|
||||||
|
if (islandPropsEntries.length > 0) {
|
||||||
|
const stringifiedProps = JSON.stringify(
|
||||||
|
Object.fromEntries(islandPropsEntries.map((prop) => [prop[0], prop[1][1]])),
|
||||||
|
void 0,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
tooltip.sections.push({
|
||||||
|
title: "Props",
|
||||||
|
content: `<pre><code>${escape(stringifiedProps)}</code></pre>`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const islandComponentPath = island.getAttribute("component-url");
|
||||||
|
if (islandComponentPath) {
|
||||||
|
tooltip.sections.push({
|
||||||
|
content: islandComponentPath,
|
||||||
|
clickDescription: "Click to go to file",
|
||||||
|
async clickAction() {
|
||||||
|
await fetch(
|
||||||
|
"/__open-in-editor?file=" + encodeURIComponent(
|
||||||
|
window.__astro_dev_toolbar__.root + islandComponentPath.slice(1)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return tooltip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export {
|
||||||
|
xray_default as default
|
||||||
|
};
|
||||||
|
//# sourceMappingURL=xray-XH6VIXDC.js.map
|
||||||
+7
File diff suppressed because one or more lines are too long
+128
@@ -0,0 +1,128 @@
|
|||||||
|
declare namespace QuickLRU {
|
||||||
|
interface Options<KeyType, ValueType> {
|
||||||
|
/**
|
||||||
|
The maximum number of milliseconds an item should remain in the cache.
|
||||||
|
|
||||||
|
@default Infinity
|
||||||
|
|
||||||
|
By default, `maxAge` will be `Infinity`, which means that items will never expire.
|
||||||
|
Lazy expiration upon the next write or read call.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified by the `set(key, value, maxAge)` method.
|
||||||
|
*/
|
||||||
|
readonly maxAge?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The maximum number of items before evicting the least recently used items.
|
||||||
|
*/
|
||||||
|
readonly maxSize: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Called right before an item is evicted from the cache.
|
||||||
|
|
||||||
|
Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`).
|
||||||
|
*/
|
||||||
|
onEviction?: (key: KeyType, value: ValueType) => void;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare class QuickLRU<KeyType, ValueType>
|
||||||
|
implements Iterable<[KeyType, ValueType]> {
|
||||||
|
/**
|
||||||
|
The stored item count.
|
||||||
|
*/
|
||||||
|
readonly size: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Simple ["Least Recently Used" (LRU) cache](https://en.m.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29).
|
||||||
|
|
||||||
|
The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop.
|
||||||
|
|
||||||
|
@example
|
||||||
|
```
|
||||||
|
import QuickLRU = require('quick-lru');
|
||||||
|
|
||||||
|
const lru = new QuickLRU({maxSize: 1000});
|
||||||
|
|
||||||
|
lru.set('🦄', '🌈');
|
||||||
|
|
||||||
|
lru.has('🦄');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
lru.get('🦄');
|
||||||
|
//=> '🌈'
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
constructor(options: QuickLRU.Options<KeyType, ValueType>);
|
||||||
|
|
||||||
|
[Symbol.iterator](): IterableIterator<[KeyType, ValueType]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set an item. Returns the instance.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified with the `maxAge` option. If not specified, the global `maxAge` value will be used in case it is specified in the constructor, otherwise the item will never expire.
|
||||||
|
|
||||||
|
@returns The list instance.
|
||||||
|
*/
|
||||||
|
set(key: KeyType, value: ValueType, options?: {maxAge?: number}): this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get an item.
|
||||||
|
|
||||||
|
@returns The stored item or `undefined`.
|
||||||
|
*/
|
||||||
|
get(key: KeyType): ValueType | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if an item exists.
|
||||||
|
*/
|
||||||
|
has(key: KeyType): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get an item without marking it as recently used.
|
||||||
|
|
||||||
|
@returns The stored item or `undefined`.
|
||||||
|
*/
|
||||||
|
peek(key: KeyType): ValueType | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delete an item.
|
||||||
|
|
||||||
|
@returns `true` if the item is removed or `false` if the item doesn't exist.
|
||||||
|
*/
|
||||||
|
delete(key: KeyType): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Delete all items.
|
||||||
|
*/
|
||||||
|
clear(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Update the `maxSize` in-place, discarding items as necessary. Insertion order is mostly preserved, though this is not a strong guarantee.
|
||||||
|
|
||||||
|
Useful for on-the-fly tuning of cache sizes in live systems.
|
||||||
|
*/
|
||||||
|
resize(maxSize: number): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all the keys.
|
||||||
|
*/
|
||||||
|
keys(): IterableIterator<KeyType>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all the values.
|
||||||
|
*/
|
||||||
|
values(): IterableIterator<ValueType>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all entries, starting with the oldest (ascending in recency).
|
||||||
|
*/
|
||||||
|
entriesAscending(): IterableIterator<[KeyType, ValueType]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Iterable for all entries, starting with the newest (descending in recency).
|
||||||
|
*/
|
||||||
|
entriesDescending(): IterableIterator<[KeyType, ValueType]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export = QuickLRU;
|
||||||
+263
@@ -0,0 +1,263 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
class QuickLRU {
|
||||||
|
constructor(options = {}) {
|
||||||
|
if (!(options.maxSize && options.maxSize > 0)) {
|
||||||
|
throw new TypeError('`maxSize` must be a number greater than 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof options.maxAge === 'number' && options.maxAge === 0) {
|
||||||
|
throw new TypeError('`maxAge` must be a number greater than 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.maxSize = options.maxSize;
|
||||||
|
this.maxAge = options.maxAge || Infinity;
|
||||||
|
this.onEviction = options.onEviction;
|
||||||
|
this.cache = new Map();
|
||||||
|
this.oldCache = new Map();
|
||||||
|
this._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_emitEvictions(cache) {
|
||||||
|
if (typeof this.onEviction !== 'function') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [key, item] of cache) {
|
||||||
|
this.onEviction(key, item.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_deleteIfExpired(key, item) {
|
||||||
|
if (typeof item.expiry === 'number' && item.expiry <= Date.now()) {
|
||||||
|
if (typeof this.onEviction === 'function') {
|
||||||
|
this.onEviction(key, item.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.delete(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getOrDeleteIfExpired(key, item) {
|
||||||
|
const deleted = this._deleteIfExpired(key, item);
|
||||||
|
if (deleted === false) {
|
||||||
|
return item.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getItemValue(key, item) {
|
||||||
|
return item.expiry ? this._getOrDeleteIfExpired(key, item) : item.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
_peek(key, cache) {
|
||||||
|
const item = cache.get(key);
|
||||||
|
|
||||||
|
return this._getItemValue(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
_set(key, value) {
|
||||||
|
this.cache.set(key, value);
|
||||||
|
this._size++;
|
||||||
|
|
||||||
|
if (this._size >= this.maxSize) {
|
||||||
|
this._size = 0;
|
||||||
|
this._emitEvictions(this.oldCache);
|
||||||
|
this.oldCache = this.cache;
|
||||||
|
this.cache = new Map();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_moveToRecent(key, item) {
|
||||||
|
this.oldCache.delete(key);
|
||||||
|
this._set(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
* _entriesAscending() {
|
||||||
|
for (const item of this.oldCache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of this.cache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
const item = this.cache.get(key);
|
||||||
|
|
||||||
|
return this._getItemValue(key, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.oldCache.has(key)) {
|
||||||
|
const item = this.oldCache.get(key);
|
||||||
|
if (this._deleteIfExpired(key, item) === false) {
|
||||||
|
this._moveToRecent(key, item);
|
||||||
|
return item.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set(key, value, {maxAge = this.maxAge === Infinity ? undefined : Date.now() + this.maxAge} = {}) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
this.cache.set(key, {
|
||||||
|
value,
|
||||||
|
maxAge
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this._set(key, {value, expiry: maxAge});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
has(key) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
return !this._deleteIfExpired(key, this.cache.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.oldCache.has(key)) {
|
||||||
|
return !this._deleteIfExpired(key, this.oldCache.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
peek(key) {
|
||||||
|
if (this.cache.has(key)) {
|
||||||
|
return this._peek(key, this.cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.oldCache.has(key)) {
|
||||||
|
return this._peek(key, this.oldCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(key) {
|
||||||
|
const deleted = this.cache.delete(key);
|
||||||
|
if (deleted) {
|
||||||
|
this._size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.oldCache.delete(key) || deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.cache.clear();
|
||||||
|
this.oldCache.clear();
|
||||||
|
this._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
resize(newSize) {
|
||||||
|
if (!(newSize && newSize > 0)) {
|
||||||
|
throw new TypeError('`maxSize` must be a number greater than 0');
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = [...this._entriesAscending()];
|
||||||
|
const removeCount = items.length - newSize;
|
||||||
|
if (removeCount < 0) {
|
||||||
|
this.cache = new Map(items);
|
||||||
|
this.oldCache = new Map();
|
||||||
|
this._size = items.length;
|
||||||
|
} else {
|
||||||
|
if (removeCount > 0) {
|
||||||
|
this._emitEvictions(items.slice(0, removeCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.oldCache = new Map(items.slice(removeCount));
|
||||||
|
this.cache = new Map();
|
||||||
|
this._size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.maxSize = newSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
* keys() {
|
||||||
|
for (const [key] of this) {
|
||||||
|
yield key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* values() {
|
||||||
|
for (const [, value] of this) {
|
||||||
|
yield value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* [Symbol.iterator]() {
|
||||||
|
for (const item of this.cache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const item of this.oldCache) {
|
||||||
|
const [key, value] = item;
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* entriesDescending() {
|
||||||
|
let items = [...this.cache];
|
||||||
|
for (let i = items.length - 1; i >= 0; --i) {
|
||||||
|
const item = items[i];
|
||||||
|
const [key, value] = item;
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
items = [...this.oldCache];
|
||||||
|
for (let i = items.length - 1; i >= 0; --i) {
|
||||||
|
const item = items[i];
|
||||||
|
const [key, value] = item;
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
const deleted = this._deleteIfExpired(key, value);
|
||||||
|
if (deleted === false) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
* entriesAscending() {
|
||||||
|
for (const [key, value] of this._entriesAscending()) {
|
||||||
|
yield [key, value.value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get size() {
|
||||||
|
if (!this._size) {
|
||||||
|
return this.oldCache.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
let oldCacheSize = 0;
|
||||||
|
for (const key of this.oldCache.keys()) {
|
||||||
|
if (!this.cache.has(key)) {
|
||||||
|
oldCacheSize++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.min(this._size + oldCacheSize, this.maxSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = QuickLRU;
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"name": "@alloc/quick-lru",
|
||||||
|
"version": "5.2.0",
|
||||||
|
"description": "Simple “Least Recently Used” (LRU) cache",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "sindresorhus/quick-lru",
|
||||||
|
"funding": "https://github.com/sponsors/sindresorhus",
|
||||||
|
"author": {
|
||||||
|
"name": "Sindre Sorhus",
|
||||||
|
"email": "sindresorhus@gmail.com",
|
||||||
|
"url": "https://sindresorhus.com"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "xo && nyc ava && tsd"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.js",
|
||||||
|
"index.d.ts"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"lru",
|
||||||
|
"quick",
|
||||||
|
"cache",
|
||||||
|
"caching",
|
||||||
|
"least",
|
||||||
|
"recently",
|
||||||
|
"used",
|
||||||
|
"fast",
|
||||||
|
"map",
|
||||||
|
"hash",
|
||||||
|
"buffer"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"ava": "^2.0.0",
|
||||||
|
"coveralls": "^3.0.3",
|
||||||
|
"nyc": "^15.0.0",
|
||||||
|
"tsd": "^0.11.0",
|
||||||
|
"xo": "^0.26.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
+139
@@ -0,0 +1,139 @@
|
|||||||
|
# quick-lru [](https://travis-ci.org/sindresorhus/quick-lru) [](https://coveralls.io/github/sindresorhus/quick-lru?branch=master)
|
||||||
|
|
||||||
|
> Simple [“Least Recently Used” (LRU) cache](https://en.m.wikipedia.org/wiki/Cache_replacement_policies#Least_Recently_Used_.28LRU.29)
|
||||||
|
|
||||||
|
Useful when you need to cache something and limit memory usage.
|
||||||
|
|
||||||
|
Inspired by the [`hashlru` algorithm](https://github.com/dominictarr/hashlru#algorithm), but instead uses [`Map`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map) to support keys of any type, not just strings, and values can be `undefined`.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm install quick-lru
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
const QuickLRU = require('quick-lru');
|
||||||
|
|
||||||
|
const lru = new QuickLRU({maxSize: 1000});
|
||||||
|
|
||||||
|
lru.set('🦄', '🌈');
|
||||||
|
|
||||||
|
lru.has('🦄');
|
||||||
|
//=> true
|
||||||
|
|
||||||
|
lru.get('🦄');
|
||||||
|
//=> '🌈'
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### new QuickLRU(options?)
|
||||||
|
|
||||||
|
Returns a new instance.
|
||||||
|
|
||||||
|
### options
|
||||||
|
|
||||||
|
Type: `object`
|
||||||
|
|
||||||
|
#### maxSize
|
||||||
|
|
||||||
|
*Required*\
|
||||||
|
Type: `number`
|
||||||
|
|
||||||
|
The maximum number of items before evicting the least recently used items.
|
||||||
|
|
||||||
|
#### maxAge
|
||||||
|
|
||||||
|
Type: `number`\
|
||||||
|
Default: `Infinity`
|
||||||
|
|
||||||
|
The maximum number of milliseconds an item should remain in cache.
|
||||||
|
By default maxAge will be Infinity, which means that items will never expire.
|
||||||
|
|
||||||
|
Lazy expiration happens upon the next `write` or `read` call.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified by the `set(key, value, options)` method.
|
||||||
|
|
||||||
|
#### onEviction
|
||||||
|
|
||||||
|
*Optional*\
|
||||||
|
Type: `(key, value) => void`
|
||||||
|
|
||||||
|
Called right before an item is evicted from the cache.
|
||||||
|
|
||||||
|
Useful for side effects or for items like object URLs that need explicit cleanup (`revokeObjectURL`).
|
||||||
|
|
||||||
|
### Instance
|
||||||
|
|
||||||
|
The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop.
|
||||||
|
|
||||||
|
Both `key` and `value` can be of any type.
|
||||||
|
|
||||||
|
#### .set(key, value, options?)
|
||||||
|
|
||||||
|
Set an item. Returns the instance.
|
||||||
|
|
||||||
|
Individual expiration of an item can be specified with the `maxAge` option. If not specified, the global `maxAge` value will be used in case it is specified on the constructor, otherwise the item will never expire.
|
||||||
|
|
||||||
|
#### .get(key)
|
||||||
|
|
||||||
|
Get an item.
|
||||||
|
|
||||||
|
#### .has(key)
|
||||||
|
|
||||||
|
Check if an item exists.
|
||||||
|
|
||||||
|
#### .peek(key)
|
||||||
|
|
||||||
|
Get an item without marking it as recently used.
|
||||||
|
|
||||||
|
#### .delete(key)
|
||||||
|
|
||||||
|
Delete an item.
|
||||||
|
|
||||||
|
Returns `true` if the item is removed or `false` if the item doesn't exist.
|
||||||
|
|
||||||
|
#### .clear()
|
||||||
|
|
||||||
|
Delete all items.
|
||||||
|
|
||||||
|
#### .resize(maxSize)
|
||||||
|
|
||||||
|
Update the `maxSize`, discarding items as necessary. Insertion order is mostly preserved, though this is not a strong guarantee.
|
||||||
|
|
||||||
|
Useful for on-the-fly tuning of cache sizes in live systems.
|
||||||
|
|
||||||
|
#### .keys()
|
||||||
|
|
||||||
|
Iterable for all the keys.
|
||||||
|
|
||||||
|
#### .values()
|
||||||
|
|
||||||
|
Iterable for all the values.
|
||||||
|
|
||||||
|
#### .entriesAscending()
|
||||||
|
|
||||||
|
Iterable for all entries, starting with the oldest (ascending in recency).
|
||||||
|
|
||||||
|
#### .entriesDescending()
|
||||||
|
|
||||||
|
Iterable for all entries, starting with the newest (descending in recency).
|
||||||
|
|
||||||
|
#### .size
|
||||||
|
|
||||||
|
The stored item count.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<b>
|
||||||
|
<a href="https://tidelift.com/subscription/pkg/npm-quick-lru?utm_source=npm-quick-lru&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
|
||||||
|
</b>
|
||||||
|
<br>
|
||||||
|
<sub>
|
||||||
|
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
|
||||||
|
</sub>
|
||||||
|
</div>
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021 Fred K. Schott
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
"""
|
||||||
|
This license applies to parts of the `packages/create-astro` and `packages/astro` subdirectories originating from the https://github.com/sveltejs/kit repository:
|
||||||
|
|
||||||
|
Copyright (c) 2020 [these people](https://github.com/sveltejs/kit/graphs/contributors)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
This license applies to parts of the `packages/create-astro` and `packages/astro` subdirectories originating from the https://github.com/vitejs/vite repository:
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
"""
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
# @astrojs/check ✅
|
||||||
|
|
||||||
|
This package powers the `astro check` CLI command for running type checking and diagnostics in Astro projects.
|
||||||
|
|
||||||
|
This package's internal logic is powered by [the Astro language server](https://github.com/withastro/astro/blob/main/packages/language-tools/language-server/src/check.ts).
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Read [the Astro type checking docs][docs].
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
- Get help in the [Astro Discord][discord]. Post questions in our `#support` forum, or visit our dedicated `#editors` channel to discuss current development and more!
|
||||||
|
|
||||||
|
- Submit bug reports and feature requests as [GitHub issues][issues].
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
This package is maintained by Astro's Core team. You're welcome to submit an issue or PR! These links will help you get started:
|
||||||
|
|
||||||
|
- [Contributor Manual][contributing]
|
||||||
|
- [Code of Conduct][coc]
|
||||||
|
- [Community Guide][community]
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|
||||||
|
Copyright (c) 2022–present [Astro][astro]
|
||||||
|
|
||||||
|
[astro]: https://astro.build/
|
||||||
|
[docs]: https://docs.astro.build/en/guides/typescript/#type-checking
|
||||||
|
[contributing]: https://github.com/withastro/astro/blob/main/packages/language-tools/CONTRIBUTING.md
|
||||||
|
[coc]: https://github.com/withastro/.github/blob/main/CODE_OF_CONDUCT.md
|
||||||
|
[community]: https://github.com/withastro/.github/blob/main/COMMUNITY_GUIDE.md
|
||||||
|
[discord]: https://astro.build/chat/
|
||||||
|
[issues]: https://github.com/withastro/astro/issues
|
||||||
|
[astro-integration]: https://docs.astro.build/en/guides/integrations/
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import path from 'node:path';
|
||||||
|
import { check, parseArgsAsCheckConfig } from '../dist/index.js';
|
||||||
|
|
||||||
|
const args = parseArgsAsCheckConfig(process.argv.slice(2));
|
||||||
|
|
||||||
|
console.info(`Getting diagnostics for Astro files in ${path.resolve(args.root)}...`);
|
||||||
|
|
||||||
|
const result = await check(args);
|
||||||
|
|
||||||
|
if (typeof result === 'boolean') {
|
||||||
|
process.exit(result ? 1 : 0);
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
import { options } from './options.js';
|
||||||
|
/**
|
||||||
|
* Given a list of arguments from the command line (such as `process.argv`), return parsed and processed options
|
||||||
|
*/
|
||||||
|
export declare function parseArgsAsCheckConfig(args: string[]): {
|
||||||
|
[x: string]: unknown;
|
||||||
|
readonly root: string;
|
||||||
|
readonly watch: boolean;
|
||||||
|
readonly tsconfig: string | undefined;
|
||||||
|
readonly minimumFailingSeverity: "error" | "warning" | "hint";
|
||||||
|
readonly minimumSeverity: "error" | "warning" | "hint";
|
||||||
|
readonly preserveWatchOutput: boolean;
|
||||||
|
_: (string | number)[];
|
||||||
|
$0: string;
|
||||||
|
};
|
||||||
|
export type Flags = Pick<ReturnType<typeof parseArgsAsCheckConfig>, keyof typeof options>;
|
||||||
|
export declare function check(flags: Partial<Flags> & {
|
||||||
|
watch: true;
|
||||||
|
}): Promise<void>;
|
||||||
|
export declare function check(flags: Partial<Flags> & {
|
||||||
|
watch: false;
|
||||||
|
}): Promise<boolean>;
|
||||||
|
export declare function check(flags: Partial<Flags>): Promise<boolean | void>;
|
||||||
+110
@@ -0,0 +1,110 @@
|
|||||||
|
import { createRequire } from 'node:module';
|
||||||
|
import path from 'node:path';
|
||||||
|
import { AstroCheck } from '@astrojs/language-server';
|
||||||
|
import { watch } from 'chokidar';
|
||||||
|
import { bold, dim, red, yellow } from 'kleur/colors';
|
||||||
|
import yargs from 'yargs';
|
||||||
|
import { hideBin } from 'yargs/helpers';
|
||||||
|
import { options } from './options.js';
|
||||||
|
/**
|
||||||
|
* Given a list of arguments from the command line (such as `process.argv`), return parsed and processed options
|
||||||
|
*/
|
||||||
|
export function parseArgsAsCheckConfig(args) {
|
||||||
|
return yargs(hideBin(args)).options(options).parseSync();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Print diagnostics according to the given flags, and return whether or not the program should exit with an error code.
|
||||||
|
*/
|
||||||
|
export async function check(flags) {
|
||||||
|
const workspaceRoot = path.resolve(flags.root ?? process.cwd());
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
const checker = new AstroCheck(workspaceRoot, require.resolve('typescript'), flags.tsconfig);
|
||||||
|
let req = 0;
|
||||||
|
if (flags.watch) {
|
||||||
|
function createWatcher(rootPath, extensions) {
|
||||||
|
return watch(rootPath, {
|
||||||
|
ignored(pathStr, stats) {
|
||||||
|
if (pathStr.includes('node_modules') || pathStr.includes('.git'))
|
||||||
|
return true;
|
||||||
|
if (stats?.isFile() && !extensions.includes(path.extname(pathStr)))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
ignoreInitial: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Dynamically get the list of extensions to watch from the files already included in the project
|
||||||
|
const checkedExtensions = Array.from(new Set(checker.linter.getRootFileNames().map((fileName) => path.extname(fileName))));
|
||||||
|
createWatcher(workspaceRoot, checkedExtensions)
|
||||||
|
.on('add', (fileName) => {
|
||||||
|
checker.linter.fileCreated(fileName);
|
||||||
|
update();
|
||||||
|
})
|
||||||
|
.on('unlink', (fileName) => {
|
||||||
|
checker.linter.fileDeleted(fileName);
|
||||||
|
update();
|
||||||
|
})
|
||||||
|
.on('change', (fileName) => {
|
||||||
|
checker.linter.fileUpdated(fileName);
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async function update() {
|
||||||
|
if (!flags.preserveWatchOutput)
|
||||||
|
process.stdout.write('\x1Bc');
|
||||||
|
await lint();
|
||||||
|
}
|
||||||
|
async function lint() {
|
||||||
|
const currentReq = ++req;
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||||
|
const isCanceled = () => currentReq !== req;
|
||||||
|
if (isCanceled())
|
||||||
|
return;
|
||||||
|
const minimumSeverity = flags.minimumSeverity || 'hint';
|
||||||
|
const result = await checker.lint({
|
||||||
|
logErrors: {
|
||||||
|
level: minimumSeverity,
|
||||||
|
},
|
||||||
|
cancel: isCanceled,
|
||||||
|
});
|
||||||
|
console.info([
|
||||||
|
bold(`Result (${result.fileChecked} file${result.fileChecked === 1 ? '' : 's'}): `),
|
||||||
|
['error', 'warning', 'hint'].includes(minimumSeverity)
|
||||||
|
? result.errors > 0
|
||||||
|
? bold(red(`${result.errors} ${result.errors === 1 ? 'error' : 'errors'}`))
|
||||||
|
: dim('0 errors')
|
||||||
|
: undefined,
|
||||||
|
['warning', 'hint'].includes(minimumSeverity)
|
||||||
|
? result.warnings > 0
|
||||||
|
? bold(yellow(`${result.warnings} ${result.warnings === 1 ? 'warning' : 'warnings'}`))
|
||||||
|
: dim('0 warnings')
|
||||||
|
: undefined,
|
||||||
|
['hint'].includes(minimumSeverity)
|
||||||
|
? dim(`${result.hints} ${result.hints === 1 ? 'hint' : 'hints'}\n`)
|
||||||
|
: undefined,
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(`\n${dim('-')} `));
|
||||||
|
if (flags.watch) {
|
||||||
|
console.info('Watching for changes...');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch (flags.minimumFailingSeverity) {
|
||||||
|
case 'error':
|
||||||
|
return result.errors > 0;
|
||||||
|
case 'warning':
|
||||||
|
return result.errors + result.warnings > 0;
|
||||||
|
case 'hint':
|
||||||
|
return result.errors + result.warnings + result.hints > 0;
|
||||||
|
case undefined:
|
||||||
|
default:
|
||||||
|
return result.errors > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Always lint on first run, even in watch mode.
|
||||||
|
const lintResult = await lint();
|
||||||
|
if (!flags.watch)
|
||||||
|
return lintResult;
|
||||||
|
}
|
||||||
|
//# sourceMappingURL=index.js.map
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
export declare const options: {
|
||||||
|
readonly root: {
|
||||||
|
readonly type: "string";
|
||||||
|
readonly default: string;
|
||||||
|
readonly description: "Manually specify a root dir to check in. By default, the current working directory is used.";
|
||||||
|
};
|
||||||
|
readonly watch: {
|
||||||
|
readonly type: "boolean";
|
||||||
|
readonly default: false;
|
||||||
|
readonly alias: "w";
|
||||||
|
};
|
||||||
|
readonly tsconfig: {
|
||||||
|
readonly type: "string";
|
||||||
|
readonly description: "Manually specify a path to a `tsconfig.json` or `jsconfig.json` to use. If not specified, the program will attempt to find a config, if it cannot it'll attempt to automatically infer the project's configuration.";
|
||||||
|
readonly default: undefined;
|
||||||
|
};
|
||||||
|
readonly minimumFailingSeverity: {
|
||||||
|
readonly choices: readonly ["error", "warning", "hint"];
|
||||||
|
readonly description: "Minimum error severity needed to exit with an error code. Choosing 'hint' will for example cause the program to exit with an error if there's any unfixed hints.";
|
||||||
|
readonly default: "error";
|
||||||
|
};
|
||||||
|
readonly minimumSeverity: {
|
||||||
|
readonly choices: readonly ["error", "warning", "hint"];
|
||||||
|
readonly description: "Minimum diagnostic severity to show. Choosing `warning` will, for example, show both errors and warnings, but not hints. ";
|
||||||
|
readonly default: "hint";
|
||||||
|
};
|
||||||
|
readonly preserveWatchOutput: {
|
||||||
|
readonly type: "boolean";
|
||||||
|
readonly description: "If set to false, output won't be cleared between checks in watch mode.";
|
||||||
|
readonly default: false;
|
||||||
|
};
|
||||||
|
};
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
export const options = {
|
||||||
|
root: {
|
||||||
|
type: 'string',
|
||||||
|
default: process.cwd(),
|
||||||
|
description: 'Manually specify a root dir to check in. By default, the current working directory is used.',
|
||||||
|
},
|
||||||
|
watch: { type: 'boolean', default: false, alias: 'w' },
|
||||||
|
tsconfig: {
|
||||||
|
type: 'string',
|
||||||
|
description: "Manually specify a path to a `tsconfig.json` or `jsconfig.json` to use. If not specified, the program will attempt to find a config, if it cannot it'll attempt to automatically infer the project's configuration.",
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
minimumFailingSeverity: {
|
||||||
|
choices: ['error', 'warning', 'hint'],
|
||||||
|
description: "Minimum error severity needed to exit with an error code. Choosing 'hint' will for example cause the program to exit with an error if there's any unfixed hints.",
|
||||||
|
default: 'error',
|
||||||
|
},
|
||||||
|
minimumSeverity: {
|
||||||
|
choices: ['error', 'warning', 'hint'],
|
||||||
|
description: 'Minimum diagnostic severity to show. Choosing `warning` will, for example, show both errors and warnings, but not hints. ',
|
||||||
|
default: 'hint',
|
||||||
|
},
|
||||||
|
preserveWatchOutput: {
|
||||||
|
type: 'boolean',
|
||||||
|
description: "If set to false, output won't be cleared between checks in watch mode.",
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
//# sourceMappingURL=options.js.map
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2012 Paul Miller (https://paulmillr.com), Elan Shanker
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the “Software”), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
+305
@@ -0,0 +1,305 @@
|
|||||||
|
# Chokidar [](https://github.com/paulmillr/chokidar)
|
||||||
|
|
||||||
|
> Minimal and efficient cross-platform file watching library
|
||||||
|
|
||||||
|
## Why?
|
||||||
|
|
||||||
|
There are many reasons to prefer Chokidar to raw fs.watch / fs.watchFile in 2024:
|
||||||
|
|
||||||
|
- Events are properly reported
|
||||||
|
- macOS events report filenames
|
||||||
|
- events are not reported twice
|
||||||
|
- changes are reported as add / change / unlink instead of useless `rename`
|
||||||
|
- Atomic writes are supported, using `atomic` option
|
||||||
|
- Some file editors use them
|
||||||
|
- Chunked writes are supported, using `awaitWriteFinish` option
|
||||||
|
- Large files are commonly written in chunks
|
||||||
|
- File / dir filtering is supported
|
||||||
|
- Symbolic links are supported
|
||||||
|
- Recursive watching is always supported, instead of partial when using raw events
|
||||||
|
- Includes a way to limit recursion depth
|
||||||
|
|
||||||
|
Chokidar relies on the Node.js core `fs` module, but when using
|
||||||
|
`fs.watch` and `fs.watchFile` for watching, it normalizes the events it
|
||||||
|
receives, often checking for truth by getting file stats and/or dir contents.
|
||||||
|
The `fs.watch`-based implementation is the default, which
|
||||||
|
avoids polling and keeps CPU usage down. Be advised that chokidar will initiate
|
||||||
|
watchers recursively for everything within scope of the paths that have been
|
||||||
|
specified, so be judicious about not wasting system resources by watching much
|
||||||
|
more than needed. For some cases, `fs.watchFile`, which utilizes polling and uses more resources, is used.
|
||||||
|
|
||||||
|
Made for [Brunch](https://brunch.io/) in 2012,
|
||||||
|
it is now used in [~30 million repositories](https://www.npmjs.com/browse/depended/chokidar) and
|
||||||
|
has proven itself in production environments.
|
||||||
|
|
||||||
|
**Sep 2024 update:** v4 is out! It decreases dependency count from 13 to 1, removes
|
||||||
|
support for globs, adds support for ESM / Common.js modules, and bumps minimum node.js version from v8 to v14.
|
||||||
|
Check out [upgrading](#upgrading).
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
Install with npm:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install chokidar
|
||||||
|
```
|
||||||
|
|
||||||
|
Use it in your code:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import chokidar from 'chokidar';
|
||||||
|
|
||||||
|
// One-liner for current directory
|
||||||
|
chokidar.watch('.').on('all', (event, path) => {
|
||||||
|
console.log(event, path);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Extended options
|
||||||
|
// ----------------
|
||||||
|
|
||||||
|
// Initialize watcher.
|
||||||
|
const watcher = chokidar.watch('file, dir, or array', {
|
||||||
|
ignored: (path, stats) => stats?.isFile() && !path.endsWith('.js'), // only watch js files
|
||||||
|
persistent: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Something to use when events are received.
|
||||||
|
const log = console.log.bind(console);
|
||||||
|
// Add event listeners.
|
||||||
|
watcher
|
||||||
|
.on('add', path => log(`File ${path} has been added`))
|
||||||
|
.on('change', path => log(`File ${path} has been changed`))
|
||||||
|
.on('unlink', path => log(`File ${path} has been removed`));
|
||||||
|
|
||||||
|
// More possible events.
|
||||||
|
watcher
|
||||||
|
.on('addDir', path => log(`Directory ${path} has been added`))
|
||||||
|
.on('unlinkDir', path => log(`Directory ${path} has been removed`))
|
||||||
|
.on('error', error => log(`Watcher error: ${error}`))
|
||||||
|
.on('ready', () => log('Initial scan complete. Ready for changes'))
|
||||||
|
.on('raw', (event, path, details) => { // internal
|
||||||
|
log('Raw event info:', event, path, details);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 'add', 'addDir' and 'change' events also receive stat() results as second
|
||||||
|
// argument when available: https://nodejs.org/api/fs.html#fs_class_fs_stats
|
||||||
|
watcher.on('change', (path, stats) => {
|
||||||
|
if (stats) console.log(`File ${path} changed size to ${stats.size}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Watch new files.
|
||||||
|
watcher.add('new-file');
|
||||||
|
watcher.add(['new-file-2', 'new-file-3']);
|
||||||
|
|
||||||
|
// Get list of actual paths being watched on the filesystem
|
||||||
|
let watchedPaths = watcher.getWatched();
|
||||||
|
|
||||||
|
// Un-watch some files.
|
||||||
|
await watcher.unwatch('new-file');
|
||||||
|
|
||||||
|
// Stop watching. The method is async!
|
||||||
|
await watcher.close().then(() => console.log('closed'));
|
||||||
|
|
||||||
|
// Full list of options. See below for descriptions.
|
||||||
|
// Do not use this example!
|
||||||
|
chokidar.watch('file', {
|
||||||
|
persistent: true,
|
||||||
|
|
||||||
|
// ignore .txt files
|
||||||
|
ignored: (file) => file.endsWith('.txt'),
|
||||||
|
// watch only .txt files
|
||||||
|
// ignored: (file, _stats) => _stats?.isFile() && !file.endsWith('.txt'),
|
||||||
|
|
||||||
|
awaitWriteFinish: true, // emit single event when chunked writes are completed
|
||||||
|
atomic: true, // emit proper events when "atomic writes" (mv _tmp file) are used
|
||||||
|
|
||||||
|
// The options also allow specifying custom intervals in ms
|
||||||
|
// awaitWriteFinish: {
|
||||||
|
// stabilityThreshold: 2000,
|
||||||
|
// pollInterval: 100
|
||||||
|
// },
|
||||||
|
// atomic: 100,
|
||||||
|
|
||||||
|
interval: 100,
|
||||||
|
binaryInterval: 300,
|
||||||
|
|
||||||
|
cwd: '.',
|
||||||
|
depth: 99,
|
||||||
|
|
||||||
|
followSymlinks: true,
|
||||||
|
ignoreInitial: false,
|
||||||
|
ignorePermissionErrors: false,
|
||||||
|
usePolling: false,
|
||||||
|
alwaysStat: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
`chokidar.watch(paths, [options])`
|
||||||
|
|
||||||
|
* `paths` (string or array of strings). Paths to files, dirs to be watched
|
||||||
|
recursively.
|
||||||
|
* `options` (object) Options object as defined below:
|
||||||
|
|
||||||
|
#### Persistence
|
||||||
|
|
||||||
|
* `persistent` (default: `true`). Indicates whether the process
|
||||||
|
should continue to run as long as files are being watched.
|
||||||
|
|
||||||
|
#### Path filtering
|
||||||
|
|
||||||
|
* `ignored` function, regex, or path. Defines files/paths to be ignored.
|
||||||
|
The whole relative or absolute path is tested, not just filename. If a function with two arguments
|
||||||
|
is provided, it gets called twice per path - once with a single argument (the path), second
|
||||||
|
time with two arguments (the path and the
|
||||||
|
[`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats)
|
||||||
|
object of that path).
|
||||||
|
* `ignoreInitial` (default: `false`). If set to `false` then `add`/`addDir` events are also emitted for matching paths while
|
||||||
|
instantiating the watching as chokidar discovers these file paths (before the `ready` event).
|
||||||
|
* `followSymlinks` (default: `true`). When `false`, only the
|
||||||
|
symlinks themselves will be watched for changes instead of following
|
||||||
|
the link references and bubbling events through the link's path.
|
||||||
|
* `cwd` (no default). The base directory from which watch `paths` are to be
|
||||||
|
derived. Paths emitted with events will be relative to this.
|
||||||
|
|
||||||
|
#### Performance
|
||||||
|
|
||||||
|
* `usePolling` (default: `false`).
|
||||||
|
Whether to use fs.watchFile (backed by polling), or fs.watch. If polling
|
||||||
|
leads to high CPU utilization, consider setting this to `false`. It is
|
||||||
|
typically necessary to **set this to `true` to successfully watch files over
|
||||||
|
a network**, and it may be necessary to successfully watch files in other
|
||||||
|
non-standard situations. Setting to `true` explicitly on MacOS overrides the
|
||||||
|
`useFsEvents` default. You may also set the CHOKIDAR_USEPOLLING env variable
|
||||||
|
to true (1) or false (0) in order to override this option.
|
||||||
|
* _Polling-specific settings_ (effective when `usePolling: true`)
|
||||||
|
* `interval` (default: `100`). Interval of file system polling, in milliseconds. You may also
|
||||||
|
set the CHOKIDAR_INTERVAL env variable to override this option.
|
||||||
|
* `binaryInterval` (default: `300`). Interval of file system
|
||||||
|
polling for binary files.
|
||||||
|
([see list of binary extensions](https://github.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json))
|
||||||
|
* `alwaysStat` (default: `false`). If relying upon the
|
||||||
|
[`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats)
|
||||||
|
object that may get passed with `add`, `addDir`, and `change` events, set
|
||||||
|
this to `true` to ensure it is provided even in cases where it wasn't
|
||||||
|
already available from the underlying watch events.
|
||||||
|
* `depth` (default: `undefined`). If set, limits how many levels of
|
||||||
|
subdirectories will be traversed.
|
||||||
|
* `awaitWriteFinish` (default: `false`).
|
||||||
|
By default, the `add` event will fire when a file first appears on disk, before
|
||||||
|
the entire file has been written. Furthermore, in some cases some `change`
|
||||||
|
events will be emitted while the file is being written. In some cases,
|
||||||
|
especially when watching for large files there will be a need to wait for the
|
||||||
|
write operation to finish before responding to a file creation or modification.
|
||||||
|
Setting `awaitWriteFinish` to `true` (or a truthy value) will poll file size,
|
||||||
|
holding its `add` and `change` events until the size does not change for a
|
||||||
|
configurable amount of time. The appropriate duration setting is heavily
|
||||||
|
dependent on the OS and hardware. For accurate detection this parameter should
|
||||||
|
be relatively high, making file watching much less responsive.
|
||||||
|
Use with caution.
|
||||||
|
* *`options.awaitWriteFinish` can be set to an object in order to adjust
|
||||||
|
timing params:*
|
||||||
|
* `awaitWriteFinish.stabilityThreshold` (default: 2000). Amount of time in
|
||||||
|
milliseconds for a file size to remain constant before emitting its event.
|
||||||
|
* `awaitWriteFinish.pollInterval` (default: 100). File size polling interval, in milliseconds.
|
||||||
|
|
||||||
|
#### Errors
|
||||||
|
|
||||||
|
* `ignorePermissionErrors` (default: `false`). Indicates whether to watch files
|
||||||
|
that don't have read permissions if possible. If watching fails due to `EPERM`
|
||||||
|
or `EACCES` with this set to `true`, the errors will be suppressed silently.
|
||||||
|
* `atomic` (default: `true` if `useFsEvents` and `usePolling` are `false`).
|
||||||
|
Automatically filters out artifacts that occur when using editors that use
|
||||||
|
"atomic writes" instead of writing directly to the source file. If a file is
|
||||||
|
re-added within 100 ms of being deleted, Chokidar emits a `change` event
|
||||||
|
rather than `unlink` then `add`. If the default of 100 ms does not work well
|
||||||
|
for you, you can override it by setting `atomic` to a custom value, in
|
||||||
|
milliseconds.
|
||||||
|
|
||||||
|
### Methods & Events
|
||||||
|
|
||||||
|
`chokidar.watch()` produces an instance of `FSWatcher`. Methods of `FSWatcher`:
|
||||||
|
|
||||||
|
* `.add(path / paths)`: Add files, directories for tracking.
|
||||||
|
Takes an array of strings or just one string.
|
||||||
|
* `.on(event, callback)`: Listen for an FS event.
|
||||||
|
Available events: `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `ready`,
|
||||||
|
`raw`, `error`.
|
||||||
|
Additionally `all` is available which gets emitted with the underlying event
|
||||||
|
name and path for every event other than `ready`, `raw`, and `error`. `raw` is internal, use it carefully.
|
||||||
|
* `.unwatch(path / paths)`: Stop watching files or directories.
|
||||||
|
Takes an array of strings or just one string.
|
||||||
|
* `.close()`: **async** Removes all listeners from watched files. Asynchronous, returns Promise. Use with `await` to ensure bugs don't happen.
|
||||||
|
* `.getWatched()`: Returns an object representing all the paths on the file
|
||||||
|
system being watched by this `FSWatcher` instance. The object's keys are all the
|
||||||
|
directories (using absolute paths unless the `cwd` option was used), and the
|
||||||
|
values are arrays of the names of the items contained in each directory.
|
||||||
|
|
||||||
|
### CLI
|
||||||
|
|
||||||
|
Check out third party [chokidar-cli](https://github.com/open-cli-tools/chokidar-cli),
|
||||||
|
which allows to execute a command on each change, or get a stdio stream of change events.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
Sometimes, Chokidar runs out of file handles, causing `EMFILE` and `ENOSP` errors:
|
||||||
|
|
||||||
|
* `bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell`
|
||||||
|
* `Error: watch /home/ ENOSPC`
|
||||||
|
|
||||||
|
There are two things that can cause it.
|
||||||
|
|
||||||
|
1. Exhausted file handles for generic fs operations
|
||||||
|
- Can be solved by using [graceful-fs](https://www.npmjs.com/package/graceful-fs),
|
||||||
|
which can monkey-patch native `fs` module used by chokidar: `let fs = require('fs'); let grfs = require('graceful-fs'); grfs.gracefulify(fs);`
|
||||||
|
- Can also be solved by tuning OS: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`.
|
||||||
|
2. Exhausted file handles for `fs.watch`
|
||||||
|
- Can't seem to be solved by graceful-fs or OS tuning
|
||||||
|
- It's possible to start using `usePolling: true`, which will switch backend to resource-intensive `fs.watchFile`
|
||||||
|
|
||||||
|
All fsevents-related issues (`WARN optional dep failed`, `fsevents is not a constructor`) are solved by upgrading to v4+.
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
- **v4 (Sep 2024):** remove glob support and bundled fsevents. Decrease dependency count from 13 to 1. Rewrite in typescript. Bumps minimum node.js requirement to v14+
|
||||||
|
- **v3 (Apr 2019):** massive CPU & RAM consumption improvements; reduces deps / package size by a factor of 17x and bumps Node.js requirement to v8.16+.
|
||||||
|
- **v2 (Dec 2017):** globs are now posix-style-only. Tons of bugfixes.
|
||||||
|
- **v1 (Apr 2015):** glob support, symlink support, tons of bugfixes. Node 0.8+ is supported
|
||||||
|
- **v0.1 (Apr 2012):** Initial release, extracted from [Brunch](https://github.com/brunch/brunch/blob/9847a065aea300da99bd0753f90354cde9de1261/src/helpers.coffee#L66)
|
||||||
|
|
||||||
|
### Upgrading
|
||||||
|
|
||||||
|
If you've used globs before and want do replicate the functionality with v4:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// v3
|
||||||
|
chok.watch('**/*.js');
|
||||||
|
chok.watch("./directory/**/*");
|
||||||
|
|
||||||
|
// v4
|
||||||
|
chok.watch('.', {
|
||||||
|
ignored: (path, stats) => stats?.isFile() && !path.endsWith('.js'), // only watch js files
|
||||||
|
});
|
||||||
|
chok.watch('./directory');
|
||||||
|
|
||||||
|
// other way
|
||||||
|
import { glob } from 'node:fs/promises';
|
||||||
|
const watcher = watch(await Array.fromAsync(glob('**/*.js')));
|
||||||
|
|
||||||
|
// unwatching
|
||||||
|
// v3
|
||||||
|
chok.unwatch('**/*.js');
|
||||||
|
// v4
|
||||||
|
chok.unwatch(await glob('**/*.js'));
|
||||||
|
```
|
||||||
|
|
||||||
|
## Also
|
||||||
|
|
||||||
|
Why was chokidar named this way? What's the meaning behind it?
|
||||||
|
|
||||||
|
>Chowkidar is a transliteration of a Hindi word meaning 'watchman, gatekeeper', चौकीदार. This ultimately comes from Sanskrit _ चतुष्क_ (crossway, quadrangle, consisting-of-four). This word is also used in other languages like Urdu as (چوکیدار) which is widely used in Pakistan and India.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT (c) Paul Miller (<https://paulmillr.com>), see [LICENSE](LICENSE) file.
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user