postcss-import-url
Advanced tools
Comparing version 7.1.0 to 7.2.0
248
index.js
@@ -10,6 +10,7 @@ const postcss = require('postcss'); | ||
const defaults = { | ||
recursive: true, | ||
resolveUrls: false, | ||
modernBrowser: false, | ||
userAgent: null, | ||
recursive: true, | ||
resolveUrls: false, | ||
modernBrowser: false, | ||
userAgent: null, | ||
dataUrls: false, | ||
}; | ||
@@ -20,99 +21,102 @@ const space = postcss.list.space; | ||
function postcssImportUrl(options) { | ||
options = assign({}, defaults, options || {}); | ||
options = assign({}, defaults, options || {}); | ||
async function importUrl(tree, _, parentRemoteFile) { | ||
parentRemoteFile = parentRemoteFile || tree.source.input.file; | ||
const imports = []; | ||
tree.walkAtRules('import', function checkAtRule(atRule) { | ||
const params = space(atRule.params); | ||
let remoteFile = cleanupRemoteFile(params[0]); | ||
if (parentRemoteFile) { | ||
remoteFile = resolveRelative(remoteFile, parentRemoteFile); | ||
} | ||
if (!isUrl(remoteFile)) { | ||
return; | ||
} | ||
imports[imports.length] = createPromise(remoteFile, options).then( | ||
async r => { | ||
let newNode = postcss.parse(r.body); | ||
let hasLayer = params.find(param => param.includes('layer')); | ||
let hasSupports = params.find(param => param.includes('supports')); | ||
async function importUrl(tree, _, parentRemoteFile) { | ||
parentRemoteFile = parentRemoteFile || tree.source.input.file; | ||
const imports = []; | ||
tree.walkAtRules('import', function checkAtRule(atRule) { | ||
const params = space(atRule.params); | ||
let remoteFile = cleanupRemoteFile(params[0]); | ||
if (parentRemoteFile) { | ||
remoteFile = resolveRelative(remoteFile, parentRemoteFile); | ||
} | ||
if (!isUrl(remoteFile)) { | ||
return; | ||
} | ||
imports[imports.length] = createPromise(remoteFile, options).then( | ||
async r => { | ||
let newNode = postcss.parse(r.body); | ||
let hasLayer = params.find(param => param.includes('layer')); | ||
let hasSupports = params.find(param => param.includes('supports')); | ||
const mediaQueries = params | ||
.slice(hasLayer ? (hasSupports ? 3 : 2) : 1) | ||
.join(' '); | ||
const mediaQueries = params | ||
.slice(hasLayer ? (hasSupports ? 3 : 2) : 1) | ||
.join(' '); | ||
if (mediaQueries) { | ||
const mediaNode = postcss.atRule({ | ||
name: 'media', | ||
params: mediaQueries, | ||
source: atRule.source, | ||
}); | ||
mediaNode.append(newNode); | ||
newNode = mediaNode; | ||
} else { | ||
newNode.source = atRule.source; | ||
} | ||
if (mediaQueries) { | ||
const mediaNode = postcss.atRule({ | ||
name: 'media', | ||
params: mediaQueries, | ||
source: atRule.source, | ||
}); | ||
mediaNode.append(newNode); | ||
newNode = mediaNode; | ||
} else { | ||
newNode.source = atRule.source; | ||
} | ||
if (hasSupports) { | ||
const supportQuery = params.find(param => | ||
param.includes('supports'), | ||
); | ||
if (hasSupports) { | ||
const supportQuery = params.find(param => | ||
param.includes('supports'), | ||
); | ||
let init = supportQuery.indexOf('('); | ||
let fin = supportQuery.indexOf(')'); | ||
let query = supportQuery.substr(init + 1, fin - init - 1); | ||
let init = supportQuery.indexOf('('); | ||
let fin = supportQuery.indexOf(')'); | ||
let query = supportQuery.substr(init + 1, fin - init - 1); | ||
const supportsNode = postcss.atRule({ | ||
name: 'supports', | ||
params: `(${query})`, | ||
source: atRule.source, | ||
}); | ||
supportsNode.append(newNode); | ||
newNode = supportsNode; | ||
} else { | ||
newNode.source = atRule.source; | ||
} | ||
const supportsNode = postcss.atRule({ | ||
name: 'supports', | ||
params: `(${query})`, | ||
source: atRule.source, | ||
}); | ||
supportsNode.append(newNode); | ||
newNode = supportsNode; | ||
} else { | ||
newNode.source = atRule.source; | ||
} | ||
if (hasLayer) { | ||
const layer = params.find(param => param.includes('layer')); | ||
if (hasLayer) { | ||
const layer = params.find(param => param.includes('layer')); | ||
let init = layer.indexOf('('); | ||
let fin = layer.indexOf(')'); | ||
let layerName = layer.substr(init + 1, fin - init - 1); | ||
let init = layer.indexOf('('); | ||
let fin = layer.indexOf(')'); | ||
let layerName = layer.substr(init + 1, fin - init - 1); | ||
const layerNode = postcss.atRule({ | ||
name: 'layer', | ||
params: layerName, | ||
source: newNode.source, | ||
}); | ||
const layerNode = postcss.atRule({ | ||
name: 'layer', | ||
params: layerName, | ||
source: newNode.source, | ||
}); | ||
layerNode.append(newNode); | ||
newNode = layerNode; | ||
} | ||
layerNode.append(newNode); | ||
newNode = layerNode; | ||
} | ||
if (options.resolveUrls) { | ||
// Convert relative paths to absolute paths | ||
newNode = newNode.replaceValues( | ||
urlRegexp, | ||
{ fast: 'url(' }, | ||
url => resolveUrls(url, remoteFile), | ||
); | ||
} | ||
const tree = await (options.recursive | ||
? importUrl(newNode, null, r.parent) | ||
: Promise.resolve(newNode)); | ||
atRule.replaceWith(tree); | ||
}, | ||
if (options.resolveUrls) { | ||
// Convert relative paths to absolute paths | ||
newNode = newNode.replaceValues(urlRegexp, { fast: 'url(' }, url => | ||
resolveUrls(url, remoteFile), | ||
); | ||
}); | ||
await Promise.all(imports); | ||
return tree; | ||
} | ||
} | ||
return { | ||
postcssPlugin: 'postcss-import-url', | ||
Once: importUrl, | ||
}; | ||
const importedTree = await (options.recursive | ||
? importUrl(newNode, null, r.parent) | ||
: Promise.resolve(newNode)); | ||
if (options.dataUrls) { | ||
atRule.params = `url(data:text/css;base64,${Buffer.from(importedTree.toString()).toString('base64')})`; | ||
} else { | ||
atRule.replaceWith(importedTree); | ||
} | ||
}, | ||
); | ||
}); | ||
await Promise.all(imports); | ||
return tree; | ||
} | ||
return { | ||
postcssPlugin: 'postcss-import-url', | ||
Once: importUrl, | ||
}; | ||
} | ||
@@ -124,46 +128,46 @@ | ||
function cleanupRemoteFile(value) { | ||
if (value.substr(0, 3) === 'url') { | ||
value = value.substr(3); | ||
} | ||
value = trim(value, '\'"()'); | ||
return value; | ||
if (value.substr(0, 3) === 'url') { | ||
value = value.substr(3); | ||
} | ||
value = trim(value, '\'"()'); | ||
return value; | ||
} | ||
function resolveUrls(to, from) { | ||
return 'url("' + resolveRelative(cleanupRemoteFile(to), from) + '")'; | ||
return 'url("' + resolveRelative(cleanupRemoteFile(to), from) + '")'; | ||
} | ||
function createPromise(remoteFile, options) { | ||
const reqOptions = urlParse(remoteFile); | ||
reqOptions.headers = {}; | ||
reqOptions.headers['connection'] = 'keep-alive'; | ||
if (options.modernBrowser) { | ||
reqOptions.headers['user-agent'] = | ||
'Mozilla/5.0 AppleWebKit/538.0 Chrome/88.0.0.0 Safari/538'; | ||
} | ||
if (options.userAgent) { | ||
reqOptions.headers['user-agent'] = String(options.userAgent); | ||
} | ||
function executor(resolve, reject) { | ||
const request = hh.get(reqOptions, response => { | ||
let body = ''; | ||
response.on('data', chunk => { | ||
body += chunk.toString(); | ||
}); | ||
response.on('end', () => { | ||
resolve({ | ||
body: body, | ||
parent: remoteFile, | ||
}); | ||
}); | ||
const reqOptions = urlParse(remoteFile); | ||
reqOptions.headers = {}; | ||
reqOptions.headers['connection'] = 'keep-alive'; | ||
if (options.modernBrowser) { | ||
reqOptions.headers['user-agent'] = | ||
'Mozilla/5.0 AppleWebKit/538.0 Chrome/88.0.0.0 Safari/538'; | ||
} | ||
if (options.userAgent) { | ||
reqOptions.headers['user-agent'] = String(options.userAgent); | ||
} | ||
function executor(resolve, reject) { | ||
const request = hh.get(reqOptions, response => { | ||
let body = ''; | ||
response.on('data', chunk => { | ||
body += chunk.toString(); | ||
}); | ||
response.on('end', () => { | ||
resolve({ | ||
body: body, | ||
parent: remoteFile, | ||
}); | ||
request.on('error', reject); | ||
request.end(); | ||
} | ||
return new Promise(executor); | ||
}); | ||
}); | ||
request.on('error', reject); | ||
request.end(); | ||
} | ||
return new Promise(executor); | ||
} | ||
function urlParse(remoteFile) { | ||
const reqOptions = url.parse(remoteFile); | ||
return reqOptions; | ||
const reqOptions = url.parse(remoteFile); | ||
return reqOptions; | ||
} |
{ | ||
"name": "postcss-import-url", | ||
"version": "7.1.0", | ||
"version": "7.2.0", | ||
"description": "PostCSS plugin inlines remote files.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -9,3 +9,3 @@ # postcss-import-url | ||
body { | ||
font-size: 13px; | ||
font-size: 13px; | ||
} | ||
@@ -17,9 +17,10 @@ ``` | ||
@font-face { | ||
font-family: 'Tangerine'; | ||
font-style: normal; | ||
font-weight: 400; | ||
src: url(https://fonts.gstatic.com/s/tangerine/v12/IurY6Y5j_oScZZow4VOxCZZM.woff2) format('woff2'); | ||
font-family: 'Tangerine'; | ||
font-style: normal; | ||
font-weight: 400; | ||
src: url(https://fonts.gstatic.com/s/tangerine/v12/IurY6Y5j_oScZZow4VOxCZZM.woff2) | ||
format('woff2'); | ||
} | ||
body { | ||
font-size: 13px; | ||
font-size: 13px; | ||
} | ||
@@ -34,4 +35,4 @@ ``` | ||
postcss([importUrl(options)]).process(css, { | ||
// Define a `from` option to resolve relative @imports in the initial css to a url. | ||
from: 'https://example.com/styles.css', | ||
// Define a `from` option to resolve relative @imports in the initial css to a url. | ||
from: 'https://example.com/styles.css', | ||
}); | ||
@@ -44,11 +45,12 @@ ``` | ||
- `recursive` (boolean) To import URLs recursively (default: `true`) | ||
- `resolveUrls` (boolean) To transform relative URLs found in remote stylesheets into fully qualified URLs ([see #18](https://github.com/unlight/postcss-import-url/pull/18)) (default: `false`) | ||
- `modernBrowser` (boolean) Set user-agent string to 'Mozilla/5.0 AppleWebKit/537.36 Chrome/80.0.0.0 Safari/537.36', this option maybe useful for importing fonts from Google. Google check `user-agent` header string and respond can be different (default: `false`) | ||
- `userAgent` (string) Custom user-agent header (default: `null`) | ||
- `recursive` (boolean) To import URLs recursively (default: `true`) | ||
- `resolveUrls` (boolean) To transform relative URLs found in remote stylesheets into fully qualified URLs ([see #18](https://github.com/unlight/postcss-import-url/pull/18)) (default: `false`) | ||
- `modernBrowser` (boolean) Set user-agent string to 'Mozilla/5.0 AppleWebKit/537.36 Chrome/80.0.0.0 Safari/537.36', this option maybe useful for importing fonts from Google. Google check `user-agent` header string and respond can be different (default: `false`) | ||
- `userAgent` (string) Custom user-agent header (default: `null`) | ||
- `dataUrls` (boolean) Store fetched CSS as base64 encoded data URLs (default: `false`) | ||
## Known Issues | ||
- Google fonts returns different file types per the user agent. Because postcss runs in a shell, | ||
Google returns truetype fonts rather than the better woff2 format. | ||
Use option `modernBrowser` to explicitly load woff2 fonts. | ||
- Google fonts returns different file types per the user agent. Because postcss runs in a shell, | ||
Google returns truetype fonts rather than the better woff2 format. | ||
Use option `modernBrowser` to explicitly load woff2 fonts. |
149
53
9199