summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Drew Powers <1369770+drwpow@users.noreply.github.com> 2021-04-02 12:50:30 -0600
committerGravatar GitHub <noreply@github.com> 2021-04-02 12:50:30 -0600
commitb58b493948ef7b6453ba8c4e94c4bd2fcaea8452 (patch)
tree4bb0426f35e3c7e6a8c7523e6f0aaa1e90407113 /src
parent004b3ea6a0b48ecc04d2a0daf9aae374983bed08 (diff)
downloadastro-b58b493948ef7b6453ba8c4e94c4bd2fcaea8452.tar.gz
astro-b58b493948ef7b6453ba8c4e94c4bd2fcaea8452.tar.zst
astro-b58b493948ef7b6453ba8c4e94c4bd2fcaea8452.zip
Fix body from being scoped (#56)
Diffstat (limited to 'src')
-rw-r--r--src/compiler/optimize/postcss-scoped-styles/index.ts9
-rw-r--r--src/compiler/optimize/styles.ts30
2 files changed, 30 insertions, 9 deletions
diff --git a/src/compiler/optimize/postcss-scoped-styles/index.ts b/src/compiler/optimize/postcss-scoped-styles/index.ts
index 0d1253350..01c0acd94 100644
--- a/src/compiler/optimize/postcss-scoped-styles/index.ts
+++ b/src/compiler/optimize/postcss-scoped-styles/index.ts
@@ -12,6 +12,9 @@ interface Selector {
const CSS_SEPARATORS = new Set([' ', ',', '+', '>', '~']);
+/** HTML tags that should never get scoped classes */
+export const NEVER_SCOPED_TAGS = new Set<string>(['base', 'body', 'font', 'frame', 'frameset', 'head', 'html', 'link', 'meta', 'noframes', 'noscript', 'script', 'style', 'title']);
+
/**
* Scope Selectors
* Given a selector string (`.btn>span,.nav>span`), add an additional CSS class to every selector (`.btn.myClass>span.myClass,.nav.myClass>span.myClass`)
@@ -62,6 +65,12 @@ export function scopeSelectors(selector: string, className: string) {
continue;
}
+ // don‘t scope body, title, etc.
+ if (NEVER_SCOPED_TAGS.has(value)) {
+ ss = head + value + tail;
+ continue;
+ }
+
// scope everything else
let newSelector = ss.substring(start, end);
const pseudoIndex = newSelector.indexOf(':');
diff --git a/src/compiler/optimize/styles.ts b/src/compiler/optimize/styles.ts
index 36e6f1d7d..72781fefe 100644
--- a/src/compiler/optimize/styles.ts
+++ b/src/compiler/optimize/styles.ts
@@ -7,7 +7,7 @@ import sass from 'sass';
import { RuntimeMode } from '../../@types/astro';
import { OptimizeOptions, Optimizer } from '../../@types/optimizer';
import type { TemplateNode } from '../../parser/interfaces';
-import astroScopedStyles from './postcss-scoped-styles/index.js';
+import astroScopedStyles, { NEVER_SCOPED_TAGS } from './postcss-scoped-styles/index.js';
type StyleType = 'css' | 'scss' | 'sass' | 'postcss';
@@ -26,9 +26,6 @@ const getStyleType: Map<string, StyleType> = new Map([
['text/scss', 'scss'],
]);
-/** HTML tags that should never get scoped classes */
-const NEVER_SCOPED_TAGS = new Set<string>(['html', 'head', 'body', 'script', 'style', 'link', 'meta']);
-
/** Should be deterministic, given a unique filename */
function hashFromFilename(filename: string): string {
const hash = crypto.createHash('sha256');
@@ -55,6 +52,15 @@ export interface TransformStyleOptions {
mode: RuntimeMode;
}
+/** given a class="" string, does it contain a given class? */
+function hasClass(classList: string, className: string): boolean {
+ if (!className) return false;
+ for (const c of classList.split(' ')) {
+ if (className === c.trim()) return true;
+ }
+ return false;
+}
+
/** Convert styles to scoped CSS */
async function transformStyle(code: string, { type, filename, scopedClass, mode }: TransformStyleOptions): Promise<StyleTransformResult> {
let styleType: StyleType = 'css'; // important: assume CSS as default
@@ -149,12 +155,18 @@ export default function optimizeStyles({ compileOptions, filename, fileID }: Opt
const attr = node.attributes[classIndex];
for (let k = 0; k < attr.value.length; k++) {
if (attr.value[k].type === 'Text') {
- // string literal
- attr.value[k].raw += ' ' + scopedClass;
- attr.value[k].data += ' ' + scopedClass;
+ // don‘t add same scopedClass twice
+ if (!hasClass(attr.value[k].data, scopedClass)) {
+ // string literal
+ attr.value[k].raw += ' ' + scopedClass;
+ attr.value[k].data += ' ' + scopedClass;
+ }
} else if (attr.value[k].type === 'MustacheTag' && attr.value[k]) {
- // MustacheTag
- attr.value[k].content = `(${attr.value[k].content}) + ' ${scopedClass}'`;
+ // don‘t add same scopedClass twice (this check is a little more basic, but should suffice)
+ if (!attr.value[k].content.includes(`' ${scopedClass}'`)) {
+ // MustacheTag
+ attr.value[k].content = `(${attr.value[k].content}) + ' ${scopedClass}'`;
+ }
}
}
}