Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: webpack-contrib/css-loader
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 9497d74d35a72e22d056b711fdfc7f3166482b36
Choose a base ref
...
head repository: webpack-contrib/css-loader
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 634ab49c17b284e55e62105109412ebd37e234b5
Choose a head ref

Commits on Nov 17, 2016

  1. Update README.md

    Fixes #227
    SpaceK33z authored Nov 17, 2016
    Copy the full SHA
    9df4467 View commit details

Commits on Nov 18, 2016

  1. add issue templates

    SpaceK33z committed Nov 18, 2016
    Copy the full SHA
    564f521 View commit details
  2. expose getLocalIdent (#357)

    * expose getLocalIdent
    
    * add test & docs
    longlho authored and sokra committed Nov 18, 2016
    Copy the full SHA
    46ebca3 View commit details

Commits on Nov 25, 2016

  1. Copy the full SHA
    85a2156 View commit details

Commits on Dec 2, 2016

  1. 0.26.1

    sokra committed Dec 2, 2016
    Copy the full SHA
    5b856b2 View commit details

Commits on Dec 7, 2016

  1. Add license file

    SpaceK33z authored Dec 7, 2016
    Copy the full SHA
    a38e254 View commit details
  2. Bump source-map-list to 0.1.7 (#383)

    gaearon authored and SpaceK33z committed Dec 7, 2016
    Copy the full SHA
    851a22b View commit details
  3. Copy the full SHA
    5735e5d View commit details

Commits on Dec 8, 2016

  1. Add files to package.json. (#388)

    Move from `.npmignore` to `files` field in `package.json`.
    wtgtybhertgeghgtwtg authored and SpaceK33z committed Dec 8, 2016
    Copy the full SHA
    08e9d47 View commit details

Commits on Jan 11, 2017

  1. Merge pull request #380 from michael-ciniawsky/readme

    docs(README): refactor for webpack v2
    TheLarkInn authored Jan 11, 2017
    Copy the full SHA
    9508990 View commit details

Commits on Jan 21, 2017

  1. Copy the full SHA
    4bd7130 View commit details
  2. Merge pull request #407 from christianvuerings/readme-minimize

    README - fix default for minimize
    TheLarkInn authored Jan 21, 2017
    Copy the full SHA
    e54549e View commit details
  3. ci(Travis): updates Travis validations

     - Validate against current node versions
     - Test against both Webpack 1.4.x & 2.2.x
     - Remove deprecated .eslintrc
     - .eslint.yml generated from current code ( no changes )
     - add yarn lock file set to binary in git
     - ignores console for eslint in test helpers
    joshwiens committed Jan 21, 2017
    Copy the full SHA
    2fd0c78 View commit details
  4. Merge pull request #408 from d3viant0ne/d3viant0ne-TravisValidations

    ci(Travis): updates Travis validations
    TheLarkInn authored Jan 21, 2017
    Copy the full SHA
    793390a View commit details

Commits on Jan 23, 2017

  1. Fix Maintainer section look (#409)

    montogeek authored and SpaceK33z committed Jan 23, 2017
    Copy the full SHA
    199897f View commit details

Commits on Feb 21, 2017

  1. Copy the full SHA
    7c45e94 View commit details

Commits on Feb 24, 2017

  1. Copy the full SHA
    f8cdaca View commit details
  2. Merge pull request #428 from helloyou2012/master

    fix deprecation warning (loader-utils)
    bebraw authored Feb 24, 2017
    Copy the full SHA
    7732614 View commit details
  3. Copy the full SHA
    d7317ca View commit details

Commits on Mar 9, 2017

  1. Copy the full SHA
    c769ac3 View commit details
  2. Copy the full SHA
    3362b10 View commit details
  3. docs(readme): add intro to usage

    simon04 authored and joshwiens committed Mar 9, 2017
    Copy the full SHA
    d4ac0e0 View commit details
  4. Copy the full SHA
    a2b85d7 View commit details
  5. chore(release): 0.26.4

    joshwiens committed Mar 9, 2017
    Copy the full SHA
    24aac10 View commit details
  6. Copy the full SHA
    2303df4 View commit details
  7. docs: README.md line endings

    joscha authored and joshwiens committed Mar 9, 2017
    Copy the full SHA
    d7308bc View commit details
  8. fix: minimizeOptions should be query.minimize!

    It's a mistake according to the doc.
    
    Init `minimizeOptions` should be `query.minimize` rather than just query.
    
    https://github.com/webpack/css-loader#minification
    JounQin authored and joshwiens committed Mar 9, 2017
    Copy the full SHA
    16c0858 View commit details
  9. test: fix test error

    JounQin authored and joshwiens committed Mar 9, 2017
    Copy the full SHA
    ac7ab1f View commit details
  10. feat: Include the sourceMappingURL & sourceURL when toString()

    This feature is useful when you need to pass the result of css-loader to angular: call to require('to-string-loader!css-loader? sourceMap!sass-loader?sourceMap!./ test.scss') will include source mapping, And finally assigned to the component's styles metadata
    Zhicheng Wang authored and joshwiens committed Mar 9, 2017
    Copy the full SHA
    6da7e90 View commit details

Commits on Mar 10, 2017

  1. chore(release): add standard-version & update travis build (#446)

    * chore(release): add standard-version & scripts
    
    * docs(readme): update coverage badge
    
    * ci(travis): fix minimum nodejs version
    joshwiens authored Mar 10, 2017
    Copy the full SHA
    17faa31 View commit details
  2. feat: allow removal of original class name (#445)

    * feat: allow removal of original class name
    
    * add comment for 1.0.0
    
    * docs: move table
    
    * docs: consistency
    joscha authored and joshwiens committed Mar 10, 2017
    Copy the full SHA
    3f78361 View commit details
  3. chore(release): 0.27.0

    joshwiens committed Mar 10, 2017
    Copy the full SHA
    9504ea5 View commit details
  4. Copy the full SHA
    0eedd9f View commit details
  5. fix: Can't resolve 'fs' when bundle with webpack #447

    This is a webpack core level problem. Hackfixing for now.
    
    Closes #447.
    bebraw committed Mar 10, 2017
    Copy the full SHA
    75c6bee View commit details
  6. chore: Update changelog

    bebraw committed Mar 10, 2017
    Copy the full SHA
    d1d289e View commit details
  7. 0.27.1

    bebraw committed Mar 10, 2017
    Copy the full SHA
    0252643 View commit details

Commits on Mar 12, 2017

  1. Copy the full SHA
    27ca5a0 View commit details
  2. chore: Update change log

    bebraw committed Mar 12, 2017
    Copy the full SHA
    408bf91 View commit details
  3. 0.27.2

    bebraw committed Mar 12, 2017
    Copy the full SHA
    ee7234b View commit details

Commits on Mar 13, 2017

  1. Remove extra source map file + write source maps only if they are ena…

    …bled (#453)
    
    * chore: Eliminate convert-source-map
    
    The needed functionality has been extracted to a function.
    
    * fix: Write sourcemaps only if `sourceMap` is enabled
    bebraw authored Mar 13, 2017
    Copy the full SHA
    4250129 View commit details
  2. chore(release): 0.27.3

    bebraw committed Mar 13, 2017
    Copy the full SHA
    76ee8c2 View commit details

Commits on Mar 15, 2017

  1. Copy the full SHA
    04dabca View commit details

Commits on Mar 18, 2017

  1. Copy the full SHA
    c8db489 View commit details

Commits on Mar 30, 2017

  1. Copy the full SHA
    76eb7f6 View commit details
  2. chore(release): 0.28.0

    bebraw committed Mar 30, 2017
    Copy the full SHA
    2f562f8 View commit details

Commits on Mar 31, 2017

  1. Copy the full SHA
    2ee7552 View commit details

Commits on Apr 17, 2017

  1. Copy the full SHA
    534ea55 View commit details

Commits on Apr 18, 2017

  1. Copy the full SHA
    f99dd75 View commit details
  2. Copy the full SHA
    bff9c7f View commit details
  3. Copy the full SHA
    6ee2fc6 View commit details
Showing with 29,641 additions and 1,844 deletions.
  1. +145 −0 .circleci/config.yml
  2. +13 −0 .editorconfig
  3. +3 −0 .eslintignore
  4. +0 −10 .eslintrc
  5. +11 −0 .eslintrc.js
  6. +3 −0 .gitattributes
  7. +6 −0 .github/CODEOWNERS
  8. +124 −0 .github/CONTRIBUTING.md
  9. +16 −0 .github/ISSUE_TEMPLATE.md
  10. +51 −0 .github/ISSUE_TEMPLATE/BUG.md
  11. +30 −0 .github/ISSUE_TEMPLATE/DOCS.md
  12. +28 −0 .github/ISSUE_TEMPLATE/FEATURE.md
  13. +33 −0 .github/ISSUE_TEMPLATE/MODIFICATION.md
  14. +9 −0 .github/ISSUE_TEMPLATE/SUPPORT.md
  15. +35 −0 .github/PULL_REQUEST_TEMPLATE.md
  16. +18 −2 .gitignore
  17. +0 −3 .npmignore
  18. +5 −0 .prettierrc
  19. +0 −12 .travis.yml
  20. +231 −0 CHANGELOG.md
  21. +20 −0 LICENSE
  22. +677 −259 README.md
  23. +42 −0 appveyor.yml
  24. +0 −5 index.js
  25. +0 −29 lib/compile-exports.js
  26. +0 −50 lib/css-base.js
  27. +0 −14 lib/getImportPrefix.js
  28. +0 −16 lib/getLocalIdent.js
  29. +0 −124 lib/loader.js
  30. +0 −46 lib/localsLoader.js
  31. +0 −251 lib/processCss.js
  32. +0 −5 locals.js
  33. +12,782 −0 package-lock.json
  34. +107 −29 package.json
  35. +28 −0 src/CssSyntaxError.js
  36. +20 −0 src/Warning.js
  37. +3 −0 src/cjs.js
  38. +354 −0 src/index.js
  39. +86 −0 src/options.json
  40. +5 −0 src/plugins/index.js
  41. +94 −0 src/plugins/postcss-icss-parser.js
  42. +108 −0 src/plugins/postcss-import-parser.js
  43. +120 −0 src/plugins/postcss-url-parser.js
  44. +82 −0 src/runtime/api.js
  45. +17 −0 src/runtime/url-escape.js
  46. +84 −0 src/utils.js
  47. +202 −0 test/__snapshots__/camelCase-option.test.js.snap
  48. +115 −0 test/__snapshots__/errors.test.js.snap
  49. +120 −0 test/__snapshots__/getLocalIdent-option.test.js.snap
  50. +227 −0 test/__snapshots__/icss.test.js.snap
  51. +1,775 −0 test/__snapshots__/import-option.test.js.snap
  52. +191 −0 test/__snapshots__/importLoaders-option.test.js.snap
  53. +1,202 −0 test/__snapshots__/loader.test.js.snap
  54. +302 −0 test/__snapshots__/localIdentName-option.test.js.snap
  55. +5,380 −0 test/__snapshots__/modules-option.test.js.snap
  56. +255 −0 test/__snapshots__/sourceMap-option.test.js.snap
  57. +1,983 −0 test/__snapshots__/url-option.test.js.snap
  58. +101 −0 test/camelCase-option.test.js
  59. +0 −24 test/camelCaseTest.js
  60. +8 −0 test/cjs.test.js
  61. +0 −37 test/cssBaseTest.js
  62. +89 −0 test/errors.test.js
  63. +113 −0 test/fixtures/basic.css
  64. +4 −0 test/fixtures/basic.js
  65. 0 test/fixtures/empty.css
  66. +7 −0 test/fixtures/icss/tests-cases/duplicate-export-in-multiple-export/source.css
  67. +4 −0 test/fixtures/icss/tests-cases/duplicate-export/source.css
  68. +1 −0 test/fixtures/icss/tests-cases/empty-export/source.css
  69. +1 −0 test/fixtures/icss/tests-cases/empty-import/source.css
  70. +4 −0 test/fixtures/icss/tests-cases/export-reserved-keywords/source.css
  71. +3 −0 test/fixtures/icss/tests-cases/export/source.css
  72. +14 −0 test/fixtures/icss/tests-cases/import-reserved-keywords/source.css
  73. +4 −0 test/fixtures/icss/tests-cases/import-reserved-keywords/vars.css
  74. +11 −0 test/fixtures/icss/tests-cases/import/source.css
  75. +3 −0 test/fixtures/icss/tests-cases/import/vars.css
  76. +7 −0 test/fixtures/icss/tests-cases/multiple-export/source.css
  77. +7 −0 test/fixtures/icss/tests-cases/multiple-keys-values-in-export/source.css
  78. +3 −0 test/fixtures/import/alias.css
  79. BIN test/fixtures/import/img.png
  80. +67 −0 test/fixtures/import/import.css
  81. +3 −0 test/fixtures/import/node_modules/package/test.css
  82. +3 −0 test/fixtures/import/node_modules/package/tilde.css
  83. +3 −0 test/fixtures/import/other-query.css
  84. +3 −0 test/fixtures/import/query.css
  85. +3 −0 test/fixtures/import/relative.css
  86. +5 −0 test/fixtures/import/test-media.css
  87. +3 −0 test/fixtures/import/test-nested-media.css
  88. +3 −0 test/fixtures/import/test-other.css
  89. +3 −0 test/fixtures/import/test.css
  90. +3 −0 test/fixtures/import/top-relative.css
  91. +3 −0 test/fixtures/import/url.css
  92. +3 −0 test/fixtures/imported.css
  93. +3 −0 test/fixtures/invalid.css
  94. +3 −0 test/fixtures/modules/alias.css
  95. +20 −0 test/fixtures/modules/camelCase.css
  96. +58 −0 test/fixtures/modules/composes.css
  97. +7 −0 test/fixtures/modules/getLocalIdent.css
  98. +3 −0 test/fixtures/modules/imported-simple.css
  99. +1 −0 test/fixtures/modules/issue-286/dep.css
  100. +1 −0 test/fixtures/modules/issue-286/source.css
  101. +3 −0 test/fixtures/modules/issue-636/foo.scss
  102. +3 −0 test/fixtures/modules/issue-636/source.scss
  103. +27 −0 test/fixtures/modules/localIdentName.css
  104. +3 −0 test/fixtures/modules/node_modules/package/style.css
  105. +3 −0 test/fixtures/modules/relative.css
  106. +1 −0 test/fixtures/modules/something.css
  107. +3 −0 test/fixtures/modules/test-other.css
  108. 0 test/{moduleTestCases → fixtures/modules/tests-cases}/class-names/source.css
  109. +1 −0 test/fixtures/modules/tests-cases/comment-in-local/source.css
  110. BIN test/fixtures/modules/tests-cases/comments/img.png
  111. +2 −2 test/{moduleTestCases → fixtures/modules/tests-cases}/comments/source.css
  112. +11 −0 test/fixtures/modules/tests-cases/composes-1/file.css
  113. +3 −0 test/fixtures/modules/tests-cases/composes-1/source.css
  114. +11 −0 test/fixtures/modules/tests-cases/composes-2/file.css
  115. +3 −0 test/fixtures/modules/tests-cases/composes-2/source.css
  116. +3 −0 test/fixtures/modules/tests-cases/composes-multiple/file1.css
  117. +3 −0 test/fixtures/modules/tests-cases/composes-multiple/file2.css
  118. +4 −0 test/fixtures/modules/tests-cases/composes-multiple/source.css
  119. +3 −0 test/fixtures/modules/tests-cases/composes-with-importing/file.css
  120. +3 −0 test/fixtures/modules/tests-cases/composes-with-importing/source.css
  121. +2 −0 test/fixtures/modules/tests-cases/composes/source.css
  122. +5 −0 test/fixtures/modules/tests-cases/declaration-value/source.css
  123. BIN test/fixtures/modules/tests-cases/issue-589/img.png
  124. +4 −0 test/fixtures/modules/tests-cases/issue-589/source.css
  125. 0 test/{moduleTestCases → fixtures/modules/tests-cases}/keyframes-and-animation/source.css
  126. 0 test/{moduleTestCases → fixtures/modules/tests-cases}/leak-scope/source.css
  127. +4 −0 test/fixtures/modules/tests-cases/local-2/source.css
  128. +7 −0 test/fixtures/modules/tests-cases/local-and-composes/source.css
  129. +3 −0 test/fixtures/modules/tests-cases/local-with-string/source.css
  130. +7 −0 test/fixtures/modules/tests-cases/local/source.css
  131. +1 −0 test/fixtures/modules/tests-cases/media-2/file.css
  132. +6 −0 test/fixtures/modules/tests-cases/media-2/source.css
  133. +7 −0 test/fixtures/modules/tests-cases/media/source.css
  134. +2 −0 test/fixtures/modules/tests-cases/mode-switching/source.css
  135. 0 test/{moduleTestCases → fixtures/modules/tests-cases}/simple/source.css
  136. BIN test/fixtures/modules/tests-cases/urls/img img.png
  137. BIN test/fixtures/modules/tests-cases/urls/img.png
  138. +14 −0 test/fixtures/modules/tests-cases/urls/source.css
  139. +2 −0 test/fixtures/modules/tests-cases/values-1/source.css
  140. +2 −0 test/fixtures/modules/tests-cases/values-2/source.css
  141. +1 −0 test/fixtures/modules/tests-cases/values-3/file.css
  142. +2 −0 test/fixtures/modules/tests-cases/values-3/source.css
  143. +1 −0 test/fixtures/modules/tests-cases/values-4/file1.css
  144. +1 −0 test/fixtures/modules/tests-cases/values-4/file2.css
  145. +3 −0 test/fixtures/modules/tests-cases/values-4/source.css
  146. +1 −0 test/fixtures/modules/tests-cases/values-5/file1.css
  147. +3 −0 test/fixtures/modules/tests-cases/values-5/source.css
  148. +1 −0 test/fixtures/modules/tests-cases/values-6/file1.css
  149. +3 −0 test/fixtures/modules/tests-cases/values-6/source.css
  150. +1 −0 test/fixtures/modules/tests-cases/values-7/file1.css
  151. +3 −0 test/fixtures/modules/tests-cases/values-7/source.css
  152. +6 −0 test/fixtures/modules/tests-cases/values-8/source.css
  153. +29 −0 test/fixtures/modules/tests-cases/values-9/source.css
  154. 0 test/{moduleTestCases → fixtures/modules/tests-cases}/values/source.css
  155. +3 −0 test/fixtures/modules/top-relative.css
  156. +2 −0 test/fixtures/modules/values.css
  157. +4 −0 test/fixtures/nested-import/imported.css
  158. +6 −0 test/fixtures/nested-import/source.css
  159. BIN test/fixtures/postcss-present-env/img1x.png
  160. BIN test/fixtures/postcss-present-env/img2x.png
  161. +39 −0 test/fixtures/postcss-present-env/source.css
  162. +7 −0 test/fixtures/scss/source.scss
  163. +5 −0 test/fixtures/source-map-loader.js
  164. +3 −0 test/fixtures/source-map/basic.css
  165. 0 test/fixtures/url/font with spaces.eot
  166. 0 test/fixtures/url/font.eot
  167. 0 test/fixtures/url/font.svg
  168. 0 test/fixtures/url/font.woff
  169. 0 test/fixtures/url/font.woff2
  170. BIN test/fixtures/url/img img.png
  171. BIN test/fixtures/url/img-from-imported.png
  172. BIN test/fixtures/url/img-simple.png
  173. BIN test/fixtures/url/img.png
  174. BIN test/fixtures/url/img1x.png
  175. BIN test/fixtures/url/img2x.png
  176. +3 −0 test/fixtures/url/imported.css
  177. BIN test/fixtures/url/nested/img.png
  178. 0 test/fixtures/url/node_modules/package/font.ttf
  179. BIN test/fixtures/url/node_modules/package/img.png
  180. BIN test/fixtures/url/other-img.png
  181. +207 −0 test/fixtures/url/url.css
  182. +107 −0 test/getLocalIdent-option.test.js
  183. +227 −139 test/helpers.js
  184. +24 −0 test/icss.test.js
  185. +84 −0 test/import-option.test.js
  186. +106 −0 test/importLoaders-option.test.js
  187. +0 −42 test/importTest.js
  188. +167 −0 test/loader.test.js
  189. +120 −0 test/localIdentName-option.test.js
  190. +0 −220 test/localTest.js
  191. +0 −52 test/localsTest.js
  192. +0 −17 test/moduleMinimizeTest.js
  193. +0 −3 test/moduleMinimizeTestCases/keyframes-and-animation/expected.css
  194. +0 −28 test/moduleMinimizeTestCases/keyframes-and-animation/source.css
  195. +0 −17 test/moduleTest.js
  196. +0 −3 test/moduleTestCases/class-names/expected.css
  197. +0 −11 test/moduleTestCases/comments/expected.css
  198. +0 −48 test/moduleTestCases/keyframes-and-animation/expected.css
  199. +0 −37 test/moduleTestCases/leak-scope/expected.css
  200. +0 −11 test/moduleTestCases/simple/expected.css
  201. +0 −12 test/moduleTestCases/urls/expected.css
  202. +0 −12 test/moduleTestCases/urls/source.css
  203. +0 −5 test/moduleTestCases/values/expected.css
  204. +120 −0 test/modules-option.test.js
  205. +19 −0 test/runtime/__snapshots__/api.test.js.snap
  206. +19 −0 test/runtime/__snapshots__/url-escape.test.js.snap
  207. +93 −0 test/runtime/api.test.js
  208. +15 −0 test/runtime/url-escape.test.js
  209. +0 −35 test/simpleTest.js
  210. +239 −0 test/sourceMap-option.test.js
  211. +0 −64 test/sourceMapTest.js
  212. +84 −0 test/url-option.test.js
  213. +0 −101 test/urlTest.js
  214. +0 −69 test/valuesTest.js
145 changes: 145 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
unit_tests: &unit_tests
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
name: Install Latest NPM.
# npm@3 is buggy
command: if [[ $(npm -v | cut -c -1) > 3 ]] ; then npm i -g npm@latest; else echo "Skip npm updating"; fi
- run:
name: NPM Install.
command: npm ci || npm i
- run:
name: Run Test.
command: npm run ci:test
canary_tests: &canary_tests
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
name: Install Latest NPM.
command: npm i -g npm@latest
- run:
name: NPM Install.
command: npm ci
- run:
name: Install Webpack Canary.
command: npm i --no-save webpack@next
- run:
name: Run Test.
command: if [[ $(compver --name webpack --gte next --lt latest) < 1 ]] ; then printf "Next is older than Latest - Skipping Canary Suite"; else npm run ci:test; fi

version: 2
jobs:
dependency_cache:
docker:
- image: webpackcontrib/circleci-node-base:latest
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
name: Install Latest NPM.
command: npm i -g npm@latest
- run:
name: NPM Install.
command: npm ci
- save_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
paths:
- ./node_modules
node6-latest:
docker:
- image: webpackcontrib/circleci-node6:latest
<<: *unit_tests
node8-latest:
docker:
- image: webpackcontrib/circleci-node8:latest
<<: *unit_tests
node10-latest:
docker:
- image: webpackcontrib/circleci-node10:latest
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
name: Install Latest NPM.
command: npm i -g npm@latest
- run:
name: NPM Install.
command: npm ci
- run:
name: Run Test.
command: npm run ci:coverage
- run:
name: Submit coverage data to codecov.
command: bash <(curl -s https://codecov.io/bash)
when: on_success
node10-canary:
docker:
- image: webpackcontrib/circleci-node10:latest
<<: *canary_tests
analysis:
docker:
- image: webpackcontrib/circleci-node-base:latest
steps:
- checkout
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
name: Install Latest NPM.
command: npm i -g npm@latest
- run:
name: NPM Install.
command: npm ci
- run:
name: Run linting.
command: npm run lint
- run:
name: Run NPM Audit.
command: npm run security
- run:
name: Validate Commit Messages.
command: npm run ci:lint:commits

workflows:
version: 2
test:
jobs:
- dependency_cache
- analysis:
requires:
- dependency_cache
filters:
tags:
only: /.*/
- node6-latest:
requires:
- dependency_cache
filters:
tags:
only: /.*/
- node8-latest:
requires:
- analysis
- node6-latest
filters:
tags:
only: /.*/
- node10-latest:
requires:
- analysis
- node6-latest
filters:
tags:
only: /.*/
- node10-canary:
requires:
- analysis
- node6-latest
filters:
tags:
only: /.*/
13 changes: 13 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# editorconfig.org

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/node_modules
/src/runtime
/dist
10 changes: 0 additions & 10 deletions .eslintrc

This file was deleted.

11 changes: 11 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
root: true,
plugins: ['prettier'],
extends: ['@webpack-contrib/eslint-config-webpack'],
rules: {
'prettier/prettier': [
'error',
{ singleQuote: true, trailingComma: 'es5', arrowParens: 'always' },
],
},
};
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package-lock.json -diff
* text=auto
bin/* eol=lf
6 changes: 6 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# These are the default owners for everything in
# webpack-contrib
@webpack-contrib/org-maintainers

# Add repository specific users / groups
# below here for libs that are not maintained by the org.
124 changes: 124 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
## Contributing in @webpack-contrib

We'd always love contributions to further improve the webpack / webpack-contrib ecosystem!
Here are the guidelines we'd like you to follow:

* [Questions and Problems](#question)
* [Issues and Bugs](#issue)
* [Feature Requests](#feature)
* [Pull Request Submission Guidelines](#submit-pr)
* [Commit Message Conventions](#commit)

### <a name="question"></a> Got a Question or Problem?

Please submit support requests and questions to StackOverflow using the tag [[webpack]](http://stackoverflow.com/tags/webpack).
StackOverflow is better suited for this kind of support though you may also inquire in [Webpack Gitter](https://gitter.im/webpack/webpack).
The issue tracker is for bug reports and feature discussions.

### <a name="issue"></a> Found an Issue or Bug?

Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.

We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we ask that you to provide a minimal reproduction scenario (github repo or failing test case). Having a live, reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions like:

- version of Webpack used
- version of the loader / plugin you are creating a bug report for
- the use-case that fails

A minimal reproduce scenario allows us to quickly confirm a bug (or point out config problems) as well as confirm that we are fixing the right problem.

We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it.

Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced.

### <a name="feature"></a> Feature Requests?

You can *request* a new feature by creating an issue on Github.

If you would like to *implement* a new feature, please submit an issue with a proposal for your work `first`, to be sure that particular makes sense for the project.

### <a name="submit-pr"></a> Pull Request Submission Guidelines

Before you submit your Pull Request (PR) consider the following guidelines:

- Search Github for an open or closed PR that relates to your submission. You don't want to duplicate effort.
- Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit). Adherence to these conventions is necessary because release notes are automatically generated from these messages.
- Fill out our `Pull Request Template`. Your pull request will not be considered if it is ignored.
- Please sign the `Contributor License Agreement (CLA)` when a pull request is opened. We cannot accept your pull request without this. Make sure you sign with the primary email address associated with your local / github account.

### <a name="commit"></a> Webpack Contrib Commit Conventions

Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
format that includes a **type**, a **scope** and a **subject**:

```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```

The **header** is mandatory and the **scope** of the header is optional.

Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
to read on GitHub as well as in various git tools.

The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.

Examples:
```
docs(readme): update install instructions
```
```
fix: refer to the `entrypoint` instead of the first `module`
```

#### Revert
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit.
In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.

#### Type
Must be one of the following:

* **build**: Changes that affect the build system or external dependencies (example scopes: babel, npm)
* **chore**: Changes that fall outside of build / docs that do not effect source code (example scopes: package, defaults)
* **ci**: Changes to our CI configuration files and scripts (example scopes: circleci, travis)
* **docs**: Documentation only changes (example scopes: readme, changelog)
* **feat**: A new feature
* **fix**: A bug fix
* **perf**: A code change that improves performance
* **refactor**: A code change that neither fixes a bug nor adds a feature
* **revert**: Used when reverting a committed change
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons)
* **test**: Addition of or updates to Jest tests

#### Scope
The scope is subjective & depends on the `type` see above. A good example would be a change to a particular class / module.

#### Subject
The subject contains a succinct description of the change:

* use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize the first letter
* no dot (.) at the end

#### Body
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
The body should include the motivation for the change and contrast this with previous behavior.

#### Footer
The footer should contain any information about **Breaking Changes** and is also the place to
reference GitHub issues that this commit **Closes**.

**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.

Example

```
BREAKING CHANGE: Updates to `Chunk.mapModules`.
This release is not backwards compatible with `Webpack 2.x` due to breaking changes in webpack/webpack#4764
Migration: see webpack/webpack#5225
```
16 changes: 16 additions & 0 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!--
👉🏽 Need support, advice, or help? Don't open an issue!
Head to StackOverflow or https://gitter.im/webpack/webpack.
Hey there!
You arrived at this template because you felt none of the other options
matched the kind of issue you'd like to report. Please use this opportunity to
tell us about your particular type of issue so we can try to accomodate
similar issues in the future.
PLEASE do note, if you're using this to report an issue already covered by the
existing template types, your issue may be closed as invalid. Our issue
templates contain fields that help us help you, and without that important
info, we might as well be ice-skating uphill, carrying a wooly mammoth.
-->
51 changes: 51 additions & 0 deletions .github/ISSUE_TEMPLATE/BUG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: 🐛 Bug Report
about: Something went awry and you'd like to tell us about it.

---

<!--
Issues are so 🔥
If you remove or skip this template, you'll make the 🐼 sad and the mighty god
of Github will appear and pile-drive the close button from a great height
while making animal noises.
👉🏽 Need support, advice, or help? Don't open an issue!
Head to StackOverflow or https://gitter.im/webpack/webpack.
-->

* Operating System:
* Node Version:
* NPM Version:
* webpack Version:
* css-loader Version:

### Expected Behavior

<!-- Remove this section if not reporting a bug or modification request. -->

### Actual Behavior

<!-- Remove this section if not reporting a bug or modification request. -->

### Code

```js
// webpack.config.js
// If your bitchin' code blocks are over 20 lines, please paste a link to a gist
// (https://gist.github.com).
```

```js
// additional code, HEY YO remove this block if you don't need it
```

### How Do We Reproduce?

<!--
Remove this section if not reporting a bug.
If your webpack config is over 50 lines long, please provide a URL to a repo
for your beefy 🍖 app that we can use to reproduce.
-->
30 changes: 30 additions & 0 deletions .github/ISSUE_TEMPLATE/DOCS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
name: 📚 Documentation
about: Are the docs lacking or missing something? Do they need some new 🔥 hotness? Tell us here.

---

<!--
Issues are so 🔥
If you remove or skip this template, you'll make the 🐼 sad and the mighty god
of Github will appear and pile-drive the close button from a great height
while making animal noises.
👉🏽 Need support, advice, or help? Don't open an issue!
Head to StackOverflow or https://gitter.im/webpack/webpack.
-->

Documentation Is:

<!-- Please place an x (no spaces!) in all [ ] that apply -->

- [ ] Missing
- [ ] Needed
- [ ] Confusing
- [ ] Not Sure?

### Please Explain in Detail...


### Your Proposal for Changes
28 changes: 28 additions & 0 deletions .github/ISSUE_TEMPLATE/FEATURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: ✨ Feature Request
about: Suggest an idea for this project

---

<!--
Issues are so 🔥
If you remove or skip this template, you'll make the 🐼 sad and the mighty god
of Github will appear and pile-drive the close button from a great height
while making animal noises.
👉🏽 Need support, advice, or help? Don't open an issue!
Head to StackOverflow or https://gitter.im/webpack/webpack.
-->

* Operating System:
* Node Version:
* NPM Version:
* webpack Version:
* css-loader Version:

### Feature Proposal



### Feature Use Case
33 changes: 33 additions & 0 deletions .github/ISSUE_TEMPLATE/MODIFICATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: 🔧 Modification Request
about: Would you like something work differently? Have an alternative approach? This is the template for you.

---

<!--
Issues are so 🔥
If you remove or skip this template, you'll make the 🐼 sad and the mighty god
of Github will appear and pile-drive the close button from a great height
while making animal noises.
👉🏽 Need support, advice, or help? Don't open an issue!
Head to StackOverflow or https://gitter.im/webpack/webpack.
-->

* Operating System:
* Node Version:
* NPM Version:
* webpack Version:
* css-loader Version:


### Expected Behavior / Situation



### Actual Behavior / Situation



### Modification Proposal
9 changes: 9 additions & 0 deletions .github/ISSUE_TEMPLATE/SUPPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
name: 🆘 Support, Help, and Advice
about: 👉🏽 Need support, help, or advice? Don't open an issue! Head to StackOverflow or https://gitter.im/webpack/webpack.

---

Hey there! If you need support, help, or advice then this is not the place to ask.
Please visit [StackOverflow](https://stackoverflow.com/questions/tagged/webpack)
or [the Webpack Gitter](https://gitter.im/webpack/webpack) instead.
35 changes: 35 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<!--
HOLY CRAP a Pull Request. We ❤️ those!
If you remove or skip this template, you'll make the 🐼 sad and the mighty god
of Github will appear and pile-drive the close button from a great height
while making animal noises.
Please place an x (no spaces!) in all [ ] that apply
-->

This PR contains a:

- [ ] **bugfix**
- [ ] new **feature**
- [ ] **code refactor**
- [ ] **test update** <!-- if bug or feature is checked, this should be too -->
- [ ] **typo fix**
- [ ] **metadata update**

### Motivation / Use-Case

<!--
Please explain the motivation or use-case for your change.
What existing problem does the PR solve?
If this PR addresses an issue, please link to the issue.
-->

### Breaking Changes

<!--
If this PR introduces a breaking change, please describe the impact and a
migration path for existing applications.
-->

### Additional Info
20 changes: 18 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,18 @@
node_modules
coverage
logs
*.log
npm-debug.log*
.eslintcache

/coverage
/dist
/local
/reports
/node_modules

.DS_Store
Thumbs.db
.idea
*.iml
.vscode
*.sublime-project
*.sublime-workspace
3 changes: 0 additions & 3 deletions .npmignore

This file was deleted.

5 changes: 5 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"singleQuote": true,
"trailingComma": "es5",
"arrowParens": "always"
}
12 changes: 0 additions & 12 deletions .travis.yml

This file was deleted.

231 changes: 231 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
# Change Log

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

<a name="2.0.0"></a>
# [2.0.0](https://github.com/webpack-contrib/css-loader/compare/v1.0.1...v2.0.0) (2018-12-07)


### Bug Fixes

* broken unucode characters ([#850](https://github.com/webpack-contrib/css-loader/issues/850)) ([f599c70](https://github.com/webpack-contrib/css-loader/commit/f599c70))
* correctly processing `urls()` with `?#hash` ([#803](https://github.com/webpack-contrib/css-loader/issues/803)) ([417d105](https://github.com/webpack-contrib/css-loader/commit/417d105))
* don't break loader on invalid or not exists url or import token ([#827](https://github.com/webpack-contrib/css-loader/issues/827)) ([9e52d26](https://github.com/webpack-contrib/css-loader/commit/9e52d26))
* don't duplicate import with same media in different case ([#819](https://github.com/webpack-contrib/css-loader/issues/819)) ([9f66e33](https://github.com/webpack-contrib/css-loader/commit/9f66e33))
* emit warnings on broken `import` at-rules ([#806](https://github.com/webpack-contrib/css-loader/issues/806)) ([4bdf08b](https://github.com/webpack-contrib/css-loader/commit/4bdf08b))
* handle uppercase `URL` in `import` at-rules ([#818](https://github.com/webpack-contrib/css-loader/issues/818)) ([3ebdcd5](https://github.com/webpack-contrib/css-loader/commit/3ebdcd5))
* inconsistent generate class names for css modules on difference os ([#812](https://github.com/webpack-contrib/css-loader/issues/812)) ([0bdf9b7](https://github.com/webpack-contrib/css-loader/commit/0bdf9b7))
* reduce number of `require` for `urls()` ([#854](https://github.com/webpack-contrib/css-loader/issues/854)) ([3338656](https://github.com/webpack-contrib/css-loader/commit/3338656))
* support deduplication of string module ids (optimization.namedModules) ([#789](https://github.com/webpack-contrib/css-loader/issues/789)) ([e3bb83a](https://github.com/webpack-contrib/css-loader/commit/e3bb83a))
* support module resolution in `composes` ([#845](https://github.com/webpack-contrib/css-loader/issues/845)) ([453248f](https://github.com/webpack-contrib/css-loader/commit/453248f))
* same `urls()` resolving logic for `modules` (`local` and `global`) and without modules ([#843](https://github.com/webpack-contrib/css-loader/issues/843)) ([fdcf687](https://github.com/webpack-contrib/css-loader/commit/fdcf687))

### Features

* allow to disable css modules and **disable their by default** ([#842](https://github.com/webpack-contrib/css-loader/issues/842)) ([889dc7f](https://github.com/webpack-contrib/css-loader/commit/889dc7f))
* disable `import` option doesn't affect on `composes` ([#822](https://github.com/webpack-contrib/css-loader/issues/822)) ([f9aa73c](https://github.com/webpack-contrib/css-loader/commit/f9aa73c))
* allow to filter `urls` ([#856](https://github.com/webpack-contrib/css-loader/issues/856)) ([5e702e7](https://github.com/webpack-contrib/css-loader/commit/5e702e7))
* allow to filter `import` at-rules ([#857](https://github.com/webpack-contrib/css-loader/issues/857)) ([5e6034c](https://github.com/webpack-contrib/css-loader/commit/5e6034c))
* emit warning on invalid `urls()` ([#832](https://github.com/webpack-contrib/css-loader/issues/832)) ([da95db8](https://github.com/webpack-contrib/css-loader/commit/da95db8))
* added `exportOnlyLocals` option ([#824](https://github.com/webpack-contrib/css-loader/issues/824)) ([e9327c0](https://github.com/webpack-contrib/css-loader/commit/e9327c0))
* reuse `postcss` ast from other loaders (i.e `postcss-loader`) ([#840](https://github.com/webpack-contrib/css-loader/issues/840)) ([1dad1fb](https://github.com/webpack-contrib/css-loader/commit/1dad1fb))
* schema options ([b97d997](https://github.com/webpack-contrib/css-loader/commit/b97d997))


### BREAKING CHANGES

* resolving logic for `uls()` and `import` at-rules works the same everywhere, it does not matter whether css modules are enabled (with `global` and `local` module) or not. Examples - `url('image.png')` as `require('./image.png')`, `url('./image.png')` as `require('./image.png')`, `url('~module/image.png')` as `require('module/image.png')`.
* by default css modules are disabled (now `modules: false` disable all css modules features), you can return old behaviour change this on `modules: 'global'`
* `css-loader/locals` was dropped in favor `exportOnlyLocals` option
* `import` option only affect on `import` at-rules and doesn't affect on `composes` declarations
* invalid `@import` at rules now emit warnings
* use `postcss@7`



<a name="1.0.1"></a>
## [1.0.1](https://github.com/webpack-contrib/css-loader/compare/v1.0.0...v1.0.1) (2018-10-29)


### Bug Fixes

* **loader:** trim unquoted import urls ([#783](https://github.com/webpack-contrib/css-loader/issues/783)) ([21fcddf](https://github.com/webpack-contrib/css-loader/commit/21fcddf))



<a name="1.0.0"></a>
# [1.0.0](https://github.com/webpack-contrib/css-loader/compare/v0.28.11...v1.0.0) (2018-07-06)


### BREAKING CHANGES

* remove `minimize` option, use [`postcss-loader`](https://github.com/postcss/postcss-loader) with [`cssnano`](https://github.com/cssnano/cssnano) or use [`optimize-cssnano-plugin`](https://github.com/intervolga/optimize-cssnano-plugin) plugin
* remove `module` option, use `modules` option instead
* remove `camelcase` option, use `camelCase` option instead
* remove `root` option, use [`postcss-loader`](https://github.com/postcss/postcss-loader) with [`postcss-url`](https://github.com/postcss/postcss-url) plugin
* remove `alias` option, use [`resolve.alias`](https://webpack.js.org/configuration/resolve/) feature or use [`postcss-loader`](https://github.com/postcss/postcss-loader) with [`postcss-url`](https://github.com/postcss/postcss-url) plugin
* update `postcss` to `6` version
* minimum require `nodejs` version is `6.9`
* minimum require `webpack` version is `4`



<a name="0.28.11"></a>
## [0.28.11](https://github.com/webpack-contrib/css-loader/compare/v0.28.10...v0.28.11) (2018-03-16)


### Bug Fixes

* **lib/processCss:** don't check `mode` for `url` handling (`options.modules`) ([#698](https://github.com/webpack-contrib/css-loader/issues/698)) ([c788450](https://github.com/webpack-contrib/css-loader/commit/c788450))



<a name="0.28.10"></a>
## [0.28.10](https://github.com/webpack-contrib/css-loader/compare/v0.28.9...v0.28.10) (2018-02-22)


### Bug Fixes

* **getLocalIdent:** add `rootContext` support (`webpack >= v4.0.0`) ([#681](https://github.com/webpack-contrib/css-loader/issues/681)) ([9f876d2](https://github.com/webpack-contrib/css-loader/commit/9f876d2))



<a name="0.28.9"></a>
## [0.28.9](https://github.com/webpack-contrib/css-loader/compare/v0.28.8...v0.28.9) (2018-01-17)


### Bug Fixes

* ignore invalid URLs (`url()`) ([#663](https://github.com/webpack-contrib/css-loader/issues/663)) ([d1d8221](https://github.com/webpack-contrib/css-loader/commit/d1d8221))



<a name="0.28.8"></a>
## [0.28.8](https://github.com/webpack-contrib/css-loader/compare/v0.28.7...v0.28.8) (2018-01-05)


### Bug Fixes

* **loader:** correctly check if source map is `undefined` ([#641](https://github.com/webpack-contrib/css-loader/issues/641)) ([0dccfa9](https://github.com/webpack-contrib/css-loader/commit/0dccfa9))
* proper URL escaping and wrapping (`url()`) ([#627](https://github.com/webpack-contrib/css-loader/issues/627)) ([8897d44](https://github.com/webpack-contrib/css-loader/commit/8897d44))



<a name="0.28.7"></a>
## [0.28.7](https://github.com/webpack/css-loader/compare/v0.28.6...v0.28.7) (2017-08-30)


### Bug Fixes

* pass resolver to `localsLoader` (`options.alias`) ([#601](https://github.com/webpack/css-loader/issues/601)) ([8f1b57c](https://github.com/webpack/css-loader/commit/8f1b57c))



<a name="0.28.6"></a>
## [0.28.6](https://github.com/webpack/css-loader/compare/v0.28.5...v0.28.6) (2017-08-30)


### Bug Fixes

* add support for aliases starting with `/` (`options.alias`) ([#597](https://github.com/webpack/css-loader/issues/597)) ([63567f2](https://github.com/webpack/css-loader/commit/63567f2))



<a name="0.28.5"></a>
## [0.28.5](https://github.com/webpack/css-loader/compare/v0.28.4...v0.28.5) (2017-08-17)


### Bug Fixes

* match mutliple dashes (`options.camelCase`) ([#556](https://github.com/webpack/css-loader/issues/556)) ([1fee601](https://github.com/webpack/css-loader/commit/1fee601))
* stricter `[@import](https://github.com/import)` tolerance ([#593](https://github.com/webpack/css-loader/issues/593)) ([2e4ec09](https://github.com/webpack/css-loader/commit/2e4ec09))



<a name="0.28.4"></a>
## [0.28.4](https://github.com/webpack/css-loader/compare/v0.28.3...v0.28.4) (2017-05-30)


### Bug Fixes

* preserve leading underscore in class names ([#543](https://github.com/webpack/css-loader/issues/543)) ([f6673c8](https://github.com/webpack/css-loader/commit/f6673c8))



<a name="0.28.3"></a>
## [0.28.3](https://github.com/webpack/css-loader/compare/v0.28.2...v0.28.3) (2017-05-25)


### Bug Fixes

* correct plugin order for CSS Modules ([#534](https://github.com/webpack/css-loader/issues/534)) ([b90f492](https://github.com/webpack/css-loader/commit/b90f492))



<a name="0.28.2"></a>
## [0.28.2](https://github.com/webpack/css-loader/compare/v0.28.1...v0.28.2) (2017-05-22)


### Bug Fixes

* source maps path on `windows` ([#532](https://github.com/webpack/css-loader/issues/532)) ([c3d0d91](https://github.com/webpack/css-loader/commit/c3d0d91))



<a name="0.28.1"></a>
## [0.28.1](https://github.com/webpack/css-loader/compare/v0.28.0...v0.28.1) (2017-05-02)


### Bug Fixes

* allow to specify a full hostname as a root URL ([#521](https://github.com/webpack/css-loader/issues/521)) ([06d27a1](https://github.com/webpack/css-loader/commit/06d27a1))
* case insensitivity of [@import](https://github.com/import) ([#514](https://github.com/webpack/css-loader/issues/514)) ([de4356b](https://github.com/webpack/css-loader/commit/de4356b))
* don't handle empty [@import](https://github.com/import) and url() ([#513](https://github.com/webpack/css-loader/issues/513)) ([868fc94](https://github.com/webpack/css-loader/commit/868fc94))
* imported variables are replaced in exports if followed by a comma ([#504](https://github.com/webpack/css-loader/issues/504)) ([956bad7](https://github.com/webpack/css-loader/commit/956bad7))
* loader now correctly handles `url` with space(s) ([#495](https://github.com/webpack/css-loader/issues/495)) ([534ea55](https://github.com/webpack/css-loader/commit/534ea55))
* url with a trailing space is now handled correctly ([#494](https://github.com/webpack/css-loader/issues/494)) ([e1ec4f2](https://github.com/webpack/css-loader/commit/e1ec4f2))
* use `btoa` instead `Buffer` ([#501](https://github.com/webpack/css-loader/issues/501)) ([fbb0714](https://github.com/webpack/css-loader/commit/fbb0714))


### Performance Improvements

* generate source maps only when explicitly set ([#478](https://github.com/webpack/css-loader/issues/478)) ([b8f5c8f](https://github.com/webpack/css-loader/commit/b8f5c8f))



<a name="0.28.0"></a>
# [0.28.0](https://github.com/webpack/css-loader/compare/v0.27.3...v0.28.0) (2017-03-30)


### Features

* add alias feature to rewrite URLs ([#274](https://github.com/webpack/css-loader/issues/274)) ([c8db489](https://github.com/webpack/css-loader/commit/c8db489))



<a name="0.27.3"></a>
## [0.27.3](https://github.com/webpack/css-loader/compare/v0.27.2...v0.27.3) (2017-03-13)



<a name="0.27.2"></a>
# [0.27.2](https://github.com/webpack/css-loader/compare/v0.27.1...v0.27.2) (2017-03-12)

<a name="0.27.1"></a>
# [0.27.1](https://github.com/webpack/css-loader/compare/v0.27.0...v0.27.1) (2017-03-10)

<a name="0.27.0"></a>
# [0.27.0](https://github.com/webpack/css-loader/compare/v0.26.2...v0.27.0) (2017-03-10)


### Bug Fixes

* **sourcemaps:** use abs paths & remove sourceRoot ([c769ac3](https://github.com/webpack/css-loader/commit/c769ac3))
* `minimizeOptions` should be `query.minimize`! ([16c0858](https://github.com/webpack/css-loader/commit/16c0858))
* do not export duplicate keys ([#420](https://github.com/webpack/css-loader/issues/420)) ([a2b85d7](https://github.com/webpack/css-loader/commit/a2b85d7))


### Features

* allow removal of original class name ([#445](https://github.com/webpack/css-loader/issues/445)) ([3f78361](https://github.com/webpack/css-loader/commit/3f78361))
* Include the sourceMappingURL & sourceURL when toString() ([6da7e90](https://github.com/webpack/css-loader/commit/6da7e90))
20 changes: 20 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Copyright JS Foundation and other contributors

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
936 changes: 677 additions & 259 deletions README.md

Large diffs are not rendered by default.

42 changes: 42 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
branches:
only:
- master
- next
init:
- git config --global core.autocrlf input
cache:
- node_modules
- '%APPDATA%\npm-cache'
environment:
matrix:
- nodejs_version: '11'
webpack_version: latest
job_part: test
- nodejs_version: '10'
webpack_version: latest
job_part: test
- nodejs_version: '8'
webpack_version: latest
job_part: test
- nodejs_version: '6'
webpack_version: latest
job_part: test
- nodejs_version: '6'
webpack_version: latest
job_part: next
build: 'off'
matrix:
fast_finish: true
install:
- ps: Install-Product node $env:nodejs_version x64
- npm i -g npm@latest
- npm ci
- npm i -g @webpack-contrib/tag-versions
before_test:
- cmd: npm install webpack@%webpack_version%
test_script:
- node --version
- node --version
- npm --version
- cmd: FOR /F %%I in ('compver --name webpack --gte %webpack_version% --lt latest') do SET COMPARED_VERSION_RESULT=%%I
- cmd: IF %COMPARED_VERSION_RESULT% NEQ -1 (npm run ci:test) ELSE (ECHO "Next is older than Latest - Skipping Canary Suite")
5 changes: 0 additions & 5 deletions index.js

This file was deleted.

29 changes: 0 additions & 29 deletions lib/compile-exports.js

This file was deleted.

50 changes: 0 additions & 50 deletions lib/css-base.js

This file was deleted.

14 changes: 0 additions & 14 deletions lib/getImportPrefix.js

This file was deleted.

16 changes: 0 additions & 16 deletions lib/getLocalIdent.js

This file was deleted.

124 changes: 0 additions & 124 deletions lib/loader.js

This file was deleted.

46 changes: 0 additions & 46 deletions lib/localsLoader.js

This file was deleted.

251 changes: 0 additions & 251 deletions lib/processCss.js

This file was deleted.

5 changes: 0 additions & 5 deletions locals.js

This file was deleted.

12,782 changes: 12,782 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

136 changes: 107 additions & 29 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,41 +1,119 @@
{
"name": "css-loader",
"version": "0.26.0",
"author": "Tobias Koppers @sokra",
"version": "2.0.0",
"description": "css loader module for webpack",
"license": "MIT",
"repository": "webpack-contrib/css-loader",
"author": "Tobias Koppers @sokra",
"homepage": "https://github.com/webpack-contrib/css-loader",
"bugs": "https://github.com/webpack-contrib/css-loader/issues",
"main": "dist/cjs.js",
"engines": {
"node": ">=0.12.0"
"node": ">= 6.9.0 <7.0.0 || >= 8.9.0"
},
"scripts": {
"start": "npm run build -- -w",
"build": "cross-env NODE_ENV=production babel src -d dist --ignore 'src/**/*.test.js' --copy-files",
"clean": "del-cli dist",
"lint": "eslint --cache src test",
"prebuild": "npm run clean",
"prepublish": "npm run build",
"release": "standard-version",
"security": "npm audit",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --collectCoverageFrom='src/**/*.js' --coverage",
"ci:lint": "npm run lint && npm run security",
"ci:lint:commits": "commitlint --from=${CIRCLE_BRANCH} --to=${CIRCLE_SHA1}",
"ci:test": "npm run test -- --runInBand",
"ci:coverage": "npm run test:coverage -- --runInBand",
"defaults": "webpack-defaults"
},
"files": [
"dist/",
"lib/",
"index.js"
],
"peerDependencies": {
"webpack": "^4.0.0"
},
"dependencies": {
"babel-code-frame": "^6.11.0",
"css-selector-tokenizer": "^0.7.0",
"cssnano": ">=2.6.1 <4",
"loader-utils": "~0.2.2",
"lodash.camelcase": "^4.3.0",
"object-assign": "^4.0.1",
"postcss": "^5.0.6",
"postcss-modules-extract-imports": "^1.0.0",
"postcss-modules-local-by-default": "^1.0.1",
"postcss-modules-scope": "^1.0.0",
"postcss-modules-values": "^1.1.0",
"source-list-map": "^0.1.4"
"icss-utils": "^4.0.0",
"loader-utils": "^1.0.2",
"lodash": "^4.17.11",
"postcss": "^7.0.6",
"postcss-modules-extract-imports": "^2.0.0",
"postcss-modules-local-by-default": "^2.0.2",
"postcss-modules-scope": "^2.0.0",
"postcss-modules-values": "^2.0.0",
"postcss-value-parser": "^3.3.0",
"schema-utils": "^1.0.0"
},
"devDependencies": {
"codecov.io": "^0.1.2",
"coveralls": "^2.11.2",
"istanbul": "^0.4.5",
"mocha": "^3.1.2",
"should": "^11.1.1"
"@babel/cli": "^7.1.5",
"@babel/core": "^7.1.6",
"@babel/polyfill": "^7.0.0",
"@babel/preset-env": "^7.1.6",
"@commitlint/cli": "^7.2.1",
"@commitlint/config-conventional": "^7.1.2",
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "^23.6.0",
"cross-env": "^5.2.0",
"del": "^3.0.0",
"del-cli": "^1.1.0",
"eslint": "^5.9.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-prettier": "^3.0.0",
"file-loader": "^2.0.0",
"husky": "^1.2.0",
"jest": "^23.6.0",
"lint-staged": "^8.1.0",
"memory-fs": "^0.4.1",
"postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.4.0",
"prettier": "^1.15.2",
"sass": "^1.15.1",
"sass-loader": "^7.1.0",
"standard-version": "^4.0.0",
"strip-ansi": "^5.0.0",
"webpack": "^4.26.1",
"webpack-defaults": "^2.3.0"
},
"scripts": {
"test": "mocha",
"travis": "npm run cover -- --report lcovonly",
"cover": "istanbul cover node_modules/mocha/bin/_mocha",
"publish-patch": "mocha && npm version patch && git push && git push --tags && npm publish"
"keywords": [
"webpack",
"css",
"loader",
"url",
"import"
],
"babel": {
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "6.9.0"
},
"useBuiltIns": "usage"
}
]
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"repository": {
"type": "git",
"url": "git@github.com:webpack/css-loader.git"
"lint-staged": {
"*.js": [
"eslint --fix",
"git add"
]
},
"license": "MIT"
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
}
}
28 changes: 28 additions & 0 deletions src/CssSyntaxError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export default class CssSyntaxError extends Error {
constructor(error) {
super(error);

const { reason, line, column } = error;

this.name = 'CssSyntaxError';

// Based on https://github.com/postcss/postcss/blob/master/lib/css-syntax-error.es6#L132
// We don't need `plugin` and `file` properties.
this.message = `${this.name}\n\n`;

if (typeof line !== 'undefined') {
this.message += `(${line}:${column}) `;
}

this.message += `${reason}`;

const code = error.showSourceCode();

if (code) {
this.message += `\n\n${code}\n`;
}

// We don't need stack https://github.com/postcss/postcss/blob/master/docs/guidelines/runner.md#31-dont-show-js-stack-for-csssyntaxerror
this.stack = false;
}
}
20 changes: 20 additions & 0 deletions src/Warning.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export default class Warning extends Error {
constructor(warning) {
super(warning);
const { text, line, column } = warning;
this.name = 'Warning';

// Based on https://github.com/postcss/postcss/blob/master/lib/warning.es6#L74
// We don't need `plugin` properties.
this.message = `${this.name}\n\n`;

if (typeof line !== 'undefined') {
this.message += `(${line}:${column}) `;
}

this.message += `${text}`;

// We don't need stack https://github.com/postcss/postcss/blob/master/docs/guidelines/runner.md#31-dont-show-js-stack-for-csssyntaxerror
this.stack = false;
}
}
3 changes: 3 additions & 0 deletions src/cjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const loader = require('./index');

module.exports = loader.default;
354 changes: 354 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,354 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
import validateOptions from 'schema-utils';
import postcss from 'postcss';
import postcssPkg from 'postcss/package.json';
import localByDefault from 'postcss-modules-local-by-default';
import extractImports from 'postcss-modules-extract-imports';
import modulesScope from 'postcss-modules-scope';
import modulesValues from 'postcss-modules-values';
import {
getOptions,
isUrlRequest,
urlToRequest,
getRemainingRequest,
getCurrentRequest,
stringifyRequest,
} from 'loader-utils';
import camelCase from 'lodash/camelCase';

import schema from './options.json';
import { importParser, icssParser, urlParser } from './plugins';
import {
getLocalIdent,
getImportPrefix,
placholderRegExps,
dashesCamelCase,
getFilter,
} from './utils';
import Warning from './Warning';
import CssSyntaxError from './CssSyntaxError';

export default function loader(content, map, meta) {
const options = getOptions(this) || {};

validateOptions(schema, options, 'CSS Loader');

const callback = this.async();
const sourceMap = options.sourceMap || false;

/* eslint-disable no-param-reassign */
if (sourceMap) {
if (map) {
if (typeof map === 'string') {
map = JSON.stringify(map);
}

if (map.sources) {
map.sources = map.sources.map((source) => source.replace(/\\/g, '/'));
map.sourceRoot = '';
}
}
} else {
// Some loaders (example `"postcss-loader": "1.x.x"`) always generates source map, we should remove it
map = null;
}
/* eslint-enable no-param-reassign */

// Reuse CSS AST (PostCSS AST e.g 'postcss-loader') to avoid reparsing
if (meta) {
const { ast } = meta;

if (ast && ast.type === 'postcss' && ast.version === postcssPkg.version) {
// eslint-disable-next-line no-param-reassign
content = ast.root;
}
}

const plugins = [];

if (options.modules) {
const loaderContext = this;
const mode =
typeof options.modules === 'boolean' ? 'local' : options.modules;

plugins.push(
modulesValues,
localByDefault({ mode }),
extractImports(),
modulesScope({
generateScopedName: function generateScopedName(exportName) {
const localIdentName = options.localIdentName || '[hash:base64]';
const customGetLocalIdent = options.getLocalIdent || getLocalIdent;

return customGetLocalIdent(
loaderContext,
localIdentName,
exportName,
{
regExp: options.localIdentRegExp,
hashPrefix: options.hashPrefix || '',
context: options.context,
}
);
},
})
);
}

if (options.import !== false) {
plugins.push(
importParser({
filter: getFilter(options.import, this.resourcePath),
})
);
}

if (options.url !== false) {
plugins.push(
urlParser({
filter: getFilter(options.url, this.resourcePath, (value) =>
isUrlRequest(value)
),
})
);
}

plugins.push(icssParser());

postcss(plugins)
.process(content, {
// we need a prefix to avoid path rewriting of PostCSS
from: `/css-loader!${getRemainingRequest(this)
.split('!')
.pop()}`,
to: getCurrentRequest(this)
.split('!')
.pop(),
map: options.sourceMap
? {
prev: map,
sourcesContent: true,
inline: false,
annotation: false,
}
: null,
})
.then((result) => {
result
.warnings()
.forEach((warning) => this.emitWarning(new Warning(warning)));

const messages = result.messages || [];

// Run other loader (`postcss-loader`, `sass-loader` and etc) for importing CSS
const importUrlPrefix = getImportPrefix(this, options.importLoaders);

// Prepare replacer to change from `___CSS_LOADER_IMPORT___INDEX___` to `require('./file.css').locals`
const importItemReplacer = (placeholder) => {
const match = placholderRegExps.importItem.exec(placeholder);
const idx = Number(match[1]);

const message = messages.find(
// eslint-disable-next-line no-shadow
(message) =>
message.type === 'icss-import' &&
message.item &&
message.item.index === idx
);

if (!message) {
return placeholder;
}

const { item } = message;
const importUrl = importUrlPrefix + urlToRequest(item.url);

if (options.exportOnlyLocals) {
return `" + require(${stringifyRequest(
this,
importUrl
)})[${JSON.stringify(item.export)}] + "`;
}

return `" + require(${stringifyRequest(
this,
importUrl
)}).locals[${JSON.stringify(item.export)}] + "`;
};

const exports = messages
.filter((message) => message.type === 'export')
.reduce((accumulator, message) => {
const { key, value } = message.item;

let valueAsString = JSON.stringify(value);

valueAsString = valueAsString.replace(
placholderRegExps.importItemG,
importItemReplacer
);

function addEntry(k) {
accumulator.push(`\t${JSON.stringify(k)}: ${valueAsString}`);
}

let targetKey;

switch (options.camelCase) {
case true:
addEntry(key);
targetKey = camelCase(key);

if (targetKey !== key) {
addEntry(targetKey);
}
break;
case 'dashes':
addEntry(key);
targetKey = dashesCamelCase(key);

if (targetKey !== key) {
addEntry(targetKey);
}
break;
case 'only':
addEntry(camelCase(key));
break;
case 'dashesOnly':
addEntry(dashesCamelCase(key));
break;
default:
addEntry(key);
break;
}

return accumulator;
}, []);

if (options.exportOnlyLocals) {
return callback(
null,
exports.length > 0
? `module.exports = {\n${exports.join(',\n')}\n};`
: ''
);
}

const imports = messages
.filter((message) => message.type === 'import')
.map((message) => {
const { url } = message.item;
const media = message.item.media || '';

if (!isUrlRequest(url)) {
return `exports.push([module.id, ${JSON.stringify(
`@import url(${url});`
)}, ${JSON.stringify(media)}]);`;
}

const importUrl = importUrlPrefix + urlToRequest(url);

return `exports.i(require(${stringifyRequest(
this,
importUrl
)}), ${JSON.stringify(media)});`;
}, this);

let cssAsString = JSON.stringify(result.css).replace(
placholderRegExps.importItemG,
importItemReplacer
);

// Helper for ensuring valid CSS strings from requires
let hasUrlEscapeHelper = false;

messages
.filter((message) => message.type === 'url')
.forEach((message) => {
if (!hasUrlEscapeHelper) {
imports.push(
`var urlEscape = require(${stringifyRequest(
this,
require.resolve('./runtime/url-escape.js')
)});`
);

hasUrlEscapeHelper = true;
}

const { item } = message;
const { url, placeholder } = item;
// Remove `#hash` and `?#hash` from `require`
const [normalizedUrl, singleQuery, hashValue] = url.split(/(\?)?#/);
const hash =
singleQuery || hashValue
? `"${singleQuery ? '?' : ''}${hashValue ? `#${hashValue}` : ''}"`
: '';

imports.push(
`var ${placeholder} = urlEscape(require(${stringifyRequest(
this,
urlToRequest(normalizedUrl)
)})${hash ? ` + ${hash}` : ''});`
);

cssAsString = cssAsString.replace(
new RegExp(placeholder, 'g'),
() => `" + ${placeholder} + "`
);
});

let newMap = result.map;

if (sourceMap && newMap) {
// Add a SourceMap
newMap = newMap.toJSON();

if (newMap.sources) {
newMap.sources = newMap.sources.map(
(source) =>
source
.split('!')
.pop()
.replace(/\\/g, '/'),
this
);
newMap.sourceRoot = '';
}

newMap.file = newMap.file
.split('!')
.pop()
.replace(/\\/g, '/');
newMap = JSON.stringify(newMap);
}

const runtimeCode = `exports = module.exports = require(${stringifyRequest(
this,
require.resolve('./runtime/api')
)})(${!!sourceMap});\n`;
const importCode =
imports.length > 0 ? `// Imports\n${imports.join('\n')}\n\n` : '';
const moduleCode = `// Module\nexports.push([module.id, ${cssAsString}, ""${
newMap ? `,${newMap}` : ''
}]);\n\n`;
const exportsCode =
exports.length > 0
? `// Exports\nexports.locals = {\n${exports.join(',\n')}\n};`
: '';

// Embed runtime
return callback(
null,
runtimeCode + importCode + moduleCode + exportsCode
);
})
.catch((error) => {
callback(
error.name === 'CssSyntaxError' ? new CssSyntaxError(error) : error
);
});
}
86 changes: 86 additions & 0 deletions src/options.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"additionalProperties": false,
"properties": {
"url": {
"anyOf": [
{
"type": "boolean"
},
{
"instanceof": "Function"
}
]
},
"import": {
"anyOf": [
{
"type": "boolean"
},
{
"instanceof": "Function"
}
]
},
"modules": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "string",
"enum": ["local", "global"]
}
]
},
"localIdentName": {
"type": "string"
},
"localIdentRegExp": {
"anyOf": [
{
"type": "string"
},
{
"instanceof": "RegExp"
}
]
},
"context": {
"type": "string"
},
"hashPrefix": {
"type": "string"
},
"getLocalIdent": {
"instanceof": "Function"
},
"sourceMap": {
"type": "boolean"
},
"camelCase": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "string",
"enum": ["dashes", "only", "dashesOnly"]
}
]
},
"importLoaders": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "number"
}
]
},
"exportOnlyLocals": {
"type": "boolean"
}
},
"type": "object"
}
5 changes: 5 additions & 0 deletions src/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import importParser from './postcss-import-parser';
import icssParser from './postcss-icss-parser';
import urlParser from './postcss-url-parser';

export { importParser, icssParser, urlParser };
94 changes: 94 additions & 0 deletions src/plugins/postcss-icss-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import postcss from 'postcss';
import valueParser from 'postcss-value-parser';
import { extractICSS } from 'icss-utils';
import loaderUtils from 'loader-utils';

const pluginName = 'postcss-icss-parser';

export default postcss.plugin(
pluginName,
() =>
function process(css, result) {
const imports = {};
const icss = extractICSS(css);
const exports = icss.icssExports;

Object.keys(icss.icssImports).forEach((key) => {
const url = loaderUtils.parseString(key);

Object.keys(icss.icssImports[key]).forEach((prop) => {
const index = Object.keys(imports).length;

imports[`$${prop}`] = index;

result.messages.push({
pluginName,
type: 'icss-import',
item: { url, export: icss.icssImports[key][prop], index },
});

const alreadyIncluded = result.messages.find(
(message) =>
message.pluginName === pluginName &&
message.type === 'import' &&
message.item.url === url &&
message.item.media === ''
);

if (alreadyIncluded) {
return;
}

result.messages.push({
pluginName,
type: 'import',
item: { url, media: '' },
});
});
});

function replaceImportsInString(str) {
const tokens = valueParser(str);

tokens.walk((node) => {
if (node.type !== 'word') {
return;
}

const token = node.value;
const importIndex = imports[`$${token}`];

if (typeof importIndex === 'number') {
// eslint-disable-next-line no-param-reassign
node.value = `___CSS_LOADER_IMPORT___${importIndex}___`;
}
});

return tokens.toString();
}

// Replace tokens in declarations
css.walkDecls((decl) => {
// eslint-disable-next-line no-param-reassign
decl.value = replaceImportsInString(decl.value.toString());
});

// Replace tokens in at-rules
css.walkAtRules((atrule) => {
// eslint-disable-next-line no-param-reassign
atrule.params = replaceImportsInString(atrule.params.toString());
});

// Replace tokens in export
Object.keys(exports).forEach((exportName) => {
result.messages.push({
pluginName,
type: 'export',
item: {
key: exportName,
value: replaceImportsInString(exports[exportName]),
},
});
});
}
);
108 changes: 108 additions & 0 deletions src/plugins/postcss-import-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import postcss from 'postcss';
import valueParser from 'postcss-value-parser';

const pluginName = 'postcss-import-parser';

function getArg(nodes) {
return nodes.length !== 0 && nodes[0].type === 'string'
? nodes[0].value
: valueParser.stringify(nodes);
}

function getUrl(node) {
if (node.type === 'function' && node.value.toLowerCase() === 'url') {
return getArg(node.nodes);
}

if (node.type === 'string') {
return node.value;
}

return null;
}

function parseImport(params) {
const { nodes } = valueParser(params);

if (nodes.length === 0) {
return null;
}

const url = getUrl(nodes[0]);

if (!url || url.trim().length === 0) {
return null;
}

return {
url,
media: valueParser
.stringify(nodes.slice(1))
.trim()
.toLowerCase(),
};
}

function walkAtRules(css, result, filter) {
const items = [];

css.walkAtRules(/^import$/i, (atRule) => {
// Convert only top-level @import
if (atRule.parent.type !== 'root') {
return;
}

if (atRule.nodes) {
result.warn(
"It looks like you didn't end your @import statement correctly. " +
'Child nodes are attached to it.',
{ node: atRule }
);
return;
}

const parsed = parseImport(atRule.params);

if (!parsed) {
// eslint-disable-next-line consistent-return
return result.warn(`Unable to find uri in '${atRule.toString()}'`, {
node: atRule,
});
}

if (filter && !filter(parsed)) {
return;
}

atRule.remove();

const { url, media } = parsed;

items.push({ url, media });
});

return items;
}

function uniq(array) {
return array.reduce(
(acc, d) =>
!acc.find((el) => el.url === d.url && el.media === d.media)
? [...acc, d]
: acc,
[]
);
}

export default postcss.plugin(
pluginName,
(options = {}) =>
function process(css, result) {
const traversed = walkAtRules(css, result, options.filter);
const paths = uniq(traversed);

paths.forEach((item) => {
result.messages.push({ pluginName, type: 'import', item });
});
}
);
120 changes: 120 additions & 0 deletions src/plugins/postcss-url-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import postcss from 'postcss';
import valueParser from 'postcss-value-parser';

const pluginName = 'postcss-url-parser';

function getArg(nodes) {
return nodes.length !== 0 && nodes[0].type === 'string'
? nodes[0].value
: valueParser.stringify(nodes);
}

function walkUrls(parsed, callback) {
parsed.walk((node) => {
if (node.type !== 'function' || node.value.toLowerCase() !== 'url') {
return;
}

/* eslint-disable */
node.before = '';
node.after = '';
/* eslint-enable */

callback(node, getArg(node.nodes));

// Do not traverse inside url
// eslint-disable-next-line consistent-return
return false;
});
}

function walkDeclsWithUrl(css, result, filter) {
const items = [];

css.walkDecls((decl) => {
if (!/url\(/i.test(decl.value)) {
return;
}

const parsed = valueParser(decl.value);
const urls = [];

walkUrls(parsed, (node, url) => {
if (url.trim().replace(/\\[\r\n]/g, '').length === 0) {
result.warn(`Unable to find uri in '${decl.toString()}'`, {
node: decl,
});

return;
}

if (filter && !filter(url)) {
return;
}

urls.push(url);
});

if (urls.length === 0) {
return;
}

items.push({ decl, parsed, urls });
});

return items;
}

function flatten(array) {
return array.reduce((acc, d) => [...acc, ...d], []);
}

function uniq(array) {
return array.reduce(
(acc, d) => (acc.indexOf(d) === -1 ? [...acc, d] : acc),
[]
);
}

export default postcss.plugin(
pluginName,
(options = {}) =>
function process(css, result) {
const traversed = walkDeclsWithUrl(css, result, options.filter);
const paths = uniq(flatten(traversed.map((item) => item.urls)));

if (paths.length === 0) {
return;
}

const urls = {};

paths.forEach((path, index) => {
const placeholder = `___CSS_LOADER_URL___${index}___`;

urls[path] = placeholder;

result.messages.push({
pluginName,
type: 'url',
item: { url: path, placeholder },
});
});

traversed.forEach((item) => {
walkUrls(item.parsed, (node, url) => {
const value = urls[url];

if (!value) {
return;
}

// eslint-disable-next-line no-param-reassign
node.nodes = [{ type: 'word', value }];
});

// eslint-disable-next-line no-param-reassign
item.decl.value = item.parsed.toString();
});
}
);
82 changes: 82 additions & 0 deletions src/runtime/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
// css base code, injected by the css-loader
module.exports = function(useSourceMap) {
var list = [];

// return the list of modules as css string
list.toString = function toString() {
return this.map(function(item) {
var content = cssWithMappingToString(item, useSourceMap);
if (item[2]) {
return '@media ' + item[2] + '{' + content + '}';
} else {
return content;
}
}).join('');
};

// import a list of modules into the list
list.i = function(modules, mediaQuery) {
if (typeof modules === 'string') {
modules = [[null, modules, '']];
}
var alreadyImportedModules = {};
for (var i = 0; i < this.length; i++) {
var id = this[i][0];
if (id != null) {
alreadyImportedModules[id] = true;
}
}
for (i = 0; i < modules.length; i++) {
var item = modules[i];
// skip already imported module
// this implementation is not 100% perfect for weird media query combinations
// when a module is imported multiple times with different media queries.
// I hope this will never occur (Hey this way we have smaller bundles)
if (item[0] == null || !alreadyImportedModules[item[0]]) {
if (mediaQuery && !item[2]) {
item[2] = mediaQuery;
} else if (mediaQuery) {
item[2] = '(' + item[2] + ') and (' + mediaQuery + ')';
}
list.push(item);
}
}
};
return list;
};

function cssWithMappingToString(item, useSourceMap) {
var content = item[1] || '';
var cssMapping = item[3];
if (!cssMapping) {
return content;
}

if (useSourceMap && typeof btoa === 'function') {
var sourceMapping = toComment(cssMapping);
var sourceURLs = cssMapping.sources.map(function(source) {
return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */';
});

return [content]
.concat(sourceURLs)
.concat([sourceMapping])
.join('\n');
}

return [content].join('\n');
}

// Adapted from convert-source-map (MIT)
function toComment(sourceMap) {
// eslint-disable-next-line no-undef
var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
var data =
'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;

return '/*# ' + data + ' */';
}
17 changes: 17 additions & 0 deletions src/runtime/url-escape.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = function escape(url) {
if (typeof url !== 'string') {
return url;
}

// If url is already wrapped in quotes, remove them
if (/^['"].*['"]$/.test(url)) {
url = url.slice(1, -1);
}
// Should url be wrapped?
// See https://drafts.csswg.org/css-values-3/#urls
if (/["'() \t\n]/.test(url)) {
return '"' + url.replace(/"/g, '\\"').replace(/\n/g, '\\n') + '"';
}

return url;
};
84 changes: 84 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
import path from 'path';

import loaderUtils from 'loader-utils';

const placholderRegExps = {
importItemG: /___CSS_LOADER_IMPORT___([0-9]+)___/g,
importItem: /___CSS_LOADER_IMPORT___([0-9]+)___/,
};

function getImportPrefix(loaderContext, importLoaders) {
if (importLoaders === false) {
return '';
}

const numberImportedLoaders = parseInt(importLoaders, 10) || 0;
const loadersRequest = loaderContext.loaders
.slice(
loaderContext.loaderIndex,
loaderContext.loaderIndex + 1 + numberImportedLoaders
)
.map((x) => x.request)
.join('!');

return `-!${loadersRequest}!`;
}

function dashesCamelCase(str) {
return str.replace(/-+(\w)/g, (match, firstLetter) =>
firstLetter.toUpperCase()
);
}

function getLocalIdent(loaderContext, localIdentName, localName, options) {
if (!options.context) {
// eslint-disable-next-line no-param-reassign
options.context = loaderContext.rootContext;
}

const request = path
.relative(options.context, loaderContext.resourcePath)
.replace(/\\/g, '/');

// eslint-disable-next-line no-param-reassign
options.content = `${options.hashPrefix + request}+${localName}`;

// eslint-disable-next-line no-param-reassign
localIdentName = localIdentName.replace(/\[local\]/gi, localName);

const hash = loaderUtils.interpolateName(
loaderContext,
localIdentName,
options
);

return hash
.replace(new RegExp('[^a-zA-Z0-9\\-_\u00A0-\uFFFF]', 'g'), '-')
.replace(/^((-?[0-9])|--)/, '_$1');
}

function getFilter(filter, resourcePath, defaultFilter = null) {
return (content) => {
if (defaultFilter && !defaultFilter(content)) {
return false;
}

if (typeof filter === 'function') {
return !filter(content, resourcePath);
}

return true;
};
}

export {
getImportPrefix,
getLocalIdent,
placholderRegExps,
dashesCamelCase,
getFilter,
};
202 changes: 202 additions & 0 deletions test/__snapshots__/camelCase-option.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`camelCase option dashes: errors 1`] = `Array []`;

exports[`camelCase option dashes: locals 1`] = `
Object {
"btn--info_is-disabled_1": "jDvNwV-WRSMB9n2z9QrzR",
"btn-info_is-disabled": "_1XTfjK5gKYeSzbdZhEXRpF",
"btnInfo_isDisabled": "_1XTfjK5gKYeSzbdZhEXRpF",
"btnInfo_isDisabled_1": "jDvNwV-WRSMB9n2z9QrzR",
"foo": "bar",
"my-btn-info_is-disabled": "value",
"myBtnInfo_isDisabled": "value",
"simple": "_1penVf9PMtov2qLxmtsMjq",
}
`;

exports[`camelCase option dashes: module (evaluated) 1`] = `
Array [
Array [
1,
"._1XTfjK5gKYeSzbdZhEXRpF {
color: blue;
}
.jDvNwV-WRSMB9n2z9QrzR {
color: blue;
}
._1penVf9PMtov2qLxmtsMjq {
color: red;
}
a {
color: yellow;
}
",
"",
],
]
`;

exports[`camelCase option dashes: warnings 1`] = `Array []`;

exports[`camelCase option dashesOnly: errors 1`] = `Array []`;

exports[`camelCase option dashesOnly: locals 1`] = `
Object {
"btnInfo_isDisabled": "_1XTfjK5gKYeSzbdZhEXRpF",
"btnInfo_isDisabled_1": "jDvNwV-WRSMB9n2z9QrzR",
"foo": "bar",
"myBtnInfo_isDisabled": "value",
"simple": "_1penVf9PMtov2qLxmtsMjq",
}
`;

exports[`camelCase option dashesOnly: module (evaluated) 1`] = `
Array [
Array [
1,
"._1XTfjK5gKYeSzbdZhEXRpF {
color: blue;
}
.jDvNwV-WRSMB9n2z9QrzR {
color: blue;
}
._1penVf9PMtov2qLxmtsMjq {
color: red;
}
a {
color: yellow;
}
",
"",
],
]
`;

exports[`camelCase option dashesOnly: warnings 1`] = `Array []`;

exports[`camelCase option not specified: errors 1`] = `Array []`;

exports[`camelCase option not specified: locals 1`] = `
Object {
"btn--info_is-disabled_1": "jDvNwV-WRSMB9n2z9QrzR",
"btn-info_is-disabled": "_1XTfjK5gKYeSzbdZhEXRpF",
"foo": "bar",
"my-btn-info_is-disabled": "value",
"simple": "_1penVf9PMtov2qLxmtsMjq",
}
`;

exports[`camelCase option not specified: module (evaluated) 1`] = `
Array [
Array [
1,
"._1XTfjK5gKYeSzbdZhEXRpF {
color: blue;
}
.jDvNwV-WRSMB9n2z9QrzR {
color: blue;
}
._1penVf9PMtov2qLxmtsMjq {
color: red;
}
a {
color: yellow;
}
",
"",
],
]
`;

exports[`camelCase option not specified: warnings 1`] = `Array []`;

exports[`camelCase option only: errors 1`] = `Array []`;

exports[`camelCase option only: locals 1`] = `
Object {
"btnInfoIsDisabled": "_1XTfjK5gKYeSzbdZhEXRpF",
"btnInfoIsDisabled1": "jDvNwV-WRSMB9n2z9QrzR",
"foo": "bar",
"myBtnInfoIsDisabled": "value",
"simple": "_1penVf9PMtov2qLxmtsMjq",
}
`;

exports[`camelCase option only: module (evaluated) 1`] = `
Array [
Array [
1,
"._1XTfjK5gKYeSzbdZhEXRpF {
color: blue;
}
.jDvNwV-WRSMB9n2z9QrzR {
color: blue;
}
._1penVf9PMtov2qLxmtsMjq {
color: red;
}
a {
color: yellow;
}
",
"",
],
]
`;

exports[`camelCase option only: warnings 1`] = `Array []`;

exports[`camelCase option true: errors 1`] = `Array []`;

exports[`camelCase option true: locals 1`] = `
Object {
"btn--info_is-disabled_1": "jDvNwV-WRSMB9n2z9QrzR",
"btn-info_is-disabled": "_1XTfjK5gKYeSzbdZhEXRpF",
"btnInfoIsDisabled": "_1XTfjK5gKYeSzbdZhEXRpF",
"btnInfoIsDisabled1": "jDvNwV-WRSMB9n2z9QrzR",
"foo": "bar",
"my-btn-info_is-disabled": "value",
"myBtnInfoIsDisabled": "value",
"simple": "_1penVf9PMtov2qLxmtsMjq",
}
`;

exports[`camelCase option true: module (evaluated) 1`] = `
Array [
Array [
1,
"._1XTfjK5gKYeSzbdZhEXRpF {
color: blue;
}
.jDvNwV-WRSMB9n2z9QrzR {
color: blue;
}
._1penVf9PMtov2qLxmtsMjq {
color: red;
}
a {
color: yellow;
}
",
"",
],
]
`;

exports[`camelCase option true: warnings 1`] = `Array []`;
115 changes: 115 additions & 0 deletions test/__snapshots__/errors.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`validation 1`] = `
"CSS Loader Invalid Options
options.url should be boolean
options.url should pass \\"instanceof\\" keyword validation
options.url should match some schema in anyOf
"
`;

exports[`validation 2`] = `
"CSS Loader Invalid Options
options.import should be boolean
options.import should pass \\"instanceof\\" keyword validation
options.import should match some schema in anyOf
"
`;

exports[`validation 3`] = `
"CSS Loader Invalid Options
options.modules should be boolean
options.modules should be equal to one of the allowed values
options.modules should match some schema in anyOf
"
`;

exports[`validation 4`] = `
"CSS Loader Invalid Options
options.modules should be boolean
options.modules should be equal to one of the allowed values
options.modules should match some schema in anyOf
"
`;

exports[`validation 5`] = `
"CSS Loader Invalid Options
options.modules should be boolean
options.modules should be equal to one of the allowed values
options.modules should match some schema in anyOf
"
`;

exports[`validation 6`] = `
"CSS Loader Invalid Options
options.localIdentName should be string
"
`;

exports[`validation 7`] = `
"CSS Loader Invalid Options
options.localIdentRegExp should be string
options.localIdentRegExp should pass \\"instanceof\\" keyword validation
options.localIdentRegExp should match some schema in anyOf
"
`;

exports[`validation 8`] = `
"CSS Loader Invalid Options
options.context should be string
"
`;

exports[`validation 9`] = `
"CSS Loader Invalid Options
options.hashPrefix should be string
"
`;

exports[`validation 10`] = `
"CSS Loader Invalid Options
options.getLocalIdent should pass \\"instanceof\\" keyword validation
"
`;

exports[`validation 11`] = `
"CSS Loader Invalid Options
options.sourceMap should be boolean
"
`;

exports[`validation 12`] = `
"CSS Loader Invalid Options
options.camelCase should be boolean
options.camelCase should be equal to one of the allowed values
options.camelCase should match some schema in anyOf
"
`;

exports[`validation 13`] = `
"CSS Loader Invalid Options
options.importLoaders should be boolean
options.importLoaders should be number
options.importLoaders should match some schema in anyOf
"
`;

exports[`validation 14`] = `
"CSS Loader Invalid Options
options.exportOnlyLocals should be boolean
"
`;
120 changes: 120 additions & 0 deletions test/__snapshots__/getLocalIdent-option.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`getLocalIdent option should accepts arguments: errors 1`] = `Array []`;

exports[`getLocalIdent option should accepts arguments: locals 1`] = `
Object {
"abc": "foo",
"def": "foo",
"ghi": "foo",
"jkl": "foo",
}
`;

exports[`getLocalIdent option should accepts arguments: module (evaluated) 1`] = `
Array [
Array [
1,
".foo .foo {
color: red;
}
.foo .foo {
color: blue;
}
",
"",
],
]
`;

exports[`getLocalIdent option should accepts arguments: warnings 1`] = `Array []`;

exports[`getLocalIdent option should respect \`context\` option: errors 1`] = `Array []`;

exports[`getLocalIdent option should respect \`context\` option: locals 1`] = `
Object {
"abc": "_1hksQTRR0UD9eKPUBlgn0X",
"def": "_3oo37UGTAgyDe0MeQom-28",
"ghi": "_2ZRWT_7WiIKpOei7U0eJzJ",
"jkl": "aQ1rQfhbWSRMXFXxIfQcx",
}
`;

exports[`getLocalIdent option should respect \`context\` option: module (evaluated) 1`] = `
Array [
Array [
1,
"._1hksQTRR0UD9eKPUBlgn0X ._3oo37UGTAgyDe0MeQom-28 {
color: red;
}
._2ZRWT_7WiIKpOei7U0eJzJ .aQ1rQfhbWSRMXFXxIfQcx {
color: blue;
}
",
"",
],
]
`;

exports[`getLocalIdent option should respect \`context\` option: warnings 1`] = `Array []`;

exports[`getLocalIdent option should work (\`modules: false\`): errors 1`] = `Array []`;

exports[`getLocalIdent option should work (\`modules: false\`): locals 1`] = `
Object {
"def": "foo",
"ghi": "foo",
"jkl": "foo",
}
`;

exports[`getLocalIdent option should work (\`modules: false\`): module (evaluated) 1`] = `
Array [
Array [
1,
".abc .foo {
color: red;
}
.foo .foo {
color: blue;
}
",
"",
],
]
`;

exports[`getLocalIdent option should work (\`modules: false\`): warnings 1`] = `Array []`;

exports[`getLocalIdent option should work (\`modules: true\`): errors 1`] = `Array []`;

exports[`getLocalIdent option should work (\`modules: true\`): locals 1`] = `
Object {
"abc": "foo",
"def": "foo",
"ghi": "foo",
"jkl": "foo",
}
`;

exports[`getLocalIdent option should work (\`modules: true\`): module (evaluated) 1`] = `
Array [
Array [
1,
".foo .foo {
color: red;
}
.foo .foo {
color: blue;
}
",
"",
],
]
`;

exports[`getLocalIdent option should work (\`modules: true\`): warnings 1`] = `Array []`;
227 changes: 227 additions & 0 deletions test/__snapshots__/icss.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`ICSS case duplicate-export: errors 1`] = `Array []`;

exports[`ICSS case duplicate-export: locals 1`] = `
Object {
"_test": "_right_value",
}
`;

exports[`ICSS case duplicate-export: module (evaluated) 1`] = `
Array [
Array [
1,
"
",
"",
],
]
`;

exports[`ICSS case duplicate-export: warnings 1`] = `Array []`;

exports[`ICSS case duplicate-export-in-multiple-export: errors 1`] = `Array []`;

exports[`ICSS case duplicate-export-in-multiple-export: locals 1`] = `
Object {
"_test": "_right_value",
}
`;

exports[`ICSS case duplicate-export-in-multiple-export: module (evaluated) 1`] = `
Array [
Array [
1,
"
",
"",
],
]
`;

exports[`ICSS case duplicate-export-in-multiple-export: warnings 1`] = `Array []`;

exports[`ICSS case empty-export: errors 1`] = `Array []`;

exports[`ICSS case empty-export: locals 1`] = `undefined`;

exports[`ICSS case empty-export: module (evaluated) 1`] = `
Array [
Array [
1,
"
",
"",
],
]
`;

exports[`ICSS case empty-export: warnings 1`] = `Array []`;

exports[`ICSS case empty-import: errors 1`] = `Array []`;

exports[`ICSS case empty-import: locals 1`] = `undefined`;

exports[`ICSS case empty-import: module (evaluated) 1`] = `
Array [
Array [
1,
"
",
"",
],
]
`;

exports[`ICSS case empty-import: warnings 1`] = `Array []`;

exports[`ICSS case export: errors 1`] = `Array []`;

exports[`ICSS case export: locals 1`] = `
Object {
"_test": "_test",
}
`;

exports[`ICSS case export: module (evaluated) 1`] = `
Array [
Array [
1,
"
",
"",
],
]
`;

exports[`ICSS case export: warnings 1`] = `Array []`;

exports[`ICSS case export-reserved-keywords: errors 1`] = `Array []`;

exports[`ICSS case export-reserved-keywords: locals 1`] = `
Object {
"constructor": "constructor",
"toString": "toString",
}
`;

exports[`ICSS case export-reserved-keywords: module (evaluated) 1`] = `
Array [
Array [
1,
"
",
"",
],
]
`;

exports[`ICSS case export-reserved-keywords: warnings 1`] = `Array []`;

exports[`ICSS case import: errors 1`] = `Array []`;

exports[`ICSS case import: locals 1`] = `
Object {
"primary-color": "red",
}
`;

exports[`ICSS case import: module (evaluated) 1`] = `
Array [
Array [
2,
"
",
"",
],
Array [
1,
".className {
color: red;
}
",
"",
],
]
`;

