mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
Fix Astro HMR style-only change detection (#10139)
This commit is contained in:
parent
43f87467c6
commit
3c73441eb2
3 changed files with 77 additions and 4 deletions
5
.changeset/twenty-monkeys-thank.md
Normal file
5
.changeset/twenty-monkeys-thank.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"astro": patch
|
||||
---
|
||||
|
||||
Fixes style-only change detection for Astro files if both the markup and styles are updated
|
|
@ -65,7 +65,7 @@ const scriptRE = /<script(?:\s.*?)?>.*?<\/script>/gs;
|
|||
// eslint-disable-next-line regexp/no-super-linear-backtracking
|
||||
const styleRE = /<style(?:\s.*?)?>.*?<\/style>/gs;
|
||||
|
||||
function isStyleOnlyChanged(oldCode: string, newCode: string) {
|
||||
export function isStyleOnlyChanged(oldCode: string, newCode: string) {
|
||||
if (oldCode === newCode) return false;
|
||||
|
||||
// Before we can regex-capture style tags, we remove the frontmatter and scripts
|
||||
|
@ -89,9 +89,14 @@ function isStyleOnlyChanged(oldCode: string, newCode: string) {
|
|||
// Finally, we can compare styles
|
||||
const oldStyles: string[] = [];
|
||||
const newStyles: string[] = [];
|
||||
oldCode.match(styleRE)?.forEach((m) => oldStyles.push(m));
|
||||
newCode.match(styleRE)?.forEach((m) => newStyles.push(m));
|
||||
// The length must also be the same for style only change. If style tags are added/removed,
|
||||
oldCode = oldCode.replace(styleRE, (m) => (oldStyles.push(m), ''));
|
||||
newCode = newCode.replace(styleRE, (m) => (newStyles.push(m), ''));
|
||||
|
||||
// Remaining of `oldCode` and `newCode` is the markup, return false if they're different
|
||||
if (oldCode !== newCode) return false;
|
||||
|
||||
// Finally, check if only the style changed.
|
||||
// The length must also be the same for style only change. If style tags are added/removed,
|
||||
// we need to regenerate the main Astro file so that its CSS imports are also added/removed
|
||||
return oldStyles.length === newStyles.length && !isArrayEqual(oldStyles, newStyles);
|
||||
}
|
||||
|
|
63
packages/astro/test/units/vite-plugin-astro/hmr.test.js
Normal file
63
packages/astro/test/units/vite-plugin-astro/hmr.test.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
import { describe, it } from 'node:test';
|
||||
import * as assert from 'node:assert/strict';
|
||||
import { isStyleOnlyChanged } from '../../../dist/vite-plugin-astro/hmr.js';
|
||||
|
||||
describe('isStyleOnlyChanged', () => {
|
||||
it('should return false if nothing change', () => {
|
||||
const oldCode = 'a';
|
||||
const newCode = 'a';
|
||||
assert.equal(isStyleOnlyChanged(oldCode, newCode), false);
|
||||
});
|
||||
|
||||
it('should return false if script has changed', () => {
|
||||
const oldCode = '<script>console.log("Hello");</script><style>body { color: red; }</style>';
|
||||
const newCode = '<script>console.log("Hi");</script><style>body { color: red; }</style>';
|
||||
assert.equal(isStyleOnlyChanged(oldCode, newCode), false);
|
||||
});
|
||||
|
||||
it('should return true if only style has changed', () => {
|
||||
const oldCode = '<style>body { color: red; }</style>';
|
||||
const newCode = '<style>body { color: blue; }</style>';
|
||||
assert.equal(isStyleOnlyChanged(oldCode, newCode), true);
|
||||
});
|
||||
|
||||
it('should return false if style tags are added or removed', () => {
|
||||
const oldCode = '<style>body { color: red; }</style>';
|
||||
const newCode = '<style>body { color: red; }</style><style>a { color: blue; }</style>';
|
||||
assert.equal(isStyleOnlyChanged(oldCode, newCode), false);
|
||||
});
|
||||
|
||||
it('should return false if frontmatter has changed', () => {
|
||||
const oldCode = `
|
||||
---
|
||||
title: Hello
|
||||
---
|
||||
<style>body { color: red; }</style>`;
|
||||
const newCode = `
|
||||
---
|
||||
title: Hi
|
||||
---
|
||||
<style>body { color: red; }</style>`;
|
||||
assert.equal(isStyleOnlyChanged(oldCode, newCode), false);
|
||||
});
|
||||
|
||||
it('should return false if both frontmatter and style have changed', () => {
|
||||
const oldCode = `
|
||||
---
|
||||
title: Hello
|
||||
---
|
||||
<style>body { color: red; }</style>`;
|
||||
const newCode = `
|
||||
---
|
||||
title: Hi
|
||||
---
|
||||
<style>body { color: blue; }</style>`;
|
||||
assert.equal(isStyleOnlyChanged(oldCode, newCode), false);
|
||||
});
|
||||
|
||||
it('should return false if both markup and style have changed', () => {
|
||||
const oldCode = '<h1>Hello</h1><style>body { color: red; }</style>';
|
||||
const newCode = '<h1>Hi</h1><style>body { color: blue; }</style>';
|
||||
assert.equal(isStyleOnlyChanged(oldCode, newCode), false);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue