0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-27 22:19:04 -05:00

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>
This commit is contained in:
liruifengv 2024-01-26 17:44:54 +08:00 committed by GitHub
parent 00e6adb033
commit bd880e8437
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 84 additions and 6 deletions

View file

@ -0,0 +1,5 @@
---
"astro": patch
---
Applies the correct escaping to identifiers used with `transition:name`.

View file

@ -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

View file

@ -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>

View file

@ -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'
);
});
});

View file

@ -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",

View file

@ -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);

10
pnpm-lock.yaml generated
View file

@ -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: