mirror of
https://github.com/cloudflare/vinext.git
synced 2026-09-14 19:04:59 +08:00
vinext@0.2.0
20 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b891b01d41 |
fix(fonts): detect trailing comma past comments when injecting font options (#2051)
The font plugins inject an extra option into the user's `next/font` options
object by string-splicing before the closing `}`. They chose the separator by
testing whether the text before `}` ends with `,`, but that test ran on the
raw source, so a trailing comment hid a real trailing comma:
`Inter({ weight: "400", /* x */ })` produced `{ weight: "400", /* x */, _vinext: … }`
— a double comma and a syntax error that broke the build.
Add a shared, string-aware `hasTrailingComma`/`lastSignificantChar` helper
(`utils/has-trailing-comma.ts`) that forward-scans tracking string and comment
state, and use it at both font injection sites and in dynamic-preload-metadata
(which previously kept a private comment-stripper). A stateful scan — rather
than stripping comments with a regex — is required so a `//` inside a string
literal (e.g. a URL) can never be mistaken for a comment and corrupt the
trailing-comma decision.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
b77dcfebdc |
test(msw): migrate font-google.test.ts from fetch hijacking to MSW (#1447)
Replaces 16 ad-hoc `globalThis.fetch = async () => new Response(...)`
swaps with a small `mockGoogleFontsCSS(body, opts?)` helper backed by
MSW's `server.use(http.get(...))`. The helper records every URL it
sees so the two tests that previously asserted on `fetchedUrls.find()`
just read `mock.urls` instead, and the one test that asserted on a
hit-count read `mock.count()`.
Two sites need bespoke handling:
- The Inter/Roboto URL-branching test uses an inline
`server.use(http.get("https://fonts.googleapis.com/*", ({ request }) => ...))`
that returns different CSS based on the URL.
- The "network error" test uses `HttpResponse.error()` to make the
fetch reject (replacing the previous `throw new TypeError(...)` in
the swapped fetch).
Handlers are reset between tests by the global `afterEach` in
`tests/_msw/setup.ts`, so the per-test `try { ... } finally
{ globalThis.fetch = originalFetch }` boilerplate disappears (the
`finally` blocks now only call `fs.rmSync` on the temp font root).
This is PR 2 of the MSW migration. PR 1 (#1444) introduced the
infrastructure and migrated `tests/font-google-build.test.ts`. A
follow-up will migrate `tests/fetch-cache.test.ts` and the in-test
fetch stub inside the font block of `tests/app-router.test.ts`.
|
||
|
|
d504f022b0 |
fix(assets): default assetsDir to _next/static (Next.js parity) (#1411)
* fix(assets): default assetsDir to _next/static (Next.js parity) Closes #1337. Supersedes #1383. vinext's default `assetsDir` was Vite's historical `assets/`, so URL emission (`/_next/static/...` via `resolveAssetUrlPrefix("")`) and on-disk layout (`dist/client/assets/...`) disagreed in the empty-`assetPrefix` case. The `build.assetsDir` and `experimental.renderBuiltUrl` Vite overrides only applied when `assetPrefix` was configured, leaving the no-prefix branch serving from a different path than the URL contract Next.js's client runtime and test harness assert against. This commit flips the default to Next.js's canonical layout: - `resolveAssetsDir("")` returns `_next/static` (was `assets`) - `build.assetsDir` is now set unconditionally from `resolveAssetsDir` - Vite's default `base + assetsDir` composition produces correct URLs in the no-prefix case; `renderBuiltUrl` stays gated on `assetPrefix` because it's only needed for the configured cases - Drops the legacy `/assets/` branches in prod-server (3 sites) and static-file-cache (hard cutover — see PR description for rationale) - Updates `_headers` generation, precompress default, fonts plugin `DEFAULT_ASSETS_DIR` to match the new default With the layout aligned, invalid `_next/static/*` requests naturally return plain-text `404 + "Not Found"` from the static-file layer instead of falling through to the page renderer (which would produce an HTML 404 with bootstrap scripts and CSS). This replaces #1383's parity short-circuit with the natural code path: - Node prod-server (App + Pages branches): missing asset under `resolveAppRouterAssetPath` returns `text/plain; charset=utf-8` 404 - Cloudflare worker entry: `isNextStaticPath` recognises asset-shape after ASSETS-binding misses; returns `notFoundStaticAssetResponse` Mirrors Next.js: packages/next/src/server/lib/router-server.ts. Adds `tests/invalid-static-asset-404.test.ts` (3 App Router + 3 Pages Router cases — no prefix / basePath / assetPrefix) ported from Next.js e2e suites. Updates 11 source files + 12 test files; 914+ tests pass in the touched suites (asset-prefix, app-router, pages-router, deploy, font-google, static-file-cache, serve-static, precompress, features, routing, isr-cache, build-optimization, app-rsc/ssr, standalone, middleware, shims). Ported from Next.js: - test/e2e/invalid-static-asset-404-app/*.test.ts - test/e2e/invalid-static-asset-404-pages/*.test.ts * fix(e2e): update cloudflare-pages-router hydration spec for _next/static * PR #1411 approved. Clean fix, 2 nits. Co-authored-by: james-elicx <james-elicx@users.noreply.github.com> * refactor(assets): derive isHashed checks from ASSET_PREFIX_URL_DIR Replace hardcoded '_next/static' string literals in runtime code paths with the ASSET_PREFIX_URL_DIR constant so the asset URL convention has a single source of truth. - server/prod-server.ts isHashed: pathname.includes(`/${ASSET_PREFIX_URL_DIR}/`) - server/prod-server.ts public-dir guard: startsWith(`/${ASSET_PREFIX_URL_DIR}/`) - server/static-file-cache.ts isHashed: both startsWith + includes derived - plugins/fonts.ts DEFAULT_ASSETS_DIR = ASSET_PREFIX_URL_DIR Behavioural no-op — the constant is '_next/static' so the resolved strings are identical. Centralises the URL contract so future changes to ASSET_PREFIX_URL_DIR (or a refactor that derives it from build config) flow through to every consumer. Doc-comment references to '_next/static' left in place — they describe the canonical value for human readers and are not code paths. --------- Co-authored-by: ask-bonk[bot] <ask-bonk[bot]@users.noreply.github.com> Co-authored-by: james-elicx <james-elicx@users.noreply.github.com> |
||
|
|
b46e9b8c44 |
fix(font): match Next.js font result style semantics (#1186)
* fix(font): match Next.js font result style semantics
Font loaders returned incomplete style exports, emitted Google variable classes unconditionally, and accepted adjustFontFallback without producing a metric-adjusted fallback face. Apps that read next/font results or rely on the generated class rule diverged from Next.js.
The shim assumed font-family was the only exported style concern and that the runtime Google loader should always synthesize a variable class. Reuse the existing static Google font transform boundary to inject fallback CSS, share the single-face style decision between Google and local loaders, and only return variable classes when requested.
Regression coverage ports the relevant Next.js font result expectations and checks adjusted fallback injection, disabled fallback behaviour, and single local source style exports.
* fix(font): avoid fallback metrics output collision
The package build emits imported JSON as JavaScript beside compiled TypeScript. Naming the data file fallback-metrics.json let the JSON artifact collide with fallback-metrics.ts on Windows, so the installed dist module could lack the named fallback helper exports.
Rename the generated data file to fallback-metrics-data.json and update the import so the packed output has distinct fallback-metrics.js and fallback-metrics-data.js modules.
* fix(font): preserve validated Google face metadata
Static Google font calls validated and fetched one concrete face, but the runtime shim recomputed exported style fields from raw options. Italic-only families could therefore load an italic face while returning a normal class rule.
Thread validated single-face weight and style through internal transform options, prefer them in the runtime shim, and harden emitted font descriptor values before class-rule and local font-face CSS generation.
Regression tests cover italic-only Google metadata handoff and unsafe font-style values for Google and local font shims.
* fix(font): omit ambiguous Google font style
Google style resolution treated a multi-style array the same as an omitted style option. That made ambiguous requests such as normal plus italic export fontStyle normal, even though no single face was selected.
Only default to normal when the style option is actually omitted. Multi-style arrays now produce no exported fontStyle, with a regression covering the class rule output.
* fix(font): tighten Google font runtime payload
* test(font): expect internal font payload in build output
* refactor(font): consolidate duplicated CSS sanitization functions into font-utils
Address review feedback:
- Remove sanitizeCSSValue wrapper in font-local.ts, use sanitizeFontDescriptorValue directly
- Add cross-module invariant comments for '{family} Fallback' naming convention
- Consolidate escapeCSSString, sanitizeCSSVarName, and sanitizeFallback into
font-utils.ts (previously duplicated across font-google-base.ts, font-local.ts,
and fallback-metrics.ts)
---------
Co-authored-by: James <james@eli.cx>
|
||
|
|
aba335d5f3 |
fix(dev): self-host Google Fonts in dev mode (#1038)
The build pipeline already rewrites `next/font/google` calls to embed self-hosted @font-face CSS pointing at `/<assetsDir>/_vinext_fonts/...`, but the call-site rewrite was gated behind `isBuild`. Dev requests for those URLs 404'd because nothing copies the cached `.vinext/fonts/` files into the dev server's served paths, and once `_selfHostedCSS` is present the shim no longer emits the fonts.googleapis.com `<link>` — so dev showed unstyled glyphs with no CDN fallback. Drop the build-only gate and add a `configureServer` middleware that serves the cached files directly under the same URL prefix the @font-face CSS embeds. Reuse the prod `CONTENT_TYPES` map so dev and prod hand out identical MIME types. Regression spec navigates to a new `/font-google-test` route in app-basic that uses Geist + Geist_Mono, asserts no CDN URL leaks into the HTML, and fetches a preload URL to verify the dev middleware returns a real font/woff2 body. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c63155d913 |
fix(fonts): stabilize next/font/google runtime registrations (#956)
* fix(fonts): make Google font shim registrations stable Repeated next/font/google calls currently mint counter-based class names and append new SSR style rules. During dev HMR, the app module can re-evaluate while the shim module stays alive, so stale classes and links accumulate and the first emitted :root variable keeps winning. The bad invariant was treating each runtime call as a new font registration. Use a deterministic identity for each family and options pair, remove the non-Next :root variable rule, and keep variable declarations scoped to the returned variable class. Regression coverage verifies stable class identities, no :root emission, and no SSR style growth for repeated equivalent calls. * fix(fonts): address Google font review feedback The first PR version left two edge cases in the new stable identity path: crafted font family names could still leak unsafe selector characters into class names, and omitted display hashed differently from explicit display: swap even though both generate the same font URL. Sanitize the readable family segment used in selectors, normalize display to the same default used by buildGoogleFontsUrl, and tighten the CSS variable regression so it checks CSS added by the current call instead of accumulated module state. * fix(fonts): canonicalize Google font identity hashing Equivalent Google font loader options could generate the same CSS and font URL while still producing different class identities. That reintroduced duplicate SSR style rules when option arrays used a different order or representation. The identity hash now canonicalizes unordered option sets, default-style equivalence, and fallback whitespace before hashing. A focused regression test covers reordered weights and subsets, explicit normal style, and trimmed fallback names. * fix(fonts): normalize default fallback font identities Omitting next/font/google fallback produced the same CSS as fallback: ["sans-serif"] but still hashed a different raw option shape. That left the most common default call path outside the deterministic identity dedupe. The identity hash now uses the resolved fallback list and no longer includes the serialized font-family CSS string. Regression coverage verifies implicit and explicit default fallback calls share class and variable identities, and the :root assertion now checks only styles added by its own test. |
||
|
|
dcb417dfa3 |
fix(fonts): google fonts building perfectly (it was just a regex 😭) (#920)
* fix(fonts): google fonts building perfectly (it was just a regex 😭) * fix(fonts): allow newlines inside bracket clauses Previous fix's [^;\n]+? blocked the semicolon-less line bug but also stopped matching multi-line bracket imports/exports — Prettier wraps specifiers across lines once the clause crosses printWidth. Clause is now a sequence of brace blocks (newlines allowed inside, but [^}] keeps the lazy match from spanning past the matching close brace) or single non-;\n chars. Multi-line shapes match again; the original swallow-prevention guard still holds. Reverts the export regex back to [^}]+ — } already delimits, so the extra \n exclusion was over-defensive. * fix(fonts): apply formatter to test file --------- Co-authored-by: MrIago <28714061+MrIago@users.noreply.github.com> |
||
|
|
696948aca4 |
fix(next/font/google): use real axis range, validate options at build time (#885) (#893)
* shim: rewrite buildGoogleFontsUrl on top of the new build-url helper
Replace the inline URL builder in shims/font-google-base.ts with a thin
wrapper around the pure buildGoogleFontsUrl helper from PR 1
(packages/vinext/src/build/google-fonts/build-url.ts). The shim still
takes a FontOptions object and still returns a CSS URL, so external
callers and the existing 84 unit tests are unaffected.
Two visible behaviour changes:
1. Empty options no longer emit `:wght@100..900`. They emit no axis
segment at all, which makes Google return the default static face
(HTTP 200) for every font, including narrow-axis families like Sen
that previously got HTTP 400. This is the dev fallback only; the
build plugin always pre-resolves the real axis range from metadata
in production.
2. Italic-only requests no longer drop the ital axis. Pre-fix the outer
guard `weights.length > 0 || styles.length > 0` entered the block
but the inner branch only handled the wght path, so a call like
`Inter({ style: ['italic'] })` produced `family=Inter&display=swap`
with no italic anywhere in the URL. The shim now derives an ital
array from style and falls back to weight '400' when ital is set
without an explicit weight, so Google has somewhere to attach the
ital axis in the URL.
The shim deliberately does not import font-data.json or validate.ts: a
388 KB metadata file in the Worker bundle would dwarf the rest of the
shim, and the production path already has the metadata-aware variant.
Refs #885.
* plugin: validate options against metadata, surface HTTP errors as build errors
Replace the inline URL builder in plugins/fonts.ts with the pipeline added
in PR 1: validateGoogleFontOptions parses the call's options against the
bundled font metadata, getFontAxes resolves the actual `wght` range for
variable fonts, and buildGoogleFontsUrl emits the URL.
Three behaviour changes:
1. Variable fonts called with no `weight` now request the font's real
axis range (Sen 400..800, Inter 100..900) instead of a hardcoded
100..900. This is the user-visible fix for issue #885: Sen returns
HTTP 200 with all five face files instead of HTTP 400.
2. Validation errors surface as build errors with the source file path
attached. Unknown family, missing weight on a static font (Anton,
Archivo Black, etc.), unknown weight, mixing 'variable' with explicit
weights, axes on non-variable fonts, invalid display values, and
missing/unknown subsets are now all caught at transform time. Pre-fix
these silently produced URLs that Google rejected at request time.
3. HTTP non-2xx responses from Google are now distinguished from network
errors. A 4xx/5xx is wrapped in GoogleFontsHttpError and surfaced
with the failing URL plus the response body, because pre-fix the
silent `catch { return; }` skipped self-hosting and let the runtime
CDN path retry the same broken URL in the browser. Network errors
(offline dev) still fall through silently to keep `vp dev` usable
without a connection.
The fontCache key is the URL, so existing on-disk caches under
`.vinext/fonts/<hash>/` will be stale for affected fonts after this
change. One refetch per font on the next build.
Refs #885.
* tests: regression coverage for the #885 narrow-axis bug and validator throws
Five new tests in tests/font-google.test.ts plus subset additions to
existing fixtures whose Inter() / Roboto() calls were missing them.
Shim regressions:
- buildGoogleFontsUrl with empty options must not emit `:wght@100..900`
- buildGoogleFontsUrl with style-only options must keep the ital axis
visible in the URL
Plugin regressions:
- Sen() with no weight must fetch `:wght@400..800`, not `:wght@100..900`
- unknown families throw a build error with the file path attached
- non-variable fonts called without an explicit weight throw at build
time instead of silently emitting a broken URL
- HTTP 4xx/5xx from Google surfaces as a build error containing the URL
and the response body
- network errors (DNS, ECONNREFUSED, AbortError) still fall through
silently so offline dev keeps working
The existing plugin transform tests passed `Inter({ weight: '400' })`
without subsets; the validator now treats that as a missing-subsets
error (matches Next.js behaviour), so those fixtures gain
`subsets: ['latin']`. The two nested-brace regression tests still
exercise the parser's balanced-brace logic but use a benign
`_placeholder` field instead of `axes: { wght: 400 }`, which is
semantically invalid for Inter under the new validator.
Refs #885.
* address google font review feedback
|
||
|
|
a5ff8653ad | refactor: remove internal re-exports from entry (#828) | ||
|
|
4f61aedc8f |
fix: emit served URLs for next/font/google self-hosted assets (#819)
* fix: emit served URLs for next/font/google self-hosted assets
`fetchAndCacheFont()` in `packages/vinext/src/plugins/fonts.ts` downloads
Google Fonts `.woff2` files into `<root>/.vinext/fonts/<family>-<urlHash>/`
and rewrites the cached `@font-face` CSS with
`css.split(fontUrl).join(path.join(fontDir, filename))` — an absolute
dev-machine filesystem path. That CSS is then embedded verbatim as
`_selfHostedCSS` in the server bundle, and every downstream consumer reads
from the same leaked string:
1. The injected `<style data-vinext-fonts>` block's
`@font-face { src: url(...) }` (via `ssrFontStyles` in
`shims/font-google-base.ts`).
2. The HTML body's `<link rel="preload">` tags emitted from
`server/app-ssr-entry.ts:renderFontHtml()` via
`collectFontPreloadsFromCSS()`'s url-extraction regex.
3. The HTTP `Link:` response header emitted from
`buildAppPageFontLinkHeader()` in `server/app-page-execution.ts` and
set on the response in `server/app-page-response.ts:242`.
Production requests on workerd produce header and body preload entries
like `</home/<user>/<project>/.vinext/fonts/geist-<hash>/geist-<hash>.woff2>`
— the browser requests `<origin>/home/<user>/...`, workerd returns 404
(the cached files are never copied into `dist/client/` either), and the
console fills with `downloadable font: download failed` and
`preloaded with link preload was not used` warnings on every page view.
Because preload is high-priority for fonts, the broken request contends
with real critical-path traffic.
The fix adds `_rewriteCachedFontCssToServedUrls()` which replaces the
`cacheDir` prefix with the served URL namespace `/assets/_vinext_fonts`
right before `_selfHostedCSS` is embedded in the bundle. A matching
`writeBundle` hook on the `vinext:google-fonts` plugin (client environment
only) recursively copies every `.woff2`/`.woff`/`.ttf`/`.otf`/`.eot` file
out of `<root>/.vinext/fonts/` into
`<clientOutDir>/assets/_vinext_fonts/` preserving the subdirectory
structure, so the rewritten URLs resolve against the origin instead of
404ing. No config surface is added — this does not implement `#472`
(`assetPrefix` support), it just stops leaking the filesystem path
regardless of `assetPrefix`.
The existing `_headers` rule for `/assets/*` covers the new namespace,
and `StaticFileCache` picks the copied files up via its recursive walk of
`dist/client/`, so `Content-Type: font/woff2` and
`Cache-Control: public, max-age=31536000, immutable` and an automatic
content-hashed ETag all flow through without any server-side changes. On
Cloudflare the edge returns `CF-Cache-Status: HIT` on the second request,
unchanged from other assets.
## Tests
Two new regression tests, both verified to fail on `main` (before this
commit) and pass with the fix:
- **Unit** — `tests/font-google.test.ts`: five cases in a new
`_rewriteCachedFontCssToServedUrls` describe block that drive the
helper directly with crafted cache directories, multi-occurrence
replacements, regex-metacharacter paths, empty cacheDir, and
no-op CSS. Failure on `main`: the symbol does not exist, then
asserts would detect the leaked `/home/` prefix even if it did.
- **Integration** — `tests/app-router.test.ts`, in a new
`App Router Production server self-hosted next/font/google headers`
describe block. Builds the existing `tests/fixtures/font-google-multiple`
fixture (`Geist` + `Geist_Mono` via `next/font/google`) with a mocked
fetch that stands in for the Google Fonts CDN — the mock returns CSS
with real `https://fonts.gstatic.com/...` URLs so
`fetchAndCacheFont`'s regex actually exercises the path-rewriting code
that was the bug source. Starts `startProdServer()` on a random port
and asserts on the raw HTTP response: (a) `Link:` header contains the
served URL and neither the absolute fixture path nor `.vinext/fonts`
appears anywhere in it, (b) body `<link rel="preload">` tags match
`/assets/_vinext_fonts/...`, (c) the injected `<style data-vinext-fonts>`
block's `@font-face src: url()` also uses the served URL, and (d) the
copied font file serves 200 with `content-type: font/woff2` and an
`immutable` cache-control. Failure on `main`: asserts produce the
leaked path verbatim, e.g.
`src: url(/home/<user>/.../.vinext/fonts/geist-<hash>/geist-<hash>.woff2)`.
A separate fixture is used instead of extending `app-basic` because
`app-basic` is shared by every integration test in the file — adding
`next/font/google` to its root layout would force a real Google Fonts
network fetch into every test run.
## Verified
With the fix applied:
| Check | Result |
|---|---|
| `pnpm test:unit` | **2853 / 2853** pass |
| `pnpm test:integration` | **1262 / 1262** pass (2 pre-existing skips) |
| `pnpm run check` (lint + format + types) | **0** warnings, **0** errors |
| `pnpm test:e2e` — `app-router` project | **322 / 322** pass (3 flaky on retry, 9 pre-existing skips) |
| `pnpm test:e2e` — `cloudflare-workers` project (Miniflare) | **38 / 38** pass (1 flaky on retry) |
Both new tests were also re-run with the fix reverted on a clean tree to
confirm they deterministically catch the regression — the integration
suite printed the leaked path verbatim and the unit suite failed at the
export site.
End-to-end runtime verification on `workerd` (Miniflare, via
`wrangler dev`) against `examples/app-router-cloudflare` with a
`next/font/google` layout import:
- **Before** — `curl -sI /` returns
`Link: </home/<user>/<project>/.vinext/fonts/geist-<hash>/geist-<hash>.woff2>; rel=preload; as=font; ...`,
the body `<link rel="preload">` tags contain the same path, and
requesting the leaked path returns `HTTP/1.1 404 Not Found`.
- **After** — the same `curl -sI /` returns
`Link: </assets/_vinext_fonts/geist-<hash>/geist-<hash>.woff2>; rel=preload; as=font; ...`,
the body `<link>` tags match, and `curl -sI` on the served URL returns
`HTTP/1.1 200 OK`, `Content-Type: font/woff2`,
`Cache-Control: public, max-age=31536000, immutable`,
`CF-Cache-Status: HIT` on the second request.
## References
- #472 — `assetPrefix` / `basePath` support in `next.config` (orthogonal:
this PR does not implement `assetPrefix`, it just stops the absolute
filesystem path from leaking into the preload emitters regardless of
whether `assetPrefix` is set)
- #812 — parallel `applyMiddlewareRequestHeaders` sealed-snapshot
invalidation fix that followed the same report-and-fixture pattern
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(fonts): address review feedback on PR #819
Three follow-ups from `ask-bonk`'s review of
|
||
|
|
d60c8107bc |
fix(fonts): handle nested-brace options objects in self-hosting transform (#723)
* fix(fonts): handle nested-brace options objects in self-hosting transform
namedCallRe and memberCallRe used \{[^}]*\} which stops at the first
closing brace, so calls like Inter({ axes: { wght: 400 } }) were silently
skipped and fell back to CDN delivery.
Replace both regexes with a lookahead-only pattern plus a
findBalancedObject() helper that tracks brace depth and skips string
literals, correctly extracting the full options object regardless of
nesting depth.
Adds two regression tests: one for the named-import path and one for the
default-import proxy (namespace member) path.
* fix(fonts): address bonk review — template literal interpolations, dedup, hoisting
- Fix _findBalancedObject to correctly skip ${...} interpolations inside
template literals. The previous backtick skipper treated any '}' as the
end of the string, which would prematurely exit for values like
`val ${nested}`. Now tracks an exprDepth counter inside interpolations.
- Extract _findCallEnd(code, objEnd) helper that skips whitespace and
returns the index after ')'. Removes ~20 lines of duplicated logic
between the named-call and member-call branches.
- Hoist both helpers to module level (top-level exported functions) so
they are not recreated on every transform() call.
- Add tests: integration test for string values containing brace chars
(Inter({ label: "font {bold}" })), plus unit describe blocks for
_findBalancedObject and _findCallEnd covering string/template/escape/
interpolation/whitespace/null edge cases.
|
||
|
|
a7dd2d56af | fix(fonts): double-comma syntax error when font options have a trailing comma (#719) | ||
|
|
1ff166eb92 |
chore: turn on more lint rules (#714)
* chore: turn on more lint rules * fmt * add todos |
||
|
|
c9d1ddbee6 |
fix(google-fonts): use closure variables instead of this for plugin sstate (#53)
* fix(google-fonts): use closure variables instead of this for plugin state
Vite does not bind `this` to the plugin object when calling hooks like
configResolved and transform.handler. Using `this._isBuild` etc. results
in a TypeError at startup ('Cannot set properties of undefined').
Replace the property-based state with closure variables so the plugin
works correctly regardless of how Vite invokes the hooks.
* fix(google-fonts): fix indentation of plugin object properties inside IIFE return
* fix: update tests to use closure-compatible plugin initialization
Tests were reaching into plugin internals (_isBuild, _fontCache,
_cacheDir) which are now closure variables after the IIFE refactor.
Updated to drive state through configResolved hook and mock fetch
for cache tests.
* fix(google-fonts): apply closure-variable fix on top of main's refactored plugin
main rewrote the plugin to add virtual module import rewriting but kept
the broken this-binding pattern. Apply the PR's fix: wrap in an IIFE so
state is held in closure vars (isBuild, fontCache, cacheDir) instead of
(this as any)._isBuild etc.
* fmt
* fix tests: replace plugin._isBuild direct access with initPlugin() helper
The google-fonts plugin closure fix removes the _isBuild/_fontCache/_cacheDir
properties from the returned Plugin object. Three tests from main's refactor
still used plugin._isBuild = false directly; replace with initPlugin(plugin,
{ command: 'serve' }) to simulate dev mode via the configResolved hook.
* fix: silence no-unused-vars lint warnings in font-google tests
Remove unused cacheDir variable and prefix unused fetch mock parameters
with underscore (_input, _init) per oxlint convention.
---------
Co-authored-by: Steve Faulkner <sfaulkner@cloudflare.com>
Co-authored-by: James <james@eli.cx>
|
||
|
|
7325f0fc7d |
feat(font): replace generated google font catalog with virtual import rewrites (#656)
Reworks the font-catalog removal from #262 using per-import virtual modules so named imports keep normal ESM semantics, aliased/default calls still self-host in build mode, and dependency imports are transformed too. Credit to @yunus25jmi1 for the original PR and direction in #262. |
||
|
|
c17d6941be |
chore: migrate to vite plus (#535)
* chore: migrate to vite plus
* Disable typeAware and typeCheck
* Update CI
* Fix CI
* Fix test
* Clean
* Run test with vp
* Try revert
* react: false In test
* Fix test
* Revert "Try revert"
This reverts commit
|
||
|
|
764a496ce7 |
add oxfmt formatter (#380)
* add oxfmt formatter: config, scripts, CI, editor setup, docs * rebuild lockfile * fix: add Format to required checks list, remove dead ignore pattern * run fmt * add format to agents.md again |
||
|
|
c0bc16c549 | fix: export all google font (#57) | ||
|
|
98b243493f |
fix: resolve CodeQL security alerts (ReDoS, incomplete sanitization, bad code gen) (#87)
Refactor chained .replace() to single-pass tokenizers in pattern matching: - matchConfigPattern in config-matchers.ts and index.ts - escapeHeaderSource (new) replaces inline chained escaping in matchHeaders/applyHeaders - matchMiddlewarePattern in prod server entry template - matchPattern in middleware.ts Also: - escapeHeaderSource correctly handles :param(constraint) patterns - Fix decodeURIComponent parity gap in index.ts matchConfigPattern - Fix redundant dot in middleware.ts tokenizer char class - Add lgtm suppression comments for false positives in test files - Add unit tests for escapeHeaderSource |
||
|
|
12fea722b6 | Initial public release of vinext |