summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar liruifengv <liruifeng1024@gmail.com> 2024-01-26 17:44:54 +0800
committerGravatar GitHub <noreply@github.com> 2024-01-26 10:44:54 +0100
commitbd880e8437ea2df16f322f604865c1148a9fd4cf (patch)
treecfa5965140530d844f52ce8afbd783167786e9d2
parent00e6adb033c882c92fdbb3989b2fc1b78acb3bd7 (diff)
downloadastro-bd880e8437ea2df16f322f604865c1148a9fd4cf.tar.gz
astro-bd880e8437ea2df16f322f604865c1148a9fd4cf.tar.zst
astro-bd880e8437ea2df16f322f604865c1148a9fd4cf.zip
fix: fix `transition:name` can be unicode (#9822)
* fix: fix `transition:name` can be unicode * delete prefix - * use for func * add changeset * Update .changeset/cold-bobcats-shave.md Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com> * fix review issue * fix review issue * add comment * add \ to regex * fix some issue * delete unused import * remove a rule * remove valid rule -- * Update transition.ts Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com> * Update transition.ts Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com> * Update transition.ts Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com> * Update transition.ts Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com> * Update transition.ts Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com> * Update transition.ts Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com> * Update transition.ts Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com> * format * use cssesc to escape name * test: add e2e test * add charset for layout * use the raw value for e2e test * use cssesc instead of toValidIdent * uncomment --------- Co-authored-by: Martin Trapp <94928215+martrapp@users.noreply.github.com> Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
-rw-r--r--.changeset/cold-bobcats-shave.md5
-rw-r--r--packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro1
-rw-r--r--packages/astro/e2e/fixtures/view-transitions/src/pages/transition-name.astro16
-rw-r--r--packages/astro/e2e/view-transitions.test.js48
-rw-r--r--packages/astro/package.json2
-rw-r--r--packages/astro/src/runtime/server/transition.ts8
-rw-r--r--pnpm-lock.yaml10
7 files changed, 84 insertions, 6 deletions
diff --git a/.changeset/cold-bobcats-shave.md b/.changeset/cold-bobcats-shave.md
new file mode 100644
index 000000000..ac05fde49
--- /dev/null
+++ b/.changeset/cold-bobcats-shave.md
@@ -0,0 +1,5 @@
+---
+"astro": patch
+---
+
+Applies the correct escaping to identifiers used with `transition:name`.
diff --git a/packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro b/packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro
index ef82078e7..8643f273f 100644
--- a/packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro
+++ b/packages/astro/e2e/fixtures/view-transitions/src/components/Layout.astro
@@ -22,6 +22,7 @@ const { link } = Astro.props as Props;
<ViewTransitions handleForms />
<DarkMode />
<meta name="script-executions" content="0">
+ <meta charset="utf-8">
<script is:inline defer>
{
// Increment a global to see if this is running more than once
diff --git a/packages/astro/e2e/fixtures/view-transitions/src/pages/transition-name.astro b/packages/astro/e2e/fixtures/view-transitions/src/pages/transition-name.astro
new file mode 100644
index 000000000..22fb47aab
--- /dev/null
+++ b/packages/astro/e2e/fixtures/view-transitions/src/pages/transition-name.astro
@@ -0,0 +1,16 @@
+---
+import Layout from '../components/Layout.astro';
+---
+<Layout>
+ <div id="one" transition:name="front-end">front-end</div>
+ <div id="two" transition:name="开源">开源</div>
+ <div id="three" transition:name="开a源">开a源</div>
+ <div id="four" transition:name="c开a源c">c开a源c</div>
+ <div id="five" transition:name="オープンソース">オープンソース</div>
+ <div id="six" transition:name="开$源">开$源</div>
+ <div id="seven" transition:name="开.源">开.源</div>
+ <div id="eight" transition:name="🐎👱❤">🐎👱❤</div>
+ <div id="nine" transition:name="--9">--9</div>
+ <div id="ten" transition:name="10">10</div>
+ <div id="eleven" transition:name="-11">-11</div>
+</Layout>
diff --git a/packages/astro/e2e/view-transitions.test.js b/packages/astro/e2e/view-transitions.test.js
index 0da1010b2..af1f89f3e 100644
--- a/packages/astro/e2e/view-transitions.test.js
+++ b/packages/astro/e2e/view-transitions.test.js
@@ -1227,4 +1227,52 @@ test.describe('View Transitions', () => {
expect(loads.length, 'There should only be 1 page load').toEqual(1);
});
+
+ test('transition:name should be escaped correctly', async ({ page, astro }) => {
+ await page.goto(astro.resolveUrl('/transition-name'));
+ await expect(page.locator('#one'), 'should be escaped correctly').toHaveCSS(
+ 'view-transition-name',
+ 'front-end'
+ );
+ await expect(page.locator('#two'), 'should be escaped correctly').toHaveCSS(
+ 'view-transition-name',
+ '开源'
+ );
+ await expect(page.locator('#three'), 'should be escaped correctly').toHaveCSS(
+ 'view-transition-name',
+ '开a源'
+ );
+ await expect(page.locator('#four'), 'should be escaped correctly').toHaveCSS(
+ 'view-transition-name',
+ 'c开a源c'
+ );
+ await expect(page.locator('#five'), 'should be escaped correctly').toHaveCSS(
+ 'view-transition-name',
+ 'オープンソース'
+ );
+ await expect(page.locator('#six'), 'should be escaped correctly').toHaveCSS(
+ 'view-transition-name',
+ '开\\$源'
+ );
+ await expect(page.locator('#seven'), 'should be escaped correctly').toHaveCSS(
+ 'view-transition-name',
+ '开\\.源'
+ );
+ await expect(page.locator('#eight'), 'should be escaped correctly').toHaveCSS(
+ 'view-transition-name',
+ '🐎👱❤'
+ );
+ await expect(page.locator('#nine'), 'should be escaped correctly').toHaveCSS(
+ 'view-transition-name',
+ '--9'
+ );
+ await expect(page.locator('#ten'), 'should be escaped correctly').toHaveCSS(
+ 'view-transition-name',
+ '\\31 0'
+ );
+ await expect(page.locator('#eleven'), 'should be escaped correctly').toHaveCSS(
+ 'view-transition-name',
+ '-\\31 1'
+ );
+ });
});
diff --git a/packages/astro/package.json b/packages/astro/package.json
index ce8dae159..538243b44 100644
--- a/packages/astro/package.json
+++ b/packages/astro/package.json
@@ -134,6 +134,7 @@
"clsx": "^2.0.0",
"common-ancestor-path": "^1.0.1",
"cookie": "^0.6.0",
+ "cssesc": "^3.0.0",
"debug": "^4.3.4",
"deterministic-object-hash": "^2.0.1",
"devalue": "^4.3.2",
@@ -191,6 +192,7 @@
"@types/common-ancestor-path": "^1.0.2",
"@types/connect": "^3.4.38",
"@types/cookie": "^0.5.4",
+ "@types/cssesc": "^3.0.2",
"@types/debug": "^4.1.12",
"@types/diff": "^5.0.8",
"@types/dlv": "^1.1.4",
diff --git a/packages/astro/src/runtime/server/transition.ts b/packages/astro/src/runtime/server/transition.ts
index 9d039da9d..477f6b5e4 100644
--- a/packages/astro/src/runtime/server/transition.ts
+++ b/packages/astro/src/runtime/server/transition.ts
@@ -7,6 +7,7 @@ import type {
} from '../../@types/astro.js';
import { fade, slide } from '../../transitions/index.js';
import { markHTMLString } from './escape.js';
+import cssesc from 'cssesc';
const transitionNameMap = new WeakMap<SSRResult, number>();
function incrementTransitionNumber(result: SSRResult) {
@@ -23,11 +24,6 @@ export function createTransitionScope(result: SSRResult, hash: string) {
return `astro-${hash}-${num}`;
}
-// Ensure animationName is a valid CSS identifier
-function toValidIdent(name: string): string {
- return name.replace(/[^a-zA-Z0-9\-\_]/g, '_').replace(/^\_+|\_+$/g, '');
-}
-
type Entries<T extends Record<string, any>> = Iterable<[keyof T, T[keyof T]]>;
const getAnimations = (name: TransitionAnimationValue) => {
@@ -58,7 +54,7 @@ export function renderTransition(
// Default to `fade` (similar to `initial`, but snappier)
if (!animationName) animationName = 'fade';
const scope = createTransitionScope(result, hash);
- const name = transitionName ? toValidIdent(transitionName) : scope;
+ const name = transitionName ? cssesc(transitionName, { isIdentifier: true }) : scope;
const sheet = new ViewTransitionStyleSheet(scope, name);
const animations = getAnimations(animationName);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c85679e9a..d44b17292 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -551,6 +551,9 @@ importers:
cookie:
specifier: ^0.6.0
version: 0.6.0
+ cssesc:
+ specifier: ^3.0.0
+ version: 3.0.0
debug:
specifier: ^4.3.4
version: 4.3.4(supports-color@8.1.1)
@@ -712,6 +715,9 @@ importers:
'@types/cookie':
specifier: ^0.5.4
version: 0.5.4
+ '@types/cssesc':
+ specifier: ^3.0.2
+ version: 3.0.2
'@types/debug':
specifier: ^4.1.12
version: 4.1.12
@@ -7345,6 +7351,10 @@ packages:
resolution: {integrity: sha512-7z/eR6O859gyWIAjuvBWFzNURmf2oPBmJlfVWkwehU5nzIyjwBsTh7WMmEEV4JFnHuQ3ex4oyTvfKzcyJVDBNA==}
dev: true
+ /@types/cssesc@3.0.2:
+ resolution: {integrity: sha512-Qii6nTRktvtI380EloxH/V7MwgrYxkPgBI+NklUjQuhzgAd1AqT3QDJd+eD+0doRADgfwvtagLRo7JFa7aMHXg==}
+ dev: true
+
/@types/debug@4.1.12:
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
dependencies: