├── .husky ├── pre-commit └── commit-msg ├── .github ├── FUNDING.yml ├── CODEOWNERS ├── workflows │ ├── dependency-review.yml │ └── nodejs.yml ├── ISSUE_TEMPLATE │ ├── SUPPORT.md │ ├── FEATURE.md │ ├── DOCS.md │ ├── MODIFICATION.md │ └── BUG.md ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── CONTRIBUTING.md ├── test ├── fixtures │ ├── data.json │ ├── error-export-null.js │ ├── error-require.js │ ├── executableFileEntry.js │ ├── error-return-sync-wrong-obj.js │ ├── error-call-sync.js │ ├── error-return-async-wrong-obj.js │ ├── error-return-sync-invalid-code.js │ ├── babel.js │ ├── cacheable.js │ ├── error-return-async-invalid-code.js │ ├── error-call-async.js │ ├── code-es.js │ ├── simple.js │ ├── code-commonjs.js │ ├── args.js │ ├── buffer.js │ ├── async-function.js │ ├── promise.js │ ├── executableFile.js │ ├── executableFileES.mjs │ ├── module-parent.js │ ├── promise-compex.js │ ├── dependencies.js │ ├── error-emitted-with-dependencies.js │ ├── dependencies-via-context.js │ └── presets │ │ ├── modernizr.js │ │ └── figlet.js ├── helpers │ ├── compile.js │ ├── index.js │ ├── readAsset.js │ ├── execute.js │ ├── normalizeErrors.js │ ├── helperLoader.js │ └── getCompiler.js ├── cjs.test.js ├── __snapshots__ │ ├── executableFile.test.js.snap │ └── loader.test.js.snap ├── validate-options.test.js ├── executableFile.test.js └── loader.test.js ├── .eslintignore ├── .prettierignore ├── .gitattributes ├── src ├── cjs.js ├── options.json └── index.js ├── .eslintrc.js ├── jest.config.js ├── lint-staged.config.js ├── commitlint.config.js ├── .editorconfig ├── .gitignore ├── babel.config.js ├── .cspell.json ├── LICENSE ├── package.json ├── CHANGELOG.md └── README.md /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | lint-staged 2 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | commitlint --edit $1 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | open_collective: webpack 2 | -------------------------------------------------------------------------------- /test/fixtures/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "years": "10" 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/error-export-null.js: -------------------------------------------------------------------------------- 1 | module.exports = null; 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /coverage 2 | /dist 3 | /node_modules 4 | /test/fixtures -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | /coverage 2 | /dist 3 | /node_modules 4 | /test/fixtures 5 | CHANGELOG.md -------------------------------------------------------------------------------- /test/fixtures/error-require.js: -------------------------------------------------------------------------------- 1 | throw new Error('This is a typical require() error'); 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | yarn.lock -diff 2 | * text=auto 3 | bin/* eol=lf 4 | package-lock.json -diff -------------------------------------------------------------------------------- /src/cjs.js: -------------------------------------------------------------------------------- 1 | const loader = require("./index"); 2 | 3 | module.exports = loader.default; 4 | -------------------------------------------------------------------------------- /test/fixtures/executableFileEntry.js: -------------------------------------------------------------------------------- 1 | const data = require('./data.json'); 2 | 3 | module.exports = {data}; 4 | -------------------------------------------------------------------------------- /src/options.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Val Loader options", 3 | "type": "object", 4 | "additionalProperties": true 5 | } 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ["@webpack-contrib/eslint-config-webpack", "prettier"], 4 | }; 5 | -------------------------------------------------------------------------------- /test/fixtures/error-return-sync-wrong-obj.js: -------------------------------------------------------------------------------- 1 | function errorReturnWrongObj() { 2 | return null; 3 | } 4 | 5 | module.exports = errorReturnWrongObj; 6 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transformIgnorePatterns: [ 3 | "/node_modules/", 4 | "\\.pnp\\.[^\\/]+$", 5 | "/test/fixtures/", 6 | ], 7 | }; 8 | -------------------------------------------------------------------------------- /test/fixtures/error-call-sync.js: -------------------------------------------------------------------------------- 1 | function errorCallSync() { 2 | throw new Error('Calling the function failed'); 3 | } 4 | 5 | module.exports = errorCallSync; 6 | -------------------------------------------------------------------------------- /lint-staged.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "*": ["prettier --write --ignore-unknown", "cspell --no-must-find-files"], 3 | "*.js": ["eslint --cache --fix"], 4 | }; 5 | -------------------------------------------------------------------------------- /test/fixtures/error-return-async-wrong-obj.js: -------------------------------------------------------------------------------- 1 | function errorReturnWrongObj() { 2 | return Promise.resolve(null); 3 | } 4 | 5 | module.exports = errorReturnWrongObj; 6 | -------------------------------------------------------------------------------- /test/fixtures/error-return-sync-invalid-code.js: -------------------------------------------------------------------------------- 1 | function errorReturnInvalidCode() { 2 | return { 3 | code: null, 4 | }; 5 | } 6 | 7 | module.exports = errorReturnInvalidCode; 8 | -------------------------------------------------------------------------------- /test/fixtures/babel.js: -------------------------------------------------------------------------------- 1 | function babel() { 2 | return { 3 | code: 'module.exports = "hello world";', 4 | }; 5 | } 6 | 7 | module.exports = { 8 | default: babel, 9 | }; 10 | -------------------------------------------------------------------------------- /test/fixtures/cacheable.js: -------------------------------------------------------------------------------- 1 | function cacheable() { 2 | return { 3 | cacheable: true, 4 | code: 'module.exports = "hello world";', 5 | }; 6 | } 7 | 8 | module.exports = cacheable; 9 | -------------------------------------------------------------------------------- /test/fixtures/error-return-async-invalid-code.js: -------------------------------------------------------------------------------- 1 | function errorReturnInvalidCode() { 2 | return Promise.resolve({ 3 | code: null, 4 | }); 5 | } 6 | 7 | module.exports = errorReturnInvalidCode; 8 | -------------------------------------------------------------------------------- /test/fixtures/error-call-async.js: -------------------------------------------------------------------------------- 1 | function errorCallAsync() { 2 | return Promise.reject( 3 | new Error('Calling the function failed asynchronously') 4 | ); 5 | } 6 | 7 | module.exports = errorCallAsync; 8 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ["@commitlint/config-conventional"], 3 | rules: { 4 | "header-max-length": [0], 5 | "body-max-line-length": [0], 6 | "footer-max-line-length": [0], 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These are the default owners for everything in 2 | # webpack-contrib 3 | @webpack-contrib/org-maintainers 4 | 5 | # Add repository specific users / groups 6 | # below here for libs that are not maintained by the org. 7 | -------------------------------------------------------------------------------- /test/fixtures/code-es.js: -------------------------------------------------------------------------------- 1 | function codeES() { 2 | return { 3 | code: 'export default "hello world";', 4 | sourceMap: { isASourceMap: true }, 5 | ast: { isAnAst: true }, 6 | }; 7 | } 8 | 9 | module.exports = codeES; 10 | -------------------------------------------------------------------------------- /test/fixtures/simple.js: -------------------------------------------------------------------------------- 1 | function simple() { 2 | return { 3 | code: 'module.exports = "hello world";', 4 | sourceMap: { isASourceMap: true }, 5 | ast: { isAnAst: true }, 6 | }; 7 | } 8 | 9 | module.exports = simple; 10 | -------------------------------------------------------------------------------- /test/fixtures/code-commonjs.js: -------------------------------------------------------------------------------- 1 | function codeES() { 2 | return { 3 | code: 'module.exports = "hello world";', 4 | sourceMap: { isASourceMap: true }, 5 | ast: { isAnAst: true }, 6 | }; 7 | } 8 | 9 | module.exports = codeES; 10 | -------------------------------------------------------------------------------- /test/fixtures/args.js: -------------------------------------------------------------------------------- 1 | function args(options) { 2 | return { 3 | code: 'module.exports = "hello world";', 4 | // We use the ast property because it is not validated 5 | ast: [options], 6 | }; 7 | } 8 | 9 | module.exports = args; 10 | -------------------------------------------------------------------------------- /test/fixtures/buffer.js: -------------------------------------------------------------------------------- 1 | function buffer() { 2 | return { 3 | code: Buffer.from('module.exports = "hello world";'), 4 | sourceMap: { isASourceMap: true }, 5 | ast: { isAnAst: true }, 6 | }; 7 | } 8 | 9 | module.exports = buffer; 10 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /test/fixtures/async-function.js: -------------------------------------------------------------------------------- 1 | async function simple() { 2 | return { 3 | code: 'module.exports = "hello world";', 4 | sourceMap: { isASourceMap: true }, 5 | ast: { isAnAst: true }, 6 | }; 7 | } 8 | 9 | module.exports = simple; 10 | -------------------------------------------------------------------------------- /test/helpers/compile.js: -------------------------------------------------------------------------------- 1 | export default (compiler) => 2 | new Promise((resolve, reject) => { 3 | compiler.run((error, stats) => { 4 | if (error) { 5 | return reject(error); 6 | } 7 | 8 | return resolve(stats); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /test/fixtures/promise.js: -------------------------------------------------------------------------------- 1 | function promise() { 2 | return Promise.resolve({ 3 | cacheable: true, 4 | code: 'module.exports = "hello world";', 5 | sourceMap: { isASourceMap: true }, 6 | ast: { isAnAst: true }, 7 | }); 8 | } 9 | 10 | module.exports = promise; 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | 4 | .idea 5 | .vscode 6 | .eslintcache 7 | *.sublime-project 8 | *.sublime-workspace 9 | 10 | /dist 11 | /local 12 | /reports 13 | /coverage 14 | /node_modules 15 | /test/output 16 | 17 | logs 18 | *.log 19 | npm-debug.log* 20 | yarn-debug.log* 21 | *.iml 22 | -------------------------------------------------------------------------------- /test/fixtures/executableFile.js: -------------------------------------------------------------------------------- 1 | module.exports = function yearsInMs(options, loaderContext, content) { 2 | const {years} = JSON.parse(content); 3 | const value = years * 365 * 24 * 60 * 60 * 1000; 4 | 5 | return { 6 | cacheable: true, 7 | code: "module.exports = " + value, 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /test/fixtures/executableFileES.mjs: -------------------------------------------------------------------------------- 1 | export default function yearsInMs(options, loaderContext, content) { 2 | const {years} = JSON.parse(content); 3 | const value = years * 365 * 24 * 60 * 60 * 1000; 4 | 5 | return { 6 | cacheable: true, 7 | code: "export default " + value, 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /test/fixtures/module-parent.js: -------------------------------------------------------------------------------- 1 | function simple() { 2 | return { 3 | code: 'module.exports = "hello world";', 4 | sourceMap: { isASourceMap: true }, 5 | ast: { 6 | isAnAst: true, 7 | hasParent: Boolean(module.parent) 8 | }, 9 | }; 10 | } 11 | 12 | module.exports = simple; 13 | -------------------------------------------------------------------------------- /test/cjs.test.js: -------------------------------------------------------------------------------- 1 | import src from "../src"; 2 | import cjs from "../src/cjs"; 3 | 4 | describe("CJS", () => { 5 | it("should export loader", () => { 6 | expect(cjs).toEqual(src); 7 | }); 8 | 9 | it('should export "raw" flag', () => { 10 | expect(cjs.raw).toBeUndefined(); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/fixtures/promise-compex.js: -------------------------------------------------------------------------------- 1 | function promise() { 2 | return new Promise((resolve) => { 3 | setTimeout(() => { 4 | resolve({ 5 | code: 'module.exports = "hello world";', 6 | sourceMap: { isASourceMap: true }, 7 | ast: { isAnAst: true }, 8 | }) 9 | }, 100) 10 | }); 11 | } 12 | 13 | module.exports = promise; 14 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | const MIN_BABEL_VERSION = 7; 2 | 3 | module.exports = (api) => { 4 | api.assertVersion(MIN_BABEL_VERSION); 5 | api.cache(true); 6 | 7 | return { 8 | presets: [ 9 | [ 10 | "@babel/preset-env", 11 | { 12 | targets: { 13 | node: "18.12.0", 14 | }, 15 | }, 16 | ], 17 | ], 18 | }; 19 | }; 20 | -------------------------------------------------------------------------------- /.github/workflows/dependency-review.yml: -------------------------------------------------------------------------------- 1 | name: "Dependency Review" 2 | on: [pull_request] 3 | 4 | permissions: 5 | contents: read 6 | 7 | jobs: 8 | dependency-review: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: "Checkout Repository" 12 | uses: actions/checkout@v4 13 | - name: "Dependency Review" 14 | uses: actions/dependency-review-action@v4 15 | -------------------------------------------------------------------------------- /test/helpers/index.js: -------------------------------------------------------------------------------- 1 | import compile from "./compile"; 2 | import execute from "./execute"; 3 | import getCompiler from "./getCompiler"; 4 | import helperLoader from "./helperLoader"; 5 | import normalizeErrors from "./normalizeErrors"; 6 | import readAsset from "./readAsset"; 7 | 8 | export { 9 | compile, 10 | execute, 11 | getCompiler, 12 | helperLoader, 13 | normalizeErrors, 14 | readAsset, 15 | }; 16 | -------------------------------------------------------------------------------- /test/helpers/readAsset.js: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | 3 | export default (asset, compiler, stats) => { 4 | const usedFs = compiler.outputFileSystem; 5 | const outputPath = stats.compilation.outputOptions.path; 6 | let data = ""; 7 | 8 | try { 9 | data = usedFs.readFileSync(path.join(outputPath, asset)).toString(); 10 | } catch (error) { 11 | data = error.toString(); 12 | } 13 | 14 | return data; 15 | }; 16 | -------------------------------------------------------------------------------- /test/fixtures/dependencies.js: -------------------------------------------------------------------------------- 1 | function dependencies() { 2 | return { 3 | dependencies: [ 4 | require.resolve('./args.js'), 5 | require.resolve('./simple.js'), 6 | ], 7 | buildDependencies: [ 8 | require.resolve('./args.js'), 9 | require.resolve('./simple.js'), 10 | ], 11 | contextDependencies: [__dirname], 12 | code: 'module.exports = "hello world";', 13 | }; 14 | } 15 | 16 | module.exports = dependencies; 17 | -------------------------------------------------------------------------------- /test/fixtures/error-emitted-with-dependencies.js: -------------------------------------------------------------------------------- 1 | function errorEmittedWithDependencies(options, loaderOptions) { 2 | loaderOptions.emitError(new Error('Calling the function failed')); 3 | 4 | return { 5 | dependencies: [ 6 | require.resolve('./args.js'), 7 | require.resolve('./simple.js'), 8 | ], 9 | contextDependencies: [__dirname], 10 | code: 'module.exports = "hello world";', 11 | }; 12 | } 13 | 14 | module.exports = errorEmittedWithDependencies; 15 | -------------------------------------------------------------------------------- /.cspell.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2", 3 | "language": "en,en-gb", 4 | "words": [ 5 | "serviceworker", 6 | "flexbox", 7 | "modernizr", 8 | "compex", 9 | "memfs", 10 | "Modernizr", 11 | "serviceworker", 12 | "commitlint", 13 | "modenizr" 14 | ], 15 | 16 | "ignorePaths": [ 17 | "CHANGELOG.md", 18 | "package.json", 19 | "dist/**", 20 | "**/__snapshots__/**", 21 | "package-lock.json", 22 | "node_modules", 23 | "coverage", 24 | "*.log" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/SUPPORT.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🆘 Support, Help, and Advice 3 | about: 👉🏽 Need support, help, or advice? Don't open an issue - visit "GitHub Discussions" or "Stack Overflow" instead. 4 | --- 5 | 6 | Hey there! 👋 7 | 8 | If you need support, help, or advice then this is not the right place to ask. 9 | 10 | Please visit one of the following instead: 11 | 12 | - [GitHub Discussions](https://github.com/webpack/webpack/discussions) 13 | - [Stack Overflow](https://stackoverflow.com/questions/tagged/webpack) 14 | 15 | Thanks for understanding! 16 | -------------------------------------------------------------------------------- /test/fixtures/dependencies-via-context.js: -------------------------------------------------------------------------------- 1 | function dependencies(options, loaderContext) { 2 | loaderContext.addDependency(require.resolve('./args.js')); 3 | loaderContext.addDependency(require.resolve('./simple.js')); 4 | loaderContext.addBuildDependency(require.resolve('./args.js')); 5 | loaderContext.addBuildDependency(require.resolve('./simple.js')); 6 | loaderContext.addBuildDependency(__dirname); 7 | loaderContext.addContextDependency(__dirname); 8 | 9 | return { 10 | code: 'module.exports = "hello world";', 11 | }; 12 | } 13 | 14 | module.exports = dependencies; 15 | -------------------------------------------------------------------------------- /test/fixtures/presets/modernizr.js: -------------------------------------------------------------------------------- 1 | const modernizr = require("modernizr"); 2 | 3 | module.exports = function(options) { 4 | return new Promise(function(resolve) { 5 | // It is impossible to throw an error because modernizr causes the process.exit(1) 6 | modernizr.build(options, function(output) { 7 | resolve({ 8 | cacheable: true, 9 | code: `var modernizr; var hadGlobal = 'Modernizr' in window; var oldGlobal = window.Modernizr; ${output} modernizr = window.Modernizr; if (hadGlobal) { window.Modernizr = oldGlobal; } else { delete window.Modernizr; } export default modernizr;` 10 | }); 11 | }); 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /test/helpers/execute.js: -------------------------------------------------------------------------------- 1 | import Module from "module"; 2 | import path from "path"; 3 | 4 | const parentModule = module; 5 | 6 | export default (code) => { 7 | const resource = "test.js"; 8 | const module = new Module(resource, parentModule); 9 | // eslint-disable-next-line no-underscore-dangle 10 | module.paths = Module._nodeModulePaths( 11 | path.resolve(__dirname, "../fixtures"), 12 | ); 13 | module.filename = resource; 14 | 15 | // eslint-disable-next-line no-underscore-dangle 16 | module._compile( 17 | `let __export__;${code};module.exports = __export__;`, 18 | resource, 19 | ); 20 | 21 | return module.exports; 22 | }; 23 | -------------------------------------------------------------------------------- /test/helpers/normalizeErrors.js: -------------------------------------------------------------------------------- 1 | function removeCWD(str) { 2 | const isWin = process.platform === "win32"; 3 | let cwd = process.cwd(); 4 | 5 | if (isWin) { 6 | // eslint-disable-next-line no-param-reassign 7 | str = str.replace(/\\/g, "/"); 8 | // eslint-disable-next-line no-param-reassign 9 | cwd = cwd.replace(/\\/g, "/"); 10 | } 11 | 12 | return str 13 | .replace(/\(from .*?\)/, "(from `replaced original path`)") 14 | .replace(new RegExp(cwd, "g"), "") 15 | .replace( 16 | /Cannot read property 'get' of undefined/, 17 | "Cannot read properties of undefined (reading 'get')", 18 | ); 19 | } 20 | 21 | export default (errors) => 22 | errors.map((error) => 23 | removeCWD(error.toString().split("\n").slice(0, 2).join("\n")), 24 | ); 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/FEATURE.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ✨ Feature Request 3 | about: Suggest an idea for this project 4 | --- 5 | 6 | 7 | 8 | 9 | ### Feature Proposal 10 | 11 | 12 | 13 | 14 | 15 | 16 | ### Feature Use Case 17 | 18 | 19 | 20 | ### Please paste the results of `npx webpack-cli info` here, and mention other relevant information. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/DOCS.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 📚 Documentation 3 | about: Are the docs lacking or missing something? Do they need some new 🔥 hotness? Tell us here. 4 | --- 5 | 6 | 7 | 8 | 9 | Documentation is: 10 | 11 | 12 | 13 | - [ ] Missing 14 | - [ ] Needed 15 | - [ ] Confusing 16 | - [ ] Not Sure? 17 | 18 | ### Please Explain in Detail... 19 | 20 | 21 | 22 | 23 | 24 | 25 | ### Your Proposal for Changes 26 | -------------------------------------------------------------------------------- /test/__snapshots__/executableFile.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`executableFile option should emit error: errors 1`] = ` 4 | [ 5 | "ModuleBuildError: Module build failed (from \`replaced original path\`): 6 | Error: Unable to require "/test/fixtures/error-require.js": Error: This is a typical require() error", 7 | ] 8 | `; 9 | 10 | exports[`executableFile option should emit error: warnings 1`] = `[]`; 11 | 12 | exports[`executableFile option should work with commonjs format: errors 1`] = `[]`; 13 | 14 | exports[`executableFile option should work with commonjs format: result 1`] = ` 15 | "{ 16 | "content": "module.exports = 315360000000", 17 | "map": null, 18 | "meta": null, 19 | "dependencies": [ 20 | "test/fixtures/data.json" 21 | ], 22 | "contextDependencies": [], 23 | "buildDependencies": [] 24 | }" 25 | `; 26 | 27 | exports[`executableFile option should work with commonjs format: warnings 1`] = `[]`; 28 | -------------------------------------------------------------------------------- /test/helpers/helperLoader.js: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | 3 | function rel(p) { 4 | return path.relative(process.cwd(), p); 5 | } 6 | 7 | export default function helperLoader(content, map, meta) { 8 | const dependencies = this.getDependencies().map((dependency) => 9 | rel(dependency).replace(/\\/g, "/"), 10 | ); 11 | const contextDependencies = this.getContextDependencies().map((dependency) => 12 | rel(dependency).replace(/\\/g, "/"), 13 | ); 14 | 15 | const buildDependencies = Array.from( 16 | this._module.buildInfo.buildDependencies || [], 17 | ).map((dependency) => rel(dependency).replace(/\\/g, "/")); 18 | const json = JSON.stringify( 19 | { 20 | content, 21 | map, 22 | meta, 23 | dependencies, 24 | contextDependencies, 25 | buildDependencies, 26 | }, 27 | null, 28 | " ", 29 | ) 30 | .replace(/\u2028/g, "\\u2028") 31 | .replace(/\u2029/g, "\\u2029"); 32 | 33 | this.emitFile("val-loader.js", json, false); 34 | 35 | return ``; 36 | } 37 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | This PR contains a: 12 | 13 | - [ ] **bugfix** 14 | - [ ] new **feature** 15 | - [ ] **code refactor** 16 | - [ ] **test update** 17 | - [ ] **typo fix** 18 | - [ ] **metadata update** 19 | 20 | ### Motivation / Use-Case 21 | 22 | 27 | 28 | ### Breaking Changes 29 | 30 | 34 | 35 | ### Additional Info 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/MODIFICATION.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🔧 Modification Request 3 | about: Want something to work differently? Have an alternative approach? This is the template for you. 4 | --- 5 | 6 | 7 | 8 | 9 | ### Modification Proposal 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ### Expected Behavior / Situation 18 | 19 | 20 | 21 | ### Actual Behavior / Situation 22 | 23 | 24 | 25 | ### Please paste the results of `npx webpack-cli info` here, and mention other relevant information. 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | 'Software'), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /test/helpers/getCompiler.js: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | 3 | import webpack from "webpack"; 4 | import { createFsFromVolume, Volume } from "memfs"; 5 | 6 | export default (fixture, loaderOptions = {}, config = {}) => { 7 | const fullConfig = { 8 | mode: "development", 9 | devtool: config.devtool || false, 10 | context: path.resolve(__dirname, "../fixtures"), 11 | entry: path.resolve(__dirname, "../fixtures", fixture), 12 | output: { 13 | path: path.resolve(__dirname, "../outputs/"), 14 | filename: "[name].bundle.js", 15 | }, 16 | module: { 17 | rules: [ 18 | { 19 | test: /\.js$/i, 20 | rules: [ 21 | { 22 | loader: require.resolve("./helperLoader.js"), 23 | }, 24 | { 25 | loader: require.resolve("../../src"), 26 | options: loaderOptions, 27 | }, 28 | ], 29 | }, 30 | ], 31 | }, 32 | plugins: [], 33 | ...config, 34 | }; 35 | 36 | const compiler = webpack(fullConfig); 37 | 38 | if (!config.outputFileSystem) { 39 | compiler.outputFileSystem = createFsFromVolume(new Volume()); 40 | } 41 | 42 | return compiler; 43 | }; 44 | -------------------------------------------------------------------------------- /test/fixtures/presets/figlet.js: -------------------------------------------------------------------------------- 1 | const figlet = require("figlet"); 2 | 3 | function wrapOutput(output, config) { 4 | let figletOutput = ""; 5 | 6 | if (config.textBefore) { 7 | figletOutput += encodeURI(`${config.textBefore}\n`); 8 | } 9 | 10 | output.split("\n").forEach(line => { 11 | figletOutput += encodeURI(`${line}\n`); 12 | }); 13 | 14 | if (config.textAfter) { 15 | figletOutput += encodeURI(`${config.textAfter}\n`); 16 | } 17 | 18 | return `module.exports = decodeURI("${figletOutput}");`; 19 | } 20 | 21 | module.exports = function (options) { 22 | const defaultConfig = { 23 | fontOptions: { 24 | font: "ANSI Shadow", 25 | horizontalLayout: "default", 26 | kerning: "default", 27 | verticalLayout: "default" 28 | }, 29 | text: "FIGLET-LOADER", 30 | textAfter: null, 31 | textBefore: null 32 | }; 33 | 34 | const config = Object.assign({}, defaultConfig, options); 35 | 36 | return new Promise(function(resolve, reject) { 37 | figlet.text(config.text, config.fontOptions, (error, output) => { 38 | if (error) { 39 | return reject(error) 40 | } 41 | 42 | resolve({ 43 | code: 'module.exports = ' + wrapOutput(output, config) 44 | }); 45 | }); 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/BUG.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug Report 3 | about: Something went awry and you'd like to tell us about it. 4 | --- 5 | 6 | 7 | 8 | 9 | ### Bug report 10 | 11 | 12 | 13 | 14 | 15 | 16 | ### Actual Behavior 17 | 18 | 19 | 20 | ### Expected Behavior 21 | 22 | 23 | 24 | 25 | ### How Do We Reproduce? 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ### Please paste the results of `npx webpack-cli info` here, and mention other relevant information. 34 | -------------------------------------------------------------------------------- /test/validate-options.test.js: -------------------------------------------------------------------------------- 1 | import { getCompiler, compile } from "./helpers"; 2 | 3 | describe("validate options", () => { 4 | const tests = { 5 | unknown: { 6 | success: [1, true, false, "test", /test/, [], {}, { foo: "bar" }], 7 | failure: [], 8 | }, 9 | }; 10 | 11 | function stringifyValue(value) { 12 | if ( 13 | Array.isArray(value) || 14 | (value && typeof value === "object" && value.constructor === Object) 15 | ) { 16 | return JSON.stringify(value); 17 | } 18 | 19 | return value; 20 | } 21 | 22 | async function createTestCase(key, value, type) { 23 | it(`should ${ 24 | type === "success" ? "successfully validate" : "throw an error on" 25 | } the "${key}" option with "${stringifyValue(value)}" value`, async () => { 26 | const compiler = getCompiler("simple.js", { [key]: value }); 27 | 28 | let stats; 29 | 30 | try { 31 | stats = await compile(compiler); 32 | } finally { 33 | if (type === "success") { 34 | expect(stats.hasErrors()).toBe(false); 35 | } else if (type === "failure") { 36 | const { 37 | compilation: { errors }, 38 | } = stats; 39 | 40 | expect(errors).toHaveLength(1); 41 | expect(() => { 42 | throw new Error(errors[0].error.message); 43 | }).toThrowErrorMatchingSnapshot(); 44 | } 45 | } 46 | }); 47 | } 48 | 49 | for (const [key, values] of Object.entries(tests)) { 50 | for (const type of Object.keys(values)) { 51 | for (const value of values[type]) { 52 | createTestCase(key, value, type); 53 | } 54 | } 55 | } 56 | }); 57 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "val-loader", 3 | "version": "6.0.0", 4 | "description": "val loader module for webpack", 5 | "license": "MIT", 6 | "repository": "webpack-contrib/val-loader", 7 | "author": "Tobias Koppers @sokra", 8 | "homepage": "https://github.com/webpack-contrib/val-loader", 9 | "bugs": "https://github.com/webpack-contrib/val-loader/issues", 10 | "funding": { 11 | "type": "opencollective", 12 | "url": "https://opencollective.com/webpack" 13 | }, 14 | "main": "dist/cjs.js", 15 | "engines": { 16 | "node": ">= 18.12.0" 17 | }, 18 | "scripts": { 19 | "start": "npm run build -- -w", 20 | "clean": "del-cli dist", 21 | "prebuild": "npm run clean", 22 | "build": "cross-env NODE_ENV=production babel src -d dist --copy-files", 23 | "commitlint": "commitlint --from=master", 24 | "security": "npm audit --production", 25 | "lint:prettier": "prettier --list-different .", 26 | "lint:js": "eslint --cache .", 27 | "lint:spelling": "cspell --no-must-find-files --cache --quiet \"**/*.*\"", 28 | "lint": "npm-run-all -l -p \"lint:**\"", 29 | "fix:js": "npm run lint:js -- --fix", 30 | "fix:prettier": "npm run lint:prettier -- --write", 31 | "fix": "npm-run-all -l fix:js fix:prettier", 32 | "test:only": "cross-env NODE_ENV=test NODE_OPTIONS=--experimental-vm-modules jest", 33 | "test:watch": "npm run test:only -- --watch", 34 | "test:coverage": "npm run test:only -- --collectCoverageFrom=\"src/**/*.js\" --coverage", 35 | "pretest": "npm run lint", 36 | "test": "npm run test:coverage", 37 | "prepare": "husky && npm run build", 38 | "release": "standard-version" 39 | }, 40 | "files": [ 41 | "dist" 42 | ], 43 | "peerDependencies": { 44 | "webpack": "^5.0.0" 45 | }, 46 | "devDependencies": { 47 | "@babel/cli": "^7.24.6", 48 | "@babel/core": "^7.24.6", 49 | "@babel/preset-env": "^7.24.6", 50 | "@commitlint/cli": "^18.6.1", 51 | "@commitlint/config-conventional": "^18.6.2", 52 | "@webpack-contrib/eslint-config-webpack": "^3.0.0", 53 | "cross-env": "^7.0.3", 54 | "cspell": "^8.8.3", 55 | "del": "^7.1.0", 56 | "del-cli": "^5.1.0", 57 | "eslint": "^8.57.0", 58 | "eslint-config-prettier": "^9.1.0", 59 | "eslint-plugin-import": "^2.29.1", 60 | "figlet": "^1.7.0", 61 | "husky": "^9.1.3", 62 | "jest": "^30.0.0", 63 | "lint-staged": "^15.2.5", 64 | "memfs": "^4.9.2", 65 | "modernizr": "^3.13.0", 66 | "npm-run-all": "^4.1.5", 67 | "prettier": "^3.3.0", 68 | "standard-version": "^9.5.0", 69 | "webpack": "^5.91.0" 70 | }, 71 | "keywords": [ 72 | "webpack", 73 | "loader", 74 | "execute", 75 | "val" 76 | ] 77 | } 78 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: val-loader 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - next 8 | pull_request: 9 | branches: 10 | - master 11 | - next 12 | 13 | permissions: 14 | contents: read 15 | 16 | jobs: 17 | lint: 18 | name: Lint - ${{ matrix.os }} - Node v${{ matrix.node-version }} 19 | 20 | env: 21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 22 | 23 | strategy: 24 | matrix: 25 | os: [ubuntu-latest] 26 | node-version: [lts/*] 27 | 28 | runs-on: ${{ matrix.os }} 29 | 30 | concurrency: 31 | group: lint-${{ matrix.os }}-v${{ matrix.node-version }}-${{ github.ref }} 32 | cancel-in-progress: true 33 | 34 | steps: 35 | - uses: actions/checkout@v4 36 | with: 37 | fetch-depth: 0 38 | 39 | - name: Use Node.js ${{ matrix.node-version }} 40 | uses: actions/setup-node@v4 41 | with: 42 | node-version: ${{ matrix.node-version }} 43 | cache: "npm" 44 | 45 | - name: Install dependencies 46 | run: npm ci 47 | 48 | - name: Lint 49 | run: npm run lint 50 | 51 | - name: Security audit 52 | run: npm run security 53 | 54 | - name: Validate PR commits with commitlint 55 | if: github.event_name == 'pull_request' 56 | run: npx commitlint --from ${{ github.event.pull_request.head.sha }}~${{ github.event.pull_request.commits }} --to ${{ github.event.pull_request.head.sha }} --verbose 57 | 58 | test: 59 | name: Test - ${{ matrix.os }} - Node v${{ matrix.node-version }}, Webpack ${{ matrix.webpack-version }} 60 | 61 | strategy: 62 | matrix: 63 | os: [ubuntu-latest, windows-latest, macos-latest] 64 | node-version: [18.x, 20.x, 22.x, 24.x] 65 | webpack-version: [latest] 66 | 67 | runs-on: ${{ matrix.os }} 68 | 69 | concurrency: 70 | group: test-${{ matrix.os }}-v${{ matrix.node-version }}-${{ matrix.webpack-version }}-${{ github.ref }} 71 | cancel-in-progress: true 72 | 73 | steps: 74 | - uses: actions/checkout@v4 75 | 76 | - name: Use Node.js ${{ matrix.node-version }} 77 | uses: actions/setup-node@v4 78 | with: 79 | node-version: ${{ matrix.node-version }} 80 | cache: "npm" 81 | 82 | - name: Install dependencies 83 | run: npm ci 84 | 85 | - name: Install webpack ${{ matrix.webpack-version }} 86 | if: matrix.webpack-version != 'latest' 87 | run: npm i webpack@${{ matrix.webpack-version }} 88 | 89 | - name: Run tests for webpack version ${{ matrix.webpack-version }} 90 | run: npm run test:coverage -- --ci 91 | 92 | - name: Submit coverage data to codecov 93 | uses: codecov/codecov-action@v5 94 | with: 95 | token: ${{ secrets.CODECOV_TOKEN }} 96 | -------------------------------------------------------------------------------- /test/executableFile.test.js: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | 3 | import { getCompiler, compile, readAsset, normalizeErrors } from "./helpers"; 4 | 5 | describe("executableFile option", () => { 6 | it("should work with commonjs format", async () => { 7 | const compiler = getCompiler( 8 | "executableFileEntry.js", 9 | {}, 10 | { 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.(json)$/i, 15 | rules: [ 16 | { 17 | loader: require.resolve("./helpers/helperLoader.js"), 18 | }, 19 | { 20 | loader: require.resolve("../src"), 21 | options: { 22 | executableFile: path.resolve( 23 | __dirname, 24 | "fixtures", 25 | "executableFile.js", 26 | ), 27 | }, 28 | }, 29 | ], 30 | }, 31 | { 32 | test: /\.json$/i, 33 | type: "asset/resource", 34 | }, 35 | ], 36 | }, 37 | }, 38 | ); 39 | const stats = await compile(compiler); 40 | 41 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot( 42 | "result", 43 | ); 44 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot( 45 | "warnings", 46 | ); 47 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors"); 48 | }); 49 | 50 | // TODO jest have not good support for ES modules for testing it, tested manually 51 | it.skip("should work with ES modules format", async () => { 52 | const compiler = getCompiler( 53 | "executableFileEntry.js", 54 | {}, 55 | { 56 | module: { 57 | rules: [ 58 | { 59 | test: /\.(json)$/i, 60 | rules: [ 61 | { 62 | loader: require.resolve("./helpers/helperLoader.js"), 63 | }, 64 | { 65 | loader: require.resolve("../src"), 66 | options: { 67 | executableFile: path.resolve( 68 | __dirname, 69 | "fixtures", 70 | "executableFileES.mjs", 71 | ), 72 | }, 73 | }, 74 | ], 75 | }, 76 | { 77 | test: /\.json$/i, 78 | type: "asset/resource", 79 | }, 80 | ], 81 | }, 82 | }, 83 | ); 84 | const stats = await compile(compiler); 85 | 86 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot( 87 | "result", 88 | ); 89 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot( 90 | "warnings", 91 | ); 92 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors"); 93 | }); 94 | 95 | it("should emit error", async () => { 96 | const compiler = getCompiler( 97 | "executableFileEntry.js", 98 | {}, 99 | { 100 | module: { 101 | rules: [ 102 | { 103 | test: /\.(json)$/i, 104 | rules: [ 105 | { 106 | loader: require.resolve("./helpers/helperLoader.js"), 107 | }, 108 | { 109 | loader: require.resolve("../src"), 110 | options: { 111 | executableFile: path.resolve( 112 | __dirname, 113 | "fixtures", 114 | "error-require.js", 115 | ), 116 | }, 117 | }, 118 | ], 119 | }, 120 | { 121 | test: /\.json$/i, 122 | type: "asset/resource", 123 | }, 124 | ], 125 | }, 126 | }, 127 | ); 128 | const stats = await compile(compiler); 129 | 130 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot( 131 | "warnings", 132 | ); 133 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors"); 134 | }); 135 | }); 136 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import Module from "module"; 2 | import { pathToFileURL } from "url"; 3 | 4 | import schema from "./options.json"; 5 | 6 | const parentModule = module; 7 | 8 | function execute(code, loaderContext) { 9 | const module = new Module(loaderContext.resource, parentModule); 10 | 11 | // eslint-disable-next-line no-underscore-dangle 12 | module.paths = Module._nodeModulePaths(loaderContext.context); 13 | // Use the path without webpack-specific parts (`resourceQuery` or `resourceFragment`) 14 | module.filename = loaderContext.resourcePath; 15 | 16 | // eslint-disable-next-line no-underscore-dangle 17 | module._compile(code, loaderContext.resource); 18 | 19 | return module.exports; 20 | } 21 | 22 | function processResult(loaderContext, result) { 23 | if (!result || typeof result !== "object" || "code" in result === false) { 24 | loaderContext.callback( 25 | new Error( 26 | `The returned result of module "${loaderContext.resource}" is not an object with a "code" property`, 27 | ), 28 | ); 29 | 30 | return; 31 | } 32 | 33 | if ( 34 | typeof result.code !== "string" && 35 | result.code instanceof Buffer === false 36 | ) { 37 | loaderContext.callback( 38 | new Error( 39 | `The returned code of module "${loaderContext.resource}" is neither a string nor an instance of Buffer`, 40 | ), 41 | ); 42 | 43 | return; 44 | } 45 | 46 | (result.dependencies || []).forEach((dep) => 47 | loaderContext.addDependency(dep), 48 | ); 49 | 50 | (result.contextDependencies || []).forEach((dep) => 51 | loaderContext.addContextDependency(dep), 52 | ); 53 | 54 | (result.buildDependencies || []).forEach((dep) => 55 | loaderContext.addBuildDependency(dep), 56 | ); 57 | 58 | // Defaults to false which is a good default here because we assume that 59 | // results tend to be not cacheable when this loader is necessary 60 | loaderContext.cacheable(Boolean(result.cacheable)); 61 | 62 | loaderContext.callback( 63 | null, 64 | result.code, 65 | result.sourceMap || null, 66 | result.ast || null, 67 | ); 68 | } 69 | 70 | export default async function loader(content) { 71 | const options = this.getOptions(schema); 72 | const { executableFile } = options; 73 | const callback = this.async(); 74 | 75 | let exports; 76 | 77 | if (executableFile) { 78 | try { 79 | // eslint-disable-next-line global-require,import/no-dynamic-require 80 | exports = require(executableFile); 81 | } catch (requireError) { 82 | try { 83 | let importESM; 84 | 85 | try { 86 | // eslint-disable-next-line no-new-func 87 | importESM = new Function("id", "return import(id);"); 88 | } catch (e) { 89 | importESM = null; 90 | } 91 | 92 | if ( 93 | requireError.code === "ERR_REQUIRE_ESM" && 94 | pathToFileURL && 95 | importESM 96 | ) { 97 | const urlForConfig = pathToFileURL(executableFile); 98 | 99 | exports = await importESM(urlForConfig); 100 | } else { 101 | throw requireError; 102 | } 103 | } catch (error) { 104 | callback(new Error(`Unable to require "${executableFile}": ${error}`)); 105 | 106 | return; 107 | } 108 | } 109 | } else { 110 | try { 111 | exports = execute(content, this); 112 | } catch (error) { 113 | callback(new Error(`Unable to execute "${this.resource}": ${error}`)); 114 | 115 | return; 116 | } 117 | } 118 | 119 | const func = exports && exports.default ? exports.default : exports; 120 | 121 | if (typeof func !== "function") { 122 | callback( 123 | new Error( 124 | `Module "${this.resource}" does not export a function as default`, 125 | ), 126 | ); 127 | return; 128 | } 129 | 130 | let result; 131 | 132 | try { 133 | result = func(options, this, content); 134 | } catch (error) { 135 | callback(new Error(`Module "${this.resource}" throw error: ${error}`)); 136 | return; 137 | } 138 | 139 | if (result && typeof result.then === "function") { 140 | result 141 | .then((res) => processResult(this, res)) 142 | .catch((error) => { 143 | callback(new Error(`Module "${this.resource}" throw error: ${error}`)); 144 | }); 145 | 146 | return; 147 | } 148 | 149 | // No return necessary because processResult calls this.callback() 150 | processResult(this, result); 151 | } 152 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | 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. 4 | 5 | ## [6.0.0](https://github.com/webpack-contrib/val-loader/compare/v5.0.1...v6.0.0) (2024-01-15) 6 | 7 | 8 | ### ⚠ BREAKING CHANGES 9 | 10 | * minimum supported Node.js version is `18.12.0` ([#151](https://github.com/webpack-contrib/val-loader/issues/151)) ([ed762dc](https://github.com/webpack-contrib/val-loader/commit/ed762dcacd5aec8f462db8a7fa0da3c8d001f4b0)) 11 | 12 | ### [5.0.1](https://github.com/webpack-contrib/val-loader/compare/v5.0.0...v5.0.1) (2022-11-29) 13 | 14 | 15 | ### Bug Fixes 16 | 17 | * compatibility with webpack cache ([#122](https://github.com/webpack-contrib/val-loader/issues/122)) ([41c08e3](https://github.com/webpack-contrib/val-loader/commit/41c08e3056741f9e0be1e4e45dc607a83d88b4e7)) 18 | 19 | ## [5.0.0](https://github.com/webpack-contrib/val-loader/compare/v4.0.0...v5.0.0) (2022-05-17) 20 | 21 | 22 | ### ⚠ BREAKING CHANGES 23 | 24 | * minimum supported `Node.js` version is `14.15.0` 25 | 26 | ## [4.0.0](https://github.com/webpack-contrib/val-loader/compare/v3.1.0...v4.0.0) (2021-05-14) 27 | 28 | 29 | ### ⚠ BREAKING CHANGES 30 | 31 | * minimum supported `Node.js` version is `12.13.0` 32 | 33 | ## [3.1.0](https://github.com/webpack-contrib/val-loader/compare/v3.0.0...v3.1.0) (2021-03-01) 34 | 35 | 36 | ### Features 37 | 38 | * added the `buildDependensies` option ([#63](https://github.com/webpack-contrib/val-loader/issues/63)) ([04be3eb](https://github.com/webpack-contrib/val-loader/commit/04be3ebd9515358929c661b3c9db98ba3d870ac1)) 39 | * added the `executableFile` option ([#65](https://github.com/webpack-contrib/val-loader/issues/65)) ([b46090f](https://github.com/webpack-contrib/val-loader/commit/b46090f323e3d2dcd75cbd552bd9447f98fd63e8)) 40 | * support ECMA modules for the `executableFile` option ([#66](https://github.com/webpack-contrib/val-loader/issues/66)) ([1e6675f](https://github.com/webpack-contrib/val-loader/commit/1e6675fdf325c0973b1314fa3ad7984eaba197b9)) 41 | 42 | ## [3.0.0](https://github.com/webpack-contrib/val-loader/compare/v2.1.2...v3.0.0) (2020-12-22) 43 | 44 | 45 | ### ⚠ BREAKING CHANGES 46 | 47 | * minimum supported webpack version is `5` 48 | 49 | ### [2.1.2](https://github.com/webpack-contrib/val-loader/compare/v2.1.1...v2.1.2) (2020-10-09) 50 | 51 | ### Chore 52 | 53 | * update `schema-utils` 54 | 55 | ### [2.1.1](https://github.com/webpack-contrib/val-loader/compare/v2.1.0...v2.1.1) (2020-04-09) 56 | 57 | ### Chore 58 | 59 | * update deps 60 | 61 | ## [2.1.0](https://github.com/webpack-contrib/val-loader/compare/v2.0.2...v2.1.0) (2019-12-17) 62 | 63 | 64 | ### Features 65 | 66 | * pass `loaderContext` as 2nd parameter ([#47](https://github.com/webpack-contrib/val-loader/issues/47)) ([cd5dd47](https://github.com/webpack-contrib/val-loader/commit/cd5dd471f41dc5dbb541e09ea8af0f3ed0ad23de)) 67 | 68 | ### [2.0.2](https://github.com/webpack-contrib/val-loader/compare/v2.0.1...v2.0.2) (2019-11-25) 69 | 70 | 71 | ### Chore 72 | 73 | * add the `funding` field in `package.json` 74 | 75 | 76 | 77 | ### [2.0.1](https://github.com/webpack-contrib/val-loader/compare/v2.0.0...v2.0.1) (2019-11-19) 78 | 79 | 80 | ### Bug Fixes 81 | 82 | * link on package ([#44](https://github.com/webpack-contrib/val-loader/issues/44)) ([f234364](https://github.com/webpack-contrib/val-loader/commit/f234364a0c98f05fd0c4203c0a3946d6f0075adc)) 83 | 84 | ### [2.0.0](https://github.com/webpack-contrib/val-loader/compare/v1.1.1...v2.0.0) (2019-11-14) 85 | 86 | 87 | ### Bug Fixes 88 | 89 | * support `webpack@5` 90 | 91 | 92 | ### Features 93 | 94 | * better handle errors from a module 95 | * pass `module.parent` to a module 96 | * validate loader options 97 | 98 | 99 | ### BREAKING CHANGES 100 | 101 | * minimum supported node version is `10.13.0` 102 | * minimum supported webpack version is `4.0.0` 103 | 104 | 105 | 106 | 107 | ## [1.1.1](https://github.com/webpack-contrib/val-loader/compare/v1.1.0...v1.1.1) (2018-06-21) 108 | 109 | 110 | ### Bug Fixes 111 | 112 | * add support for `webpack@4` ([#30](https://github.com/webpack-contrib/val-loader/issues/30)) ([fea518d](https://github.com/webpack-contrib/val-loader/commit/fea518d)) 113 | 114 | 115 | 116 | 117 | # [1.1.0](https://github.com/webpack-contrib/val-loader/compare/v1.0.2...v1.1.0) (2017-11-19) 118 | 119 | 120 | ### Features 121 | 122 | * add support for `contextDependencies` in the `{Object}` interface (`options.contextDependencies`) ([#23](https://github.com/webpack-contrib/val-loader/issues/23)) ([78aa6fe](https://github.com/webpack-contrib/val-loader/commit/78aa6fe)) 123 | 124 | 125 | 126 | 127 | ## [1.0.2](https://github.com/webpack-contrib/val-loader/compare/v1.0.1...v1.0.2) (2017-03-21) 128 | 129 | 130 | ### Bug Fixes 131 | 132 | * **.babelrc:** enable modules ([b0b116a](https://github.com/webpack-contrib/val-loader/commit/b0b116a)) 133 | 134 | 135 | 136 | 137 | ## [1.0.1](https://github.com/webpack-contrib/val-loader/compare/v1.0.0...v1.0.1) (2017-03-20) 138 | 139 | 140 | ### Bug Fixes 141 | 142 | * **src:** add CJS wrapper ([cd043f5](https://github.com/webpack-contrib/val-loader/commit/cd043f5)) 143 | 144 | 145 | 146 | 147 | # [1.0.0](https://github.com/webpack-contrib/val-loader/compare/v0.5.1...v1.0.0) (2017-03-16) 148 | 149 | 150 | ### Features 151 | 152 | * change expected module API ([caf2aab](https://github.com/webpack-contrib/val-loader/commit/caf2aab)) 153 | 154 | 155 | ### BREAKING CHANGES 156 | 157 | * this commit introduces a major refactoring of the loader. 158 | * remove node 0.10 and node 0.12 support 159 | * the loaded module must now export a function 160 | * this function will be called with the loader options 161 | * this function must return an object with this structure 162 | 163 | Property | Type | Description 164 | :--------|:-----|:----------- 165 | `code` | `string|Buffer` | **Required**. The code that is passed to the next loader or to webpack. 166 | `sourceMap` | [`SourceMap`](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit) | **Optional**. Will be pased to the next loader or to webpack. 167 | `ast` | `any` | **Optional**. An [Abstract Syntax Tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) that will be passed to the next loader. Useful to speed up the build time if the next loader uses the same AST. 168 | `dependencies` | `Array` | **Default: `[]`**. An array of absolute, native paths to file dependencies that need to be watched for changes. 169 | `cacheable` | `boolean` | **Default: `false`**. Flag whether the code can be re-used in watch mode if none of the `dependencies` have changed. 170 | 171 | * the function may also return a promise for async results 172 | * switch tooling to webpack-defaults 173 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing in @webpack-contrib 2 | 3 | We'd always love contributions to further improve the webpack / webpack-contrib ecosystem! 4 | Here are the guidelines we'd like you to follow: 5 | 6 | - [Questions and Problems](#question) 7 | - [Issues and Bugs](#issue) 8 | - [Feature Requests](#feature) 9 | - [Pull Request Submission Guidelines](#submit-pr) 10 | - [Commit Message Conventions](#commit) 11 | 12 | ## Got a Question or Problem? 13 | 14 | Please submit support requests and questions to StackOverflow using the tag [[webpack]](http://stackoverflow.com/tags/webpack). 15 | StackOverflow is better suited for this kind of support though you may also inquire in [Webpack Gitter](https://gitter.im/webpack/webpack). 16 | The issue tracker is for bug reports and feature discussions. 17 | 18 | ## Found an Issue or Bug? 19 | 20 | Before you submit an issue, please search the issue tracker, an issue for your problem may already exist, and the discussion might inform you of workarounds readily available. 21 | 22 | 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 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: 23 | 24 | - version of Webpack used 25 | - version of the loader / plugin you are creating a bug report for 26 | - the use-case that fails 27 | 28 | 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. 29 | 30 | We will be insisting on a minimal reproduction scenario in order to save the maintainers' time and ultimately be able to fix more bugs. We understand that sometimes it might be hard to extract essential bits of code from a larger codebase, but we really need to isolate the problem before we can fix it. 31 | 32 | Unfortunately, we are unable to investigate or fix bugs without a minimal reproduction, so if we don't hear back from you, we may have to close an issue that doesn't have enough info to be reproduced. 33 | 34 | ## Feature Requests? 35 | 36 | You can _request_ a new feature by creating an issue on GitHub. 37 | 38 | If you would like to _implement_ a new feature yourself, please **first submit an issue** with a proposal to ensure the idea aligns with the goals of the project. 39 | 40 | ## Pull Request Submission Guidelines 41 | 42 | Before you submit your Pull Request (PR) consider the following guidelines: 43 | 44 | - Search GitHub for an open or closed PR related to your submission to avoid duplicating effort. 45 | - Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit). This is important because release notes are automatically generated from these messages. 46 | - Complete the `Pull Request Template`. Pull requests that ignore the template will not be reviewed. 47 | - Please sign the `Contributor License Agreement (CLA)` when you open your pull request. We cannot accept your contribution without it. Be sure to sign using the primary email address associated with your local and GitHub account. 48 | 49 | ## Webpack Contrib Commit Conventions 50 | 51 | Each commit message consists of a **header**, a **body** and a **footer**. The header has a special 52 | format that includes a **type**, a **scope** and a **subject**: 53 | 54 | ``` 55 | (): 56 | 57 | 58 | 59 |