exports[`ICSS case import: warnings 1`] = `Array []`;

exports[`ICSS case import-reserved-keywords: errors 1`] = `Array []`;

exports[`ICSS case import-reserved-keywords: locals 1`] = `
Object {
"primary-color": "red",
"secondary-color": "block",
}
`;

exports[`ICSS case import-reserved-keywords: module (evaluated) 1`] = `
Array [
Array [
2,
"
",
"",
],
Array [
1,
".className {
color: red;
display: block;
}
",
"",
],
]
`;

exports[`ICSS case import-reserved-keywords: warnings 1`] = `Array []`;

exports[`ICSS case multiple-export: errors 1`] = `Array []`;

exports[`ICSS case multiple-export: locals 1`] = `
Object {
"_foo": "_bar",
"_test": "_test",
}
`;

exports[`ICSS case multiple-export: module (evaluated) 1`] = `
Array [
Array [
1,
"
",
"",
],
]
`;

exports[`ICSS case multiple-export: warnings 1`] = `Array []`;

exports[`ICSS case multiple-keys-values-in-export: errors 1`] = `Array []`;

exports[`ICSS case multiple-keys-values-in-export: locals 1`] = `
Object {
"_test": "_test",
"_test1": "1",
"_test2": "'string'",
"_test3": "1px 2px 3px",
"_test4": "1px 2px 3px, 1px 2px 3px",
}
`;

exports[`ICSS case multiple-keys-values-in-export: module (evaluated) 1`] = `
Array [
Array [
1,
"
",
"",
],
]
`;

exports[`ICSS case multiple-keys-values-in-export: warnings 1`] = `Array []`;
Loading