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
|
// eslint-disable-next-line regexp/no-super-linear-backtracking
|
||||||
const styleRE = /<style(?:\s.*?)?>.*?<\/style>/gs;
|
const styleRE = /<style(?:\s.*?)?>.*?<\/style>/gs;
|
||||||
|
|
||||||
function isStyleOnlyChanged(oldCode: string, newCode: string) {
|
export function isStyleOnlyChanged(oldCode: string, newCode: string) {
|
||||||
if (oldCode === newCode) return false;
|
if (oldCode === newCode) return false;
|
||||||
|
|
||||||
// Before we can regex-capture style tags, we remove the frontmatter and scripts
|
// 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
|
// Finally, we can compare styles
|
||||||
const oldStyles: string[] = [];
|
const oldStyles: string[] = [];
|
||||||
const newStyles: string[] = [];
|
const newStyles: string[] = [];
|
||||||
oldCode.match(styleRE)?.forEach((m) => oldStyles.push(m));
|
oldCode = oldCode.replace(styleRE, (m) => (oldStyles.push(m), ''));
|
||||||
newCode.match(styleRE)?.forEach((m) => newStyles.push(m));
|
newCode = newCode.replace(styleRE, (m) => (newStyles.push(m), ''));
|
||||||
// The length must also be the same for style only change. If style tags are added/removed,
|
|
||||||
|
// 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
|
// 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);
|
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