Skip to content

Stripping the terminating semicolon from @import ...; results in invalid CSS output #2

Closed
@stakx

Description

@stakx

Problem description:

I noticed that using this plugin can result in invalid CSS being output when using @import statements. Say there's a line @import url(blah); in the input. This will be output as @import url(blah). Notice that the terminating semicolon is no longer present. This results in syntactically invalid CSS as this statement and the next one are no longer separated by the ; terminator, causing web browsers to skip one (or both?) of them.

Cause:

I took a look at the source code:

const RESOLVE_RULE = /@import\s+[^;]*;|url\(([^)]*)\)/g

Note that the first case matches only when a terminating semicolon is present, and that semicolon gets included. That match is later passed to parse-import:

const parsed = parseImport(statement)

That module has dedicated logic (second line below) to strip away any trailing semicolon:

	return imports.map(function (imp) {
		imp = imp.replace(/(?:;)$/g, '');


		return {
			path: path(imp),
			condition: condition(imp),
			rule: imp
		};
	});

which is why it's stripped away in the final (now syntactically invalid) output.

Possible solution:

lib/css-replace.js could be augmented as follows:

       const parsed = parseImport(statement)
       if (!parsed.length) {
         throw new Error(`parse rule ${statement} failed`)
       }

+      if (!parsed[0].rule.endsWith(';')) {
+        parsed[0].rule += ';'
+      }
+
       /**
        * parsed[0]: {
        *   path: 'foobar.css',
        *   condition: 'print',
-       *   rule: '@import url("foobar.css") print'
+       *   rule: '@import url("foobar.css") print;'
        * }
        */

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions