feat: scaffold Astro + Tailwind project

This commit is contained in:
TerryM
2026-05-12 16:16:03 +08:00
parent 906eb5c763
commit 03d3800c6c
12097 changed files with 1266600 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
/**
* True when a module id is a propagated-assets boundary.
*
* @example
* `/src/post.mdx?astroPropagatedAssets` stops CSS graph traversal so styles
* from one content render do not bleed into unrelated pages.
*/
export declare function isPropagatedAssetBoundary(id: string): boolean;

View File

@@ -0,0 +1,11 @@
import { PROPAGATED_ASSET_FLAG } from "../../content/consts.js";
function isPropagatedAssetBoundary(id) {
try {
return new URL(id, "file://").searchParams.has(PROPAGATED_ASSET_FLAG);
} catch {
return false;
}
}
export {
isPropagatedAssetBoundary
};

View File

@@ -0,0 +1,21 @@
import type { SSRResult } from '../../types/public/internal.js';
export interface HeadPropagator {
init(result: SSRResult): unknown | Promise<unknown>;
}
/**
* Runs all registered propagators and collects emitted head HTML strings.
*
* This iterates the live `Set`, so propagators discovered during iteration
* are also processed in the same pass.
*
* @example
* If a layout initializes and discovers a nested component that also emits
* `<link rel="stylesheet">`, both head chunks are collected before flush.
*/
export declare function collectPropagatedHeadParts(input: {
propagators: Set<HeadPropagator>;
result: SSRResult;
isHeadAndContent: (value: unknown) => value is {
head: string;
};
}): Promise<string[]>;

View File

@@ -0,0 +1,18 @@
async function collectPropagatedHeadParts(input) {
const collectedHeadParts = [];
const iterator = input.propagators.values();
while (true) {
const { value, done } = iterator.next();
if (done) {
break;
}
const returnValue = await value.init(input.result);
if (input.isHeadAndContent(returnValue) && returnValue.head) {
collectedHeadParts.push(returnValue.head);
}
}
return collectedHeadParts;
}
export {
collectPropagatedHeadParts
};

View File

@@ -0,0 +1,7 @@
/**
* Returns true when source contains the `astro-head-inject` marker comment.
*
* @example
* `//! astro-head-inject` in a helper module marks parent importers as `in-tree`.
*/
export declare function hasHeadInjectComment(source: string): boolean;

View File

@@ -0,0 +1,7 @@
const HEAD_INJECT_COMMENT_EXP = /(?:^\/\/|\/\/!)\s*astro-head-inject/;
function hasHeadInjectComment(source) {
return HEAD_INJECT_COMMENT_EXP.test(source);
}
export {
hasHeadInjectComment
};

View File

@@ -0,0 +1,18 @@
export type ModuleId = string;
export type ImporterGraph = Map<ModuleId, Set<ModuleId>>;
/**
* Computes all importer ancestors that should be treated as `in-tree`.
*
* @example
* If `Button.astro` is imported by `PostLayout.astro`, which is imported by
* `src/pages/blog.astro`, then seeding with `Button.astro` marks all three.
*/
export declare function computeInTreeAncestors(input: {
seeds: Iterable<ModuleId>;
importerGraph: ImporterGraph;
stopAt?: (id: ModuleId) => boolean;
}): Set<ModuleId>;
export declare function buildImporterGraphFromModuleInfo(moduleIds: Iterable<ModuleId>, getModuleInfo: (id: string) => {
importers: readonly string[];
dynamicImporters: readonly string[];
} | null): ImporterGraph;

