Skip to content

Local files using file:// prefix are not inlined with local inlining and produce errors with remote inlining enabled #1210

Description

@Jaakkonen

Environment

  • clean-css version - Latest git master 68b1de6
  • node.js version - node -v: 14.19.1
  • operating system: Arch Linux

Configuration options

const CleanCSS = require('.')
const input = `
@import "file://local-file-1.css";
@import "local-file-2.css";
#a {
    display: none;
}
`
const output = new CleanCSS({inline: ['local']}).minify(input)
console.log(output)

Input CSS

/* local-file-1.css */
#b {
    display: none;
}

/* local-file-2.css */
#c {
    display: none;
}

Actual output CSS

@import url(file://local-file-1.css);#c{display:none}#a{display:none}

Expected output CSS

#b{display:none};#c{display:none}#a{display:none}

Full output

{
  styles: '@import url(file://local-file-1.css);#c{display:none}#a{display:none}',
  stats: {
    efficiency: 0.4122807017543859,
    minifiedSize: 67,
    originalSize: 114,
    timeSpent: 7
  },
  errors: [],
  inlinedStylesheets: [ '/tmp/tmp.rzBdAx3QU9/clean-css/local-file-2.css' ],
  warnings: [
    'Skipping remote @import of "file://local-file-1.css" as no callback given.'
  ]
}

Extra findings

When enabling remote inlining by setting {inline: ['local', 'remote']} neither resource is inlined.

new CleanCSS({inline: ['local', 'remote']}).minify(input)

// Returns
{
  styles: '@import url(file://local-file-1.css);@import url(local-file-2.css);#a{display:none}',
  stats: {
    efficiency: 0.07777777777777772,
    minifiedSize: 83,
    originalSize: 90,
    timeSpent: 6
  },
  errors: [],
  inlinedStylesheets: [],
  warnings: [
    'Skipping remote @import of "file://local-file-1.css" as no callback given.',
    'Skipping local @import of "local-file-2.css" as resource is not allowed.'
  ]
}

but when trying with {inline: ['all']} the file without URL format is inlined

new CleanCSS({inline: ['all']}).minify(input)

// Returns
{
  styles: '@import url(file://local-file-1.css);#c{display:none}#a{display:none}',
  stats: {
    efficiency: 0.4051724137931034,
    minifiedSize: 69,
    originalSize: 116,
    timeSpent: 7
  },
  errors: [],
  inlinedStylesheets: [ '/tmp/tmp.rzBdAx3QU9/clean-css/local-file-2.css' ],
  warnings: [
    'Skipping remote @import of "file://local-file-1.css" as no callback given.'
  ]
}

and when having the required callback function for remote inlining an error is produced by _http_client.js trying to fetch the file://local-file-1.css URL which has invalid protocol:

new CleanCSS({inline: ['all']}).minify(input, (err, output) => {})

// Produces error
_http_client.js:159
    throw new ERR_INVALID_PROTOCOL(protocol, expectedProtocol);
    ^

TypeError [ERR_INVALID_PROTOCOL]: Protocol "file:" not supported. Expected "https:"
    at new NodeError (internal/errors.js:322:7)
    at new ClientRequest (_http_client.js:159:11)
    at request (https.js:370:10)
    at get (https.js:404:15)
    at Object.loadRemoteResource [as fetch] (/tmp/tmp.rzBdAx3QU9/clean-css/lib/reader/load-remote-resource.js:32:3)
    at inlineRemoteStylesheet (/tmp/tmp.rzBdAx3QU9/clean-css/lib/reader/read-sources.js:281:20)
    at inlineStylesheet (/tmp/tmp.rzBdAx3QU9/clean-css/lib/reader/read-sources.js:210:5)
    at doInlineImports (/tmp/tmp.rzBdAx3QU9/clean-css/lib/reader/read-sources.js:190:14)
    at inline (/tmp/tmp.rzBdAx3QU9/clean-css/lib/reader/read-sources.js:178:10)
    at fromStyles (/tmp/tmp.rzBdAx3QU9/clean-css/lib/reader/read-sources.js:151:5) {
  code: 'ERR_INVALID_PROTOCOL'
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions