From 8405f32b9aa09bef534e67717bf7de3d52477547 Mon Sep 17 00:00:00 2001 From: Roman_Vasilev Date: Sat, 13 Feb 2021 15:08:14 +0400 Subject: [PATCH] fix: Set element source property fix #27 --- .eslintrc.js | 3 ++ .prettierrc.js | 3 +- index.js | 106 +++++++++++++++++++++++++++---------------------- package.json | 7 ++-- test/test.js | 57 +++++++++++++++++++++----- 5 files changed, 114 insertions(+), 62 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index eb7e444..a32f8c9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,6 +6,9 @@ module.exports = { mocha: true, es6: true, }, + parserOptions: { + ecmaVersion: 2020, + }, extends: ['eslint:recommended'], plugins: [], rules: { diff --git a/.prettierrc.js b/.prettierrc.js index 8748676..d569de6 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -1,9 +1,10 @@ module.exports = { - printWidth: 100, + printWidth: 88, trailingComma: 'all', tabWidth: 4, semi: true, singleQuote: true, + arrowParens: 'avoid', overrides: [ { files: '*.{json,yml}', diff --git a/index.js b/index.js index 2a75884..a739d5f 100644 --- a/index.js +++ b/index.js @@ -1,62 +1,69 @@ -var postcss = require('postcss'); -var hh = require('http-https'); -var isUrl = require('is-url'); -var trim = require('lodash.trim'); -var resolveRelative = require('resolve-relative-url'); -var assign = require('lodash.assign'); -var defaults = { +const postcss = require('postcss'); +const hh = require('http-https'); +const isUrl = require('is-url'); +const trim = require('lodash.trim'); +const resolveRelative = require('resolve-relative-url'); +const assign = require('lodash.assign'); +const url = require('url'); + +const defaults = { recursive: true, resolveUrls: false, modernBrowser: false, userAgent: null, }; -var space = postcss.list.space; -var url = require('url'); -var urlRegexp = /url\(["']?.+?['"]?\)/g; +const space = postcss.list.space; +const urlRegexp = /url\(["']?.+?['"]?\)/g; function postcssImportUrl(options) { options = assign({}, defaults, options || {}); - function importUrl(tree, dummy, parentRemoteFile) { + async function importUrl(tree, _, parentRemoteFile) { parentRemoteFile = parentRemoteFile || tree.source.input.file; - var imports = []; + const imports = []; tree.walkAtRules('import', function checkAtRule(atRule) { - var params = space(atRule.params); - var remoteFile = cleanupRemoteFile(params[0]); + 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(function (r) { - var newNode = postcss.parse(r.body); - var mediaQueries = params.slice(1).join(' '); - if (mediaQueries) { - var mediaNode = postcss.atRule({ - name: 'media', - params: mediaQueries, - }); - mediaNode.append(newNode); - newNode = mediaNode; - } + if (!isUrl(remoteFile)) { + return; + } + imports[imports.length] = createPromise(remoteFile, options).then( + async r => { + let newNode = postcss.parse(r.body); + const mediaQueries = params.slice(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 (options.resolveUrls) { - // Convert relative paths to absolute paths - newNode = newNode.replaceValues(urlRegexp, { fast: 'url(' }, function (url) { - return resolveUrls(url, remoteFile); - }); - } + if (options.resolveUrls) { + // Convert relative paths to absolute paths + newNode = newNode.replaceValues( + urlRegexp, + { fast: 'url(' }, + url => resolveUrls(url, remoteFile), + ); + } - var p = options.recursive - ? importUrl(newNode, null, r.parent) - : Promise.resolve(newNode); - return p.then(function (tree) { + const tree = await (options.recursive + ? importUrl(newNode, null, r.parent) + : Promise.resolve(newNode)); atRule.replaceWith(tree); - }); - }); - }); - return Promise.all(imports).then(function () { - return tree; + }, + ); }); + await Promise.all(imports); + return tree; } return { @@ -81,23 +88,23 @@ function resolveUrls(to, from) { } function createPromise(remoteFile, options) { - var reqOptions = url.parse(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/80.0.0.0 Safari/538'; + '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) { - var request = hh.get(reqOptions, function (response) { - var body = ''; - response.on('data', function (chunk) { + const request = hh.get(reqOptions, response => { + let body = ''; + response.on('data', chunk => { body += chunk.toString(); }); - response.on('end', function () { + response.on('end', () => { resolve({ body: body, parent: remoteFile, @@ -109,3 +116,8 @@ function createPromise(remoteFile, options) { } return new Promise(executor); } + +function urlParse(remoteFile) { + const reqOptions = url.parse(remoteFile); + return reqOptions; +} diff --git a/package.json b/package.json index 94c697f..232a53d 100644 --- a/package.json +++ b/package.json @@ -38,11 +38,12 @@ "gulp-connect": "^5.7.0", "gulp-eslint": "^6.0.0", "gulp-mocha": "^7.0.2", - "husky": "^4.3.5", - "postcss": "^8.2.0", + "husky": "^4.3.8", + "ololog": "^1.1.164", + "postcss": "^8.2.4", "precise-commits": "^1.0.2", "prettier": "^2.2.1", - "semantic-release": "^17.3.0", + "semantic-release": "^17.3.7", "tcp-ping": "^0.1.1" }, "directories": { diff --git a/test/test.js b/test/test.js index bc77149..6b04366 100644 --- a/test/test.js +++ b/test/test.js @@ -3,11 +3,14 @@ const expect = require('expect'); const fs = require('fs'); const plugin = require('../'); const tcpp = require('tcp-ping'); +const log = require('ololog'); -const fixture1Css = fs.readFileSync(__dirname + '/fixture-1/style.css', { encoding: 'utf8' }); +const fixture1Css = fs.readFileSync(__dirname + '/fixture-1/style.css', { + encoding: 'utf8', +}); const testEqual = function (input, output, pluginOptions, postcssOptions, done) { - getResult(input, pluginOptions, postcssOptions).then((result) => { + getResult(input, pluginOptions, postcssOptions).then(result => { expect(result.css.trim()).toEqual(output.trim()); expect(result.warnings()).toHaveLength(0); done(); @@ -15,7 +18,7 @@ const testEqual = function (input, output, pluginOptions, postcssOptions, done) }; const testContains = function (input, value, pluginOptions, postcssOptions, done) { - getResult(input, pluginOptions, postcssOptions).then((result) => { + getResult(input, pluginOptions, postcssOptions).then(result => { expect(result.css).toContain(value); expect(result.warnings()).toHaveLength(0); done(); @@ -50,7 +53,8 @@ describe('import with media queries', function () { }); it('rule print', function (done) { - const input = "@import url('http://fonts.googleapis.com/css?family=Tangerine') print"; + const input = + "@import url('http://fonts.googleapis.com/css?family=Tangerine') print"; testContains(input, '@media print', {}, {}, done); }); @@ -106,7 +110,8 @@ describe('import url tangerine', function () { } it('empty', async () => { - const input = "@import 'http://fonts.googleapis.com/css?family=Tangerine' ;"; + const input = + "@import 'http://fonts.googleapis.com/css?family=Tangerine' ;"; const result = await getResult(input); assertOutputTangerine(result); }); @@ -124,13 +129,15 @@ describe('import url tangerine', function () { }); it('url single quotes', async () => { - const input = "@import url('http://fonts.googleapis.com/css?family=Tangerine');"; + const input = + "@import url('http://fonts.googleapis.com/css?family=Tangerine');"; const result = await getResult(input); assertOutputTangerine(result); }); it('url double quotes', async () => { - const input = '@import url("http://fonts.googleapis.com/css?family=Tangerine");'; + const input = + '@import url("http://fonts.googleapis.com/css?family=Tangerine");'; const result = await getResult(input); assertOutputTangerine(result); }); @@ -143,7 +150,7 @@ describe('import url tangerine', function () { }); describe('recursive import', function () { - it('ping server', (done) => { + it('ping server', done => { tcpp.probe('localhost', 1234, function (err) { done(err); }); @@ -218,7 +225,13 @@ describe('recursive import', function () { it('does not resolve relative URLs when option.resolveURLs is false', function (done) { const input = '@import url(http://localhost:1234/fixture-3/style.css)'; - testContains(input, "src: url('./font.woff');", { resolveUrls: false }, {}, done); + testContains( + input, + "src: url('./font.woff');", + { resolveUrls: false }, + {}, + done, + ); }); var _opts = { resolveUrls: true }; @@ -341,14 +354,36 @@ describe('recursive import', function () { describe('google font woff', function () { it('option modernBrowser should import woff', function (done) { const input = '@import url(http://fonts.googleapis.com/css?family=Tangerine);'; - testContains(input, "woff2) format('woff2')", { modernBrowser: true }, {}, done); + testContains( + input, + "woff2) format('woff2')", + { modernBrowser: true }, + {}, + done, + ); }); it('option agent should import woff', function (done) { const input = '@import url(http://fonts.googleapis.com/css?family=Tangerine);'; var opts = { - userAgent: 'Mozilla/5.0 AppleWebKit/537.36 Chrome/80.0.2840.99 Safari/537.36', + userAgent: + 'Mozilla/5.0 AppleWebKit/537.36 Chrome/80.0.2840.99 Safari/537.36', }; testContains(input, "woff2) format('woff2')", opts, {}, done); }); }); + +describe('source property', () => { + it('regular import', async () => { + const input = '@import url(http://fonts.googleapis.com/css?family=Tangerine)'; + const result = await getResult(input); + expect(result.root.source.input.css).toEqual(input); + }); + + it('media import', async () => { + const input = + '@import url(http://fonts.googleapis.com/css?family=Tangerine) print'; + const result = await getResult(input); + expect(result.root.source.input.css).toEqual(input); + }); +});