32
node_modules/astro/dist/core/head-propagation/graph.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
function computeInTreeAncestors(input) {
const inTree = /* @__PURE__ */ new Set();
const seen = /* @__PURE__ */ new Set();
function walk(moduleId) {
if (seen.has(moduleId)) return;
seen.add(moduleId);
if (input.stopAt?.(moduleId)) {
return;
}
inTree.add(moduleId);
for (const importer of input.importerGraph.get(moduleId) ?? []) {
walk(importer);
}
}
for (const seed of input.seeds) {
walk(seed);
}
return inTree;
}
function buildImporterGraphFromModuleInfo(moduleIds, getModuleInfo) {
const graph = /* @__PURE__ */ new Map();
for (const id of moduleIds) {
const mod = getModuleInfo(id);
if (!mod) continue;
graph.set(id, /* @__PURE__ */ new Set([...mod.importers, ...mod.dynamicImporters]));
}
return graph;
}
export {
buildImporterGraphFromModuleInfo,
computeInTreeAncestors
};

View File

@@ -0,0 +1,22 @@
export interface HeadInstructionRenderState {
hasRenderedHead: boolean;
headInTree: boolean;
partial: boolean;
}
/**
* Policy for explicit `head` instructions.
*
* @example
* A page with `<head>{Astro.head}</head>` renders once, then blocks repeats.
*/
export declare function shouldRenderHeadInstruction(state: HeadInstructionRenderState): boolean;
/**
* Policy for fallback `maybe-head` instructions.
*
* @example
* A layout without `<head>` can inject styles with `maybe-head`, but only when
* no explicit `<head>` exists in the rendered tree.
*/
export declare function shouldRenderMaybeHeadInstruction(state: HeadInstructionRenderState): boolean;
/** Dispatches to the policy function for `head` or `maybe-head`. */
export declare function shouldRenderInstruction(type: 'head' | 'maybe-head', state: HeadInstructionRenderState): boolean;

View File

@@ -0,0 +1,14 @@
function shouldRenderHeadInstruction(state) {
return !state.hasRenderedHead && !state.partial;
}
function shouldRenderMaybeHeadInstruction(state) {
return !state.hasRenderedHead && !state.headInTree && !state.partial;
}
function shouldRenderInstruction(type, state) {
return type === "head" ? shouldRenderHeadInstruction(state) : shouldRenderMaybeHeadInstruction(state);
}
export {
shouldRenderHeadInstruction,
shouldRenderInstruction,
shouldRenderMaybeHeadInstruction
};

View File

@@ -0,0 +1,28 @@
import type { PropagationHint, SSRResult } from '../../types/public/internal.js';
/**
* Resolves the effective propagation hint for a component.
*
* Priority: explicit factory hint -> component metadata -> `none`.
*
* @example
* A runtime-created head entry uses `propagation: 'self'`, so it propagates
* even when metadata says `none`.
*/
export declare function resolvePropagationHint(input: {
factoryHint: PropagationHint | undefined;
moduleId: string | undefined;
metadataLookup: (moduleId: string) => PropagationHint | undefined;
}): PropagationHint;
/** Returns true when a hint should register a component as a propagator. */
export declare function isPropagatingHint(hint: PropagationHint): boolean;
/**
* Reads propagation metadata from an `SSRResult` + component factory.
*
* @example
* A compiled `.astro` module with metadata `in-tree` is treated as propagating
* when the factory does not set a stronger explicit hint.
*/
export declare function getPropagationHint(result: SSRResult, factory: {
propagation?: PropagationHint;
moduleId?: string | undefined;
}): PropagationHint;

View File

@@ -0,0 +1,25 @@
function resolvePropagationHint(input) {
const explicitHint = input.factoryHint ?? "none";
if (explicitHint !== "none") {
return explicitHint;
}
if (!input.moduleId) {
return "none";
}
return input.metadataLookup(input.moduleId) ?? "none";
}
function isPropagatingHint(hint) {
return hint === "self" || hint === "in-tree";
}
function getPropagationHint(result, factory) {
return resolvePropagationHint({
factoryHint: factory.propagation,
moduleId: factory.moduleId,
metadataLookup: (moduleId) => result.componentMetadata.get(moduleId)?.propagation
});
}
export {
getPropagationHint,
isPropagatingHint,
resolvePropagationHint
};