@eik/postcss-plugin 3.0.0-next.1 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,57 @@
1
+ ## [3.0.2](https://github.com/eik-lib/postcss-import-map/compare/v3.0.1...v3.0.2) (2021-09-21)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **deps:** update dependency node-fetch to v2.6.3 ([7d74f72](https://github.com/eik-lib/postcss-import-map/commit/7d74f72e111b127189158da8cfdce838292ca7c6))
7
+
8
+ ## [3.0.1](https://github.com/eik-lib/postcss-import-map/compare/v3.0.0...v3.0.1) (2021-09-06)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **deps:** update dependency node-fetch to v2.6.2 ([fcf0ae5](https://github.com/eik-lib/postcss-import-map/commit/fcf0ae5659a7f0ace755b7e36d10c6d52fd3621c))
14
+
15
+ # [3.0.0](https://github.com/eik-lib/postcss-import-map/compare/v2.0.4...v3.0.0) (2021-08-13)
16
+
17
+
18
+ ### Features
19
+
20
+ * Rename module to @eik/postcss-plugin ([#83](https://github.com/eik-lib/postcss-import-map/issues/83)) ([7efa758](https://github.com/eik-lib/postcss-import-map/commit/7efa758f4dc8162e4ca500a7628d7c80f4151b61))
21
+ * Use @eik/common to load config in a project ([#84](https://github.com/eik-lib/postcss-import-map/issues/84)) ([371dcda](https://github.com/eik-lib/postcss-import-map/commit/371dcda2c5245c3759ee4c45e27fc64f926f88fc))
22
+
23
+
24
+ ### BREAKING CHANGES
25
+
26
+ * Use logic in @eik/common to load config from eik.json or package.json
27
+
28
+ * chore: Adjust for PR comments
29
+
30
+ * chore: Remove extra whitespace
31
+
32
+ Co-authored-by: Trygve Lie <trygve.lie@finn.no>
33
+ * Rename module to @eik/postcss-plugin
34
+
35
+ Co-authored-by: Trygve Lie <trygve.lie@finn.no>
36
+
37
+ # [3.0.0-next.2](https://github.com/eik-lib/postcss-import-map/compare/v3.0.0-next.1...v3.0.0-next.2) (2021-03-02)
38
+
39
+
40
+ ### Features
41
+
42
+ * Use @eik/common to load config in a project ([#84](https://github.com/eik-lib/postcss-import-map/issues/84)) ([371dcda](https://github.com/eik-lib/postcss-import-map/commit/371dcda2c5245c3759ee4c45e27fc64f926f88fc))
43
+
44
+
45
+ ### BREAKING CHANGES
46
+
47
+ * Use logic in @eik/common to load config from eik.json or package.json
48
+
49
+ * chore: Adjust for PR comments
50
+
51
+ * chore: Remove extra whitespace
52
+
53
+ Co-authored-by: Trygve Lie <trygve.lie@finn.no>
54
+
1
55
  # [3.0.0-next.1](https://github.com/eik-lib/postcss-import-map/compare/v2.0.4...v3.0.0-next.1) (2021-02-18)
2
56
 
3
57
 
package/README.md CHANGED
@@ -1,12 +1,7 @@
1
- # postcss-import-map
1
+ # @eik/postcss-plugin
2
2
 
3
3
  PostCSS [Eik](https://eik.dev/) plugin to support the use of import maps to map "bare" import specifiers in CSS @import rules.
4
4
 
5
- **Notes:**
6
-
7
- - **This plugin should probably be used as the first plugin of your list.**
8
- - **If you use `postcss-import` please [read this.](#postcss-import-usage)**
9
-
10
5
  ## Installation
11
6
 
12
7
  ```bash
@@ -16,36 +11,36 @@ $ npm install @eik/postcss-plugin
16
11
  ## Usage
17
12
 
18
13
  ```js
19
- // dependencies
20
- var fs = require('fs');
21
- var postcss = require('postcss');
22
- var plugin = require('@eik/postcss-plugin');
14
+ const postcss = require('postcss');
15
+ const plugin = require('@eik/postcss-plugin');
16
+ const fs = require('fs');
23
17
 
24
- // css to be processed
25
- var css = fs.readFileSync('css/input.css', 'utf8');
18
+ // CSS to be processed
19
+ const css = fs.readFileSync('css/input.css', 'utf8');
26
20
 
27
- // process css
28
21
  postcss()
29
22
  .use(
30
- plugin({
31
- imports: {
32
- 'normalize.css':
33
- 'https://unpkg.com/normalize.css@8/normalize.css',
34
- },
35
- })
23
+ plugin()
36
24
  )
37
25
  .process(css, {
38
26
  // `from` option is needed here
39
27
  from: 'css/input.css',
40
28
  })
41
29
  .then(function (result) {
42
- var output = result.css;
43
-
44
- console.log(output);
30
+ console.log(result.css);
45
31
  });
46
32
  ```
47
33
 
48
- `css/input.css`:
34
+ ## Description
35
+
36
+ This plugin transforms "bare" import specifiers to absolute URL specifiers in
37
+ CSS modules by applying an Import Map ahead of time.
38
+
39
+ For a more detailed description of Import Maps, please see our [Import Maps section](https://eik.dev/docs/mapping_import_map).
40
+
41
+ The main target for Import Maps is to map import statements in EcmaScript Modules but it can be applied to CSS import statements too.
42
+
43
+ Given the following CSS:
49
44
 
50
45
  ```css
51
46
  @import 'normalize.css';
@@ -55,92 +50,128 @@ body {
55
50
  }
56
51
  ```
57
52
 
58
- will give you:
53
+ when applaying the following Import Map:
54
+
55
+ ```json
56
+ {
57
+ "imports": {
58
+ "normalize.css": "https://cdn.eik.dev/normalize.css@8/normalize.css",
59
+ },
60
+ }
61
+ ```
62
+
63
+ one will get a transformed CSS like so:
59
64
 
60
65
  ```css
61
- @import 'https://unpkg.com/normalize.css@8/normalize.css';
66
+ @import 'https://cdn.eik.dev/normalize.css@8/normalize.css';
62
67
 
63
68
  body {
64
69
  background: black;
65
70
  }
66
71
  ```
67
72
 
68
- ## PostCSS Import Usage
73
+ ## Options
69
74
 
70
- If you're using [postcss-import](https://github.com/postcss/postcss-import) make sure you update the `plugins` option.
71
- `postcss.config.js`
75
+ This plugin takes the following as options:
76
+
77
+ | option | default | type | required | details |
78
+ | ------- | --------------- | -------- | -------- | ----------------------------------------------------------------------------- |
79
+ | path | `process.cwd()` | `string` | `false` | Path to directory containing a eik.json file or package.json with eik config. |
80
+ | urls | `[]` | `array` | `false` | Array of import map URLs to fetch from. |
81
+ | maps | `[]` | `array` | `false` | Array of import map as objects. |
82
+
83
+ The plugin will attempt to read import map URLs from [`eik.json` or `package.json`](https://eik.dev/docs/overview_eik_json) files in the root of the current working directory if present.
72
84
 
73
85
  ```js
74
- module.exports = (ctx) => ({
75
- plugins: [
76
- require('@eik/postcss-plugin')(),
77
- require('postcss-import')({
78
- // It needs to be added here as well to ensure everything is mapped
79
- plugins: [require('@eik/postcss-plugin')],
80
- }),
81
- ],
82
- });
86
+ postcss()
87
+ .use(
88
+ plugin()
89
+ )
90
+ .process(css, {...})
91
+ .then(...);
83
92
  ```
84
93
 
85
- ## Reading config from eik.json or package.json
94
+ The path to the location of an `eik.json` file can be specified with the `path` option.
86
95
 
87
- By default, this plugin will try to read config from your projects `eik.json` or `package.json` files in the root of the current working directory.
96
+ ```js
97
+ postcss()
98
+ .use(
99
+ plugin({ path: '/path/to/eik-json-folder' })
100
+ )
101
+ .process(css, {...})
102
+ .then(...);
103
+ ```
88
104
 
89
- The path to the location of an `eik.json` file can be specified with the `path` option.
90
- `path` defaults to the current working directory.
105
+ The plugin can also be told which URLs to load import maps from directly using the `urls` option.
91
106
 
92
107
  ```js
93
- module.exports = (ctx) => ({
94
- plugins: [
95
- require('@eik/postcss-plugin')({ path: '/path/to/eik.json' }),
96
- require('postcss-import')({
97
- // It needs to be added here as well to ensure everything is mapped
98
- plugins: [
99
- require('@eik/postcss-plugin')({
100
- path: '/path/to/eik.json',
101
- }),
102
- ],
103
- }),
104
- ],
105
- });
108
+ postcss()
109
+ .use(
110
+ plugin({ urls: 'http://myserver/import-map' })
111
+ )
112
+ .process(css, {...})
113
+ .then(...);
114
+ ```
115
+
116
+ Additionally, individual mappings can be specified using the `maps` option.
117
+
118
+ ```js
119
+ postcss()
120
+ .use(
121
+ plugin({
122
+ maps: [{
123
+ "imports": {
124
+ "normalize.css": "https://cdn.eik.dev/normalize.css@8/normalize.css",
125
+ },
126
+ }],
127
+ })
128
+ )
129
+ .process(css, {...})
130
+ .then(...);
131
+ ```
132
+
133
+ ### Precedence
134
+
135
+ If several of the options are used, `maps` takes precedence over `urls` which takes precedence over values loaded from an `eik.json` or `package.json` file.
136
+
137
+ ie. in the following example
138
+
139
+ ```js
140
+ postcss()
141
+ .use(
142
+ plugin({
143
+ path: '/path/to/eik-json-folder',
144
+ urls: ['http://myserver/import-map'],
145
+ maps: [{
146
+ "imports": {
147
+ "normalize.css": "https://cdn.eik.dev/normalize.css@8/normalize.css",
148
+ },
149
+ }],
150
+ })
151
+ )
152
+ .process(css, {...})
153
+ .then(...);
106
154
  ```
107
155
 
108
- The path to the location of a `package.json` file can be specified with the `packagePath` option.
109
- `packagePath` defaults to the current working directory.
156
+ Any import map URLs in `eik.json` will be loaded first, then merged with (and overridden if necessary by) the result of fetching from `http://myserver/import-map` before finally being merged with (and overriden if necessary by) specific mappings defined in `maps`.
157
+
158
+ ## PostCSS Import Usage
159
+
160
+ If you're using [postcss-import](https://github.com/postcss/postcss-import) make sure you update the `plugins` option.
161
+ `postcss.config.js`
110
162
 
111
163
  ```js
112
164
  module.exports = (ctx) => ({
113
165
  plugins: [
114
- require('@eik/postcss-plugin')({
115
- packagePath: '/path/to/package.json',
116
- }),
166
+ require('@eik/postcss-plugin')(),
117
167
  require('postcss-import')({
118
168
  // It needs to be added here as well to ensure everything is mapped
119
- plugins: [
120
- require('@eik/postcss-plugin')({
121
- packagePath: '/path/to/package.json',
122
- }),
123
- ],
169
+ plugins: [require('@eik/postcss-plugin')],
124
170
  }),
125
171
  ],
126
172
  });
127
173
  ```
128
174
 
129
- ## Options
130
-
131
- This plugin takes an [import map](https://github.com/WICG/import-maps) as options:
132
-
133
- | option | default | type | required | details |
134
- | ----------- | ------------------ | -------- | -------- | ----------------------------------------------------------- |
135
- | path | `cwd/eik.json` | `string` | `false` | Path to eik.json file. |
136
- | packagePath | `cwd/package.json` | `string` | `false` | Path to package.json file. |
137
- | urls | `[]` | `array` | `false` | Array of import map URLs to fetch from. |
138
- | imports | `{}` | `object` | `false` | Mapping between "bare" import specifiers and absolute URLs. |
139
-
140
- This module only cares about "bare" import specifies which map to absolute
141
- URLs in the import map. Any other import specifiers defined in the import map
142
- are ignored.
143
-
144
175
  ## License
145
176
 
146
177
  Copyright (c) 2020 Finn.no
package/package.json CHANGED
@@ -1,23 +1,18 @@
1
1
  {
2
2
  "name": "@eik/postcss-plugin",
3
- "version": "3.0.0-next.1",
3
+ "version": "3.0.2",
4
4
  "description": "PostCSS plugin that uses Eik defined import map files to transform bare import specifiers to absolute URLs in @import rules",
5
- "main": "dist/plugin.js",
5
+ "main": "src/plugin.js",
6
6
  "files": [
7
7
  "CHANGELOG.md",
8
8
  "package.json",
9
- "dist"
9
+ "src/"
10
10
  ],
11
- "directories": {
12
- "dist": "dist"
13
- },
14
11
  "scripts": {
15
- "prepare": "npm run -s build",
16
12
  "test": "tap test/*.js --no-coverage",
17
13
  "test:snapshot": "TAP_SNAPSHOT=1 tap test/*.js --no-coverage",
18
14
  "lint": "eslint .",
19
- "lint:fix": "eslint . --fix",
20
- "build": "rollup -c"
15
+ "lint:fix": "eslint . --fix"
21
16
  },
22
17
  "repository": {
23
18
  "type": "git",
@@ -39,23 +34,24 @@
39
34
  "devDependencies": {
40
35
  "@semantic-release/changelog": "5.0.1",
41
36
  "@semantic-release/commit-analyzer": "8.0.1",
42
- "@semantic-release/git": "9.0.0",
43
- "@semantic-release/github": "7.2.0",
44
- "@semantic-release/npm": "7.0.10",
45
- "@semantic-release/release-notes-generator": "9.0.1",
46
- "eslint": "7.20.0",
37
+ "@semantic-release/git": "9.0.1",
38
+ "@semantic-release/github": "7.2.3",
39
+ "@semantic-release/npm": "7.1.3",
40
+ "@semantic-release/release-notes-generator": "9.0.3",
41
+ "eslint": "7.32.0",
47
42
  "eslint-config-airbnb-base": "14.2.1",
48
- "eslint-plugin-import": "2.22.1",
49
- "eslint-config-prettier": "7.0.0",
50
- "fastify": "3.12.0",
51
- "postcss": "8.2.6",
52
- "rollup": "2.39.0",
53
- "semantic-release": "17.3.9",
43
+ "eslint-plugin-import": "2.24.2",
44
+ "eslint-config-prettier": "8.3.0",
45
+ "fastify": "3.21.3",
46
+ "postcss": "8.3.6",
47
+ "rollup": "2.56.3",
48
+ "semantic-release": "17.4.7",
54
49
  "tap": "14.11.0"
55
50
  },
56
51
  "dependencies": {
52
+ "@eik/common": "4.0.0-next.4",
57
53
  "css-url-parser": "1.1.3",
58
- "node-fetch": "2.6.1"
54
+ "node-fetch": "2.6.3"
59
55
  },
60
56
  "peerDependencies": {
61
57
  "postcss": "^8.0.0"
package/src/plugin.js ADDED
@@ -0,0 +1,121 @@
1
+ /* eslint-disable no-restricted-syntax, no-shadow */
2
+
3
+ const parseCssUrls = require('css-url-parser');
4
+ const { helpers } = require('@eik/common');
5
+ const fetch = require('node-fetch');
6
+
7
+ const notUrl = (url) => url.substr(0, 4) !== 'http';
8
+
9
+ async function fetchImportMaps(urls = []) {
10
+ try {
11
+ const maps = urls.map((map) => fetch(map).then((result) => {
12
+ if (result.status === 404) {
13
+ throw new Error('Import map could not be found on server');
14
+ } else if (result.status >= 400 && result.status < 500) {
15
+ throw new Error('Server rejected client request');
16
+ } else if (result.status >= 500) {
17
+ throw new Error('Server error');
18
+ }
19
+ return result.json();
20
+ }));
21
+ return await Promise.all(maps);
22
+ } catch (err) {
23
+ throw new Error(
24
+ `Unable to load import map file from server: ${err.message}`,
25
+ );
26
+ }
27
+ }
28
+
29
+ const validate = (map) => Object.keys(map.imports).map((key) => {
30
+ const value = map.imports[key];
31
+
32
+ if (notUrl(value)) {
33
+ throw Error(`Import specifier can NOT be mapped to a bare import statement. Import specifier "${key}" is being wrongly mapped to "${value}"`);
34
+ }
35
+
36
+ return { key, value };
37
+ });
38
+
39
+ module.exports = ({
40
+ path = process.cwd(),
41
+ maps = [],
42
+ urls = [],
43
+ } = {}) => {
44
+ const pMaps = Array.isArray(maps) ? maps : [maps];
45
+ const pUrls = Array.isArray(urls) ? urls : [urls];
46
+
47
+ return {
48
+ postcssPlugin: '@eik/postcss-import-map',
49
+ prepare() {
50
+ // Avoid parsing things more than necessary
51
+ const processed = new WeakMap();
52
+ // Only replace once per url
53
+ const replaced = new Set();
54
+ // Eagerly start resolving
55
+
56
+ // Reused replace logic
57
+ const applyImportMap = (mapping, decl) => {
58
+ if (processed.has(decl)) {
59
+ return;
60
+ }
61
+
62
+ let key;
63
+ // First check if it's possibly using syntax like url()
64
+ const parsedUrls = parseCssUrls(decl.params);
65
+ if (parsedUrls.length > 0) {
66
+ // eslint-disable-next-line prefer-destructuring
67
+ key = parsedUrls[0];
68
+ } else {
69
+ // Handle the common cases where it's not wrapped in url() but may have quotes
70
+ key = decl.params.replace(/["']/g, '');
71
+ }
72
+
73
+ // Webpack interop
74
+ key = key.replace(/^~/, '');
75
+
76
+ if (replaced.has(key)) {
77
+ decl.remove();
78
+ } else if (mapping.has(key)) {
79
+ // eslint-disable-next-line no-param-reassign
80
+ decl.params = `'${mapping.get(key)}'`;
81
+ replaced.add(key);
82
+ }
83
+
84
+ // Cache we've processed this
85
+ processed.set(decl, true);
86
+ };
87
+
88
+ const mapping = new Map();
89
+
90
+ return {
91
+ // Run initially once, this is to ensure it runs before postcss-import
92
+ async Once(root) {
93
+ // Load eik config from eik.json or package.json
94
+ const config = await helpers.getDefaults(path);
95
+
96
+ // Fetch import maps from the server
97
+ const fetched = await fetchImportMaps([...config.map, ...pUrls]);
98
+
99
+ const allImportMaps = [...fetched, ...pMaps];
100
+ allImportMaps.forEach((item) => {
101
+ const i = validate(item);
102
+ i.forEach((obj) => {
103
+ mapping.set(obj.key, obj.value);
104
+ });
105
+ });;
106
+
107
+ root.walkAtRules('import', (decl) => {
108
+ applyImportMap(mapping, decl);
109
+ });
110
+ },
111
+ AtRule: {
112
+ import: async (decl) => {
113
+ applyImportMap(mapping, decl);
114
+ },
115
+ },
116
+ };
117
+ },
118
+ };
119
+ };
120
+
121
+ module.exports.postcss = true;
package/dist/plugin.js DELETED
@@ -1,157 +0,0 @@
1
- 'use strict';
2
-
3
- /* eslint-disable no-restricted-syntax, no-shadow */
4
-
5
- const fs = require('fs');
6
- const path = require('path');
7
- const fetch = require('node-fetch');
8
- const parseCssUrls = require('css-url-parser');
9
-
10
- const notUrl = (url) => url.substr(0, 4) !== 'http';
11
-
12
- const notBare = (str) =>
13
- str.startsWith('/') || str.startsWith('./') || str.startsWith('../');
14
-
15
- async function readJSONFile(path) {
16
- try {
17
- const contents = await fs.promises.readFile(path);
18
- return JSON.parse(contents);
19
- } catch (err) {
20
- return {};
21
- }
22
- }
23
-
24
- async function readEikJSONMaps(eikJSONPath, pkgJSONPath) {
25
- const eikJSON = await readJSONFile(eikJSONPath);
26
- const pkgJSON = await readJSONFile(pkgJSONPath);
27
-
28
- if (eikJSON.name && pkgJSON.eik) {
29
- throw new Error('Eik configuration was defined in both in package.json and eik.json. You must specify one or the other.');
30
- }
31
-
32
- const config = { ...eikJSON, ...pkgJSON.eik };
33
-
34
- if (typeof config['import-map'] === 'string') return [config['import-map']];
35
- return config['import-map'] || [];
36
- }
37
-
38
- async function fetchImportMaps(urls = []) {
39
- try {
40
- const maps = urls.map((map) =>
41
- fetch(map).then((result) => {
42
- if (result.status === 404) {
43
- throw new Error('Import map could not be found on server');
44
- } else if (result.status >= 400 && result.status < 500) {
45
- throw new Error('Server rejected client request');
46
- } else if (result.status >= 500) {
47
- throw new Error('Server error');
48
- }
49
- return result.json();
50
- })
51
- );
52
- const results = await Promise.all(maps);
53
- const dependencies = results.map((result) => result.imports);
54
- return Object.assign({}, ...dependencies);
55
- } catch (err) {
56
- throw new Error(
57
- `Unable to load import map file from server: ${err.message}`
58
- );
59
- }
60
- }
61
-
62
- // @TODO this could be a @eik/import-map-utils package
63
- async function populateImportMap({
64
- path: eikPath = path.join(process.cwd(), 'eik.json'),
65
- packagePath = path.join(process.cwd(), 'package.json'),
66
- urls = [],
67
- imports = {},
68
- } = {}) {
69
- const mapping = new Map();
70
-
71
- const importmapUrls = await readEikJSONMaps(eikPath, packagePath);
72
- for (const map of importmapUrls) {
73
- urls.push(map);
74
- }
75
-
76
- let imprts = {};
77
- if (urls.length > 0) {
78
- imprts = { ...(await fetchImportMaps(urls)) };
79
- }
80
- Object.assign(imprts, imports);
81
-
82
- Object.keys(imprts).forEach((key) => {
83
- const value = Array.isArray(imprts[key]) ? imprts[key][0] : imprts[key];
84
-
85
- if (notBare(key)) return;
86
-
87
- if (notUrl(value))
88
- throw Error('Target for import specifier must be an absolute URL.');
89
-
90
- mapping.set(key, value);
91
- });
92
-
93
- return mapping;
94
- }
95
-
96
- module.exports = ({ path, packagePath, urls, imports } = {}) => {
97
- return {
98
- postcssPlugin: '@eik/postcss-import-map',
99
- prepare() {
100
- // Avoid parsing things more than necessary
101
- const processed = new WeakMap();
102
- // Only replace once per url
103
- const replaced = new Set();
104
- // Eagerly start resolving
105
- const mapFetch = populateImportMap({ path, packagePath, urls, imports });
106
- // Reused replace logic
107
- const applyImportMap = (mapping, decl) => {
108
- if (processed.has(decl)) {
109
- return;
110
- }
111
-
112
- let key;
113
- // First check if it's possibly using syntax like url()
114
- const parsedUrls = parseCssUrls(decl.params);
115
- if (parsedUrls.length > 0) {
116
- // eslint-disable-next-line prefer-destructuring
117
- key = parsedUrls[0];
118
- } else {
119
- // Handle the common cases where it's not wrapped in url() but may have quotes
120
- key = decl.params.replace(/["']/g, '');
121
- }
122
-
123
- // Webpack interop
124
- key = key.replace(/^~/, '');
125
-
126
- if (replaced.has(key)) {
127
- decl.remove();
128
- } else if (mapping.has(key)) {
129
- // eslint-disable-next-line no-param-reassign
130
- decl.params = `'${mapping.get(key)}'`;
131
- replaced.add(key);
132
- }
133
-
134
- // Cache we've processed this
135
- processed.set(decl, true);
136
- };
137
- return {
138
- // Run initially once, this is to ensure it runs before postcss-import
139
- async Once(root) {
140
- const mapping = await mapFetch;
141
-
142
- root.walkAtRules('import', (decl) => {
143
- applyImportMap(mapping, decl);
144
- });
145
- },
146
- AtRule: {
147
- import: async (decl) => {
148
- const mapping = await mapFetch;
149
- applyImportMap(mapping, decl);
150
- },
151
- },
152
- };
153
- },
154
- };
155
- };
156
-
157
- module.exports.postcss = true;