Full Code of lasso-js/lasso for AI

master 30fe251247ef cached
1072 files
857.7 KB
242.8k tokens
610 symbols
1 requests
Download .txt
Showing preview only (1,107K chars total). Download the full file or copy to clipboard to get everything.
Repository: lasso-js/lasso
Branch: master
Commit: 30fe251247ef
Files: 1072
Total size: 857.7 KB

Directory structure:
gitextract_n7scrtee/

├── .editorconfig
├── .eslintrc
├── .gitignore
├── .npmignore
├── .travis.yml
├── CHANGELOG.md
├── README.md
├── browser-refresh/
│   └── index.js
├── docs/
│   ├── amd.md
│   ├── bundling.md
│   ├── javascript-api.md
│   └── migration-optimizer-to-lasso.md
├── getImageInfo.js
├── index.js
├── middleware/
│   ├── index.js
│   ├── koa/
│   │   └── serveStatic.js
│   └── serveStatic.js
├── node-require-no-op.js
├── package.json
├── src/
│   ├── AsyncPackage.js
│   ├── Bundle.js
│   ├── BundleConfig.js
│   ├── BundleMappings.js
│   ├── BundleSetConfig.js
│   ├── Config.js
│   ├── DependencyList.js
│   ├── DependencyTree.js
│   ├── FlagSet.js
│   ├── InlinePos.js
│   ├── Lasso.js
│   ├── LassoCache.js
│   ├── LassoContext.js
│   ├── LassoManifest.js
│   ├── LassoPageResult.js
│   ├── LassoPrebuildResult.js
│   ├── LoaderMetadata.js
│   ├── PageBundles.js
│   ├── PageConfig.js
│   ├── Slot.js
│   ├── SlotTracker.js
│   ├── browser-refresh/
│   │   └── index.js
│   ├── bundle-builder.js
│   ├── bundling-strategies.js
│   ├── caching-fs.js
│   ├── condition.js
│   ├── config-loader.js
│   ├── content-types.js
│   ├── dependencies/
│   │   ├── Dependency.js
│   │   ├── DependencyRegistry.js
│   │   ├── RequireHandler.js
│   │   ├── dependency-comment.js
│   │   ├── dependency-dependencies.js
│   │   ├── dependency-intersection.js
│   │   ├── dependency-package.js
│   │   ├── dependency-resource.js
│   │   ├── glob.js
│   │   └── index.js
│   ├── dependency-walker.js
│   ├── flags.js
│   ├── index.js
│   ├── last-modified.js
│   ├── manifest-loader.js
│   ├── middleware/
│   │   ├── index.js
│   │   ├── koa/
│   │   │   └── serveStatic.js
│   │   └── serveStatic.js
│   ├── node-require-no-op/
│   │   └── index.js
│   ├── page-bundles-builder.js
│   ├── path.js
│   ├── plugins/
│   │   ├── lasso-image/
│   │   │   ├── index.js
│   │   │   ├── lasso-image-browser.js
│   │   │   └── package.json
│   │   ├── lasso-minify-css/
│   │   │   └── index.js
│   │   ├── lasso-minify-js/
│   │   │   └── index.js
│   │   └── lasso-resolve-css-urls/
│   │       └── index.js
│   ├── reader.js
│   ├── require/
│   │   ├── build-plugin-config.js
│   │   ├── dep-require-remap.js
│   │   ├── dep-require.js
│   │   ├── dep-runtime.js
│   │   ├── dep-transport-builtin.js
│   │   ├── dep-transport-define.js
│   │   ├── dep-transport-installed.js
│   │   ├── dep-transport-loader-metadata.js
│   │   ├── dep-transport-main.js
│   │   ├── dep-transport-ready.js
│   │   ├── dep-transport-remap.js
│   │   ├── dep-transport-run.js
│   │   ├── dep-transport-search-path.js
│   │   ├── index.js
│   │   ├── inspect-cache.js
│   │   └── util/
│   │       ├── Deduper.js
│   │       ├── DeduperContext.js
│   │       ├── StringTransformer.js
│   │       ├── Transforms.js
│   │       ├── inspect.js
│   │       ├── normalizeFSPath.js
│   │       └── streamToString.js
│   ├── resolve/
│   │   ├── builtins.js
│   │   ├── getRequireRemapFromDir.js
│   │   ├── index.js
│   │   └── parseRequire.js
│   ├── transforms.js
│   ├── util/
│   │   ├── CombinedStream.js
│   │   ├── DeferredReadable.js
│   │   ├── caching-stream.js
│   │   ├── fingerprint-stream.js
│   │   ├── hash.js
│   │   ├── index.js
│   │   ├── prebuild.js
│   │   ├── stringify-attrs.js
│   │   └── url-reader.js
│   └── writers/
│       ├── Writer.js
│       ├── file-writer.js
│       └── index.js
├── test/
│   ├── .eslintrc
│   ├── .gitignore
│   ├── api-test.js
│   ├── autotest.js
│   ├── autotests/
│   │   ├── api/
│   │   │   ├── config-fingerprint/
│   │   │   │   ├── foo.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-lassoPage-promise/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-lassoResource-buffer/
│   │   │   │   └── test.js
│   │   │   ├── lasso-lassoResource-buffer-name/
│   │   │   │   └── test.js
│   │   │   ├── lasso-lassoResource-promise/
│   │   │   │   ├── foo.txt
│   │   │   │   └── test.js
│   │   │   ├── myLasso-lassoPage-promise/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   └── test.js
│   │   │   ├── myLasso-lassoResource-promise/
│   │   │   │   ├── foo.txt
│   │   │   │   └── test.js
│   │   │   └── pollute-default-config/
│   │   │       └── test.js
│   │   ├── bundling/
│   │   │   ├── async-dependencies/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo-async.js
│   │   │   │   ├── foo-something-else.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-flags/
│   │   │   │   ├── DO_NOT_INCLUDE_ME.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-package/
│   │   │   │   ├── bar.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── bundle-getImageInfo-skip/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── bundles/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── d.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── bundling-strategy-default/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── bundling-strategy-lean/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── bundling-virtual-module/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── csp-nonce-inline-script/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── css-inline-resource-base64/
│   │   │   │   ├── expected.css
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── css-inline-resource-utf8/
│   │   │   │   ├── expected.css
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── css-resources-multiple-pages-no-bundling/
│   │   │   │   ├── foo.css
│   │   │   │   ├── foo.resource
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── custom-dependency-type-no-bundling/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── dedupe/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── d.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── dependency-code/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── escape-external-css-url/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── escape-external-js-url/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── external-js/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── external-js-inlined/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── external-js-integrity/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── fingerprints/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── glob-patterns/
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   ├── require/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── foo.js
│   │   │   │   ├── style/
│   │   │   │   │   ├── style1.css
│   │   │   │   │   └── style2.css
│   │   │   │   └── test.js
│   │   │   ├── glob-patterns-relative-paths/
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   ├── require/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── foo.js
│   │   │   │   ├── style/
│   │   │   │   │   ├── style1.css
│   │   │   │   │   └── style2.css
│   │   │   │   └── test.js
│   │   │   ├── inline-async-script/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── inline-css-html-chars/
│   │   │   │   ├── expected.html
│   │   │   │   ├── package.json
│   │   │   │   ├── style.css
│   │   │   │   └── test.js
│   │   │   ├── inline-defer-script/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── inline-script-external-attrs/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── intersection/
│   │   │   │   ├── bar.js
│   │   │   │   ├── common.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── page1.browser.json
│   │   │   │   ├── page2.browser.json
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-100percent/
│   │   │   │   ├── a.browser.json
│   │   │   │   ├── a.js
│   │   │   │   ├── ab.browser.json
│   │   │   │   ├── abc.browser.json
│   │   │   │   ├── b.js
│   │   │   │   ├── bc.browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-2/
│   │   │   │   ├── a.browser.json
│   │   │   │   ├── a.js
│   │   │   │   ├── ab.browser.json
│   │   │   │   ├── abc.browser.json
│   │   │   │   ├── b.js
│   │   │   │   ├── bc.browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-2-require/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── main.browser.json
│   │   │   │   ├── package.json
│   │   │   │   ├── shared.js
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-2str/
│   │   │   │   ├── a.browser.json
│   │   │   │   ├── a.js
│   │   │   │   ├── ab.browser.json
│   │   │   │   ├── abc.browser.json
│   │   │   │   ├── b.js
│   │   │   │   ├── bc.browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-3/
│   │   │   │   ├── a.browser.json
│   │   │   │   ├── a.js
│   │   │   │   ├── ab.browser.json
│   │   │   │   ├── abc.browser.json
│   │   │   │   ├── b.js
│   │   │   │   ├── bc.browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-50percent/
│   │   │   │   ├── a.browser.json
│   │   │   │   ├── a.js
│   │   │   │   ├── ab.browser.json
│   │   │   │   ├── abc.browser.json
│   │   │   │   ├── b.js
│   │   │   │   ├── bc.browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── modules-ready-lastSlot/
│   │   │   │   ├── body.js
│   │   │   │   ├── head.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── no-bundles/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── recurseInto-all/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── recurseInto-dir/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── recurseInto-dirtree/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── recurseInto-module/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── registerRequireExtension-not-cacheable/
│   │   │   │   ├── foo.js
│   │   │   │   ├── hello.dynamic
│   │   │   │   ├── hello.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── resource-absolute-path/
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots/
│   │   │   │   ├── foo.css
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots-inline-beginning/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots-inline-end/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots-inline-false/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots-inline-in-place/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots-inline-true/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── slots-override/
│   │   │       ├── foo.css
│   │   │       ├── foo.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-require/
│   │   │   ├── async/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── builtin/
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── globals-custom/
│   │   │   │   ├── expected.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── globals-jquery/
│   │   │   │   ├── expected.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── main-custom/
│   │   │   │   ├── bar/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── package.json
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── main-index/
│   │   │   │   ├── bar/
│   │   │   │   │   └── index.js
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── module-no-dependencies/
│   │   │   │   │   ├── expected.json
│   │   │   │   │   ├── foo.js
│   │   │   │   │   ├── package.json
│   │   │   │   │   └── test.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── main-require-redefined/
│   │   │   │   ├── bar/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── package.json
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── remap-browser-override/
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo-browser.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed/
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed-scoped/
│   │   │   │   ├── expected.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-search-path/
│   │   │   │   ├── app-modules/
│   │   │   │   │   └── bar/
│   │   │   │   │       ├── index.js
│   │   │   │   │       └── package.json
│   │   │   │   ├── expected.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transitive/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transitive-resolved/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── virtual-module/
│   │   │       ├── expected.json
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-define/
│   │   │   ├── async/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── builtin/
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── globals-foo/
│   │   │   │   ├── expected.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── globals-jquery/
│   │   │   │   ├── expected.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── main-custom/
│   │   │   │   ├── bar/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── package.json
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── main-index/
│   │   │   │   ├── bar/
│   │   │   │   │   └── index.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── module-no-dependencies/
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── remap-void/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed/
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed-scoped/
│   │   │   │   ├── expected.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-search-path/
│   │   │   │   ├── app-modules/
│   │   │   │   │   └── bar/
│   │   │   │   │       ├── index.js
│   │   │   │   │       └── package.json
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-browserify/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-browserify-config/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-multiple/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   ├── transform-a.js
│   │   │   │   ├── transform-b.js
│   │   │   │   └── transform-c.js
│   │   │   ├── transform-promise/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-stream/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-stream-config/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-stream-no-config/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-synchronous/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-synchronous-config/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transitive/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── transitive-resolved/
│   │   │       ├── bar.js
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-installed/
│   │   │   └── simple/
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-main/
│   │   │   └── simple/
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-ready/
│   │   │   └── simple/
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-remap/
│   │   │   └── simple/
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-run/
│   │   │   ├── no-wait/
│   │   │   │   ├── expected.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── wait/
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dependency-walker/
│   │   │   ├── flat/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected.txt
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── globs/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected.txt
│   │   │   │   ├── package.json
│   │   │   │   ├── require/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── foo.js
│   │   │   │   ├── style/
│   │   │   │   │   ├── style1.css
│   │   │   │   │   └── style2.css
│   │   │   │   └── test.js
│   │   │   ├── lasso-issue-136/
│   │   │   │   ├── browser.json
│   │   │   │   ├── common.js
│   │   │   │   ├── expected.txt
│   │   │   │   ├── foo1.js
│   │   │   │   ├── foo2.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected.txt
│   │   │   │   ├── foo.js
│   │   │   │   ├── nested/
│   │   │   │   │   └── index.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-mixed/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected.txt
│   │   │   │   ├── foo.js
│   │   │   │   ├── hello.css
│   │   │   │   ├── hello.js
│   │   │   │   ├── nested/
│   │   │   │   │   └── index.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── transitive-package/
│   │   │       ├── browser.json
│   │   │       ├── expected.txt
│   │   │       ├── foo.js
│   │   │       ├── nested/
│   │   │       │   ├── bar.js
│   │   │       │   └── browser.json
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── flags/
│   │   │   ├── bundling-enabled/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── desktop-a.js
│   │   │   │   ├── desktop-b.js
│   │   │   │   ├── mobile-a.js
│   │   │   │   ├── mobile-b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── if-flag-dependencies/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── desktop-a.js
│   │   │   │   ├── desktop-b.js
│   │   │   │   ├── mobile-a.js
│   │   │   │   ├── mobile-b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── if-not-flag/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── desktop-a.js
│   │   │   │   ├── desktop-b.js
│   │   │   │   ├── mobile-a.js
│   │   │   │   ├── mobile-b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── long-flags/
│   │   │   │   ├── a.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── simple/
│   │   │       ├── a.js
│   │   │       ├── b.js
│   │   │       ├── browser.json
│   │   │       ├── c.js
│   │   │       ├── desktop-a.js
│   │   │       ├── desktop-b.js
│   │   │       ├── mobile-a.js
│   │   │       ├── mobile-b.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── inspect/
│   │   │   ├── buffer/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── complex/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── first-mate/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── global-late-def/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── globals/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── lasso-loader-var/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── parse-error/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── process1/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── process2/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── process3/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── process4/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   └── simple/
│   │   │       ├── expected.json
│   │   │       └── input.js
│   │   ├── load-prebuild/
│   │   │   ├── error-invalid-path/
│   │   │   │   └── test.js
│   │   │   ├── error-no-build/
│   │   │   │   ├── page.prebuild.json
│   │   │   │   └── test.js
│   │   │   ├── load-valid-prebuild/
│   │   │   │   ├── page.prebuild.json
│   │   │   │   └── test.js
│   │   │   ├── load-valid-prebuild-multi-flags/
│   │   │   │   ├── page.prebuild.json
│   │   │   │   └── test.js
│   │   │   └── load-valid-prebuild-multi-no-flags/
│   │   │       ├── page.prebuild.json
│   │   │       └── test.js
│   │   ├── modules/
│   │   │   ├── async/
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-flags/
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-intersection/
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main1-helper.js
│   │   │   │   ├── main1.js
│   │   │   │   ├── main2-helper.js
│   │   │   │   ├── main2.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-package/
│   │   │   │   ├── bar.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── something.js
│   │   │   │   └── test.js
│   │   │   ├── async-package-css/
│   │   │   │   ├── browser.json
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── something.css
│   │   │   │   └── test.js
│   │   │   ├── async-raptor-loader/
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-unnecessary/
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── browser.json-tilde/
│   │   │   │   ├── browser.json
│   │   │   │   ├── nested/
│   │   │   │   │   ├── browser.json
│   │   │   │   │   └── nested.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── browserify-transform/
│   │   │   │   ├── foo-transform.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── browserify-transforms/
│   │   │   │   ├── bar-transform.js
│   │   │   │   ├── foo-transform.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── duplicate-name-browser-json/
│   │   │   │   ├── bar/
│   │   │   │   │   ├── browser.json
│   │   │   │   │   └── hello.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo/
│   │   │   │   │   ├── browser.json
│   │   │   │   │   └── hello.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── mask-define-vanilla-js/
│   │   │   │   ├── define-global.js
│   │   │   │   ├── library.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── missing-module/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── no-conflict/
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── registerRequireExtension-getDependencies/
│   │   │   │   ├── extra.js
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   └── world.foo
│   │   │   ├── registerRequireType/
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   └── world.foo
│   │   │   ├── registerRequireType-getDependencies-callback/
│   │   │   │   ├── extra.js
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   └── world.foo
│   │   │   ├── registerRequireType-getDependencies-promise/
│   │   │   │   ├── extra.js
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   └── world.foo
│   │   │   ├── registerRequireType-getDependencies-value/
│   │   │   │   ├── extra.js
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   └── world.foo
│   │   │   ├── require-builtin-core/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-css/
│   │   │   │   ├── foo.css
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-custom-ext/
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── require-foo-plugin.js
│   │   │   │   └── test.js
│   │   │   ├── require-custom-ext-no-plugin/
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-custom-type/
│   │   │   │   ├── foo.json
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-globals/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed-scoped-package/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-json/
│   │   │   │   ├── foo.json
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-relative/
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-flag/
│   │   │   │   ├── bar-desktop.js
│   │   │   │   ├── bar.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo-mobile.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-flag-caching/
│   │   │   │   ├── bar-desktop.js
│   │   │   │   ├── bar.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo-mobile.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-local-to-installed/
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-local-to-local/
│   │   │   │   ├── foo-browser.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-void-installed/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-void-relative/
│   │   │   │   ├── foo.js
│   │   │   │   ├── foo2.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-resolve/
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-virtual-module/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── requireRemap-not-conditional/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo-browser.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── requireRemap-plus-package-browser/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo-browser-lasso.js
│   │   │   │   ├── foo-browser.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── simple/
│   │   │       ├── main.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── plugins/
│   │   │   ├── custom-dependency-type-callback/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── custom-dependency-type-promise/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── events/
│   │   │   │   ├── async-foo.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-events.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── global-dependency-prop/
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   ├── something.foo
│   │   │   │   └── test.js
│   │   │   ├── inline-all-for-slot/
│   │   │   │   ├── bar.js
│   │   │   │   ├── baz.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-my-inline-slot.html
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-context-event-bundle-written/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-events.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-context-event-resource-written/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-events.json
│   │   │   │   ├── fonts/
│   │   │   │   │   └── fonts.css
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-writer-event-bundle-written/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-events.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-writer-event-resource-written/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-events.json
│   │   │   │   ├── fonts/
│   │   │   │   │   └── fonts.css
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── registerRequireExtension/
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   ├── something.foo
│   │   │   │   └── test.js
│   │   │   ├── registerRequireType/
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   ├── something.foo
│   │   │   │   └── test.js
│   │   │   └── write-bundle/
│   │   │       ├── browser.json
│   │   │       ├── foo.js
│   │   │       ├── package.json
│   │   │       ├── plugin.js
│   │   │       └── test.js
│   │   ├── prebuild-page/
│   │   │   ├── invalid-prebuild-config/
│   │   │   │   └── test.js
│   │   │   ├── multi-prebuild/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── page.prebuild.expected.json
│   │   │   │   ├── page1.prebuild.expected.json
│   │   │   │   └── test.js
│   │   │   ├── prebuild-resource/
│   │   │   │   ├── test-page.prebuild.expected.json
│   │   │   │   └── test.js
│   │   │   └── valid-prebuild/
│   │   │       ├── a.js
│   │   │       ├── test-page-1.prebuild.expected.json
│   │   │       └── test.js
│   │   ├── require-no-op/
│   │   │   ├── enable/
│   │   │   │   ├── test.js
│   │   │   │   ├── test.xbar
│   │   │   │   ├── test.xfoo
│   │   │   │   ├── test.ybar
│   │   │   │   └── test.yfoo
│   │   │   ├── enable-ignore-null-extension/
│   │   │   │   ├── test.js
│   │   │   │   ├── test.xbar
│   │   │   │   ├── test.xfoo
│   │   │   │   ├── test.ybar
│   │   │   │   └── test.yfoo
│   │   │   └── enable-throw-invalid-extension-type/
│   │   │       ├── test.js
│   │   │       ├── test.xbar
│   │   │       ├── test.xfoo
│   │   │       ├── test.ybar
│   │   │       └── test.yfoo
│   │   ├── resource-transforms/
│   │   │   ├── filter/
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   ├── transform.bar
│   │   │   │   └── transform.foo
│   │   │   └── stream/
│   │   │       ├── package.json
│   │   │       ├── test.js
│   │   │       ├── transform.bar
│   │   │       └── transform.foo
│   │   ├── transforms/
│   │   │   ├── minify-js/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── output-transforms/
│   │   │   │   ├── browser.json
│   │   │   │   ├── css-transform1.js
│   │   │   │   ├── css-transform2.js
│   │   │   │   ├── js-transform1-async.js
│   │   │   │   ├── js-transform2-async.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   ├── transformsA.css
│   │   │   │   └── transformsA.js
│   │   │   ├── resolve-font-urls/
│   │   │   │   ├── browser.json
│   │   │   │   ├── fonts/
│   │   │   │   │   └── fonts.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-custom-resolver/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-custom-type/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-fingerprints/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-no-bundling/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-no-fingerprints/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-no-relative/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── transform-css-urls-require/
│   │   │       ├── browser.json
│   │   │       ├── foo.css
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   └── util/
│   │       └── caching-replay-stream/
│   │           ├── .gitignore
│   │           ├── hello.txt
│   │           └── test.js
│   ├── builtins-test.js
│   ├── bundling-test.js
│   ├── dep-require-test.js
│   ├── dep-transport-define-test.js
│   ├── dep-transport-installed-test.js
│   ├── dep-transport-main-test.js
│   ├── dep-transport-ready-test.js
│   ├── dep-transport-remap-test.js
│   ├── dep-transport-run-test.js
│   ├── dependency-walker-test.js
│   ├── fixtures/
│   │   ├── builtin-foo.js
│   │   ├── file.json
│   │   ├── foo-shim.js
│   │   └── inspect-cache/
│   │       ├── bar.js
│   │       └── foo.js
│   ├── flags-test.js
│   ├── inspect-cache-test.js
│   ├── inspect-test.js
│   ├── lasso-image-test.js
│   ├── load-prebuild-test.js
│   ├── mock/
│   │   ├── LassoManifest.js
│   │   ├── MockDependency.js
│   │   ├── MockLassoContext.js
│   │   ├── MockMemoryCache.js
│   │   ├── MockRequireHandler.js
│   │   ├── condition.js
│   │   ├── create-lasso-context.js
│   │   ├── dependency-factory.js
│   │   ├── fingerprint-stream.js
│   │   ├── manifest-loader.js
│   │   └── mock-lasso.js
│   ├── modules-test.js
│   ├── plugins-test.js
│   ├── prebuild-page-test.js
│   ├── require-no-op-test.js
│   ├── resource-transforms-test.js
│   ├── transforms-test.js
│   ├── unit/
│   │   ├── AsyncPackage-test.js
│   │   ├── LassoPageResult-test.js
│   │   └── hash-test.js
│   ├── util/
│   │   ├── WriterTracker.js
│   │   ├── index.js
│   │   ├── module-search-path.js
│   │   ├── normalizeOutput.js
│   │   ├── patch-module.js
│   │   └── test-init.js
│   └── util-test.js
└── test-loop.sh

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true

# Matches multiple files with brace expansion notation
# Set default charset
[*.{js,json,marko,yml}]
charset = utf-8
indent_style = space
indent_size = 4


================================================
FILE: .eslintrc
================================================
{
  "extends": "standard",
  "rules": {
    "indent": ["error", 4],
    "semi": ["error", "always"],
    "space-before-function-paren": ["off"],
    "no-path-concat": ["off"],
    "no-useless-escape": ["off"],
    "no-eval": ["off"]
  }
}


================================================
FILE: .gitignore
================================================
/work
/build
/.idea/
/npm-debug.log
/node_modules
/*.sublime-workspace
*.orig
.DS_Store
coverage
/test/build
/test/static
*.actual.js
*.actual.html
.lasso-cache
.cache
~*
.nyc_output/
.vscode
test/autotests/prebuild-page/*/static
test/autotests/prebuild-page/*/*.prebuild.json

================================================
FILE: .npmignore
================================================
/work
/build
/.idea/
/npm-debug.log
/node_modules
/*.sublime-workspace
*.orig
.DS_Store
coverage
/test/build
*.actual.js
*.actual.html
.lasso-cache
.cache
/test
*.marko.js
*.dust.js
.nyc_output/
coverage/


================================================
FILE: .travis.yml
================================================
node_js:
- 10
- 8
- 6

sudo: false
language: node_js
# Use latest version of npm
before_install: npm install -g npm@*
script: "npm test"


================================================
FILE: CHANGELOG.md
================================================
Changelog
=========

# 4.0.3
- Fix issue where the internal lasso context data was missing for image/resource assets.

# 4.0.2
- Fix issue with caching page results in production mode.

# 4.0.1
- Fix regression with the `getImageInfo` api.

# 4.0.0
- **BREAKING**: Requires a minimum of node 16
- Upgrades internal dependencies (biggest user facing change being JS/CSS parsing and minification of newer features).

# 3.4.0

- Switches from esprima to espree to parse JavaScript (supports more modern JavaScript).

# 3.3.1

- Adds `.webp` to the list of browser-refresh extensions.

# 3.3.0

- use [terser](https://github.com/terser-js/terser) instead uglify-js because it's [no longer maintained](https://github.com/mishoo/UglifyJS2/issues/3156#issuecomment-392943058).

# 3.2.8

- Fix regression with inline scripts with `externalScriptAttrs`.

# 3.2.7

- Improve support for `defer` and `async` attributes on inline bundles.

# 3.0.0

- **BREAKING**: Remove support for Node 4
    - Significant refactors. Move to async/await internally.
    - Traspile for Node 4 support using Babel
- **BREAKING**: API methods no longer expose callbacks.
    - Plugins should no longer expect a callback
    - Plugins should return promises for async tasks
- **BREAKING**: Marko taglib and taglib-v2 removed
    - Use `@lasso/marko-taglib` instead
- Support for passing `cacheKey` property to lasso config
- Merge `lasso-require` into Lasso
    - Lasso config `lassoConfig.require.resolver` property has been split out
    into its own property `lassoConfig.resolver`

```js
const lassoConfig: {
    require: {
        transforms: ...
    },
    resolver: {
        builtins: {
            ...
        }
    }
}

const lasso = lasso.create(lassoConfig);
```

- Lasso writers now support async `init` functions

```js
module.exports = function(lasso, config) {
    lasso.config.writer = {
        async init (lassoContext) {
            await Promise.resolve();
        },

        async writeBundle (reader, lassoContext) {
            const bundle = lassoContext.bundle;
            bundle.url = 'test.com';
        },

        async writeResource (reader, lassoContext) {
            return { url: 'test.com' };
        }
    };
};
```

# 2.x

## 2.9.x

### 2.9.0

- Fixes #186 - Allow custom require handler to implement getDependencies

## 2.8.x

### 2.8.5

- Use [resolve-from](https://github.com/sindresorhus/resolve-from) to first try and resolve `browser.json`

### 2.8.4

- Fixes #185 - DependencyRegistry has an undefined stream when using `mask-define` for AMD dependencies
- Increasing default timeout to 10s
- Other minor internal changes

### 2.8.3

- Internal: use `renderToString` instead of `renderSync` ([PR #182](https://github.com/lasso-js/lasso/pull/182) by [@yomed](https://github.com/yomed))

### 2.8.2

- Fixed #180 - Defining bundles with "intersection" does not work for "require" dependencies

### 2.8.2

- Fixed #180 - Defining bundles with "intersection" does not work for "require" dependencies

### 2.8.1

- Fixed #178 - Cache key changes when lasso is reconfigured even if config did not change

### 2.8.0

- Fixed #173 - Bundle attributes

## 2.7.x

### 2.7.0

- Restored Marko v2 compatibility

## 2.6.x

### 2.6.1

- Fixes #171 - Write cache key information to disk for debugging purposes

### 2.6.0

- Added support for a new `relativeUrlsEnabled` configuration option ([PR #167](https://github.com/lasso-js/lasso/pull/167) by [@reid](https://github.com/reid))
- Upgraded [glob](https://www.npmjs.com/package/glob) version ([PR #166](https://github.com/lasso-js/lasso/pull/166) by [@yomed](https://github.com/yomed))
- Docs: various improvements to documentation by ([@yomed](https://github.com/yomed))

## 2.5.x

### 2.5.9

- Introduced Koa-compatible middleware ([PR #163](https://github.com/lasso-js/lasso/pull/163) by [@yomed](https://github.com/yomed))

### 2.5.8

- Added tests for #160 - lastSlot configuration option for the require plugin

### 2.5.7

- Upgraded to `raptor-util@2.0.0`

### 2.5.6

- Fixed #156 - Lasso is generating very long names in development triggering `ENAMETOOLONG` error [PR #157](https://github.com/lasso-js/lasso/pull/157) from [@mlrawlings](https://github.com/mlrawlings)

### 2.5.5

- Fixes #147 - EPERM 'operation not permitted' on rename
- Fixes #148 - css urls resolved incorrectly with multiple pages when bundling disabled
- Testing: Don't actually read external URLs when running tests

### 2.5.4

- Fixes #149 - if-flag is ignored in async section of browser.json

### 2.5.3

- Updated taglib type and autocomplete information for tooling
- Docs: Added [Michael Rawlings](https://github.com/mlrawlings) as a maintainer

### 2.5.2

- Added `null`/`undefined` when building async loader metadata

### 2.5.1

- Fixed #146 - Slot timeout causes other slots to timeout

### 2.5.0

- Loader metadata for lazily loading packages is no longer stored in a global variable and is instead integrated with the lasso modules client runtime. This change prevents separate lasso builds of JavaScript libraries from conflicting with each other when both added to the same web page.

### 2.4.2

- Code cleanup for base64 encoding

### 2.4.1

- Fixes #143 - Only encode new lines when using utf8 encoding for data uri

### 2.4.0

- Fixes #141 - Add support for UTF8 encoding inline images in CSS files

## 2.3.x

### 2.3.6

- Fixes #137 - Don't allow double callbacks in case of multiple errors on the same read stream

### 2.3.5

- Fixes #136 - Just use a unique ID for packages if calculateKey() is not implemented
- Added new events: `beforeAddDependencyToAsyncPageBundle`, `beforeAddDependencyToSyncPageBundle`

Example plugin:

```javascript
module.exports = exports = function(lasso, config) {
    lasso.on('beforeBuildPage', (event) => {
        var context = event.context;

        context.on('beforeAddDependencyToSyncPageBundle', (event) => {
            var dependency = event.dependency;

        });

        context.on('beforeAddDependencyToAsyncPageBundle', (event) => {
            var dependency = event.dependency;

        });
    });
};
```

### 2.3.4

- Fixed #135 - Incorrect key is calculated for require dependencies in `browser.json` files in some situations

### 2.3.3

- Fixed #134 - The `<lasso-img>` tag breaks bundling when included in a template sent to the browser
- Fixed #133 - The dependency chain should be included in error messages when walking a dependency graph

### 2.3.2

- Fixed #130 - check inline minification config value ([@yomed](https://github.com/yomed))
- Updated docs and tests

### 2.3.1

- Minor cleanup

### 2.3.0

- Fixes #84 - Allow minification to only be enabled for inline resources
- Switched from `jsonminify` to `strip-json-comments`

## 2.2.x

### 2.2.2

- Fixes #128 - getLastModified is broken when using registerRequireType

### 2.2.1

- JavaScript comments are now stripped before parsing JSON config files

### 2.2.0

- Significant improvements to performance and stability
- Resolved issues related to caching and development mode

## 2.1.x

### 2.1.1

- Fixes #116 - Conditional requireRemap is broken

### 2.1.0

- Fixes #115 - Allow conditional dependencies to be grouped

## 2.0.x

### 2.0.1

- `registerRequireType`, switch condition blocks [PR #113](https://github.com/lasso-js/lasso/pull/113)

### 2.0.0

- Marko v3 compatibility

# 1.x

## 1.16.x

### 1.16.1

- Adds support for fingerprinting inline code blocks for purpose of creating Content Security Policy (CSP) that secures statically built app.

### 1.16.0

-  Added support for custom attributes on script and style tags for slots

## 1.15.x

### 1.15.0

- Adds support for injecting a Content Security Policy nonce into inline script and style tags. Fixes [Issue #93](https://github.com/lasso-js/lasso/issues/93)

## 1.14.x

### 1.14.0

- Fixed #100 - Removed type attributes from `<script>`, `<link>` and `<style>` tags, as recommended for HTML5 best practices.

## 1.13.x

### 1.13.4

- Allow dependencies to choose default bundle name by implementing getDefaultBundleName(pageBundleName, lassoContext)

### 1.13.3

- Added test for https://github.com/lasso-js/lasso-require/issues/21

### 1.13.2

- Fixed #95 - Further sanitize relative bundle paths that are used to determine output file

### 1.13.1

- Improved name generation for unbundled dependencies
- Better OS file separator handling

### 1.13.0

- Adds support for `noConflict` lasso configuration option

## 1.12.x

### 1.12.0

- Fixes https://github.com/lasso-js/lasso-minify-js/issues/1 - Upgrade to the latest version of UglifyJS

### 1.11.12

- Fixes [#82](https://github.com/lasso-js/lasso/issues/82) - Make lasso a true singleton

### 1.11.11

- Minor correction in calculateConfigFingerprint code

### 1.11.10

- Added mask-define option for resource dependencies

### 1.11.9

- Changes to keep Lasso taglib compatible with older versions of `marko`

### 1.11.8

- Upgraded the marko dev dependency

### 1.11.7

- Documentation: Improved docs

### 1.11.6

- Documentation: Improved docs

### 1.11.5

- Fixesd [#77](https://github.com/lasso-js/lasso/issues/77) - <lasso-img> now works on the server and in the browser
- Builtin es6 support for `.es6` files
- Documentation: Added docs for #77

### 1.11.4

- Only enable the browser-refresh special reloads once

### 1.11.3

- Add web fonts to browser-refresh

### 1.11.2

- Fixed circular require issues for browser-refresh

### 1.11.1

- browser-refresh is now auto enabled.
- Code and docs cleanup

### 1.10.4

- Fixed #76 Auto switch to development mode when browser-refresh is enabled

### 1.10.3

- Fixed #75 - Generate config cache key in a stable way
- Documentation: new plugin: [lasso-autoprefixer](https://github.com/lasso-js/lasso-autoprefixer): Autoprefix CSS with vendor prefixes using [autoprefixer-core](https://github.com/postcss/autoprefixer-core)
- Documentation: Fixed #61 - Improve documentation for external resource dependencies

### 1.10.2

- Documentation: new third party plugin: [lasso-clean-css](https://github.com/yomed/lasso-clean-css)

### 1.10.1

- Fixed [#62](https://github.com/lasso-js/lasso/issues/62) - Invalidate the default lasso instance on configure

### 1.10.0

- Fixed [#57](https://github.com/lasso-js/lasso/issues/57) - Allow non-JavaScript modules to be required:

```javascript
require('lasso/node-require-no-op').enable('.less', '.css');

// ...

require('./style.less');
```

### 1.9.0

## 1.9.x

### 1.9.1

- Internal: Switched from "raptor-async/DataHolder" (deprecated) to "raptor-async/AsyncValue"

### 1.9.0

- [Issue #48](https://github.com/lasso-js/lasso/issues/48): Do not mangle bundle names
- [Issue #49](https://github.com/lasso-js/lasso/issues/49): Enhance LassoPageResult to fetch info by bundle name

## 1.8.x

### 1.8.6

- Renamed Optimizer to Lasso


================================================
FILE: README.md
================================================
Lasso.js
==================

[![Build Status](https://travis-ci.org/lasso-js/lasso.svg?branch=master)](https://travis-ci.org/lasso-js/lasso)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/lasso-js/lasso)

Lasso.js is an eBay open source Node.js-style JavaScript module bundler that also provides first-level support for optimally delivering JavaScript, CSS, images and other assets to the browser.

This tool offers many different optimizations such as a bundling, code splitting, lazy loading, conditional dependencies, compression and fingerprinted resource URLs. Plugins are provided to support pre-processors and compilers such as Less, Stylus and [Marko](https://github.com/raptorjs/marko). This developer-friendly tool does not require that you change the way that you already code and can easily be adopted by existing applications.

# Example

Install the command line interface for Lasso.js:

```text
npm install lasso-cli --global
```

Install a helper module from npm:

```text
npm install change-case
```

Create the main Node.js JavaScript module file:

__main.js:__

```javascript
var changeCase = require('change-case');
console.log(changeCase.titleCase('hello world')); // Output: 'Hello World'
```

Create a StyleSheet for the page:

__style.css__

```css
body {
    background-color: #5B83AD;
}
```

Create an HTML page to host the application:

__my-page.html:__

```html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Lasso.js Demo</title>
</head>
<body>
    <h1>Lasso.js Demo</h1>
</body>
</html>
```

Run the following command:

```bash
lasso style.css \
    --main main.js \
    --inject-into my-page.html
```

Output:

```text
Output for page "my-page":
  Resource bundle files:
    static/my-page-9ac9985e.js
    static/my-page-1ae3e9bf.css
  HTML slots file:
    build/my-page.html.json
  Updated HTML file:
    my-page.html
```

Open up `my-page.html` in your web browser and in the JavaScript console you will see the output of our program running in the browser, as well as a page styled by `style.css`.

As you can see, with Lasso.js you no longer have to struggle with managing complex build scripts. Simply let Lasso.js worry about generating all of the required resource bundles and injecting them into your page so that you can just focus on writing clean and modular code.

There's also a JavaScript API, taglib and a collection of plugins to make your job as a front-end web developer easier. Please read on to learn how you can easily utilize Lasso.js in your application.

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

# Table of Contents

- [Design Philosophy](#design-philosophy)
- [Features](#features)
- [Another Client-side Bundler?](#another-client-side-bundler)
- [Installation](#installation)
- [Usage](#usage)
	- [Command Line Interface](#command-line-interface)
	- [JSON Configuration File](#json-configuration-file)
	- [Dependencies](#dependencies)
		- [External Dependencies](#external-dependencies)
		- [Dependency Attributes](#dependency-attributes)
		- [Conditional Dependencies](#conditional-dependencies)
		- [Enabling Flags](#enabling-flags)
	- [Asynchronous/Lazy Loading](#asynchronouslazy-loading)
	- [Using the JavaScript API](#using-the-javascript-api)
		- [Configuring the Default Lasso](#configuring-the-default-lasso)
		- [Optimizing a Page](#optimizing-a-page)
		- [Creating a New Lasso](#creating-a-new-lasso)
	- [Lasso.js Taglib](#lassojs-taglib)
		- [Using Lasso.js Taglib with Marko](#using-lassojs-taglib-with-marko)
		- [`<lasso-img>`](#<lasso-img>)
	- [Client/Server Template Rendering](#clientserver-template-rendering)
	- [Runtime Optimization with Express](#runtime-optimization-with-express)
	- [Bundling](#bundling)
	- [Code Splitting](#code-splitting)
- [Configuration](#configuration)
	- [Default Configuration](#default-configuration)
	- [Complete Configuration](#complete-configuration)
- [Node.js-style Module Support](#nodejs-style-module-support)
- [Babel Support](#babel-support)
- [No Conflict Builds](#no-conflict-builds)
- [Custom attributes for Script & Style tags](#custom-attributes-for-script--style-tags)
    - [Use of defer/async with script tags](#use-of-deferasync-with-script-tags)
- [Content Security Policy Support](#content-security-policy-support)
- [Available Plugins](#available-plugins)
- [Extending Lasso.js](#extending-lassojs)
	- [Custom Plugins](#custom-plugins)
	- [Custom Dependency Types](#custom-dependency-types)
		- [Custom JavaScript Dependency Type](#custom-javascript-dependency-type)
		- [Custom CSS Dependency Type](#custom-css-dependency-type)
		- [Custom Package Type](#custom-package-type)
	- [Custom Output Transforms](#custom-output-transforms)
- [JavaScript API](#javascript-api)
- [AMD Compatibility](#amd-compatibility)
- [Sample Projects](#sample-projects)
- [Discuss](#discuss)
- [Maintainers](#maintainers)
- [Contributors](#contributors)
- [Contribute](#contribute)
- [License](#license)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

# Design Philosophy

* Dependencies should be **declarative** _or_ discovered via **static code analysis**
* Common **module loading** patterns should be supported
* Must be **extensible** to support all types of resources
* **Maximize productivity** in development
* **Maximize performance** in production
* Must be **easy to adopt** and not change how you write your code
* Can be used at **runtime or build time**
* Must be **configurable**

# Features

* Bundle Client-side Dependencies
    * Supports all types of front-end resources (JavaScript, CSS, images, Less, CoffeeScript, etc.)
    * Asynchronous/lazy loading of JS/CSS
    * Configurable resource bundling
    * Code splitting
    * JavaScript minification
    * CSS minification
    * [Fingerprinted](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching) resource URLs
    * Prefix resources with CDN host name
    * Optional Base64 image encoding inside CSS files
    * Custom output transforms
    * Declarative browser-side package dependencies using simple `browser.json` files
	* endencies
	* Image minification
    * etc.
* Browser-side Node.js Module Loader
    * Full support for [Isomorphic JavaScript](http://nerds.airbnb.com/isomorphic-javascript-future-web-apps/)
    * Conflict-free CommonJS module loader for the browser
    * Complete compatibility with Node.js
        * Supports `module.exports`, `exports`, `require`, `require.resolve`, `__dirname`, `__filename`, `process`, etc.
    * Supports the [package.json `browser` field](https://gist.github.com/defunctzombie/4339901)
    * Full support for [browserify](http://browserify.org/) shims and transforms
    * Maintains line numbers in wrapped code
* Developer Friendly
    * Generates the HTML markup required to include bundled resources
    * Disable bundling and minification in development
    * Line numbers are maintained for Node.js modules source
    * Extremely fast _incremental builds_!
        * Only modified bundles are written to disk
        * Disk caches are utilized to avoid repeating the same work
* Dependency Compilation
    * Less
    * [Marko](https://github.com/marko-js/marko)
    * Dust
    * etc.
* Extensible
    * Custom dependency compilers
    * Custom code transforms
    * Custom bundle writers
    * Custom plugins
* Configurable
    * Configurable resource bundles
    * Enable/disable transforms
    * Development-mode versus production-mode
    * Enable/disable fingerprints
    * etc.
* Flexible
    * Integrate with build tools
    * Use with Express or any other web development framework
    * JavaScript API, CLI and taglib
* Security
    * Supports the [nonce attribute](https://www.w3.org/TR/CSP2/#script-src-the-nonce-attribute) when using Content Security Policy for extra security.
* _Future_
    * Automatic image sprites

# Another Client-side Bundler?

[Browserify](http://browserify.org/) is an excellent JavaScript module bundler. We are huge supporters of writing Node.js-style modules (i.e. CommonJS), and we also believe [npm](https://www.npmjs.org/) is an excellent package manager. If you are not using a JavaScript module bundler then you are absolutely missing out. Modularity is equally important for client-side code as it is for server-side code, and a JavaScript module bundler should be part of every front-end developer's toolbox.

So why did we create Lasso.js if Browserify is such a great tool? We created Lasso.js because we wanted a top-notch JavaScript module bundler that _also_ provides first-level support for transporting CSS, "plain" JavaScript, images, fonts and other front-end assets to the browser in the most optimal way. In addition, we want to enable developers to easily create web applications that follow [widely accepted rules for creating faster-loading websites](http://stevesouders.com/examples/rules.php) (such as putting StyleSheets at the top, and JavaScript at the bottom). We also want to allow for developers to easily load additional JavaScript and StyleSheets after the initial page load.

While high performance is very important for production systems, we want to also provide a more developer-friendly experience by offering fast, incremental builds, simplifying development and by producing debuggable output code. And, of course, we do not want developers to have to learn how to code their applications in a new way so Lasso.js was built to not change how you already code. You'll even find support for Browserify shims and transforms. Therefore, if you try out Lasso.js and it is not the tool for you, then feel free to switch back to something else (it'll of course be ready if your application's requirements change in the future). eBay and other large companies rely on Lasso.js for delivering high performance websites and are committed to its success. If you try it out and find gaps, please let us know!

# Installation

The following command should be used to install the `lasso` module into your project:

```bash
npm install lasso --save
```

If you would like to use the available command line interface, then you should install the [lasso-cli](https://github.com/lasso-js/lasso-cli) module globally using the following command:

```bash
npm install lasso-cli --global
```

# Usage

## Command Line Interface

<hr>

[__Sample App:__](https://github.com/lasso-js-samples/lasso-cli) To try out and experiment with the code, please see the following project:<br>[lasso-js-samples/lasso-cli](https://github.com/lasso-js-samples/lasso-cli)

<hr>

Install the command line interface for Lasso.js:

```bash
npm install lasso-cli --global
```

In an empty directory, initialize a new Node.js project using the following command:

```bash
mkdir my-app
cd my-app
npm init
```

Install required modules into the new project:

```bash
npm install jquery
npm install lasso-less
```

Create the following files:

__add.js:__

```javascript
module.exports = function(a, b) {
    return a + b;
};
```

__main.js:__

```javascript
var add = require('./add');
var jquery = require('jquery');

jquery(function() {
    $(document.body).append('2+2=' + add(2, 2));
});
```

__style.less:__

```css
@headerColor: #5B83AD;

h1 {
    color: @headerColor;
}
```

__my-page.html:__

```html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Lasso.js Demo</title>
</head>
<body>
    <h1>Lasso.js Demo</h1>
</body>
</html>
```

Finally, run the following command to generate the resource bundles for the page and to also inject the required `<script>` and `<link>` tags into the HTML page:

```bash
lasso style.less \
    --main main.js \
    --inject-into my-page.html \
    --plugins lasso-less \
    --development
```

If everything worked correctly then you should see output similar to the following:

```text
Output for page "my-page":
  Resource bundle files:
    static/add.js
    static/raptor-modules-meta.js
    static/main.js
    static/node_modules/jquery/dist/jquery.js
    static/raptor-modules-1.0.1/client/lib/raptor-modules-client.js
    static/style.less.css
  HTML slots file:
    build/my-page.html.json
  Updated HTML file:
    my-page.html
```

The updated `my-page.html` file should be similar to the following:

```html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Lasso.js Demo</title>
    <!-- <lasso-head> -->
    <link rel="stylesheet" href="static/style.less.css">
    <!-- </lasso-head> -->
</head>
<body>
    <h1>Lasso.js Demo</h1>
    <!-- <lasso-body> -->
    <script src="static/raptor-modules-1.0.1/client/lib/raptor-modules-client.js"></script>
    <script src="static/add.js"></script>
    <script src="static/raptor-modules-meta.js"></script>
    <script src="static/node_modules/jquery/dist/jquery.js"></script>
    <script src="static/main.js"></script>
    <script>$_mod.ready();</script>
    <!-- </lasso-body> -->
</body>
</html>
```

If you open up `my-page.html` in your web browser you should see a page styled with Less and the output of running `main.js`.

Now try again with `production` mode:

```bash
lasso style.less \
    --main main.js \
    --inject-into my-page.html \
    --plugins lasso-less \
    --production
```

```
Output for page "my-page":
  Resource bundle files:
    static/my-page-2e3e9936.js
    static/my-page-169ab5d9.css
  HTML slots file:
    build/my-page.html.json
  Updated HTML file:
    my-page.html
```

The updated `my-page.html` file should be similar to the following:

```html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Lasso.js Demo</title>
    <!-- <lasso-head> -->
    <link rel="stylesheet" href="static/my-page-169ab5d9.css">
    <!-- </lasso-head> -->
</head>
<body>
    <h1>Lasso.js Demo</h1>
    <!-- <lasso-body> -->
    <script src="static/my-page-2e3e9936.js"></script>
    <script>$_mod.ready();</script>
    <!-- </lasso-body> -->
</body>
</html>
```

With the `--production` option enabled, all of the resources are concatenated together, minified and fingerprinted – perfect for high performance web applications running in production.

For more documentation on the Command Line Interface please see the [lasso-cli docs](https://github.com/lasso-js/lasso-cli).

## JSON Configuration File

<hr>

[__Sample App__](https://github.com/lasso-js-samples/lasso-config) To try out and experiment with the code, please see the following project:<br>[lasso-js-samples/lasso-config](https://github.com/lasso-js-samples/lasso-config)

<hr>

The number of command line arguments can get unwieldy so it is better to split out configuration into a separate JSON file. Let's now create a configuration file and configure a few bundles to make things more interesting:

__lasso-config.json:__

```json
{

    "plugins": [
        "lasso-less"
    ],
    "outputDir": "static",
	"fingerprintsEnabled": true,
    "minify": true,
    "resolveCssUrls": true,
    "bundlingEnabled": true,
    "bundles": [
        {
            "name": "jquery",
            "dependencies": [
                "require: jquery"
            ]
        },
        {
            "name": "math",
            "dependencies": [
                "require: ./add"
            ]
        }
    ]
}
```

In addition, let's put our page dependencies in their own JSON file:

__my-page.browser.json:__

```json
{
    "dependencies": [
        "./style.less",
        "require-run: ./main"
    ]
}
```

Now run the page lasso using the newly created JSON config file and JSON dependencies file:

```bash
lasso ./my-page.browser.json \
    --inject-into my-page.html \
    --config lasso-config.json
```

Because of the newly configured bundles, we'll see additional JavaScript bundles written to disk as shown below:

```
Output for page "my-page":
  Resource bundle files:
    static/math-169c956d.js
    static/jquery-24db89d9.js
    static/my-page-beed0921.js
    static/my-page-169ab5d9.css
  HTML slots file:
    build/my-page.html.json
  Updated HTML file:
    my-page.html
```

## Dependencies

Lasso.js walks a dependency graph to find all of the resources that need to be bundled. A dependency can either be a JavaScript or CSS resource (or a file that compiles to either JavaScript or CSS) or a dependency can be a reference to a set of transitive dependencies. Some dependencies are inferred from scanning source code and other dependencies can be made explicit by listing them out in the code of JavaScript modules or in separate `browser.json` files.

It's also possible to register your own [custom dependency types](#custom-dependency-types). With custom dependency types, you can control how resources are compiled or a custom dependency type can be used to resolve additional dependencies during optimization.

Browser dependencies can be described as shown in the following sample `browser.json` file:

```json
{
    "dependencies": [
        "./style.less",
        "../third-party/jquery.js",
        "**/*.css",
        {
            "type": "js",
            "url": "https://code.jquery.com/jquery-2.1.4.min.js"
        },
        {
            "type": "css",
            "url": "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"
        }
    ]
}
```

Alternatively, dependencies can be "required" inside a JavaScript module as shown in the following sample JavaScript code:

```javascript
require('./style.less');

// ...
```

The only caveat to using a `require()` call to add a non-JavaScript module dependency is that by default Node.js will try to load the required file as a JavaScript module if the code runs on the server. To prevent Node.js from trying to load a Less file or other non-JavaScript files as JavaScript modules you can add the following code to your main script:

```javascript
require('lasso/node-require-no-op').enable('.less', '.css');
```


For simple paths, the dependency type is inferred from the filename extension. Alternatively, the dependency type can be made explicit using either one of the following formats:

```json
[
    "./style.less",
    "less: ./style.less",
    { "type": "less", "path": "./style.less" }
]
```

_NOTE: all of the above are equivalent_

You can also create a dependency that references dependencies in a separate `browser.json` file. Dependencies that have the `browser.json` extension are automatically resolved using the require resolver if they are not relative paths. For example:
```js
[
    // Relative path:
    "./some-module/browser.json",

    // Look for "my-module/browser.json" in "node_modules":
    "my-module/browser.json"
]
```

If the path does not have a file extension then it is assumed to be a path to an `browser.json` file so the following short-hand works as well:
```js
[
    "./some-module"
    "my-module"
]
```
If you use the short-hand notation for `browser.json` dependencies, the paths will still be resolved using the require resolver as long as they are not relative paths.

### External Dependencies

Lasso.js does allow referencing external JS/CSS files in your `browser.json` files as shown below:

```json
{
    "dependencies": [
        {
            "type": "js",
            "url": "https://code.jquery.com/jquery-2.1.4.min.js"
        },
        {
            "type": "css",
            "url": "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"
        }
    ]
}
```

By default, Lasso.js will not bundle external resources with your application's JavaScript and CSS bundles. If you would prefer for an external resource to be downloaded from the remote server and bundled with your other application code during the lassoing then you can set the `external` property to `false` as shown below (`external` defaults to `true`):

```json
{
    "dependencies": [
        {
            "type": "js",
            "url": "https://code.jquery.com/jquery-2.1.4.min.js",
            "external": false
        }
    ]
}
```

Setting `external` to `false` in the above example will result in jQuery being downloaded from the CDN and bundled with all of the other JS code for the app. That is, the code for jQuery will not be served up by the jQuery CDN.

### Dependency Attributes

Adding an `attributes` object to a dependency definition will result in those attributes being defined on the html tag for that dependency.  For bundled dependencies, these attributes will be merged with latter dependencies taking priority.

The following is an example using the `integrity` and `crossorigin` attributes for [Subresource Integrity (SRI) checking](https://www.w3.org/TR/SRI/). This allows browsers to ensure that resources hosted on third-party servers have not been tampered with. Use of SRI is recommended as a best-practice, whenever libraries are loaded from a third-party source.

```json
{
    "dependencies": [{
        "type": "js",
        "url": "https://code.jquery.com/jquery-3.1.1.min.js",
        "attributes":{
            "integrity":"sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=",
            "crossorigin":"anonymous"
        }
    }]
}
```

**Generated Output:**
```html
<script
  src="https://code.jquery.com/jquery-3.1.1.min.js"
  integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8="
  crossorigin="anonymous"></script>
```

### Conditional Dependencies

Lasso.js supports conditional dependencies. Conditional dependencies is a powerful feature that allows for a page to be built differently based on certain flags (e.g. "mobile device" versus "desktop"). For caching reasons, the flags for conditional dependencies should be based on a set of enabled flag. A flag is just an arbitrary name that can be enabled/disabled before optimizing a page. For example, to make a dependency conditional such that is only included for mobile devices you can do the following:

```json
{
    "dependencies": [
        { "path": "./hello-mobile.js", "if-flag": "mobile" }
    ]
}
```

Alternatively, you can also include the desktop version of a file if the "mobile" extension is not enabled using `if-not-flag`.
```json
{
    "dependencies": [
        { "path": "./hello-desktop.js", "if-not-flag": "mobile" }
    ]
}
```

If needed, a JavaScript expression can be used to describe a more complex condition as shown in the following sample code:

```json
{
    "dependencies": [
        {
            "path": "./hello-mobile.js",
            "if": "flags.contains('phone') || flags.contains('tablet')"
        }
    ]
}
```

Finally, if you prefer, you can group your conditional dependencies if needed:

```json
{
    "dependencies": [
        {
            "if-flag": "mobile",
            "dependencies": [
                "./style-mobile.css",
                "./client-mobile.js"
            ]
        }
    ]
}
```

### Enabling Flags

The code below shows how to enable flags when optimizing a page:

__Using the JavaScript API:__

```javascript
myLasso.lassoPage({
    dependencies: [
        { path: './hello-mobile.js', 'if-flag': 'mobile' }
    ],
    flags: ['mobile', 'foo', 'bar']
})
```

__Using the Marko taglib:__

```marko
<lasso-page ... flags=['mobile', 'foo', 'bar']>
    ...
</lasso-page>
```

## Asynchronous/Lazy Loading

<hr>

[__Sample App__](https://github.com/lasso-js-samples/lasso-async)To try out and experiment with the code, please see the following project:<br>[lasso-js-samples/lasso-async](https://github.com/lasso-js-samples/lasso-async)

<hr>


Lasso.js supports asynchronously loading dependencies using the lightweight [lasso-loader](https://github.com/lasso-js/lasso-loader) module as shown in the following sample code:

```javascript
var lassoLoader = require('lasso-loader');

lassoLoader.async(function(err) {
    // Any modules that are required within the scope
    // of this function will be loaded asynchronously*.
    // Lasso.js ensures that modules are only
    // loaded once from the server.
    //
    // *Modules that were included as part of the initial
    // page load will automatically be de-duped.

    if (err) {
        // Handle the case where one or more of the
        // dependencies failed to load.
    }

    var add = require('./add');
    var jquery = require('jquery');

    jquery(function() {
        $(document.body).append('2+2=' + add(2, 2));
    });
});
```

During optimization, Lasso.js detects the call to `require('lasso-loader').async(...)` and transforms the code such that the function is not invoked until all of the required modules referenced in the body of callback function are completely loaded.

You can also specify additional explicit dependencies if necessary:

```javascript
require('lasso-loader').async(
    [
        './style.less',
        'some/other/browser.json'
    ],
    function() {
        // All of the requires nested in this function block will be lazily loaded.
        // When all of the required resources are loaded then the function will be invoked.
        var foo = require('foo');
        var bar = require('bar');
    });
```

You can also choose to declare async dependencies in an `browser.json` file:

```json
{
    "dependencies": [
        ...
    ],
    "async": {
        "my-module/lazy": [
            "require: foo",
            "require: bar",
            "./style.less",
            "some/other/browser.json"
        ]
    }
}
```

The async dependencies can then be referenced in code:
```javascript
require('lasso-loader').async(
    'my-module/lazy',
    function() {
        var foo = require('foo');
        var bar = require('bar');
    });
```

## Using the JavaScript API

<hr>

[__Sample App__](https://github.com/lasso-js-samples/lasso-js-api) To try out and experiment with the code, please see the following project:<br>[lasso-js-samples/lasso-js-api](https://github.com/lasso-js-samples/lasso-js-api)

<hr>

For added flexibility there is a JavaScript API that can be used to lasso pages as shown in the following sample code:

```javascript
var lasso = require('lasso');
lasso.configure('lasso-config.json');
lasso.lassoPage({
        name: 'my-page',
        dependencies: [
            "./style.less",
            "require-run: ./main"
        ]
    },
    function(err, lassoPageResult) {
        if (err) {
            // Handle the error
        }

        var headHtml = lassoPageResult.getHeadHtml();
        // headHtml will contain something similar to the following:
        // <link rel="stylesheet" href="static/my-page-169ab5d9.css">

        var bodyHtml = lassoPageResult.getBodyHtml();
        // bodyHtml will contain something similar to the following:
        //  <script src="static/my-page-2e3e9936.js"></script>
    });
```

The `lassoPage(options)` method supports the following options:

- `data` (`Object`) - Arbitrary data that can be made available to plugins via `lassoContext.data`.
- `cacheKey` (`String`) - A unique String to use for cache reads and writes. Defaults to `name`.
- `dependencies` (`Array`) - An array of top-level page dependencies (e.g. `['foo.js', 'foo.css', 'require: jquery']`).
- `flags` (`Array`) - The set of enabled flags (e.g. `['mobile', 'touch']`).
- `from` (`String`) - The base path for resolving relative paths for top-level dependencies.
- `name` (`String`) - The page name. Used for determining the names of the output JS/CSS bundles.
- `packagePath` (`String`) - The path to an `browser.json` file that describes the top-level dependencies.

### Configuring the Default Lasso
```javascript
var lasso = require('lasso');
lasso.configure(config);
```

If the value of the `config` argument is a `String` then it is treated as a path to a JSON configuration file.


### Optimizing a Page

The following code illustrates how to lasso a simple set of JavaScript and CSS dependencies using the default configured lasso:

```javascript
var lasso = require('lasso');
lasso.lassoPage({
        name: 'my-page',
        dependencies: [
            './foo.js',
            './bar.js',
            './baz.js',
            './qux.css'
        ]
    },
    function(err, lassoPageResult) {
        if (err) {
            console.log('Failed to lasso page: ', err);
            return;
        }

        var headHtml = lassoPageResult.getHeadHtml();
        /*
        String with a value similar to the following:
        <link rel="stylesheet" href="/static/my-page-85e3288e.css">
        */

        var bodyHtml = lassoPageResult.getBodyHtml();
        /*
        String with a value similar to the following:
        <script src="/static/bundle1-6df28666.js"></script>
        <script src="/static/bundle2-132d1091.js"></script>
        <script src="/static/my-page-1de22b65.js"></script>
        */

        // Inject the generated HTML into the <head> and <body> sections of a page...
    });
```

### Creating a New Lasso

```javascript
var myLasso = lasso.create(config);
myLasso.lassoPage(...);
```


## Lasso.js Taglib

<hr>

[__Sample App__](https://github.com/lasso-js-samples/lasso-taglib) To try out and experiment with the code, please see the following project:<br>[lasso-js-samples/lasso-taglib](https://github.com/lasso-js-samples/lasso-taglib)

<hr>

For the ultimate in usability, a taglib is provided for Marko (and Dust) to automatically lasso a page _and_ inject the required HTML markup to include the JavaScript and CSS bundles.

If you are using [Marko](https://github.com/marko-js/marko) you can utilize the available taglib for Lasso.js to easily lasso page dependencies and embed them into your page.

### Using Lasso.js Taglib with Marko

1. `npm install lasso --save`
2. `npm install marko --save`

You can now add the lasso tags to your page templates. For example:

```marko
<lasso-page package-path="./browser.json"/>

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test Page</title>
    <lasso-head/>
</head>
<body>
    <h1>Test Page</h1>
    <lasso-body/>
</body>
</html>
```

You will then need to create an `browser.json` in the same directory as your page template. For example:

_browser.json_:
```json
{
    "dependencies": [
        "./jquery.js",
        "./foo.js",
        "./bar.js",
        "./style.less"
    ]
}
```

Using Marko and Lasso.js taglib, you can simply render the page using code similar to the following:

```javascript
var template = require('marko').load('my-page.marko');
template.render({}, function(err, html) {
    // html will include all of the required <link> and <script> tags
});
```

The output of the page rendering will be similar to the following:

```html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test Page</title>
    <link rel="stylesheet" href="/static/my-page-85e3288e.css">
</head>
<body>
    <h1>Test Page</h1>
    <script src="/static/bundle1-6df28666.js"></script>
    <script src="/static/bundle2-132d1091.js"></script>
    <script src="/static/my-page-1de22b65.js"></script>
</body>
</html>
```

The lasso result is cached so you can skip the build step!

You can also configure the default page lasso used by the lasso tags:

```javascript
require('lasso').configure({...});
```

For more details, please see following documentation: [Lasso.js Taglib for Marko](taglib-marko.md)

<a name="<lasso-img"></a>

### `<lasso-img>`

The `<lasso-img>` tag can be used to render `<img>` tags while also having the image referenced by the `src` attribute automatically go through the Lasso.js asset pipeline. In addition, if the `width` and `height` attributes are not specified then those attributes will automatically be added. This tag can be rendered on both the server and in the browser.

Example:

```marko
<lasso-img src="./foo.jpg"/>
```

This might produce the following HTML output depending on how Lasso.js is configured:

```html
<img src="/static/foo-25b047cc.jpg" width="100" height="100">
```

## Client/Server Template Rendering

<hr>

[__Sample App__](https://github.com/lasso-js-samples/lasso-templates) To try out and experiment with the code, please see the following project:<br>[lasso-js-samples/lasso-templates](https://github.com/lasso-js-samples/lasso-templates)

<hr>

To demonstrate rendering of the same template on the server and the client we will start with the following Marko template:

__template.marko__

```marko
-- Hello ${data.name}!
```

_NOTE: The sample app includes sample code that illustrates how to also render both a Dust template and a Handlebars template on both the client and server._

We will then create a `main.js` file to render the template to the console:

__main.js:__

```javascript
var template = require('marko')
    .load(require.resolve('./template.marko'));

template.render(
    {
        name: 'Frank'
    },
    function(err, html) {
        console.log('Template output: ' + html);
    });
```

_NOTE: The reason we use `require.resolve('./template.marko')` instead of `require('template.marko')` is that Node.js does not understand how to load `.marko` modules and the use of the `require.extensions` has been [deprecated](http://nodejs.org/api/globals.html#globals_require_extensions). `require.resolve()` is used to get the resolved path for the template and the [marko](https://github.com/marko-js/marko) module uses that path to load template into memory._

Running `node main.js` on the server will produce the following output in the console:

```html
Template output: Hello Frank!
```

In order to automatically detect and compile required `*.marko` templates we
will need to install the [lasso-marko](https://github.com/lasso-js/lasso-marko)
plugin and [@lasso/marko-taglib](https://github.com/lasso-js/lasso-marko-taglib)
taglib using the following commands:

```bash
npm install lasso-marko
npm install @lasso/marko-taglib
```

We can then lasso the page using the following command:

```bash
lasso style.less \
    --main main.js \
    --inject-into my-page.html \
    --plugins lasso-marko
```

After opening `my-page.html` in your web browser you should then see the same output written to the browser's JavaScript console.

## Middleware for Express and Koa

Lasso includes optional middleware for both Express and Koa that can be used to serve up the static files that it generates.

### `serveStatic(options)`

The `serveStatic` middleware provided by Lasso is a small wrapper around the [send](https://github.com/pillarjs/send) package.

Supported options:

- __lasso__ - The configured lasso instance (defaults to `require('lasso').getDefaultLasso()`)
- __sendOptions__ - Pass through options for the `send` module. See [send » options](https://github.com/pillarjs/send#optionsd)

### Using `serveStatic` with Express

```javascript
app.use(require('lasso/middleware').serveStatic(options));
```

### Using `serveStatic` with Koa

```javascript
app.use(require('lasso/middleware/koa').serveStatic(options));
```

## Runtime Optimization with Express and Koa

<hr>

[__Sample App__](https://github.com/lasso-js-samples/lasso-express) To try out and experiment with the code, please see the following project:<br>[lasso-js-samples/lasso-express](https://github.com/lasso-js-samples/lasso-express)

<hr>

Lasso.js has a smart caching layer and is fast enough so that it can be used at runtime as part of your server application. The easiest way to use Lasso.js at runtime is to use the Marko taglib and simply render the page template to the response output stream.

The first time the page renders, the page will be lassoed and cached and the output of the lasso will be used to produce the final page HTML. After the first page rendering, the only work that will be done by Lasso.js is a simple cache lookup.

By default, Lasso.js writes all resource bundles into the `static/` directory at the root of your application. In addition, by default, all resource URLs will be prefixed with `/static`. If resources are to be served up by the local Express server we will need to register the appropriate middleware as shown in the following sample code:

__server.js__

```javascript
require('marko/node-require');
require('marko/express');

var express = require('express');
var compression = require('compression');
var serveStatic = require('serve-static');

// Load the page template:
var template = require('./template.marko');

// Configure the default lasso
require('lasso').configure({

});

var app = express();

// Enable gzip compression for all HTTP responses:
app.use(compression());

// Any URL that begins with "/static" will be served up
// out of the "static/" directory:
app.use(require('lasso/middleware').serveStatic());

app.get('/', function(req, res) {
    // Render the page template as normal:
    res.marko(template, {
            name: 'Frank'
        });
});
...

app.listen(8080);
```

## Bundling

By default, all dependencies required for a page will be bundled into a single JavaScript bundle and a single CSS bundle. However, Lasso.js allows application-level bundles to be configured to allow for consistent bundles across pages and for multiple bundles to be included on a single page. Because Lasso.js also generates the HTML markup to include page bundles, the page itself does not need to be changed if the bundle configuration is changed.

If a page has a dependency that is part of an application-level bundle then the dependency will be included as part of the application-level bundle instead of being aggregated with the page-level bundle.

Bundles can be configured using the `"bundles"` configuration property that accepts an array of bundle configurations. Each bundle should consist of a name and a set of dependencies to assign to that bundle.

__Bundling Example:__

Given the following configured bundles:

```json
{
    ...
    "bundles": [
        {
            "name": "bundle1",
            "dependencies": [
                "./foo.js",
                "./baz.js"
            ]
        },
        {
            "name": "bundle2",
            "dependencies": [
                "./bar.js"
            ]
        }
    ]
}
```


Optimizing a page that does not include any dependencies in application-level bundles:

```bash
lasso app.js style.css --name my-page -c lasso-config.json
```

Output:

```
Output for page "my-page":
  Resource bundle files:
    static/my-page.js
    static/my-page.css
  HTML slots file:
    build/my-page.html.json
```


Optimizing a page that includes "foo.js" that is part of "bundle1":
```bash
lasso app.js foo.js style.css --name my-page -c lasso-config.json
```

Output:

```
Output for page "my-page":
  Resource bundle files:
    static/my-page.js
    static/bundle1.js
    static/my-page.css
  HTML slots file:
    build/my-page.html.json
```

For more information on working with bundles. Please see the [bundling docs](docs/bundling.md).

## Code Splitting

<hr>

[__Sample App__](https://github.com/lasso-js-samples/lasso-code-splitting) To try out and experiment with the code, please see the following project:<br>[lasso-js-samples/lasso-code-splitting](https://github.com/lasso-js-samples/lasso-code-splitting)

<hr>

Lasso.js supports splitting out code that multiple pages/entry points have in common into separate bundles. This is accomplished by assigning an `intersection` dependency to a bundle. The `intersection` dependency is a package dependency that produces a set of dependencies that is the intersection of one or more packages. Code splitting ensures that the same code is not downloaded twice by the user when navigating a web application.

The following bundle configuration illustrates how to split out common code into a separate bundle:

```json
{
    "bundles": [
        {
            "name": "common",
            "dependencies": [
                {
                    "intersection": [
                        "./src/pages/home/browser.json",
                        "./src/pages/profile/browser.json"
                    ]
                }
            ]
        }
    ]
}
```
A less strict intersection condition is also supported via a `threshold` property.

For example, to find those dependencies that are among *at least two* of the widgets:
```json
{
    "bundles": [
        {
            "name": "common",
            "dependencies": [
                {
                    "threshold": 2,
                    "intersection": [
                        "require: ./a/widget",
                        "require: ./b/widget",
                        "require: ./c/widget"
                    ]
                }
            ]
        }
    ]
}
```

This could also be expressed as a percentage:
```json
{
    "bundles": [
        {
            "name": "common",
            "dependencies": [
                {
                    "threshold": "66%",
                    "intersection": [
                        "require: ./a/widget",
                        "require: ./b/widget",
                        "require: ./c/widget"
                    ]
                }
            ]
        }
    ]
}
```

# Configuration

## Default Configuration
```javascript
{
    // Write all bundles into the "static" directory
    "outputDir": "static",

    // URL prefix for all bundles
    "urlPrefix": "/static",

    // Include fingerprint in output files
    "fingerprintsEnabled": true
}
```

## Complete Configuration

```javascript
{
    // Configure Lasso.js plugins
    "plugins": [
        // Plugin with a default config:
        "lasso-less",
        // Plugin with custom configuration:
        {
            "plugin": "lasso-my-plugin",
            "config": { ... }
        },
        ...
    ],
    // The base output directory for generated bundles
	"outputDir": "static",

	// Optional URL prefix to prepend to relative bundle paths
	"urlPrefix": "http://mycdn/static",

	// If fingerprints are enabled then a shasum will be included in the URL.
	// This feature is used for cache busting.
	"fingerprintsEnabled": true,

	// If fingerprints are not enabled then the same output file would be
	// used for bundles that go into the head and bundles that go in the
	// body. Enabling this option will ensure that bundles have unique names
	// even if fingerprints are disabled.
	"includeSlotNames": false

    // If "minify" is set to true then output CSS and JavaScript will run
    // through a minification transform. (defaults to false)
    "minify": false,

    "minifyJS": false, // Minify JavaScript

    "minifyCSS": false, // Minify CSS

    "minifyInlineOnly": false, // Only minify inline resources

    "minifyInlineJSOnly": false, // Only minify inline JavaScript resources

    "minifyInlineCSSOnly": false, // Only minify inline CSS resources

    // If "resolveCssUrls" is set to true then URLs found in CSS files will be
    // resolved and the original URLs will be replaced with the resolved URLs.
    // (defaults to true)
    "resolveCssUrls": true,

    // If "relativeUrlsEnabled" is set to false then URLs found in CSS files will
    // be absolute based on the urlPrefix. This default is false, which creates
    // relative URLs in CSS files.
    "relativeUrlsEnabled": true,

    // If "bundlingEnabled" is set to true then dependencies will be concatenated
    // together into one or more bundles. If set to false then each dependency
    // will be written to a separate file. (defaults to true)
    "bundlingEnabled": true,

    // If you want consistent bundles across pages then those shared bundles
    // can be specified below. If a page dependency is part of a shared
    // bundle then the shared bundle will be added to the page (instead of
    // adding the dependency to the page bundle).
    "bundles": [
        {
            // Name of the bundle (used for determining the output filename)
            "name": "bundle1",

            // Set of dependencies to add to the bundle
            "dependencies": [
                "./foo.js",
                "./baz.js"
            ]
        },
        {
            "name": "bundle2",
            "dependencies": [
                "./style/*.css",
                "require: **/*.js"
            ]
        }
    ],

    // The default name of the modules runtime variable is
    // ""$_mod" but you can change that with the noConflict option.
    // This is necessary if you have a webpage that loads
    // multiple JavaScript bundles that were
    // built at different times with Lasso.
    // The string you provide will be used to create
    // a unique name for the modules runtime variable name by
    // removing or replacing illegal characters.
    "noConflict": "myapp"
}
```

# Node.js-style Module Support

Lasso.js provides full support for transporting Node.js modules to the browser. If you write your modules in the standard Node.js way (i.e. using `require`, `module.exports` and `exports`) then the module will be able to be loaded on both the server and in the browser.

This functionality is offered by the core [lasso-require](https://github.com/lasso-js/lasso-require) plugin which introduces a new `require` dependency type. For example:

```json
[
    "require: ./path-to-some-module"
]
```

If you want to include a module and have it run when loaded (i.e. self-executing) then you should use the `require-run` dependency type:

```json
[
    "require-run: ./main"
]
```

Examples of conditional requires:

```json
[
    {
        "require-run": "./foo",
        "if-flag": "bar"
    },
    {
        "require": "./foo",
        "if-flag": "bar"
    }
]
```

It's also possible to remap a require based on a flag:

```json
{
    "dependencies": [
        ...
    ],
    "requireRemap": [
        {
            "from": "./foo.js",
            "to": "./foo-mobile.js",
            "if-flag": "mobile"
        }
    ]
}
```

The [lasso-require](https://github.com/lasso-js/lasso-require) plugin will automatically scan the source to find all `require(path)` calls to determine which additional modules need to be included in the output bundles (done recursively). For a `require` to automatically be detected it must be in the form `require("<module-name>")` or `require.resolve("<module-name>")`.

The [lasso-require](https://github.com/lasso-js/lasso-require) plugin will automatically wrap all Node.js modules so that the psuedo globals (i.e. `require`, `module`, `exports`, `__filename` and `__dirname`) are made available to the module source code.

The `lasso-require` plugin also supports [browserify shims](https://github.com/substack/node-browserify#compatibility) and [browserify transforms](https://github.com/substack/node-browserify/wiki/list-of-transforms).

For more details on how the Node.js modules are supported on the browser, please see the documentation for the [lasso-js-samples/lasso-require](https://github.com/lasso-js/lasso-require) plugin.

# Babel Support

The [lasso-babel-transform](https://github.com/lasso-js/lasso-babel-transform) module provides support for transpiling JavaScript/JSX code using [babel](https://babeljs.io/). Please see the [lasso-babel-transform](https://github.com/lasso-js/lasso-babel-transform) docs for information on how to use that transform.

# No Conflict Builds

If you're using CommonJS modules in your project then this will cause the
CommonJS runtime to be included in your build. The CommonJS runtime utilizes
a global variable (`$_mod` by default). If your build output files need to
co-exist with other JavaScript files that were built by Lasso separately
then you need to make sure that your build produces a CommonJS runtime
that is isolated from other builds. That is, you should not use the default
`$_mod` global.

To enable no-conflict build, you need to configure Lasso to use a unique
CommonJS runtime global name. This can be done by setting the `noConflict`
configuration property to string that is unique to your application or project.

If you're using the JavaScript API then this is possible via:

```javascript
// To configure the default Lasso for no-conflict builds:
require('lasso').configure({
    ...
    noConflict: 'myapp'
});

// To create a new Lasso for no-conflict builds
require('lasso').create({
    ...
    noConflict: 'myapp'
});

```

See [Configuration](#configuration) for full list of configuration options.

# Custom attributes for Script & Style tags
It is also possible to add custom attributes to script and style tags for both inline and external resources. It is done using the attributes `inline-script-attrs`, `inline-style-attrs`, `external-style-attrs` and `external-script-attrs` as shown below.

__page.marko__
```marko
<lasso-page name="page" package-path="./browser.json"/>

<html>
    <head>
        <lasso-head external-style-attrs={'css-custom1': true}/>
        <lasso-slot name="ext-css-slot" external-style-attrs={'css-custom2': true}/>
        <lasso-slot name="css-slot" inline-style-attrs={'css-custom3': true}/>
    </head>
    <body>
        <lasso-body external-script-attrs={'js-custom1': true}/>
        <lasso-slot name="ext-js-slot" external-script-attrs={'js-custom2': true}/>
        <lasso-slot name="js-slot" inline-script-attrs={'js-custom3': true}/>
    </body>
</html>

```
__browser.json__
```json
{
    "dependencies": [
        { "path": "style-ext.css", "slot": "ext-css-slot" },
        { "path": "test-ext.js", "slot": "ext-js-slot" },
        "style.css",
        "test.js",
        { "path": "style-inline.css", "inline": true, "slot": "css-slot" },
        { "path": "test-inline.js", "inline": true, "slot": "js-slot" }
    ]
}
```
__Output HTML__
```html
<html>
    <head>
        <link rel="stylesheet" href="/static/page-1ae3e9bf.css" css-custom1>
        <link rel="stylesheet" href="/static/page-244694d6.css" css-custom2>
        <style css-custom3>
            body .inline {
    	        background-color: red;
	    }
	</style>
    </head>
    <body>
        <script src="/static/page-ce0ad224.js" js-custom1></script>
        <script src="/static/page-c3a331b0.js" js-custom2></script>
        <script js-custom3>
            console.log('hello-inline');
        </script>
    </body>
</html>
```

## Use of defer/async with script tags

If you add `async` or `defer` to a slot for external script attrs and Lasso encounters an inline script in that slot, it will wrap the code in a listener for `DOMContentLoaded` (for defer) or `load` (for async) to ensure that the script does not execute until the rest of the deferred scripts in that slot are loaded.

__page.marko__
```marko
<lasso-page name="page" package-path="./browser.json"/>

<html>
    <body>
        <lasso-body external-script-attrs={defer: true}/>
    </body>
</html>

```

__browser.json__
```json
{
    "dependencies": [
        "test.js",
        { "path": "test-inline.js", "inline": true }
    ]
}
```

__Output HTML__
```html
<html>
    <body>
        <script src="/static/page-ce0ad224.js" defer></script>
        <script>
            (function() { var run = function() { console.log('hello-inline'); }; if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", run); } else { run(); } })();
        </script>
    </body>
</html>
```

# Content Security Policy Support

Newer browsers support a web standard called Content Security Policy that
prevents, among other things, cross-site scripting attacks by whitelisting
inline `<script>` and `<style>` tags (see
[HTML5 Rocks: An Introduction to Content Security Policy](http://www.html5rocks.com/en/tutorials/security/content-security-policy/)).

## Securing Dynamically Built Pages
The Lasso.js taglib for Marko is used to inject the `<script>` and `<style>`
tags into the HTML output and Lasso.js provides support for injecting a nonce
attribute. When Lasso.js is configured you just need to register a
`cspNonceProvider` as shown below:

```javascript
require('lasso').configure({
    cspNonceProvider: function(out) {
        // Logic for determining the nonce will vary, but the following is one option:
        var res = out.stream;
        var nonce = res.csp && res.csp.nonce;

        // NOTE:
        // The code above assumes that there is some middleware that
        // stores the nonce into a [non-standard] `res.csp.nonce` variable.
        // Use whatever is appropriate for your app.
        return nonce; // A string value
    }
});
```

A Lasso.js plugin can also be used to register the CSP nonce provider as shown below:

```javascript
module.exports = function(lasso, pluginConfig) {
    lasso.setCSPNonceProvider(function(out) {
        return 'abc123';
    })
};
```

Registering a `cspNonceProvider` will result in a `nonce` attribute being added to all inline `<script>` and `<style>` tags rendered in either the `head` slot (`<lasso-head/>`) or the `body` slot (`<lasso-body/>`).


With a CSP nonce enable, the HTML output for a page rendered using Marko might be similar to the following:

```html
<html>
    <head>
        <!-- BEGIN head slot: -->
        <link rel="stylesheet" type="text/css" href="/static/page1-8b866529.css">
        <style type="text/css" nonce="abc123">
            body .inline {
                background-color: red;
            }
        </style>
        <!-- END head slot -->
    </head>
    <body>
        <!-- BEGIN body slot: -->
        <script type="text/javascript" src="/static/page1-1097e0f6.js"></script>
        <script type="text/javascript" nonce="abc123">
            console.log('hello-inline');
        </script>
        <!-- END body slot -->
    </body>
</html>
```

NOTE: A `nonce` attribute is only added to inline `<script>` and `<style>` tags.

As an extra convenience, Lasso.js also supports a custom `lasso-nonce`
attribute that can be dropped onto any HTML tag in your Marko template
files as shown below:

```xml
<script type="text/javascript" lasso-nonce>console.log('My inline script')</script>
<style type="text/css" lasso-nonce>.my-inline-style { }</style>
```

The output HTML will be similar to the following:

```html
<script type="text/javascript" nonce="abc123">console.log('My inline script')</script>
<style type="text/css" nonce="abc123">.my-inline-style { }</style>
```

## Securing Statically Built Pages

If your page is statically built (such as when creating a Single Page App)
then you should enable inline code fingerprinting which is way to whitelist
exactly which inline code blocks should be allowed. It is important to
emphasize, that a _nonce_ ("number once") will not properly secure a
statically built application since the HTML is built once which prevents
the nonce from changing. To secure your statically built application,
you should instead fingerprint all of the inline code blocks and include
these fingerprints in your CSP.

Here is an example of what CSP might look like if using SHA256 fingerprints:
`script-src 'self' 'sha256-viOn97JiWZ/fvh2VGIpROjZabjdtdrgtfO1wlPz9w7w='`

```javascript
require('lasso').configure({
    /* typical configuration goes here */

    // Configure Lasso with a function that will be called for fingerprinting
    // each inline code block...
    fingerprintInlineCode: function(code) {
        var shasum = crypto.createHash('sha256');
        shasum.update(code);
        return shasum.digest('base64');
    }
});

// This is the full list of fingerprints that were captured
// across all page builds
var inlineCodeFingerprints = [];

// Collect all of the fingerprints as each page is built
require('lasso').getDefaultLasso().on('afterLassoPage', function(event) {
    var lassoPageResult = event.result;
    var fingerprints = lassoPageResult.getInlineCodeFingerprints();
    fingerprints.forEach(function(fingerprint) {
        inlineCodeFingerprints.push(fingerprint);
    });
})

// NOW BUILD YOUR PAGES HERE
// ... build code goes here ...

// NOW BUILD YOUR CONTENT SECURITY POLICY:
var csp = inlineCodeFingerprints.map(function(fingerprint) {
    return `script-src 'self' 'sha256-${fingerprint}'`
}).join('; ');

```

# Available Plugins

Below is a list of plugins that are currently available:

__Core plugins:__

* [lasso-require](https://github.com/lasso-js/lasso-require): Node.js-style require for the browser (similar to [browserify](https://github.com/substack/node-browserify))
* [lasso-minify-css](https://github.com/lasso-js/lasso-minify-css): Minify CSS files using [sqwish](https://github.com/ded/sqwish)
* [lasso-minify-js](https://github.com/lasso-js/lasso-minify-js): Minify JavaScript files using [terser](https://github.com/terser-js/terser)
* [lasso-resolve-css-urls](https://github.com/lasso-js/lasso-resolve-css-urls): Replace each resource URL in a CSS file with an lassoed resource URL

__Third-party plugins__

* [lasso-dust](https://github.com/lasso-js/lasso-dust): Compile [Dust](https://github.com/linkedin/dustjs) template files to JavaScript
* [lasso-handlebars](https://github.com/lasso-js/lasso-handlebars): Compile [Handlebars](http://handlebarsjs.com/) template files to JavaScript
* [lasso-image](https://github.com/lasso-js/lasso-image): Get image info (including URL, width and height) for any image on both the server and client
* [lasso-imagemin](https://github.com/lasso-js/lasso-imagemin): Minify GIF, PNG, JPG and SVG images during optimization
* [lasso-jade](https://github.com/lasso-js/lasso-jade): Compile [Jade](http://jade-lang.com/) templates to JavaScript
* [lasso-jsx](https://github.com/lasso-js/lasso-jsx): Compile [JSX](http://facebook.github.io/react/docs/jsx-in-depth.html) files to JavaScript
* [lasso-less](https://github.com/lasso-js/lasso-less): Compile [Less](http://lesscss.org/) files to CSS
* [lasso-lodash](https://github.com/lasso-js/lasso-lodash): Compile [Lo-Dash](https://lodash.com/) files to JavaScript
* [lasso-marko](https://github.com/lasso-js/lasso-marko): Compile [Marko template](https://github.com/marko-js/marko) files to JavaScript
* [lasso-sass](https://github.com/lasso-js/lasso-sass): Compile [Sass](https://github.com/sass/node-sass) files to CSS
* [lasso-stylus](https://github.com/lasso-js/lasso-stylus): Compile [Stylus](http://learnboost.github.io/stylus/) files to CSS
* [lasso-clean-css](https://github.com/yomed/lasso-clean-css): Minify CSS files using [clean-css](https://github.com/jakubpawlowicz/clean-css)
* [lasso-autoprefixer](https://github.com/lasso-js/lasso-autoprefixer): Autoprefix CSS with vendor prefixes using [autoprefixer-core](https://github.com/postcss/autoprefixer-core)
* [lasso-modernizr](https://github.com/darkwebdev/lasso-modernizr): Generate custom [Modernizr](https://modernizr.com) build
* [lasso-optimize-iife](https://github.com/austinkelleher/lasso-optimize-iife): Optimize JavaScript immediately-invoked functions using [optimize-js](https://github.com/nolanlawson/optimize-js)
* [lasso-rtl-css](https://github.com/shadiabuhilal/lasso-rtl-css): Transform CSS from left-to-right to right-to-left using [rtlcss](https://github.com/MohammadYounes/rtlcss)
* [lasso-prepack](https://github.com/austinkelleher/lasso-prepack): Optimize JavaScript using [prepack](https://prepack.io/)
* [lasso-typescript](https://github.com/ajay2507/lasso-typescript): compile [Typescript](https://www.typescriptlang.org/) in to Javascript.
* [grunt-lasso](https://github.com/ajay2507/grunt-lasso): [Grunt](https://gruntjs.com/) plugin for Lasso js.
* [lasso-analyzer](https://github.com/ajay2507/lasso-analyzer): Bundle Analyzer plugin for Lasso js.
* [lasso-unpack](https://github.com/ajay2507/lasso-unpack): Generating an asset manifest for all source files .
* [lasso-minify-transpile-inline](https://github.com/dsathyakumar/lasso-minify-transpile-inline): Lasso JS plugin to minify & transpile `inline` single file dependency assets that are not of `type: require`.
* [rollup-plugin-lasso](https://github.com/dsathyakumar/rollup-plugin-lasso/): Bundles with Rollup (in cases where Lasso cannot be used) and pipes the output to Lasso - to be a part of Lasso's lifecycle.

To use a third-party plugin, you must first install it using `npm install`. For example:

```bash
npm install lasso-less --save
```

If you create your own plugin please send a Pull Request and it will show up above. Also, do not forget to tag your plugin with `lasso-plugin` and `lasso` in your `package.json` so that others can browse for it using [npm](https://www.npmjs.org/)

# Extending Lasso.js

Only read below if you are building plugins or transforms to further enhance the `lasso` module.

## Custom Plugins

A plugin can be used to change how the lasso operates. This includes the following:

* Register a custom dependency to support dependencies that compile to JS or CSS
    * Examples:
        * Register a dependency handler for "less" files to compiles Less to CSS
        * Register a dependency handler for "marko" files to compiles Marko template files to JS
* Register a custom bundle writer
    * Examples:
        * Upload bundles to a resource server that backs a CDN instead of writing them to disk
* Register output transforms
    * Examples:
        * Add an output transform to minify JavaScript code
        * Add an output transform to minify CSS code
        * Add an output transform to remove `console.log` from JS code
        * Add an output transform to resolve image URLs in CSS files
* Configure the lasso
    * Examples:
        * Allow a plugin to automatically configure the lasso for production usage

A plugin is simply a Node.js module that exports a function with the following signature:

```javascript
/**
 * A plugin for Lasso.js
 * @param  {lasso/lib/Lasso} lasso An instance of a Lasso that can be configured
 * @param  {Object} The plugin configuration provided by the user
 */
module.exports = function(lasso, config) {
    // Register dependency types:
    lasso.dependencies.registerJavaScriptType('my-js-type', require('./dependency-my-js-type'));
    lasso.dependencies.registerStyleSheetType('my-css-type', require('./dependency-my-css-type'));
    lasso.dependencies.registerPackageType('my-package-type', require('./dependency-my-package-type'));

    // Add an output transform
    lasso.addTransform(require('./my-transform'));

    // Register a custom Node.js/CommonJS module compiler for a custom filename extension
    // var myModule = require('./hello.test');
    lasso.dependencies.registerRequireExtension('test', function(path, context, callback) {
        callback(null, "exports.sayHello = function() { console.log('Hello!'); }");
    });
};
```

## Custom Dependency Types

There are three types of dependencies that are supported:

* __JavaScript dependency:__ Produces JavaScript code
* __CSS dependency:__ Produces CSS code
* __Package dependency:__ Produces a package of additional JavaScript and CSS dependencies

Each of these dependencies is described in the next few sections. However, it is recommended to also check out the source code of [available plugins](#available-plugins) listed above (e.g. [lasso-less](https://github.com/lasso-js/lasso-less)).

### Custom JavaScript Dependency Type

If you would like to introduce your own custom dependency types then you will need to have your plugin register a dependency handler. This is illustrated in the following sample code:

```javascript
const fs = require('fs');

module.exports = function myPlugin(lasso, config) {
    lasso.dependencies.registerJavaScriptType(
        'my-custom-type',
        {
            // Declare which properties can be passed to the dependency type
            properties: {
                'path': 'string'
            },

            // Validation checks and initialization based on properties:
            async init (context) {
                if (!this.path) {
                    throw new Error('"path" is required');
                }

                // NOTE: resolvePath can be used to resolve a provided relative path to a full path
                this.path = this.resolvePath(this.path);
            },

            // Read the resource:
            async read (context) {
                const src = await fs.promises.readFile(this.path, {encoding: 'utf8'});
                return myCompiler.compile(src);
                // NOTE: A stream can also be returned
            },

            // getSourceFile is optional and is only used to determine the last modified time
            // stamp and to give the output file a reasonable name when bundling is disabled
            getSourceFile: function() {
                return this.path;
            }
        });
};
```

Once registered, the above dependency can then be referenced from an `browser.json` as shown in the following code:

```json
{
    "dependencies": [
        "my-custom-type: hello.file"
    ]
}
```

If a custom dependency supports more than just a `path` property, additional properties could be provided as shown in the following sample code:

```json
{
    "dependencies": [
        {
            "type": "my-custom-type",
            "path": "hello.file",
            "foo": "bar",
            "hello": true
        }
    ]
}
```


### Custom CSS Dependency Type

If you would like to introduce your own custom dependency types then you will need to have your plugin register a dependency handler as shown in the following sample code:

```javascript
module.exports = function myPlugin(lasso, config) {
    lasso.dependencies.registerStyleSheetType(
        'my-custom-type',
        handler);
};
```

The `handler` argument for a CSS dependency has the exact same interface as a handler for a JavaScript dependency (described earlier).

### Custom Package Type

A custom package dependency can be used to dynamically resolve additional dependencies at optimization time. The sample package dependency handler below illustrates how a package dependency can be used to automatically include every file in a directory as a dependency:

```javascript
const { promisify } = require('util');
const fs = promisify(require('fs'));
const path = promisify(require('path'));

lasso.dependencies.registerPackageType('dir', {
    properties: {
        'path': 'string'
    },

    async init (context) {
        let path = this.path;

        if (!path) {
            callback(new Error('"path" is required'));
        }

        this.path = path = this.resolvePath(path); // Convert the relative path to an absolute path

        const stat = await fs.stat(path);
        if (!stat.isDirectory()) {
            throw new Error('Directory expected: ' + path);
        }
    },

    async getDependencies (context) {
        const dir = this.path;
        const filenames = await fs.readdir(dir);

        // Convert the filenames to full paths
        var dependencies = filenames.map(function(filename) {
            return path.join(dir, filename);
        });

        return dependencies;
    },

    getDir: function() {
        // If the dependencies are associated with a directory then return that directory.
        // Otherwise, return null
        return this.path;
    }
});
```

## Custom Output Transforms

Registered output transforms are used to process bundles as they are written to disk. As an example, an output transform can be used to minify a JavaScript or CSS bundle. Another example is that an output transform may be used to remove `console.log` statements from output JavaScript code. Transforms should be registered by a plugin using the `lasso.addTransform(transform)` method.

As an example, the following unhelpful transform will convert all JavaScript source code to upper case:

```javascript
module.exports = function (lasso, pluginConfig) {
    lasso.addTransform({

        // Only apply to JavaScript code
        contentType: 'js', //  'css' is the other option

        // Give your module a friendly name (helpful for debugging in case something goes wrong in your code)
        name: module.id,

        // If stream is set to false then a String will be provided. Otherwise, a readable stream will be provided
        stream: false,

        // Do the magic:
        transform: function(code, lassoContext) {
            return code.toUpperCase();
        }
    });
};
```

Below is the streaming version of the same transform:

```javascript
var through = require('through');

module.exports = function (lasso, pluginConfig) {
    lasso.addTransform({

        // Only apply to JavaScript code
        contentType: 'js', // 'css' is the other option

        // Give your module a friendly name (helpful for debugging in case something goes wrong in your code)
        name: module.id,

        stream: true, // We want the code to be streamed to us

        // Do the magic:
        transform: function(inStream, lassoContext) {
            return inStream.pipe(through(
                function write(data) {
                    this.queue(data.toUpperCase());
                }));
        }
    });
};
```

# JavaScript API

See [JavaScript API](./docs/javascript-api.md).

# AMD Compatibility

See [AMD Compatibility](./docs/amd.md).

# Sample Projects

* [lasso-js-samples/lasso-async](https://github.com/lasso-js-samples/lasso-async): Demonstrates asynchronous/lazy dependency loading.
* [lasso-js-samples/lasso-cli](https://github.com/lasso-js-samples/lasso-cli): Demonstrates the command-line interface.
* [lasso-js-samples/lasso-code-splitting](https://github.com/lasso-js-samples/lasso-code-splitting): Demonstrates splitting out dependencies that are common across pages into a separate bundle.
* [lasso-js-samples/lasso-config](https://github.com/lasso-js-samples/lasso-config): Demonstrates the usage of a JSON config file.
* [lasso-js-samples/lasso-express](https://github.com/lasso-js-samples/lasso-express): Demonstrates using Lasso.js at runtime as part of an Express server app.
* [lasso-js-samples/lasso-js-api](https://github.com/lasso-js-samples/lasso-js-api): Demonstrates how to use JavaScript API to lasso a page and inject the resulting head and body markup into a page.
* [lasso-js-samples/lasso-taglib](https://github.com/lasso-js-samples/lasso-taglib): Demonstrates the use of the lasso taglib for Marko.
* [lasso-js-samples/lasso-templates](https://github.com/lasso-js-samples/lasso-templates): Demonstrates the use of rendering the same templates on both the server and the client.

# Discuss

Please join us in the [Gitter chat room for Lasso.js](https://gitter.im/lasso-js/lasso) or [open a new Github issue](https://github.com/lasso-js/lasso/issues).

# Maintainers

* [Patrick Steele-Idem](https://github.com/patrick-steele-idem) (Twitter: [@psteeleidem](http://twitter.com/psteeleidem))
* [Phillip Gates-Idem](https://github.com/philidem/) (Twitter: [@philidem](https://twitter.com/philidem))
* [Michael Rawlings](https://github.com/mlrawlings) (Twitter: [@mlrawlings](https://twitter.com/mlrawlings))

# Contributors

* Vinod Kumar (Twitter: [@vinodl](https://twitter.com/vinodl))
    - [gulp-lasso](https://github.com/lasso-js/gulp-lasso)
    - [lasso-jsx](https://github.com/lasso-js/lasso-jsx)
* Merwan Rodriguez (Twitter: [@uno7](https://twitter.com/uno7))
    - [lasso-autoprefixer](https://github.com/lasso-js/lasso-autoprefixer)

# Contribute

Pull Requests welcome. Please submit Github issues for any feature enhancements, bugs or documentation problems.

# License

Apache License v2.0


================================================
FILE: browser-refresh/index.js
================================================
module.exports = require('../src/browser-refresh');


================================================
FILE: docs/amd.md
================================================
# AMD Compatibility

Lasso.js does not support the AMD module syntax. You can, however, use the [deamdify](https://github.com/jaredhanson/deamdify) Browserify transform if you have third-party AMD code that should be transformed to CommonJS syntax.

## raptor-amd

If you need a lightweight AMD runtime to support external code, you can also include the [raptor-amd](https://github.com/raptorjs/raptor-amd) module on your page. However, that module is no longer maintained and is only kept around for legacy reasons.

## Masking the AMD define function

If you have both an AMD runtime and a CommonJS runtime on the same page then modules wrapped using a UMD wrapper that first checks for `define` (instead of `module.exports`) will attempt to define the module as an AMD module instead of using CommonJS. If you find that this issue is causing problems you can add a special `"mask-define": true` property as shown below:

_browser.json_

```json
{
    "dependencies": [
        {
            "path": "path/to/some-umd-module.js",
            "mask-define": true
        }
    ]
}
```

This will result in code similar to the following:

```javascript
(function(define) { /* mask define */
    // typeof define === 'undefined'
    // ...third-party goes here
}()); // END: mask define wrapper
```

================================================
FILE: docs/bundling.md
================================================
Lasso.js Bundling
====================================

Bundling can either be enabled or disabled during page optimization. If bundling is disabled then every dependency will be written to its own file. If bundling is enabled then dependencies will be concatenated together based on the bundles configured for the application and page. Lasso.js allows both application-level and page-level bundles to be configured.

# Application-level Bundles

Application-level bundles are bundles that apply to every page that are lassoed. Application-level bundles allow for consistant bundles across pages when pages have common dependencies. Application-level bundles are typically configured as part of the lasso configuration as show below:

```json
{
    ...
    "bundles": [
        {
            "name": "jquery",
            "dependencies": [
                "require: jquery"
            ]
        },
        {
            "name": "math",
            "dependencies": [
                "require: ./add"
            ]
        }
    ]
}
```

While assigning dependencies to bundles during a page optimization, if the lasso detects that a dependency is part of a application-level bundle then that bundle will be added to the list of output bundles for the page and result in either a `<script>` or `<link>` tag including the resource associated with the application-level bundle.

# Page-level Bundles

The lasso also allows for page-level to be configured when optimizing a particular page. Application-level bundles always take precedence over page-level bundles. Page-level bundles can be configured when optimizing a page as shown in the following example JavaScript code:

```javascript
require('lasso').lassoPage({
        name: "my-page",
        dependencies: [
            ...
        ],
        bundles: [
            {
                name: "foo",
                dependencies: [
                    "require: ./foo"
                ]
            }
        ]
    });
```

If you are using the taglib, page-level bundles can be passed in as part of the attributes. For example, with Marko:

```html
<lasso-page package-path="./browser.json" bundles="./lasso-bundles.json"/>
```

# Recursive Dependencies and Bundling

When assigning a dependency to a bundle it is possible that a particular package dependency might have additional dependencies. Lasso.js gives you control over how transitive dependencies are handled via a special "recurse into" option. The possible values for "recurse into" option are the following:

* __`"all"`:__ All transitive dependencies, regardless of where they are located on disk, will be added to the bundle.
* __`"dir"`:__ Only transitive dependencies that are in the exact same directory associated with the root dependency will be added to the bundle.
* __`"dirtree"`:__ Only transitive dependencies that are in the same directory associated with the root dependency _or_ within a nested directory associated with the root dependency will be added to the bundle.
* __`"module"`:__ Only dependencies that are within the root directory of the module associated with the root dependency will be added to the bundle unless the transitive dependency is a directory under the root module's `node_modules` directory.

The "recurse into" option can be specified using the `recurseInto` property at the bundle level or at the dependency level as shown in the following sample code:

```javascript
require('lasso').lassoPage({
        name: "my-page",
        dependencies: [
            ...
        ],
        bundles: [
            {
                name: "foo",
                dependencies: [
                    // Specified for a single dependency:
                    { path: "require: foo", recurseInto: "dir" }
                ]
            },
            {
                name: "bar",
                dependencies: [
                    "require: bar"
                ],
                // Specified at the bundle level:
                reurseInto: "dir"
            }
        ]
    });
```

_NOTE: the "require" dependency type is implemented as a package dependency since it can resolve to additional transitive dependencies based on which modules are required inside the JavaScript source code._

To hopefully make things clear, let's assume we have the following project structure:

```
.
├── main.js
└── node_modules
    ├── foo
    │   ├── index.js
    │   ├── lib
    │   │   └── foo.js
    │   └── node_modules
    │       └── bar
    │           └── index.js
    └── baz
        └── index.js
```

Let's assume that we have the following transitive dependencies:

```
require('./main.js') →
└── require('foo') →
    └── require('node_modules/foo/index.js')
        └── require('node_modules/foo/lib/foo.js')
            ├── require('bar')
            │   └── require('node_modules/foo/node_modules/bar/index.js')
            └── require('baz')
                └── require('node_modules/baz/index.js')
```

Let's try optimizing our `main.js` with different bundling options:

__Option 1) all:__

```json
{
    ...
    "bundles": [
        {
            "name": "foo",
            "dependencies": [
                { "path": "require: foo", "recurseInto": "all" }
            ]
        }
    ]
}
```

Content of the "foo" bundle:

* `node_modules/foo/index.js`
* `node_modules/foo/lib/foo.js`
* `node_modules/foo/node_modules/bar/index.js`
* `node_modules/baz/index.js`

__Option 2) dir:__

```json
{
    ...
    "bundles": [
        {
            "name": "foo",
            "dependencies": [
                { "path": "require: foo", "recurseInto": "dir" }
            ]
        }
    ]
}
```

Content of the "foo" bundle:

* `node_modules/foo/index.js`

__Option 3) dirtree:__

```json
{
    ...
    "bundles": [
        {
            "name": "foo",
            "dependencies": [
                { "path": "require: foo", "recurseInto": "dirtree" }
            ]
        }
    ]
}
```

Content of the "foo" bundle:

* `node_modules/foo/index.js`
* `node_modules/foo/lib/foo.js`
* `node_modules/foo/node_modules/bar/index.js`

__Option 4) module:__

```json
{
    ...
    "bundles": [
        {
            "name": "foo",
            "dependencies": [
                { "path": "require: foo", "recurseInto": "module" }
            ]
        }
    ]
}
```

Content of the "foo" bundle:

* `node_modules/foo/index.js`
* `node_modules/foo/lib/foo.js`


================================================
FILE: docs/javascript-api.md
================================================
JavaScript API
==============

## require('lasso')

### Methods

#### configure(config)

Configures the default lasso instance using the provided `config`. The `config` can either be an object or a path to a JSON file.

#### create(config)

Creates a new configured [Lasso](#Lasso-type) instance.

#### getDefaultLasso()

Returns the default [Lasso](#Lasso-type) instance.

#### lassoPage(options, callback)

Equivalent to `require('lasso').getDefaultLasso().lassoPage(options, callback)`. See [Lasso » lassoPage](#Lasso-lassoPage) below.

#### lassoResource(pageConfig, callback)

Equivalent to `require('lasso').getDefaultLasso().lassoResource(options, callback)`. See [Lasso » lassoResource](#Lasso-lassoResource) below.

## require('lasso/middleware')

### serveStatic(options)

Express middleware to serve up static files generated by Lasso.js.

Example usage:

```javascript
app.use(require('lasso/middleware').serveStatic());
```

- Supported options:
    - __lasso__ - The configured lasso instance (defaults to `require('lasso').getDefaultLasso()`)
    - __sendOptions__ - Options passed to the [send](https://github.com/pillarjs/send) module that is used to serve up static assets

<a name="Config-type"></a>

## Config

See [./lib/Config.js](./lib/Config.js)

<a name="Lasso-type"></a>

## Lasso

### Methods

<a name="Lasso-lassoPage"></a>

#### lassoPage(options, callback)

Processes all of the dependencies for a page to produce a set of static JS and CSS bundles, as well as any other static assets.

The result will be a [LassoPageResult](#LassoPageResult-type) instance that provides the list of generated URLs for all of the static bundles, as well as a list of the generated files.

Supported options:

- __dependencies__ - An array of dependencies
- __from__ - The base directory for calculating relative paths (optional)
- __packagePath__ - A path to a `browser.json` file
- __packagePaths__ - An array of paths to `browser.json` files

<a name="Lasso-lassoResource"></a>

#### lassoResource(path|buffer[, options]) : Promise

Sends any type of resource through the Lasso.js asset pipeline and returns a `Promise` that eventually resolves to a result object with the URL. If Lasso is configured to use the default file writer then the resource referenced by the path will be copied to the static output directory. The callback will be invoked when the resource is fully written and the URL to the output resource will be part of the object that the returned promise eventually resolves to. In addition, if Lasso is configured with fingerprints enabled then a fingerprint will be added to the output resource URL.

Example usage passing an asset path:

```javascript
const myLasso = require('lasso').getDefaultLasso();

myLasso.lassoResource('path/to/foo.png')
    .then(function(result) {
        var url = result.url; // URL for the output resource
    });
```

Example usage passing a buffer:

```javascript
const fs = require('fs');
const myLasso = require('lasso').getDefaultLasso();

const imgPath = nodePath.join(__dirname, 'ebay.png');

;(async function() {
  const buffer = await fs.promises.readFile(imgPath);

  const result = await lasso.lassoResource(buffer, {
      name: 'test',
      extension: 'png'
  });

   // URL for the output resource (e.g. /static/test-02827b0c.png)
  const { url } = await myLasso.lassoResource(buffer)
})();
```

Supported options:

- __cache__ (boolean) - Whether or not the result should be cached (the resource path will be used as the cache key). The default value is `true`.
- __name__ (string) - Name to prefix the buffer path
- __extension__ (string) - File extension to append to the end of a buffer path

#### lassoResource(path[, options], callback)

This method is similar to the other version that returns a `Promise` (`lassoResource(path[, options]) : Promise`), but if a `callback` function is provided as the last argument then the usage will be as follows:

```javascript
var myLasso = require('lasso').getDefaultLasso();
myLasso.lassoResource('path/to/foo.png', function(err, result) {
    if (err) {
        // Handle the error
    } else {
        var url = result.url; // URL for the output resource
    }
});
```

### Properties

#### config

The loaded [Config](#Config-type) config instance

<a name="LassoPageResult-type"></a>

## LassoPageResult

### Methods

#### getBodyHtml()

Short-hand for `lassoPageResult.getHtmlForSlot('body')`.

#### getCSSFiles()

Returns an array of all of file paths for all of the generated JavaScript bundles

#### getCSSUrls()

Returns an array of all of URLs for all of the generated CSS bundles

#### getHeadHtml()

Short-hand for `lassoPageResult.getHtmlForSlot('head')`.

#### getHtmlBySlot()

Returns the HTML markup for each slot. The returned object will be an object. For each property of the returned object, the name will be the slot name (e.g. `head`) and the value will be the HTML markup (e.g. `<link rel="stylesheet" type="text/css" href="static/style.less.css">`).

#### getHtmlForSlot(slotName)

Example usage:

```javascript
var headHtml = lassoPageResult.getHtmlForSlot('head');
var bodyHtml = lassoPageResult.getHtmlForSlot('body');
```

#### getJavaScriptFiles()

Returns an array of all of file paths for all of the generated JavaScript bundles

#### getJavaScriptUrls()

Returns an array of all of URLs for all of the generated JavaScript bundles

#### getOutputFiles()

Returns an array of all of file paths for all of the generated files


================================================
FILE: docs/migration-optimizer-to-lasso.md
================================================
Optimizer.js to Lasso.js Upgrade Guide
======================================

- Uninstall old modules:
  - `npm uninstall optimizer --save`
  - `npm uninstall optimizer-marko --save`
  - etc.
- Install new modules
  - `npm install lasso --save`
  - `npm install lasso-marko --save`
  - etc.
- API changes
  - `require('optimizer')` → `require('lasso')`
  - `optimizer.optimizePage(...)` → `lasso.lassoPage(...)`
- Rename `optimizer.json` files to `browser.json`
- Rename `*.optimizer.json` files to `*.browser.json`
- Update Marko custom tags:
  - Rename `<optimizer-page>` to `<lasso-page>`
  - Rename `<optimizer-head>` to `<lasso-head>`
  - Rename `<optimizer-body>` to `<lasso-body>`
- browser.json changes
  - remove unnecessary spacing:  e.g. convert "require :" to "require:"


================================================
FILE: getImageInfo.js
================================================
module.exports = require('./src/plugins/lasso-image').getImageInfo;


================================================
FILE: index.js
================================================
module.exports = require('./src');


================================================
FILE: middleware/index.js
================================================
module.exports = require('../src/middleware');


================================================
FILE: middleware/koa/serveStatic.js
================================================
module.exports = require('../../src/middleware/koa/serveStatic');


================================================
FILE: middleware/serveStatic.js
================================================
module.exports = require('../src/middleware/serveStatic');


================================================
FILE: node-require-no-op.js
================================================
module.exports = require('./src/node-require-no-op');


================================================
FILE: package.json
================================================
{
  "name": "lasso",
  "description": "Lasso.js is a build tool and runtime library for building and bundling all of the resources needed by a web application",
  "repository": {
    "type": "git",
    "url": "https://github.com/lasso-js/lasso.git"
  },
  "scripts": {
    "test-coverage-report": "nyc npm run mocha && nyc report --reporter=html && open ./coverage/index.html",
    "test": "nyc npm run mocha && npm run eslint",
    "mocha": "rm -rf .cache && mocha --timeout 4000 --ui bdd --reporter spec ./test ./test/unit",
    "eslint": "eslint src/ browser-refresh/ middleware/"
  },
  "author": "Patrick Steele-Idem <pnidem@gmail.com>",
  "maintainers": "Patrick Steele-Idem <pnidem@gmail.com>",
  "dependencies": {
    "@babel/code-frame": "^7.18.6",
    "app-root-dir": "^1.0.2",
    "assert": "^2.0.0",
    "browser-refresh-client": "^1.1.4",
    "buffer": "^6.0.3",
    "clean-css": "^5.3.1",
    "complain": "^1.6.0",
    "espree": "^9.4.0",
    "estraverse": "^5.3.0",
    "events": "^3.3.0",
    "glob": "^8.0.3",
    "image-size": "^1.0.2",
    "lasso-caching-fs": "^1.0.2",
    "lasso-loader": "^3.0.2",
    "lasso-modules-client": "^2.0.7",
    "lasso-package-root": "^1.0.1",
    "lasso-resolve-from": "^1.2.0",
    "mime": "^3.0.0",
    "mkdirp": "^1.0.4",
    "path-browserify": "1.0.1",
    "process": "^0.11.10",
    "property-handlers": "^1.1.1",
    "raptor-async": "^1.1.3",
    "raptor-cache": "^2.0.4",
    "raptor-css-parser": "^1.1.6",
    "raptor-logging": "^1.1.3",
    "raptor-regexp": "^1.0.1",
    "raptor-util": "^3.2.0",
    "resolve-from": "^4.0.0",
    "send": "^0.18.0",
    "stream-browserify": "^3.0.0",
    "string_decoder": "^1.3.0",
    "strip-json-comments": "^3.1.1",
    "terser": "^5.15.0",
    "through": "^2.3.8",
    "url": "^0.11.0",
    "util": "^0.12.4"
  },
  "devDependencies": {
    "chai": "^4.3.6",
    "eslint": "^8.24.0",
    "eslint-config-standard": "^17.0.0",
    "eslint-plugin-import": "^2.26.0",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-promise": "^6.0.1",
    "eslint-plugin-standard": "^4.1.0",
    "mocha": "^10.0.0",
    "nyc": "^15.1.0",
    "require-self-ref": "^2.0.1",
    "sinon": "^14.0.0",
    "strip-ansi": "^6.0.0"
  },
  "engines": {
    "node": ">=16"
  },
  "nyc": {
    "exclude": [
      "**/coverage/**",
      "**/test/**",
      "**/cache/**"
    ]
  },
  "license": "Apache-2.0",
  "main": "./index.js",
  "publishConfig": {
    "registry": "https://registry.npmjs.org/"
  },
  "keywords": [
    "bundler",
    "build",
    "css",
    "javascript",
    "concat",
    "minify"
  ],
  "version": "4.0.4"
}


================================================
FILE: src/AsyncPackage.js
================================================
function AsyncPackage(name) {
    this.name = name;
    this.bundles = [];
    this.bundlesByKey = {};
}

AsyncPackage.prototype = {
    getName: function() {
        return this.name;
    },

    addBundle: function(bundle) {
        const bundleKey = bundle.getKey();

        if (!this.bundlesByKey[bundleKey]) {
            this.bundlesByKey[bundleKey] = true;
            this.bundles.push(bundle);
        }
    },

    getMeta: function(context) {
        const meta = {
            css: [],
            js: []
        };

        const bundles = this.bundles;

        for (let i = 0, len = bundles.length; i < len; i++) {
            const bundle = bundles[i];
            let url;
            if (!bundle.hasContent() || !(url = bundle.getUrl(context))) {
                // skip bundles without content or bundles that don't have a URL.
                // TODO: Figure out what to do with inline dependencies that belong to an async bundle
                //       These dependencies don't have a URL but code should still be included, right?
                continue;
            }
            if (bundle.isJavaScript()) {
                meta.js.push(url);
            } else if (bundle.isStyleSheet()) {
                meta.css.push(url);
            } else {
                throw new Error('Invalid bundle content type: ' + bundle.getContentType());
            }
        }

        if (!meta.js.length) {
            delete meta.js;
        }

        if (!meta.css.length) {
            delete meta.css;
        }

        return meta;
    }
};

module.exports = AsyncPackage;


================================================
FILE: src/Bundle.js
================================================
const contentTypes = require('./content-types');

const Bundle = function(name) {
    this.name = name;
    this.dependencies = [];
    this.slot = 'body';
    this.contentType = null;
    this.written = false;
    this.fingerprint = undefined;
    this.inlinePos = false;
    this.url = null;
    this.mergeInline = true;
    this.key = null;

    this.config = {};

    this.code = null;

    this.data = {};
};

Bundle.getKey = function(dependencySlot, contentType, inlinePos, targetBundleName) {
    return [dependencySlot, contentType, (inlinePos == null) ? '' : inlinePos.toString(), targetBundleName].join('/');
};

Bundle.prototype = {
    isInline: function() {
        return this.inlinePos != null;
    },

    setInlinePos: function(inlinePos) {
        this.inlinePos = inlinePos;
    },

    getInlinePos: function(inline) {
        return this.inlinePos;
    },

    isAsyncOnly: function() {
        return this.config.asyncOnly;
    },

    /**
     * This property controls whether or not the inline content
     * gets merged with other inline content targeted for the same position
     * or if remains in standalone <script> or <style> block in the
     * order that it is added
     */
    setMergeInline: function(mergeInline) {
        this.mergeInline = mergeInline;
    },

    isMergeInline: function() {
        return this.mergeInline;
    },

    addDependency: function(dependency) {
        const index = this.dependencies.length;
        this.dependencies.push(dependency);
        return index;
    },

    removeDependencyByIndex: function(index) {
        this.dependencies[index] = undefined;
    },

    getDependencies: function() {
        return this.dependencies;
    },

    hasDependencies: function() {
        return this.dependencies.length !== 0;
    },

    getName: function() {
        return this.name;
    },

    getHtmlAttributes: function() {
        const attributes = {};
        this.dependencies.forEach(function(dependency) {
            if (typeof dependency.attributes === 'object') {
                Object.keys(dependency.attributes).forEach(function(key) {
                    attributes[key] = dependency.attributes[key];
                });
            }
        });
        return attributes;
    },

    getLabel: function() {
        let contentType;

        if (this.isJavaScript()) {
            contentType = contentTypes.JS;
        } else if (this.isStyleSheet()) {
            contentType = contentTypes.CSS;
        } else {
            contentType = this.getContentType();
        }
        return '"' + this.getName() + '" (' + contentType + ', ' + this.slot + (this.inlinePos ? ', inlinePos=' + this.inlinePos : '') + ')';
    },

    getKey: function() {
        if (!this.key) {
            this.key = Bundle.getKey(this.slot, this.contentType, this.inline, this.name);
        }
        return this.key;
    },

    getSlot: function() {
        return this.slot;
    },

    setSlot: function(slot) {
        this.slot = slot;
    },

    getContentType: function() {
        return this.contentType;
    },

    setContentType: function(contentType) {
        this.contentType = contentType;
    },

    hasContent: function() {
        return (this.contentType !== contentTypes.NONE);
    },

    isJavaScript: function() {
        return this.contentType === contentTypes.JS;
    },

    isStyleSheet: function() {
        return this.contentType === contentTypes.CSS;
    },

    forEachDependency: function(callback, thisObj) {
        this.dependencies.forEach(callback, thisObj);
    },

    getFingerprint: function() {
        return this.fingerprint;
    },

    setFingerprint: function(fingerprint) {
        this.fingerprint = fingerprint;
    },

    getCode: function() {
        return this.code;
    },

    setCode: function(code) {
        this.code = code;
    },

    isWritten: function() {
        return this.written;
    },

    setWritten: function(written) {
        this.written = written !== false;
    },

    setUrl: function(url) {
        this.url = url;
    },

    getUrl: function() {
        return this.url;
    },

    setConfig: function(config) {
        this.config = config || {};
    },

    getConfig: function() {
        return this.config;
    },

    toString: function() {
        const details = [this.slot, this.contentType];
        if (this.inlinePos) {
            details.push('inlinePos=' + this.inlinePos);
        }

        return this.name + ' (' + details.join(', ') + ')';
    }
};

module.exports = Bundle;


================================================
FILE: src/BundleConfig.js
================================================
const ok = require('assert').ok;
const DependencyList = require('./DependencyList');

const BundleConfig = function(dirname, filename) {
    ok(dirname, '"dirname" is required');
    ok(typeof dirname === 'string', '"dirname" is required');

    this.name = null;
    this.fingerprintsEnabled = undefined;
    this.dependencies = [];
    this.dirname = dirname;
    this.filename = filename;
    this.enabled = true;
};

BundleConfig.prototype = {
    getRecurseInto: function() {
        // recurseInto is set by config-loader.js
        return this.recurseInto;
    },

    getDependencies: function(dependencyRegistry) {
        return new DependencyList(this.dependencies, dependencyRegistry, this.dirname, this.filename);
    },
    addDependency: function(dependency) {
        this.dependencies.push(dependency);
    },
    addDependencies: function(dependencies) {
        dependencies.forEach(this.addDependency, this);
    },
    toString: function() {
        return '[BundleConfig name=' + this.name + ', dependencies=[' + this.dependencies.toString() + ']]';
    }
};

module.exports = BundleConfig;


================================================
FILE: src/BundleMappings.js
================================================
const Bundle = require('./Bundle');
const InlinePos = require('./InlinePos');
const EventEmitter = require('events').EventEmitter;
const ok = require('assert').ok;
const hasOwn = Object.prototype.hasOwnProperty;

function safeRelativePath(path) {
    return path.replace(/[^A-Za-z0-9_.\-\/\\$@]/g, '_');
}

function BundleMappings(config, pageName) {
    BundleMappings.$super.call(this);

    ok(pageName == null || typeof pageName === 'string', 'pageName should be a String');

    this.config = config;
    this.dependencyToBundleMapping = {};
    this.bundlesByKey = {};
    this.inPlaceDeploymentEnabled = config.isInPlaceDeploymentEnabled();
    this.bundlingEnabled = config.bundlingEnabled !== false;
    this.pageName = pageName;
};

BundleMappings.prototype = {
    __BundleMappings: true,

    setParentBundleMappings: function(parentBundleMappings) {
        if (parentBundleMappings && !parentBundleMappings.__BundleMappings) {
            throw new Error('Invalid parent bundle mappings');
        }

        if (parentBundleMappings === this) {
            throw new Error('parent bundle mappings cannot be self');
        }

        // The parent bundle mappings are those defined at configuration time
        // and we may not have actually
        this.parentBundleMappings = parentBundleMappings;
    },

    getBundleMappingForDependency: function(dependency) {
        const key = dependency.getKey();
        const bundleMapping = this.dependencyToBundleMapping[key];
        if (bundleMapping) {
            return bundleMapping;
        } else if (this.parentBundleMappings) {
            return this.parentBundleMappings.getBundleMappingForDependency(dependency);
        } else {
            return undefined;
        }
    },

    getBundleForDependency: function(dependency) {
        const key = dependency.getKey();
        const bundleMapping = this.dependencyToBundleMapping[key];
        if (bundleMapping) {
            return bundleMapping.bundle;
        } else if (this.parentBundleMappings) {
            return this.parentBundleMappings.getBundleForDependency(dependency);
        } else {
            return undefined;
        }
    },

    removeBundleMapping: function(bundleMapping) {
        const dependency = bundleMapping.dependency;
        delete bundleMapping.bundleMappings.dependencyToBundleMapping[dependency.getKey()];
        bundleMapping.bundle.removeDependencyByIndex(bundleMapping.index);
    },

    addDependencyToBundle: function(dependency, targetBundleName, dependencySlot, bundleConfig, lassoContext) {
        ok(lassoContext, 'lassoContext expected');

        let targetBundle;

        if (dependency.isPackageDependency()) {
            throw new Error('Illegal argument. Dependency cannot be a package dependency. Dependency: ' + dependency.toString());
        }

        let inlinePos = dependency.inline;

        if (inlinePos != null) {
            if (inlinePos === 'true' || inlinePos === true || inlinePos === 'end') {
                inlinePos = InlinePos.END;
            } else if (inlinePos === 'beginning') {
                inlinePos = InlinePos.BEGINNING;
            } else if (inlinePos === 'in-place') {
                inlinePos = InlinePos.IN_PLACE;
            } else if (inlinePos === 'false' || inlinePos === false) {
                // normalize false to undefined (really no need to set inline to false since it is the default)
                inlinePos = undefined;
            } else {
                throw new Error('Invalid value for "inline": ' + inlinePos);
            }
        }

        const bundleKey = Bundle.getKey(dependencySlot, dependency.getContentType(), inlinePos, targetBundleName);

        targetBundle = this.bundlesByKey[bundleKey];

        if (!targetBundle) {
            targetBundle = new Bundle(targetBundleName);
            targetBundle.key = bundleKey;
            targetBundle.setInlinePos(inlinePos);
            targetBundle.setSlot(dependencySlot);
            targetBundle.setContentType(dependency.getContentType());
            targetBundle.setUrl(dependency.getUrl ? dependency.getUrl() : dependency.url);
            if (bundleConfig) {
                targetBundle.setConfig(bundleConfig);
            }

            this.bundlesByKey[bundleKey] = targetBundle;
        }

        const index = targetBundle.addDependency(dependency);

        const bundleMapping = {
            // store the index of the dependency within the bundle
            index,

            // store the bundle associated with the mapping
            bundle: targetBundle,

            // store the bundle mapping
            bundleMappings: this,

            // store the dependency associated with the mapping
            dependency
        };

        this.dependencyToBundleMapping[dependency.getKey()] = bundleMapping;

        dependency.emit('addedToBundle', {
            bundle: targetBundle,
            lassoContext
        });

        return targetBundle;
    },

    addDependencyToPageBundle: function(dependency, pageBundleName, dependencySlot, bundleConfig, lassoContext) {
        ok(lassoContext, 'lassoContext expected');

        if (dependency.isPackageDependency()) {
            throw new Error('Illegal argument. Dependency cannot be a package dependency. Dependency: ' + dependency.toString());
        }

        let bundle;
        const defaultBundleName = dependency.getDefaultBundleName(pageBundleName, lassoContext);
        const flags = lassoContext.flags;

        if (this.inPlaceDeploymentEnabled && dependency.isInPlaceDeploymentAllowed()) {
            // Create a bundle with a single dependency for each dependency
            // that allows in-place deployment
            if (!dependency.getSourceFile) {
                throw new Error('getSourceFile() is required when in-place deployment is allowed. Dependency: ' + dependency);
            }

            bundle = this.addDependencyToBundle(
                dependency,
                dependency.getSourceFile(),
                dependencySlot,
                bundleConfig,
                lassoContext);

            bundle.dependency = dependency;
            bundle.inPlaceDeployment = true;
        } else if (dependency.isExternalResource()) {
            bundle = this.addDependencyToBundle(
                dependency,
                dependency.getUrl(),
                dependencySlot,
                bundleConfig,
                lassoContext);

            bundle.dependency = dependency;
            bundle.isExternalResource = true;
        } else if (this.bundlingEnabled === false) {
            // Bundling is NOT enabled

            // We will try to find a relative path that will be used for
            // the output file of the bundle.
            // This relative path might be different from the bundle name
            // if a defaultBundleName is provided
            //
            // NOTE: If we don't have a defaultBundleName for this dependency
            // and if we don't find a relative path then we will use
            // `${dependencyType}-${pageBundleName}` as the
            // bundle name.

            let targetBundle;

            if (dependency.getUnbundledTarget) {
                targetBundle = dependency.getUnbundledTarget(lassoContext);
            }

            if (!targetBundle && dependency.getSourceFile) {
                const sourceFile = dependency.getSourceFile();

                if (sourceFile) {
                    targetBundle = lassoContext.getClientPath(sourceFile);
                }
            }

            if (targetBundle) {
                targetBundle = safeRelativePath(targetBundle);

                let prefix = pageBundleName.replace(/[\\\/]/g, '-');

                if (flags && !flags.isEmpty()) {
                    prefix += '-' + flags.getKey();
                }

                if (dependency.getUnbundledTargetPrefix) {
                    const unbundledTargetPrefix = dependency.getUnbundledTargetPrefix(lassoContext);
                    if (unbundledTargetPrefix) {
                        prefix += '/' + unbundledTargetPrefix;
                    }
                }

                targetBundle = prefix + '/' + targetBundle;
            }

            let finalBundleName = defaultBundleName || targetBundle;
            if (!finalBundleName) {
                finalBundleName = dependency.type + '-' + pageBundleName;

                if (flags && !flags.isEmpty()) {
                    finalBundleName += '-' + flags.getKey();
                }
            }

            bundle = this.addDependencyToBundle(
                dependency,
                finalBundleName,
                dependencySlot,
                null,
                lassoContext);

            // bundle.dependency = dependency;
            if (targetBundle) {
                // We associate this bundle with a relative path which will
                // be used as the output file for the bundle
                bundle.relativeOutputPath = targetBundle;
            }
        } else {
            // Bundling is enabled
            // Make sure the dependency is part of a bundle. If it not part of a preconfigured bundle then put it in a page-specific bundle
            bundle = this.addDependencyToBundle(
                dependency,
                defaultBundleName || pageBundleName,
                dependencySlot,
                bundleConfig,
                lassoContext);
        }

        return bundle;
    },

    toString: function() {
        const lines = [];
        for (const k in this.dependencyToBundleMapping) {
            if (hasOwn.call(this.dependencyToBundleMapping, k)) {
                const targetBundle = this.dependencyToBundleMapping[k].bundle;
                lines.push(k + ' --> ' + targetBundle.toString());
            }
        }

        return lines.join('\n');
    }
};

require('raptor-util').inherit(BundleMappings, EventEmitter);

module.exports = BundleMappings;


================================================
FILE: src/BundleSetConfig.js
================================================
let nextId = 0;

function BundleSetConfig(name) {
    this._id = nextId++;
    this.name = name;
    this.bundleConfigs = [];
}

BundleSetConfig.prototype = {
    addBundleConfig: function(bundleConfig) {
        this.bundleConfigs.push(bundleConfig);
    },
    forEachBundleConfig: function(callback, thisObj) {
        this.bundleConfigs.forEach(callback, thisObj);
    }
};

module.exports = BundleSetConfig;


================================================
FILE: src/Config.js
================================================
const extend = require('raptor-util').extend;
const BundleSetConfig = require('./BundleSetConfig');
const flags = require('./flags');
const ok = require('assert').ok;
const lassoRequirePlugin = require('./require');
const lassoImagePlugin = require('./plugins/lasso-image');
const crypto = require('crypto');

function createFilterFromContentType(contentType) {
    const contentTypeMap = {};

    if (Array.isArray(contentType)) {
        // Include this array if the actual content type is in the array of supported content types
        const contentTypeArray = contentType;
        if (contentTypeArray.length === 0) {
            return async function (lassoContext) {
                return true;
            };
        }

        for (let i = 0, len = contentTypeArray.length; i < len; i++) {
            contentTypeMap[contentTypeArray[i]] = true;
        }
    } else {
        contentTypeMap[contentType] = true;
    }

    return async function(lassoContext) {
        const contentType = lassoContext.contentType;
        return contentTypeMap[contentType] === true;
    };
}

const MAX_FINGERPRINT_DEPTH = 4;

function calculateConfigFingerprint(config) {
    // Instead of trying to be clever we we just going to hard code
    // handling of each support configuration for now...
    const hash = crypto.createHash('sha1');

    function hashObject(o, depth) {
        if (depth > MAX_FINGERPRINT_DEPTH) {
            return;
        }

        const keys = Object.keys(o);
        keys.sort();

        for (let i = 0; i < keys.length; i++) {
            const k = keys[i];
            const v = o[k];
            update(k, depth + 1);
            update(v, depth + 1);
        }
    }

    function hashArray(o, depth) {
        if (depth > MAX_FINGERPRINT_DEPTH) {
            return;
        }

        const len = o.length;

        for (let i = 0; i < len; i++) {
            update(o[i], depth + 1);
        }
    }

    function update(value, depth) {
        if (depth === undefined) {
            depth = 0;
        }

        if (depth > 0 && typeof v === 'function') {
            return;
        }

        if (value == null) {
            hash.update('');
            return;
        }

        if (Array.isArray(value)) {
            hashArray(value, depth);
        } else if (typeof value === 'object') {
            hashObject(value, depth);
        } else {
            hash.update(value.toString());
        }
    }

    update(config.rawConfig);

    return hash.digest('hex');
}

function Config(params) {
    this.configResource = null;

    this.bundlingEnabled = true;

    this.projectRoot = null;

    this.flags = flags.createFlagSet();
    this.params = {};
    this.bundleSetConfigsByName = {};
    this.fileWriterConfig = null;
    this.transforms = [];
    this.bundlingEnabled = true;
    this.basePath = null;
    this.writer = null;
    this.includeSlotNameForBundles = false;
    this._plugins = [];
    this.cacheProfiles = null;
    this.cacheProfile = null;
    this.cacheDir = null;
    this._requirePluginConfig = {};
    this._minifyJSPluginConfig = {};
    this._minifyCSSPluginConfig = {};
    this._imagePluginConfig = {};
    this.cspNonceProvider = null;
    this.fingerprintInlineCode = null;
    this.cacheKey = null; // The unique key to uniquely identify this lasso for caching purposes
    this.resolver = null;
    this.loadPrebuild = false; // Whether Lasso should load from a prebuild configuration or not

    if (params) {
        extend(this.params, params);
    }

    this.addDefaultPlugins();

    this._configFingerprint = null;
}

Config.prototype = {
    __Config: true,

    get outputDir() {
        return this.fileWriterConfig && this.fileWriterConfig.outputDir;
    },

    get urlPrefix() {
        return this.fileWriterConfig && this.fileWriterConfig.urlPrefix;
    },

    /**
     * The goal of this method is to return a String that uniquely identifies
     * this configuration. This is needed for caching purposes in that we want
     * to discard cached items if the configuration changes. For example, if
     * a new transform is added then the previously cached transformed items
     * should not be used.
     */
    getConfigFingerprint: function() {
        if (!this._configFingerprint) {
            this._configFingerprint = calculateConfigFingerprint(this);
        }

        return this._configFingerprint;
    },

    addDefaultPlugins: function() {
        this.addPlugin(lassoRequirePlugin, this._requirePluginConfig);
        this.addPlugin(lassoImagePlugin, this._imagePluginConfig);
    },

    getPlugins: function(pluginInfo) {
        return this._plugins;
    },

    addPlugin: function(func, config) {
        // Don't add if this is a duplicate plugin
        for (let i = 0; i < this._plugins.length; i++) {
            const curPlugin = this._plugins[i];
            if (curPlugin.func === func && curPlugin.config === config) {
                return;
            }
        }

        ok(typeof func === 'function', 'Plugin should be a function. Actual: ' + func);
        this._plugins.push({
            func,
            config: config || {}
        });
    },

    addTransform: function(transform) {
        if (!transform) {
            throw new Error('transform is required');
        }

        if (transform.enabled === false) {
            // Don't add transforms that are disabled
            return;
        }

        if (typeof transform === 'function') {
            transform = {
                transform
            };
        }

        if (typeof transform.transform !== 'function') {
            throw new Error('Invalid transform: ' + require('util').inspect(transform));
        }

        transform.name = transform.name || transform.transform.name || '(anonymous)'; // Use the function name

        if (transform.contentType) {
            // Convert the contentType to a filter
            transform = extend({}, transform);
            transform.filter = createFilterFromContentType(transform.contentType);
            delete transform.contentType;
        }

        this.transforms.push(transform);
    },

    getResolver () {
        return this.resolver;
    },

    getTransforms: function() {
        return this.transforms;
    },

    isInPlaceDeploymentEnabled: function() {
        return this.inPlaceDeploymentEnabled === true;
    },

    isBundlingEnabled: function() {
        return this.bundlingEnabled;
    },

    addBundleSetConfig: function(bundleSetConfig) {
        if (!bundleSetConfig.name) {
            bundleSetConfig.name = 'default';
        }

        if (this.bundleSetConfigsByName[bundleSetConfig.name]) {
            throw new Error('Bundles with name "' + bundleSetConfig.name + '" defined multiple times');
        }

        this.bundleSetConfigsByName[bundleSetConfig.name] = bundleSetConfig;

        return bundleSetConfig;
    },

    getBundleSetConfig: function(name) {
        return this.bundleSetConfigsByName[name];
    },

    enableFlag: function(name) {
        this.flags.add(name);
    },

    /**
     * @deprecated
     */
    enableExtension: function(name) {
        this.flags.add(name);
    },

    getFlags: function() {
        return this.flags;
    },

    setFlags: function(newFlags) {
        this.flags = flags.createFlagSet(newFlags);
    },

    getPageBundleSetConfig: function(pageName) {
        let bundleSetConfig = this.getBundleSetConfig('default');

        if (!bundleSetConfig) {
            bundleSetConfig = this.addBundleSetConfig(new BundleSetConfig('default'));
        }

        return bundleSetConfig;
    },

    setInPlaceDeploymentEnabled: function(inPlaceDeploymentEnabled) {
        this.inPlaceDeploymentEnabled = inPlaceDeploymentEnabled;
    },

    setInPlaceUrlPrefix: function(inPlaceUrlPrefix) {
        this.inPlaceUrlPrefix = inPlaceUrlPrefix;
    },

    getInPlaceUrlPrefix: function() {
        return this.inPlaceUrlPrefix;
    },

    getBasePath: function() {
        return this.basePath;
    },

    setBasePath: function(basePath) {
        this.basePath = basePath;
    },

    getWriter: function() {
        return this.writer;
    },

    setResolver (resolver) {
        this.resolver = resolver;
    },

    setWriter: function(writer) {
        this.writer = writer;
    },

    getProjectRoot: function() {
        return this.projectRoot;
    },

    setProjectRoot: function(projectRoot) {
        if (projectRoot != null) {
            const len = projectRoot.length;
            // chop off trailing slash so that our path operations are consistent
            if (projectRoot.charAt(len - 1) === '/' || projectRoot.charAt(len - 1) === '\\') {
                projectRoot = projectRoot.substring(0, len - 1);
            }
        }
        this.projectRoot = projectRoot;
    },

    setBundlingEnabled: function(bundlingEnabled) {
        this.bundlingEnabled = bundlingEnabled;
    },

    setBundlingStrategy: function(bundlingStrategy) {
        this.bundlingStrategy = bundlingStrategy;
    },

    getBundlingStrategy: function() {
        return this.bundlingStrategy;
    },

    setCacheProfiles: function(cacheProfiles) {
        this.cacheProfiles = cacheProfiles;
    },

    getCacheProfiles: function() {
        return this.cacheProfiles;
    },

    setCacheProfile: function(cacheProfile) {
        this.cacheProfile = cacheProfile;
    },

    getCacheProfile: function() {
        return this.cacheProfile;
    },

    setCacheDir: function(cacheDir) {
        this.cacheDir = cacheDir;
    },

    getCacheDir: function() {
        return this.cacheDir;
    },

    toString: function() {
        return '[' + __filename + ']'; // eslint-disable-line no-path-concat
    },

    setBundleReadTimeout: function(timeout) {
        this.bundleReadTimeout = timeout;
    },

    getBundleReadTimeout: function() {
        return this.bundleReadTimeout;
    },

    setCSPNonceProvider: function(func) {
        this.cspNonceProvider = func;
    },

    setFingerprintInlineCode: function(func) {
        this.fingerprintInlineCode = func;
    },

    setCacheKey (value) {
        this.cacheKey = value;
    },

    /**
    * Whether Lasso should load from a prebuild configuration or not
    */
    setLoadPrebuild (value) {
        this.loadPrebuild = value;
    },

    getLoadPrebuild () {
        return this.loadPrebuild;
    }
};

module.exports = Config;


================================================
FILE: src/DependencyList.js
================================================
const dependenciesModule = require('./dependencies');
const ok = require('assert').ok;

function DependencyList(dependencies, dependencyRegistry, dirname, filename) {
    ok(dirname && typeof dirname === 'string', '"dirname" argument should be a string');
    ok(!filename || typeof filename === 'string', '"filename" argument should be a string');
    ok(dependencyRegistry && dependenciesModule.isRegistry(dependencyRegistry), 'dependencyRegistry argument is not valid');

    if (dependencies) {
        if (dependencies.__DependencyList) {
            dependencies = dependencies._dependencies;
        } else if (!Array.isArray(dependencies)) {
            throw new Error('Invalid dependencies: ' + dependencies);
        }
    }

    this._dependencyRegistry = dependencyRegistry;
    this._dependencies = dependencies || [];
    this._normalized = null;

    this._dirname = dirname;
    this._filename = filename;
}

DependencyList.prototype = {
    __DependencyList: true,

    addDependency: function(config) {
        if (this._converted) {
            config = this.dependencyRegistry.createDependency(config, this._dirname, this._filename);
        }

        this._dependencies.push(config);
    },

    async normalize () {
        if (!this._normalized) {
            this._normalized = await this._dependencyRegistry.normalizeDependencies(
                this._dependencies,
                this._dirname,
                this._filename);
        }
        return this._normalized;
    },

    toString: function() {
        return '[DependencyList: ' + this._dependencies.join(',') + ']';
    },

    inspect() {
        return this._dependencies;
    }
};

DependencyList.prototype.push = DependencyList.prototype.addDependency;

DependencyList.isDependencyList = function(o) {
    return o && o.__DependencyList;
};

module.exports = DependencyList;


================================================
FILE: src/DependencyTree.js
================================================
const hasOwn = Object.prototype.hasOwnProperty;

function Node(dependency, parent) {
    this.dependency = dependency;
    this.children = [];
    this.parent = parent;
}

function DependencyTree() {
    this._root = new Node();
    this._root.isRoot = true;
    this._nodes = {};
    this._bundleTrees = {};
}

DependencyTree.prototype = {
    add: function(dependency, parentDependency) {
        const parentNode = parentDependency
            ? this._nodes[parentDependency.getKey()]
            : this._root;

        if (!parentNode) {
            throw new Error('parentNode node not found: ' + parentDependency.getKey());
        }

        const node = new Node(dependency, parentNode);

        parentNode.children.push(node);
        this._nodes[dependency.getKey()] = node;
    },

    addToBundle: function(bundle, dependency, parentDependency) {
        let bundleTree = this._bundleTrees[bundle.getKey()];
        if (!bundleTree) {
            bundleTree = this._bundleTrees[bundle.getKey()] = new DependencyTree();
            bundleTree.bundle = bundle;
        }

        const parentNode = parentDependency
            ? this._nodes[parentDependency.getKey()]
            : this._root;

        function copyNodes(node) {
            if (node.isRoot || bundleTree._nodes[node.dependency.getKey()]) {
                return;
            }

            if (node.parent) {
                copyNodes(node.parent);
            }

            bundleTree.add(node.dependency, node.parent ? node.parent.dependency : null);
        };

        copyNodes(parentNode);

        bundleTree.add(dependency, parentDependency);
    },

    bundlesToString: function() {
        const lines = [];

        for (const k in this._bundleTrees) {
            if (hasOwn.call(this._bundleTrees, k)) {
                const bundleTree = this._bundleTrees[k];
                lines.push('Bundle ' + bundleTree.bundle.toString() + ':');
                lines.push(bundleTree.toString());
            }
        }

        return lines.join('\n');
    },

    toString: function(indent) {
        const lines = [];

        function toStringHelper(node, indent) {
            for (let i = 0, len = node.children.length; i < len; i++) {
                const child = node.children[i];
                let line = indent;
                if (!child.dependency.isPackageDependency()) {
                    line += '+ ';
                }
                line += child.dependency.toString();

                lines.push(line);

                toStringHelper(child, indent + '  ');
            }
        }

        toStringHelper(this._root, indent || '');

        return lines.join('\n');
    }
};

module.exports = DependencyTree;


================================================
FILE: src/FlagSet.js
================================================
/*
 * Copyright 2011 eBay Software Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The FlagSet class is used to maintain a set
 * of flags and provides methods for adding
 * extension names and checking if an extension
 * is an enabled. It also exposes a <code>getKey()</code>
 * method that can be used to return a String
 * key that uniquely identifies the set of
 * enabled flags.
 */
const forEachEntry = require('raptor-util').forEachEntry;
const raptorRegexp = require('raptor-regexp');

function FlagSet(flags) {
    this.flagMap = {};
    this.flagList = [];
    this.key = null;

    if (flags) {
        this.addAll(flags);
    }
}

FlagSet.prototype = {
    __FlagSet: true,

    isEmpty: function() {
        return this.flagList.length === 0;
    },

    /**
     *
     * @param ext
     */
    add: function(ext) {
        if (Array.isArray(ext)) {
            this.addAll(ext);
            return;
        }

        this.flagMap[ext] = true; // Add the extension to a map for quick lookup
        this.flagList.push(ext); // Maintain an array of flags
        this.key = null; // Clear out the key so that it is regenerated since the collection changed
    },

    remove: function(ext) {
        if (this.flagMap[ext]) {
            delete this.flagMap[ext];
            this.flagList = Object.keys(this.flagMap);
            this.key = null; // Clear the key since the collection changed
        }
    },

    /**
     * Adds one or more flags to the collection. This method
     * supports an array of extension names, as well as an
     * object map with extension names as property names.
     *
     * @param flags {Array|Object|packaging.FlagSet}
     */
    addAll: function(flags) {
        if (!flags) {
            return;
        }

        if (flags instanceof FlagSet) {
            flags = flags.flagList;
        }

        if (Array.isArray(flags)) {
            flags.forEach(function(ext) {
                this.add(ext);
            }, this);
        } else if (typeof flags === 'object') {
            forEachEntry(flags, function(ext) {
                this.add(ext);
            }, this);
        }
    },

    /**
     * Returns a string that can be used to uniquely
     * identify a set of flags. If two
     * FlagSet instances contain the same set
     * of flags then the same key will be returned.
     * @returns
     */
    getKey: function() {
        if (this.key == null) {
            this.flagList.sort();
            this.key = this.flagList.join('-');
        }

        return this.key;
    },

    /**
     *
     * @param ext
     * @returns {Boolean}
     */
    contains: function(ext) {
        return this.flagMap[ext] === true;
    },

    /**
     *
     * @param ext
     * @returns {Boolean}
     */
    containsMatch: function(ext) {
        let regExp;

        if (ext instanceof RegExp) {
            regExp = ext;
        } else if (ext === '*') {
            return this.flagList.length !== 0;
        } else {
            regExp = raptorRegexp.simple(ext);
        }

        const flags = this.flagList;
        for (let i = 0, len = flags.length; i < len; i++) {
            if (regExp.test(flags[i])) {
                return true;
            }
        }

        return false;
    },

    getAll: function() {
        return this.flagList;
    },

    toString: function() {
        return this.getKey();
    }
};

module.exports = FlagSet;


================================================
FILE: src/InlinePos.js
================================================
module.exports = require('raptor-util').makeEnum([
    'IN_PLACE',
    'BEGINNING',
    'END'
]);


================================================
FILE: src/Lasso.js
================================================
const assert = require('assert');
const nodePath = require('path');
const LassoCache = require('./LassoCache');
const LassoPageResult = require('./LassoPageResult');
const LassoContext = require('./LassoContext');
const SlotTracker = require('./SlotTracker');
const logger = require('raptor-logging').logger(module);
const EventEmitter = require('events').EventEmitter;
const mime = require('mime');
const raptorUtil = require('raptor-util');
const pageBundlesBuilder = require('./page-bundles-builder');
const BundleMappings = require('./BundleMappings');
const manifestLoader = require('./manifest-loader');
const LassoManifest = require('./LassoManifest');
const flags = require('./flags');
const dependencies = require('./dependencies');
const fs = require('fs');
const commaSeparatedRegExp = /\s*,\s*/;
const ok = require('assert').ok;
const bundleBuilder = require('./bundle-builder');
const isAbsolute = require('./path').isAbsolute;
const createWriter = require('./writers').createWriter;
const perfLogger = require('raptor-logging').logger('lasso/perf');
const extend = require('raptor-util/extend');
const cachingFs = require('./caching-fs');
const createError = require('raptor-util/createError');
const resolveFrom = require('resolve-from');
const LassoPrebuildResult = require('./LassoPrebuildResult');
const { buildPrebuildName, buildPrebuildFileName } = require('./util/prebuild.js');
const hashUtil = require('./util/hash');

/**
* Cache of prebuilds by path. If there are multiple slots for the same
* path, we do not need to load the prebuild more than once.
*/
const prebuildToPath = {};

const urlRegExp = /^[^:\/]{0,5}[:]?\/\//;

const resourceHandlersByType = {
    string: {
        resource: doLassoResourceString,
        calculateKey (data, theLasso, lassoContext, options) {
            if (!isAbsolute(data)) {
                data += lassoContext.dir;
            }

            return _buildResourceCacheKey(data, theLasso, lassoContext);
        }
    },
    object: {
        resource: doLassoResourceBuffer,
        hashPath: true,
        calculateKey (data, theLasso, lassoContext, options) {
            let hash = hashUtil.generate(
                data.toString(), hashUtil.HASH_OVERFLOW_LENGTH);

            let name;
            let ext;

            if ((name = options.name)) {
                hash = `${name}-${hash}`;
            }

            if ((ext = options.extension)) {
                hash += `.${ext}`;
            }

            return hash;
        }
    }
};

function isExternalUrl(path) {
    return urlRegExp.test(path);
}

async function getLassoManifestFromOptions (options, dependencyRegistry) {
    let lassoManifest;
    const from = options.from;
    let fromFilename;
    let fromDirname;

    if (from) {
        if (typeof from === 'object') {
            if (!from.filename) {
                throw new Error('Invalid "from" object.');
            }
            fromFilename = from.filename;
            fromDirname = nodePath.dirname(fromFilename);
        } else if (typeof from === 'string') {
            const stat = cachingFs.statSync(from);
            if (!stat.exists()) {
                throw new Error('No directory exists at given "from" path ("' + from + '")');
            }

            if (stat.isDirectory()) {
                fromDirname = from;
            } else {
                fromFilename = from;
                fromDirname = nodePath.dirname(from);
            }
        }
    }

    let lassoManifestOptions;

    if (options.packagePath) {
        const packagePath = options.packagePath;

        if (typeof packagePath !== 'string') {
            throw new Error('"packagePath" option should be a string');
        }

        if (!fromDirname) {
            fromDirname = nodePath.dirname(packagePath);
        }

        lassoManifest = manifestLoader.load(packagePath, fromDirname);
        if (lassoManifest) {
            lassoManifestOptions = {
                manifest: lassoManifest,
                dependencyRegistry,
                dirname: lassoManifest.dirname,
                filename: lassoManifest.filename
            };
        }
    } else if (options.dependencies) {
        let dependencies = options.dependencies;

        if (!fromDirname) {
            fromDirname = process.cwd();
        }

        if (typeof dependencies === 'function') {
            const resolvedDependencies = await dependencies();
            return new LassoManifest({
                manifest: {
                    dependencies: resolvedDependencies
                },
                dependencyRegistry,
                dirname: fromDirname,
                filename: fromFilename
            });
        } else if (!Array.isArray(dependencies)) {
            dependencies = [dependencies];
        }

        lassoManifestOptions = {
            manifest: {
                dependencies
            },
            dependencyRegistry,
            dirname: fromDirname,
            filename: fromFilename
        };
    } else if (options.lassoManifest) {
        lassoManifestOptions = {
            manifest: options.lassoManifest,
            dependencyRegistry,
            dirname: options.lassoManifest.dirname || process.cwd(),
            filename: options.lassoManifest.filename
        };
    } else if (options.packagePaths) {
        lassoManifestOptions = {
            manifest: {
                dependencies: options.packagePaths
            },
            dependencyRegistry,
            dirname: process.cwd(),
            filename: undefined
        };
    }

    if (lassoManifestOptions) {
        return new LassoManifest(lassoManifestOptions);
    } else {
        return null;
    }
}

async function doLassoPage (theLasso, options, lassoContext) {
    const logInfoEnabled = logger.isInfoEnabled();
    const perfLogInfoEnabled = perfLogger.isInfoEnabled();

    const startTime = Date.now();

    // if we create a new context then make sure we put it
    // back into the options object for reference later
    const pageName = lassoContext.pageName = options.pageName || options.name;

    lassoContext.pageName = pageName;

    const config = theLasso.config;

    const lassoManifest = await getLassoManifestFromOptions(options, theLasso.dependencies);

    if (!lassoManifest) {
        throw new Error('Invalid options. "dependencies", "packagePath" or "lassoManifest" expected. Options: ' + require('util').inspect(options));
    }

    logger.debug('getLassoManifestFromOptions()');

    options.lassoManifest = lassoManifest;

    const pluginContext = {
        context: lassoContext,
        config,
        options,
        lasso: theLasso
    };

    // TODO: Deprecate this
    theLasso.emit('beforeOptimizePage', pluginContext);
    theLasso.emit('beforeLassoPage', pluginContext);
    theLasso.emit('beforeBuildPage', pluginContext);

    const lassoPageResult = new LassoPageResult();
    const slotTracker = new SlotTracker();

    lassoContext.lassoPageResult = lassoPageResult;

    const writer = lassoContext.writer;

    // Inline code fingerprinting is useful for building a Single Page App
    // that is using a Content Security Policy (CSP) that prevents
    // untrusted script blocks. By keeping track of inline code
    // fingerprints, a build tool could provide these as part of the CSP
    // so that inline code blocks created at build time will be trusted.
    const fingerprintInlineCode = config.fingerprintInlineCode;
    let inlineCodeFingerprints;

    if (fingerprintInlineCode) {
        inlineCodeFingerprints = [];
    }

    function onBundleWritten (bundle) {
        if (logInfoEnabled) {
            logger.info('Bundle ' + bundle + ' written.');
        }
        lassoPageResult.registerBundle(bundle, false, lassoContext);
    }

    function onAsyncBundleWritten (bundle) {
        if (logInfoEnabled) {
            logger.info('Bundle ' + bundle + ' (async) written.');
        }
        lassoPageResult.registerBundle(bundle, true, lassoContext);
    }

    function buildHtmlSlots (pageBundles) {
        pageBundles.forEachBundle(function (bundle) {
            let attrs,
                url;

            const bundleAttrs = bundle.getHtmlAttributes();

            if (bundle.isInline()) {
                if (fingerprintInlineCode) {
                    const fingerprint = config.fingerprintInlineCode(bundle.getCode());
                    if (fingerprint) {
                        inlineCodeFingerprints.push(fingerprint);
                    }
                }

                slotTracker.addInlineCode(
                    bundle.getSlot(),
                    bundle.getContentType(),
                    bundle.getCode(),
                    bundle.getInlinePos(),
                    bundle.isMergeInline());
            } else {
                url = bundle.getUrl(lassoContext);

                if (bundle.isJavaScript()) {
                    attrs = Object.assign({ src: url }, bundleAttrs);
                } else if (bundle.isStyleSheet()) {
                    attrs = Object.assign({ href: url }, bundleAttrs);
                } else if (!bundle.hasContent()) {
                    // ignore this bundle because contentType is "none"
                    return;
                } else {
                    throw new Error('Invalid bundle content type: ' + bundle.getContentType());
                }
                slotTracker.addContent(bundle.getSlot(), bundle.getContentType(), attrs);
            }
        });

        lassoPageResult.setSlotsByName(slotTracker.getSlotsByName());
        lassoPageResult.setInlineCodeFingerprints(inlineCodeFingerprints);
    }

    let pageBundles;

    let prevStartTime = startTime;

    async function buildPageBundles () {
        logger.debug('buildPageBundles BEGIN');
        pageBundles = await theLasso.buildPageBundles(options, lassoContext);
    }

    async function writeAsyncBundles () {
        if (perfLogInfoEnabled) {
            perfLogger.info('Page bundles built in ' + (Date.now() - prevStartTime) + 'ms');
        }

        prevStartTime = Date.now();

        lassoContext.setPhase('write-async-page-bundles');

        // First write out all of the async bundles
        await writer.writeBundles(
            pageBundles.forEachAsyncBundleIter(),
            onAsyncBundleWritten,
            lassoContext);
    }

    async function writeSyncBundles () {
        if (perfLogInfoEnabled) {
            perfLogger.info('Async page bundles written in ' + (Date.now() - prevStartTime) + 'ms');
        }

        prevStartTime = Date.now();

        lassoContext.setPhase('write-page-bundles');

        // Now write out all of the non-async bundles
        await writer.writeBundles(
            pageBundles.forEachBundleIter(),
            onBundleWritten,
            lassoContext);
    }

    await buildPageBundles();
    await writeAsyncBundles();
    await writeSyncBundles();

    if (perfLogInfoEnabled) {
        perfLogger.info('Page bundles written in ' + (Date.now() - prevStartTime) + 'ms');
    }

    // All of the bundles have now been persisted, now we can
    // generate all of the HTML for the page
    buildHtmlSlots(pageBundles);

    perfLogger.info('Built page "' + pageName + '" in ' + (Date.now() - startTime) + 'ms');

    if (lassoContext.cache) {
        try {
            await lassoContext.cache.flushAll();
        } catch (err) {
            // The directory may have been manually purged. Do not throw an error
            // if one is missing.
            if (err.code !== 'ENOENT') throw err;
        }
    }

    return lassoPageResult;
}

function resolvePath(path, from) {
    const firstChar = path.charAt(0);
    if (firstChar === '.') {
        // path is relative to dependency directory
        return nodePath.resolve(from, path);
    } else if (isAbsolute(path)) {
        // path is absolute
        return path;
    } else {
        // path should be resolved using require.resolve() convention first
        // and attempt relative path resolution if that fails
        try {
            return resolveFrom(from, path);
        } catch (e) {
            // Not bothering to check error code since serverResolveRequire
            // should only throw error for one reason which is "module not found".
            // if (e.code === 'MODULE_NOT_FOUND') {
            //
            // }
            const resolvedPath = nodePath.resolve(from, path);

            // Since the path looked like it was for a module we should check
            // to see if the fallback technique actually found a file. If file
            // does not exist for fallback path, then we'll report an error
            // that the module does not exist by re-throwing the original error.
            if (cachingFs.existsSync(resolvedPath)) {
                // Fallback technique found the path.
                // We might want to log something here to suggest that relative
                // paths be prefixed with "." to avoid the extra work of trying to
                // resolve path using NodeJS module search path.
            } else {
                // Path is not a module or resolved path.
                // Since the path did not start with a "." let's
                // throw the error that we caught when trying to
                // resolve as module
                throw new Error('Failed to resolve path "' + path + '". Target file does not exist. Started search from directory "' + from + '".');
            }

            // We were able to r
            return resolvedPath;
        }
    }
}

async function doLassoResourceString (theLasso, path, cacheKey, options, lassoContext) {
    const inputPath = path;

    function done (err, result) {
        if (err) {
            throw createError('Error while resolving resource URL for path "' + path + '". Error: ' + err, err);
        }

        const url = result.url;

        if (logger.isDebugEnabled()) {
            logger.debug('Resolved URL: ', inputPath, ' --> ', url);
        }

        return result;
    }

    if (isExternalUrl(path)) {
        return done(null, { url: path });
    } else {
        const writer = theLasso.writer;

        const hashStart = path.indexOf('#');

        if (hashStart !== -1) {
            path = path.substring(0, hashStart);
        }

        let queryString = '';
        const queryStart = path.indexOf('?');

        if (queryStart !== -1) {
            queryString = path.substring(queryStart);
            path = path.substring(0, queryStart);
        }

        if (!isAbsolute(path)) {
            let dir = lassoContext.dir;

            if (!dir) {
                if (lassoContext.dependency) {
                    dir = lassoContext.dependency.getDir(lassoContext);
                }

                if (!dir) {
                    dir = lassoContext.getProjectRoot();
                }
            }

            path = resolvePath(path, dir);
        }

        if (!cachingFs.existsSync(path)) {
            throw new Error('File with path "' + path + '" does not exist');
        }

        let dataURIEncoding;
        let base64Requested = false;

        if (queryString === '?base64') {
            base64Requested = true;

            if (writer.base64EncodeSupported !== true) {
                dataURIEncoding = 'base64';
            }
        } else if (queryString === '?utf8') {
            dataURIEncoding = 'utf8';
        }

        if (dataURIEncoding) {
            try {
                const fileData = await fs.promises.readFile(path);
                const dataUrl = 'data:' + mime.getType(path) + ';' + dataURIEncoding + ',' + fileData.toString(dataURIEncoding);

                return done(null, {
                    url: dataUrl
                });
            } catch (err) {
                return done(err);
            }
        } else {
            // Record that base 64 encoding was requested for this resource (this might be helpful to the writer)
            if (base64Requested) {
                lassoContext = Object.create(lassoContext);
                lassoContext.base64EncodeUrl = true;
            }

            const writeResult = await writer.writeResource(path, lassoContext);
            return done(null, writeResult);
        }
    }
}

async function doLassoResourceBuffer (theLasso, buff, cacheKey, options, lassoContext) {
    const writer = theLasso.writer;

    try {
        const result = writer.writeResourceBuffer(buff, cacheKey, lassoContext);
        const url = result.url;

        if (logger.isDebugEnabled()) {
            logger.debug('Resolved URL for buffered resource: ', url);
        }

        return result;
    } catch (err) {
        throw createError('Error while resolving buffered resource URL', err);
    }
}

function _buildResourceCacheKey (cacheKey, theLasso, lassoContext) {
    const writer = theLasso.writer;
    const buildResourceCacheKey = writer.buildResourceCacheKey;

    if (buildResourceCacheKey) {
        cacheKey = buildResourceCacheKey.call(writer, cacheKey, lassoContext);
    }

    return cacheKey;
}

function Lasso(config) {
    ok(config, 'config is required');

    Lasso.$super.call(this);

    this.config = config;

    // LassoCache instances cache information associated with a specific
    this.lassoCacheLookup = {};

    this.dependencies = dependencies.createRegistry();

    this.initPlugins();

    let writer = this.writer;
    if (!writer) {
        if (!config.writer) {
            throw new Error('Writer not configured for page lasso config');
        }

        writer = createWriter(config.writer);

        writer.lasso = this;
        writer.config = this.config;
    }

    this.writer = writer;

    this.emit('lassoConfigured', {
        config: this.config,
        lasso: this
    });
}

Lasso.prototype = {

    initPlugins: function() {
        const plugins = this.config.getPlugins();
        for (let i = 0; i < plugins.length; i++) {
            const plugin = plugins[i];
            plugin.func(this, plugin.config || {});
        }
    },

    async createAppBundleMappings (bundleSetConfig, lassoContext) {
        ok(bundleSetConfig, '"bundleSetConfig" is required');

        const dependencyRegistry = this.dependencies;
        ok(dependencyRegistry, '"this.dependencies" is required');

        logger.debug('createAppBundleMappings() begin');

        const bundleMappings = new BundleMappings(this.config);

        for (const bundleConfig of bundleSetConfig.bundleConfigs) {
            const bundleName = bundleConfig.name;

            ok(bundleName, 'Illegal state. Bundle name is required');

            await bundleBuilder.buildBundle(
                bundleMappings,
                dependencyRegistry,
                bundleConfig,
                lassoContext);
        }

        logger.debug('createAppBundleMappings() *DONE*');
        return bundleMappings;
    },

    async buildPageBundles (options, lassoContext) {
        const pageName = options.pageName;
        const config = this.getConfig();
        const bundleSetConfig = config.getPageBundleSetConfig(pageName);
        const startTime = Date.now();

        logger.debug('buildPageBundles() BEGIN');

        async function buildPageBundleMappings(appBundleMappings) {
            logger.debug('buildPageBundles() - buildPageBundleMappings() BEGIN');

            const bundleMappings = new BundleMappings(config, lassoContext.pageName);

            if (appBundleMappings) {
                bundleMappings.setParentBundleMappings(appBundleMappings);
            }

            if (perfLogger.isInfoEnabled()) {
                perfLogger.info('Bundle mappings built in ' + (Date.now() - startTime) + 'ms');
            }

            return pageBundlesBuilder.build(options, config, bundleMappings, lassoContext);
        }

        if (config.isBundlingEnabled()) {
            logger.debug('buildPageBundles() - getAppBundleMappingsCached()');
            const cachedAppBundleMappings = await this.getAppBundleMappingsCached(bundleSetConfig, lassoContext);
            return buildPageBundleMappings(cachedAppBundleMappings);
        } else {
            return buildPageBundleMappings();
        }
    },

    async getAppBundleMappingsCached (bundleSetConfig, lassoContext) {
        const lassoCache = this.getLassoCache(lassoContext);
        const cacheKey = bundleSetConfig._id;

        logger.debug('getAppBundleMappingsCached()');

        const builder = () => {
            logger.debug('getAppBundleMappingsCached - BUILDER');
            return this.createAppBundleMappings(bundleSetConfig, lassoContext);
        };

        return lassoCache.getBundleMappings(cacheKey, builder);
    },

    buildLassoCacheKey: function(lassoContext) {
        let hash = 5381;
        const keyParts = [];

        function cacheKeyAdd (str) {
            keyParts.push(str);

            let i = str.length;
            while (i) {
                hash = (hash * 33) ^ str.charCodeAt(--i);
            }
        }

        this.emit('buildCacheKey', {
            context: lassoContext,
            config: this.config,
            lasso: this,
            cacheKey: {
                add: cacheKeyAdd
            }
        });

        const flags = lassoContext.flags;
        if (flags && !flags.isEmpty()) {
            cacheKeyAdd('flags:' + flags.getKey());
        }

        cacheKeyAdd('config:' + (lassoContext.config.cacheKey || lassoContext.config.getConfigFingerprint()));

        if (hash < 0) {
            hash = 0 - hash;
        }

        return {
            value: hash.toString(16),
            parts: keyParts
        };
    },

    /**
     * This method is used by the lasso page tag to
     * @param {Object} options is an object with the following properties:
     *    - page: the render context
     *    - flags: an array of enabled flags
     * @return {LassoCache} the lasso cache associated with this page lasso
     */
    getLassoCache: function(lassoContext) {
        let cache = lassoContext.cache;
        if (!cache) {
            const config = this.getConfig();

            const keyInfo = this.buildLassoCacheKey(lassoContext);
            const key = keyInfo.value;
            cache = this.lassoCacheLookup[key];
            if (!cache) {
                cache = this.lassoCacheLookup[key] = new LassoCache(key, {
                    dir: config.getCacheDir(),
                    keyParts: keyInfo.parts,
                    profile: config.getCacheProfile(),
                    profiles: config.getCacheProfiles()
                });

                const pluginContext = {
                    context: lassoContext,
                    config,
                    options: lassoContext.options,
                    lasso: this,
                    cacheKey: key,
                    lassoCache: cache
                };

                this.emit('lassoCacheCreated', pluginContext);
            }

            lassoContext.cache = cache;
        }
        return cache;
    },

    getConfig: function() {
        return this.config;
    },

    _resolveflags: function(options) {
        const flagSet = flags.createFlagSet();

        if (options) {
            let additionalFlags = options.flags || options.extensions || options.enabledExtensions;
            if (additionalFlags) {
                if (typeof additionalFlags === 'string') {
                    additionalFlags = additionalFlags.split(commaSeparatedRegExp);
                }
                flagSet.addAll(additionalFlags);
            }
        }

        flagSet.addAll(this.config.getFlags());

        return flagSet;
    },

    /**
     * A LassoContext is created for each call to Lasso::lassoPage
     * The LassoContext contains the following:
     * - flags: Complete list of enabled flags
     * - writer: A reference to the write configured by the Lasso
     * - lasso: A reference to the Lasso
     * - cache: Lasso.jsC
     */
    createLassoContext: function(options) {
        const writer = this.writer;
        const lassoContext = new LassoContext();

        options = options || {};

        if (options.basePath) {
            lassoContext.basePath = options.basePath;
        }

        if (options.data) {
            raptorUtil.extend(lassoContext.data, options.data);
            delete options.data;
        }

        lassoContext.dependencyRegistry = this.dependencies;
        lassoContext.flags = this._resolveflags(options);
        lassoContext.config = this.config;
        lassoContext.writer = writer;
        lassoContext.lasso = this;
        lassoContext.options = options;
        // cache must come last so that all of the data above will
        // be available on the lassoContext that will be part of the subsequent
        // payload of the event that will be emitted after the cache is fetched.
        lassoContext.cache = this.getLassoCache(lassoContext);

        return lassoContext;
    },

    async lassoPage (options) {
        const lassoContext = options.lassoContext || this.createLassoContext(options);

        if (options.cache === false) {
            return doLassoPage(this, options, lassoContext);
        }

        const lassoCache = this.getLassoCache(lassoContext);
        const cacheKey = options.cacheKey || options.pageName || options.name;

        const lassoPageResult = await lassoCache.getLassoPageResult(cacheKey, {
            builder: async () => {
                // Reuse the same lasso context
                options = extend({ lassoContext }, options);
                return doLassoPage(this, options, lassoContext);
            }
        });

        this.emit('afterLassoPage', {
            context: lassoContext,
            lasso: this,
            result: lassoPageResult
        });

        return lassoPageResult;
    },

    async prebuildPage (pageConfig, { writeToDisk = true } = {}) {
        ok(pageConfig, '"pageConfig" is required by "lasso.prebuildPage(...)"');

        let pageConfigs;
        if (Array.isArray(pageConfig)) {
            pageConfigs = pageConfig;
        } else if (typeof pageConfig === 'object') {
            pageConfigs = [pageConfig];
        } else {
            throw new Error('"pageConfig" should either be an array or object passed to "lasso.prebuildPage(...)"');
        }

        const lassoPrebuildResult = new LassoPrebuildResult();

        for (let i = 0; i < pageConfigs.length; i++) {
            const pageConfig = pageConfigs[i];
            ok(typeof pageConfig === 'object', 'All pages passed to "lasso.prebuildPage(...)" should be an object');

            const cwd = process.cwd();
            const lassoPageResult = await this.lassoPage(pageConfig);
            const name = buildPrebuildName(pageConfig.pageName);

            const lassoPrebuild = lassoPageResult.toLassoPrebuild(name || cwd, pageConfig.flags);

            const pageDir = pageConfig.pageDir || cwd;
            const fileName = buildPrebuildFileName(name);
            const buildPath = nodePath.resolve(pageDir, fileName);

            lassoPrebuildResult.addBuild(buildPath, lassoPrebuild);
        }

        if (writeToDisk) await lassoPrebuildResult.write();
        return lassoPrebuildResult;
    },

    async loadPrebuild (options = {}) {
        const { path, flags } = options;
        // TODO: If the prebuild does not exist, we should just use the lassoPage flow

        // If we've already found the prebuild at this path, we can just return it
        let lassoPageResult;
        if ((lassoPageResult = prebuildToPath[path])) {
            return lassoPageResult;
        }

        let prebuildFile;
        try {
            prebuildFile = require(path);
        } catch (err) {
            throw new Error(`Error loading prebuild. No prebuild with path "${path}" exists. Error: ${err.toString()}`);
        }

        // TODO: Consider changing this to just the dash separated cache key for flags
        let build;
        if (flags) {
            for (const prebuild of prebuildFile) {
                try {
                    assert.deepEqual(prebuild.flags, flags);
                    build = prebuild;
                    break;
                } catch (err) {}
            }
        } else {
            // Try to find a prebuild that does not require flags
            for (const prebuild of prebuildFile) {
                if (!prebuild.flags || !prebuild.flags.length) {
                    build = prebuild;
                    break;
                }
            }
        }

        if (!build) {
            const flagsStr = (flags && flags.join(',')) || flags;
            throw new Error(`No build could be found using flags: "${flagsStr}" for file at path "${path}"`);
        }

        lassoPageResult = new LassoPageResult();
        lassoPageResult.setSlotsByName(build.slots);
        lassoPageResult.resources = build.resources;

        prebuildToPath[path] = lassoPageResult;

        return lassoPageResult;
    },

    /**
     * @param  {String} path The file path of the resource to bundle
     * @param  {Object} options (see below for supported options)
     */
    async lassoResource (data, options) {
        let lassoContext;
        options = options || {};

        if (options.LassoContext === true) {
            lassoContext = options;
            options = {};
        }

        if (!lassoContext) {
            lassoContext = options.lassoContext || this.createLassoContext(options);
        }

        const lassoPageResult = lassoContext.lassoPageResult;

        function done (result) {
            if (lassoPageResult && result) {
                lassoPageResult.registerResource(result);
            }

            return result;
        }

        let lassoResourceResult;

        const dataType = typeof data;
        const resourceHandlers = resourceHandlersByType[dataType];

        if (!resourceHandlers) {
            throw new Error(`Unsupported data type "${dataType}" passed to "lassoResource"`);
        }

        const useCache = options.cache !== false;

        // If the resource type has the `hashPath` property set, we have to
        // calculate the cache key to use it for the file path even if the
        // the `cache` option is not set.
        let cacheKey = null;
        if (resourceHandlers.hashPath || useCache) {
            cacheKey = resourceHandlers.calculateKey(data, this, lassoContext, options);
        }

        if (useCache) {
            const cache = this.getLassoCache(lassoContext);

            lassoResourceResult = await cache.getLassoedResource(cacheKey, async () => {
                return resourceHandlers.resource(this, data, cacheKey, options, lassoContext);
            });
        } else {
            lassoResourceResult = await resourceHandlers.resource(this, data, cacheKey, options, lassoContext);
        }

        return done(lassoResourceResult);
    },

    addTransform: function(transform) {
        this.config.addTransform(transform);
    },

    getDependencyRegistry() {
        return this.dependencies;
    }
};

raptorUtil.inherit(Lasso, EventEmitter);

module.exports = Lasso;


================================================
FILE: src/LassoCache.js
================================================
const raptorCache = require('raptor-cache');
const nodePath = require('path');
const LassoPageResult = require('./LassoPageResult');
const DEFAULT_BASE_CACHE_DIR = nodePath.join(require('app-root-dir').get(), '.cache/lasso');
const deserializeLassoPageResult = LassoPageResult.deserialize;
const serializeLassoPageResult = LassoPageResult.serialize;
const fs = require('fs');
const mkdirp = require('mkdirp');

function safeFilename(name) {
    return name.replace(/[^A-Za-z0-9_\-\.\/]/g, '-');
}

function waitImmediate() {
    return new Promise(resolve => setImmediate(resolve));
}

const CACHE_DEFAULTS = {
    '*': { // Any profile
        '*': { // Any cache
            store: 'memory' // Default to a memory store for all caches for all profiles
        },
        lassoPageResults: {
            store: 'memory',
            serialize: serializeLassoPageResult,
            deserialize: deserializeLassoPageResult
        },
        bundleMappings: {
            store: 'memory'
        },
        lassoedResources: {
            store: 'memory',
            valueType: 'json'
        },
        dependencyFingerprints: {
            store: 'disk',
            valueType: 'string'
        },
        read: {
            store: 'disk',
            singleFile: false,
            encoding: 'utf8'
        }
    },
    production: { // Read and write to disk cache in production
        lassoPageResults: {
            store: 'disk'
        },
        bundleMappings: {
            store: 'memory'
        },
        lassoedResources: {
            store: 'disk'
        },
        dependencyFingerprints: {
            store: 'disk'
        }
    }
};

class SyncCache {
    constructor() {
        this._store = {};
    }

    getSync(key) {
        return this._store[key];
    }

    putSync(key, value) {
        this._store[key] = value;
    }
}

function LassoCache(key, options) {
    const cacheProfileName = options.profile;
    const keyParts = options.keyParts;

    let cacheManager;

    if (typeof options.cacheManagerFactory === 'function') {
        cacheManager = options.cacheManagerFactory({
            profile: cacheProfileName,
            profiles: options.profiles
        });
    }

    this.cacheManager = cacheManager || options.cacheManager || raptorCache.createCacheManager({
        profile: cacheProfileName,
        profiles: options.profiles
    });

    this.key = key;

    const _this = this;

    this.cacheManager.on('cacheConfigured', function(eventArgs) {
        const cacheName = eventArgs.name;
        const cacheConfig = eventArgs.config;

        if (!cacheConfig.dir) {
            // Just in case this this cache uses a disk store we will configure a safe directory to use
            cacheConfig.dir = nodePath.join(_this.baseCacheDir, safeFilename(cacheName));
        }
    });

    this.baseCacheName = safeFilename(cacheProfileName || 'default') + (key ? '/' + safeFilename(key) : '');
    this.baseCacheDir = options.dir || DEFAULT_BASE_CACHE_DIR;

    if (keyParts) {
        const keyDir = nodePath.join(this.baseCacheDir, this.baseCacheName);
        mkdirp.sync(keyDir);
        const keyFile = nodePath.join(keyDir, 'key');

        try {
            fs.writeFileSync(keyFile, JSON.stringify(keyParts), { encoding: 'utf8' });
        } catch (e) {
            // We only write the key for debugging purposes. On machines with
            // read only disks this will fail but that is okay
        }
    }

    // Merge in the lasso defaults (the user profiles, if any, have already been merged)
    this.configureCacheDefaults(CACHE_DEFAULTS);

    this.lassoPageResultCache = this.getCache('lassoPageResults');
    this.bundleMappingsCache = this.getCache('bundleMappings');
    this.lassoedResourcesCache = this.getCache('lassoedResources');
    this.dependencyFingerprintsCache = this.getCache('dependencyFingerprints');
    this.readCache = this.getCache('read');

    this.syncCaches = {};
}

LassoCache.prototype = {
    configureCacheDefaults: function(profileName, cacheConfigName, defaults) {
        this.cacheManager.configureCacheDefaults.apply(this.cacheManager, arguments);
    },

    getCache: function(name, cacheConfigName) {
        if (!cacheConfigName) {
            cacheConfigName = name;
        }

        name = this.baseCacheName + '/' + name;
        return this.cacheManager.getCache(name, cacheConfigName);
    },

    getSyncCache: function(name) {
        return this.syncCaches[name] || (this.syncCaches[name] = new SyncCache());
    },

    flushAll () {
        return raptorCache.flushAll();
    },

    async getLassoPageResult(cacheKey, options) {
        return this.lassoPageResultCache.get(cacheKey, options);
    },

    async getBundleMappings (id, builder) {
        await waitImmediate();

        while (process.domain) {
            process.domain.exit();
        }

        return this.bundleMappingsCache.get(id.toString(), { builder });
    },

    async getLassoedResource (path, builder) {
        await waitImmediate();

        while (process.domain) {
            process.domain.exit();
        }

        return this.lassoedResourcesCache.get(path, { builder });
    },

    async getDependencyFingerprint (cacheKey, lastModified, builder) {
        await waitImmediate();

        while (process.domain) {
            process.domain.exit();
        }

        return this.dependencyFingerprintsCache.get(cacheKey, {
            lastModified,
            builder
        });
    }
};

module.exports = LassoCache;


================================================
FILE: src/LassoContext.js
================================================
const EventEmitter = require('events').EventEmitter;
const lastModified = require('./last-modified');
const cachingFs = require('./caching-fs');
const DeferredReadable = require('./util/DeferredReadable');
const manifestLoader = require('./manifest-loader');
const LassoManifest = require('./LassoManifest');
const util = require('./util');
const getClientPath = require('lasso-modules-client/transport').getClientPath;
const resolve = require('./resolve');

class LassoContext extends EventEmitter {
    constructor() {
        super();

        this.data = {};
        this.phaseData = {};
        this._phase = null;
        this.cachingFs = cachingFs;

        let nextId = 0;

        this.uniqueId = function() {
            return nextId++;
        };
    }

    deferredStream(startFn, options) {
        return new DeferredReadable(startFn, options);
    }

    /**
     * Converts a "reader" function to a function that *always* returns a stream.
     * The actual reader function may return a promise, a String, a stream or it may use a callback.
     */
    createReadStream(func) {
        return util.readStream(func);
    }

    clearData() {
        this.data = {};
    }

    getData(name) {
        return this.data[name];
    }

    setData(name, value) {
        this.data[name] = value;
    }

    async getFileLastModified (filePath) {
        const lastModifiedResult = await lastModified.forFile(filePath);
        return lastModifiedResult || -1;
    }

    setPhase(phaseName) {
        this._phase = phaseName;
        this.phaseData = {}; // Clear out the phase data
    }

    isPageBundlingPhase() {
        return this._phase === 'page-bundle-mappings';
    }

    isAppBundlingPhase() {
        return this._phase === 'app-bundle-mappings';
    }

    isAsyncBundlingPhase() {
        return this._phase === 'async-page-bundle-mappings';
    }

    readPackageFile(path) {
        const rawManifest = manifestLoader.load(path);
        return new LassoManifest({
            manifest: rawManifest,
            dependencyRegistry: this.dependencyRegistry
        });
    }

    createFingerprintStream() {
        return util.createFingerprintStream();
    }

    getClientPath(file) {
        return getClientPath(file);
    }

    getResolver() {
        if (this.resolver === undefined) {
            this.resolver = resolve.createResolver(this, getClientPath);
        }
        return this.resolver;
    }

    resolve(targetModule, fromDir, options) {
        return this.getResolver().resolve(targetModule, fromDir, options);
    }

    resolveCached(targetModule, fromDir, options) {
        return this.getResolver().resolveCached(targetModule, fromDir, options);
    }

    getProjectRoot() {
        return this.config.getProjectRoot();
    }
}

LassoContext.prototype.LassoContext = true;

module.exports = LassoContext;


================================================
FILE: src/LassoManifest.js
================================================
const extend = require('raptor-util').extend;
const DependencyList = require('./DependencyList');
const ok = require('assert').ok;

const nodePath = require('path');
const FlagSet = require('./FlagSet');
let nextId = 0;

const condition = require('./condition');

const lassoResolveFrom = require('lasso-resolve-from');

const logger = require('raptor-logging').logger(module);

const hasOwn = Object.prototype.hasOwnProperty;

function resolveBrowserPath(dir, path) {
    let resolved;

    if (path.charAt(0) === '.') {
        resolved = lassoResolveFrom(dir, path);
    } else {
        resolved = lassoResolveFrom(dir, './' + path);
        if (!resolved) {
            resolved = lassoResolveFrom(dir, path);
        }
    }

    return resolved ? resolved.path : undefined;
}

function LassoManifest(options) {
    const dependencyRegistry = options.dependencyRegistry;

    let async;

    if (options.manifest) {
        // save off the async property value
        async = options.manifest.async;

        extend(this, options.manifest);
    }

    ok(dependencyRegistry, '"dependencyRegistry" is required');

    this._uniqueId = nextId++;

    if (options.dirname) {
        this.dirname = options.dirname;
    }

    if (options.filename) {
        this.filename = options.filename;
    }

    const dirname = this.dirname;
    const filename = this.filename;

    ok(dirname, '"dirname" is required');
    ok(typeof dirname === 'string', '"dirname" must be a string');

    this.dependencies = new DependencyList(
        this.dependencies || [],
        dependencyRegistry,
        dirname,
        filename);

    this.async = null;

    if (async) {
        if (typeof async !== 'object') {
            throw new Error('async should be an object. (dirname=' + dirname + ', filename=' + filename + ')');
        }

        this.async = {};

        for (const asyncPackageName in async) {
            if (hasOwn.call(async, asyncPackageName)) {
                const asyncDependencies = async[asyncPackageName];
                this.async[asyncPackageName] = new DependencyList(
                    asyncDependencies,
                    dependencyRegistry,
                    dirname,
                    filename);
            }
        }
    }

    const requireRemap = this.requireRemap;
    if (requireRemap && Array.isArray(requireRemap)) {
        this.requireRemap = requireRemap.map((requireRemap) => {
            const from = resolveBrowserPath(dirname, requireRemap.from);
            const to = resolveBrowserPath(dirname, requireRemap.to);

            return {
                from,
                to,
                condition: condition.fromObject(requireRemap)
            };
        });
    }
}

LassoManifest.prototype = {
    __LassoManifest: true,

    getUniqueId: function() {
        return this._uniqueId;
    },

    resolve: function(relPath) {
        return nodePath.resolve(this.dirname, relPath);
    },

    /**
     *
     * @param options
     * @returns
     */
    async getDependencies (options) {
        logger.debug('getDependencies()');

        let flags = options && options.flags;
        if (!flags || !flags.__FlagSet) {
            flags = new FlagSet(flags);
        }

        logger.debug('getDependencies() Normalizing dependencies BEGIN: ', this.dependencies);

        const dependencies = await this.dependencies.normalize();
        logger.debug('getDependencies() Normalizing dependencies DONE: ', this.dependencies);
        return dependencies;
    },

    getRequireRemap: function(lassoContext) {
        if (this.requireRemap && Array.isArray(this.requireRemap)) {
            const filteredRemaps = {};
            const flags = lassoContext.flags;

            this.requireRemap.forEach(function(remap) {
                if (remap.condition && !remap.condition(flags)) {
                    return;
                }

                filteredRemaps[remap.from] = remap.to;
            });

            return filteredRemaps;
        } else {
            return {};
        }
    }
};

LassoManifest.isLassoManifest = function(o) {
    return o && o.__LassoManifest;
};

module.exports = LassoManifest;


================================================
FILE: src/LassoPageResult.js
================================================
const Slot = require('./Slot');
const EMPTY_OBJECT = {};
const hasOwn = Object.prototype.hasOwnProperty;

function LassoPageResult () {
    this.urlsBySlot = {};
    this.urlsByContentType = {};
    this.files = [];
    this.infoByBundleName = {};
    this.infoByAsyncBundleName = {};
    this.resources = [];
    this._slotsByName = {};

    /**
     * If Lasso is configured to fingerprint inline code for
     * the purpose of Content Security Policy then this property
     * will store the array of fingerprints.
     */
    this._inlineCodeFingerprints = undefined;
}

LassoPageResult.deserialize = function (reader) {
    let json = '';

    return new Promise((resolve, reject) => {
        reader()
            .on('data', function (data) {
                json += data;
            })
            .on('end', function () {
                resolve(Object.assign(new LassoPageResult(), JSON.parse(json)));
            })
            .on('error', function (err) {
                reject(err);
            });
    });
};

LassoPageResult.serialize = function(lassoPageResult) {
    return JSON.stringify(lassoPageResult);
};

LassoPageResult.prototype = {
    /**
     * Returns the HTML for all slots on the page.
     *
     * An object is returned in which property name
     * is the name of the slot and the value is the corresponding
     * HTML for the slot.
     *
     * <p>
     * Example output:
     * <js>
     * {
     *   'body': '<script src="/static/test-page-body-f01892af.js"></script>',
     *   'head': '<link rel="stylesheet" href="/static/test-page-head-bf4cf798.css">'
     * }
     * </js>
     *
     * @return {Object} An object with slot names as property names and slot HTML as property values.
     */
    get htmlBySlot() {
        const htmlBySlot = {};
        for (const slotName in this._slotsByName) {
            if (hasOwn.call(this._slotsByName, slotName)) {
                const slotHtml = this.getHtmlForSlot(slotName);
                htmlBySlot[slotName] = slotHtml;
            }
        }

        return htmlBySlot;
    },

    getHtmlBySlot: function() {
        return this.htmlBySlot;
    },

    /**
     * Returns the HTML for a single slot.
     * <p>
     * Example out:
     * <js>
     * "<script src="/static/test-page-body-f01892af.js"></script>"
     * </js>
     *
     * @param  {String} slotName The name of the slot (e.g. "head" or "body")
     * @param  {Object} data Input data to the slot that is used to render the actual slot HTML
     * @return {String} The HTML for the slot or an empty string if there is no HTML defined for the slot.
     */
    getHtmlForSlot: function(slotName, data) {
        const slots = this._slotsByName[slotName];

        if (slots) {
            const slotData = data || EMPTY_OBJECT;
            let html = '';
            let sep = '';
            for (const slot of slots) {
                html += sep + Slot.render(slot, slotData);
                sep = '\n';
            }

            return html;
        }

        return '';
    },

    getHeadHtml: function(data) {
        return this.getHtmlForSlot('head', data);
    },

    getBodyHtml: function(data) {
        return this.getHtmlForSlot('body', data);
    },

    /**
     * Synonym for {@Link raptor/lasso/LassoPageResult#getHtmlForSlot}
     */
    getSlotHtml: function(slotName, data) {
        return this.getHtmlForSlot(slotName, data);
    },

    setSlotsByName: function(slotsByName) {
        this._slotsByName = slotsByName;
    },

    registerBundle: function(bundle, async, lassoContext) {
        const bundleInfoMap = async
            ? this.infoByAsyncBundleName
            : this.infoByBundleName;

        const info = bundleInfoMap[bundle.name] || (bundleInfoMap[bundle.name] = {});
        const url = bundle.getUrl(lassoContext);
        const slot = async ? undefined : bundle.slot;

        if (url) {
            this.addUrl(url, bundle.getSlot(), bundle.getContentType(), async, slot);
            info.url = url;
        }

        if (!bundle.isExternalResource && bundle.outputFile) {
            this.addFile(bundle.outputFile, bundle.getContentType(), async, slot);
            info.file = bundle.outputFile;
        }
    },

    registerResource: function(resource) {
        this.resources.push(resource);
    },

    addUrl: function(url, slot, contentType, isAsync) {
        if (!isAsync) {
            const urlsForSlot = this.urlsBySlot[slot] || (this.urlsBySlot[slot] = []);
            urlsForSlot.push(url);
        }

        const urlsForContentType = this.urlsByContentType[contentType] || (this.urlsByContentType[contentType] = []);
        urlsForContentType.push(url);
    },

    getOutputFilesWithInfo() {
        return this.files;
    },

    addFile: function(filePath, contentType, isAsync, slot) {
        this.files.push({
            path: filePath,
            contentType,
            async: isAsync,
            slot
        });
    },

    /**
     * Returns the URLs of all the JavaScript resources for the page
     * @return {Array<String>} An array of URLs
     */
    getJavaScriptUrls: function() {
        return this.urlsByContentType.js || [];
    },

    /**
     * Returns the URLs of all the CSS resources for the page
     * @return {Array<String>} An array of URLs
     */
    getCSSUrls: function() {
        return this.urlsByContentType.css || [];
    },

    /**
     * Returns the URLs of all the JavaScript resources for the page
     * @return {Array<String>} An array of URLs
     */
    getUrlsForSlot: function(slot) {
        return this.urlsBySlot[slot] || [];
    },

    /**
     * Returns the {@Link raptor/files/File} objects for all the JavaScript resources for the page
     * @return {Array<raptor/files/File>} An array of File objects
     */
    getJavaScriptFiles: function() {
        return this.getFilePathsByContentType('js');
    },

    getFilePathsByContentType(contentType) {
        const paths = [];
        this.files.forEach((file) => {
            if (file.contentType === contentType) {
                paths.push(file.path);
            }
        });
        return paths;
    },

    /**
     * Returns the {@Link raptor/files/File} objects for all the CSS resources for the page
     * @return {Array<raptor/files/File>} An array of File objects
     */
    getCSSFiles: function() {
        return this.getFilePathsByContentType('css');
    },

    getOutputFiles: function() {
        return this.getJavaScriptFiles().concat(this.getCSSFiles());
    },

    getFileByBundleName: function(bundleName) {
        const info = this.infoByBundleName[bundleName];
        return info && info.file;
    },

    getFileByAsyncBundleName: function(bundleName) {
        const info = this.infoByAsyncBundleName[bundleName];
        return info && info.file;
    },

    getUrlByBundleName: function(bundleName) {
        const info = this.infoByBundleName[bundleName];
        return info && info.url;
    },

    getUrlByAsyncBundleName: function(bundleName) {
        const info = this.infoByAsyncBundleName[bundleName];
        return info && info.url;
    },

    getInlineCodeFingerprints: function() {
        return this._inlineCodeFingerprints;
    },

    setInlineCodeFingerprints: function(inlineCodeFingerprints) {
        this._inlineCodeFingerprints = inlineCodeFingerprints;
    },

    toLassoPrebuild (name, flags) {
        return {
            slots: this._slotsByName,
            assets: this.resources,
            name,
            flags
        };
    }
};

module.exports = LassoPageResult;


================================================
FILE: src/LassoPrebuildResult.js
================================================
const fs = require('fs');

/**
* We may want to store the prebuild in the same directory as the page
* file instead of the current working directory. There will often be
* an npm script that is running at the base of the project. In the
* AWS Lambda case, we want the prebuild file to live alongside of the
* page itself. We need to preprocess all of the builds and then write
* them individually after because there may be multiple pages that live
* in the same directory as well as multiple builds for the same page
* with different flags.
*/
class LassoPrebuildResult {
    constructor () {
        this._buildsByPath = {};
    }

    addBuild (path, build) {
        if (this._buildsByPath[path]) {
            this._buildsByPath[path].push(build);
        } else {
            this._buildsByPath[path] = [build];
        }
    }

    async write () {
        for (const buildPath in this._buildsByPath) {
            await fs.promises.writeFile(
                buildPath,
                this.serializeBuild(buildPath),
                'utf8');
        }
    }

    serializeBuild (path) {
        const build = this._buildsByPath[path];
        return JSON.stringify(build, null, 2);
    }

    getBuildByPath (path) {
        return this._buildsByPath[path];
    }

    getBuildsByPath () {
        return this._buildsByPath;
    }
}

module.exports = LassoPrebuildResult;


================================================
FILE: src/LoaderMetadata.js
================================================
const AsyncPackage = require('./AsyncPackage');
function LoaderMetadata() {
    this._packageNames = Object.create(null);
    this._asyncPackagesByName = {};
}

LoaderMetadata.prototype = {

    addAsyncPackageName: function(asyncName) {
        this._packageNames[asyncName] = true;
    },

    addBundle: function(asyncName, bundle) {
        const asyncPackage = this._asyncPackagesByName[asyncName] || (this._asyncPackagesByName[asyncName] = new AsyncPackage(asyncName));
        asyncPackage.addBundle(bundle);
    },

    /**
     * This method is used by lasso-modules-client/transport/src/code-loader-metadata.js
     * to create simple object that can be stringified to generate code for
     * lasso metadata.
     */
    toObject: function(context) {
        if (!context) {
            throw new Error('"context" is required');
        }

        // EXAMPLE RESULT:
        /*
        {
            "foo": {
                js: ['a.js'],
                css: ['b.js']
            }
        }
        */
        const result = {};

        for (const name in this._packageNames) {
            const asyncPackage = this._asyncPackagesByName[name];
            if (asyncPackage) {
                result[name] = asyncPackage.getMeta(context);
            } else {
                result[name] = {};
            }
        }

        return result;
    }
};

module.exports = LoaderMetadata;


================================================
FILE: src/PageBundles.js
================================================
const forEachEntry = require('raptor-util').forEachEntry;

/**
 *
 */
const PageBundles = function() {
    this.bundles = [];
    this.bundleLookup = {};
    this.asyncBundleLookup = {};
};

PageBundles.prototype = {
    addSyncBundle: function(bundle) {
        /*
         * Add the bundle to a page slot if it has not already been added
         */
        const bundleLookupKey = bundle.getKey();

        if (!this.bundleLookup[bundleLookupKey]) {
            this.bundleLookup[bundleLookupKey] = bundle;
            this.bundles.push(bundle);
        }
    },

    addAsyncBundle: function(bundle) {
        this.asyncBundleLookup[bundle.getKey()] = bundle;
    },

    lookupSyncBundle: function(bundle) {
        return this.bundleLookup[bundle.getKey()];
    },

    forEachBundle: function(callback, thisObj) {
        this.bundles.forEach(callback, thisObj);
    },

    forEachAsyncBundle: function(callback, thisObj) {
        forEachEntry(this.asyncBundleLookup, function(bundleKey, bundle) {
            callback.call(thisObj, bundle);
        }, this);
    },

    forEachBundleIter: function() {
        return this.forEachBundle.bind(this);
    },

    forEachAsyncBundleIter: function() {
        return this.forEachAsyncBundle.bind(this);
    }
};

module.exports = PageBundles;


================================================
FILE: src/PageConfig.js
================================================
function PageConfig() {
    this.name = null;
    this.bundleSetConfig = null;
    this.packageManifest = null;
}

PageConfig.prototype = {

    getBundleSetConfig: function() {
        return this.bundleSetConfig;
    },

    addBundleSetConfig: function(bundleSetConfig) {
        if (this.bundleSetConfig) {
            throw new Error('Page "' + this.name + '" already has bundles defined"');
        }

        this.bundleSetConfig = bundleSetConfig;
    },

    setPackageManifest: function(packageManifest) {
        this.packageManifest = packageManifest;
    },

    getPackageManifest: function() {
        return this.packageManifest;
    },

    getName: function() {
        return this.name;
    },

    toString: function() {
        return '[PageConfig name=' + this.name + ']';
    }
};

module.exports = PageConfig;


================================================
FILE: src/Slot.js
================================================
const ok = require('assert').ok;
const stringifyAttrs = require('./util/stringify-attrs');

function Slot(contentType) {
    ok(contentType, 'contentType is required');
    this.contentType = contentType;
    this.content = [];
}

Slot.prototype = {
    addInlineCode: function(code, merge) {
        if (merge) {
            const prev = this.content.length ? this.content[this.content.length - 1] : null;
            if (prev && prev.inline && prev.merge && typeof prev.code === 'string') {
                prev.code += '\n' + code;
                return;
            }
        }

        this.content.push({
            inline: true,
            code,
            merge: merge !== false
        });
    },

    addContent: function(content) {
        this.content.push({
            inline: false,
            code: content
        });
    }
};

Slot.render = function(slot, data) {
    let html = '';
    let sep = '';

    for (const content of slot.content) {
        html += sep;
        sep = '\n';

        switch (slot.contentType) {
        case 'js':
            html += (content.inline ? inlineScript : externalScript)(content.code, data);
            break;
        case 'css':
            html += (content.inline ? inlineStyle : externalStyle)(content.code, data);
            break;
        default:
            throw new Error('Invalid content type: ' + slot.contentType);
        }
    }

    return html;
};

function inlineScript(content, data) {
    const scriptAttrs = data.externalScriptAttrs;
    let result = `<script${stringifyAttrs(data.inlineScriptAttrs)}>`;

    if (scriptAttrs) {
        if (scriptAttrs.async) {
            result += wrapInDocumentLoaded(content, true);
        } else if (scriptAttrs.defer) {
            result += wrapInDocumentLoaded(content);
        } else {
            result += content;
        }
    } else {
        result += content;
    }

    return `${re
Download .txt
gitextract_n7scrtee/

├── .editorconfig
├── .eslintrc
├── .gitignore
├── .npmignore
├── .travis.yml
├── CHANGELOG.md
├── README.md
├── browser-refresh/
│   └── index.js
├── docs/
│   ├── amd.md
│   ├── bundling.md
│   ├── javascript-api.md
│   └── migration-optimizer-to-lasso.md
├── getImageInfo.js
├── index.js
├── middleware/
│   ├── index.js
│   ├── koa/
│   │   └── serveStatic.js
│   └── serveStatic.js
├── node-require-no-op.js
├── package.json
├── src/
│   ├── AsyncPackage.js
│   ├── Bundle.js
│   ├── BundleConfig.js
│   ├── BundleMappings.js
│   ├── BundleSetConfig.js
│   ├── Config.js
│   ├── DependencyList.js
│   ├── DependencyTree.js
│   ├── FlagSet.js
│   ├── InlinePos.js
│   ├── Lasso.js
│   ├── LassoCache.js
│   ├── LassoContext.js
│   ├── LassoManifest.js
│   ├── LassoPageResult.js
│   ├── LassoPrebuildResult.js
│   ├── LoaderMetadata.js
│   ├── PageBundles.js
│   ├── PageConfig.js
│   ├── Slot.js
│   ├── SlotTracker.js
│   ├── browser-refresh/
│   │   └── index.js
│   ├── bundle-builder.js
│   ├── bundling-strategies.js
│   ├── caching-fs.js
│   ├── condition.js
│   ├── config-loader.js
│   ├── content-types.js
│   ├── dependencies/
│   │   ├── Dependency.js
│   │   ├── DependencyRegistry.js
│   │   ├── RequireHandler.js
│   │   ├── dependency-comment.js
│   │   ├── dependency-dependencies.js
│   │   ├── dependency-intersection.js
│   │   ├── dependency-package.js
│   │   ├── dependency-resource.js
│   │   ├── glob.js
│   │   └── index.js
│   ├── dependency-walker.js
│   ├── flags.js
│   ├── index.js
│   ├── last-modified.js
│   ├── manifest-loader.js
│   ├── middleware/
│   │   ├── index.js
│   │   ├── koa/
│   │   │   └── serveStatic.js
│   │   └── serveStatic.js
│   ├── node-require-no-op/
│   │   └── index.js
│   ├── page-bundles-builder.js
│   ├── path.js
│   ├── plugins/
│   │   ├── lasso-image/
│   │   │   ├── index.js
│   │   │   ├── lasso-image-browser.js
│   │   │   └── package.json
│   │   ├── lasso-minify-css/
│   │   │   └── index.js
│   │   ├── lasso-minify-js/
│   │   │   └── index.js
│   │   └── lasso-resolve-css-urls/
│   │       └── index.js
│   ├── reader.js
│   ├── require/
│   │   ├── build-plugin-config.js
│   │   ├── dep-require-remap.js
│   │   ├── dep-require.js
│   │   ├── dep-runtime.js
│   │   ├── dep-transport-builtin.js
│   │   ├── dep-transport-define.js
│   │   ├── dep-transport-installed.js
│   │   ├── dep-transport-loader-metadata.js
│   │   ├── dep-transport-main.js
│   │   ├── dep-transport-ready.js
│   │   ├── dep-transport-remap.js
│   │   ├── dep-transport-run.js
│   │   ├── dep-transport-search-path.js
│   │   ├── index.js
│   │   ├── inspect-cache.js
│   │   └── util/
│   │       ├── Deduper.js
│   │       ├── DeduperContext.js
│   │       ├── StringTransformer.js
│   │       ├── Transforms.js
│   │       ├── inspect.js
│   │       ├── normalizeFSPath.js
│   │       └── streamToString.js
│   ├── resolve/
│   │   ├── builtins.js
│   │   ├── getRequireRemapFromDir.js
│   │   ├── index.js
│   │   └── parseRequire.js
│   ├── transforms.js
│   ├── util/
│   │   ├── CombinedStream.js
│   │   ├── DeferredReadable.js
│   │   ├── caching-stream.js
│   │   ├── fingerprint-stream.js
│   │   ├── hash.js
│   │   ├── index.js
│   │   ├── prebuild.js
│   │   ├── stringify-attrs.js
│   │   └── url-reader.js
│   └── writers/
│       ├── Writer.js
│       ├── file-writer.js
│       └── index.js
├── test/
│   ├── .eslintrc
│   ├── .gitignore
│   ├── api-test.js
│   ├── autotest.js
│   ├── autotests/
│   │   ├── api/
│   │   │   ├── config-fingerprint/
│   │   │   │   ├── foo.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-lassoPage-promise/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-lassoResource-buffer/
│   │   │   │   └── test.js
│   │   │   ├── lasso-lassoResource-buffer-name/
│   │   │   │   └── test.js
│   │   │   ├── lasso-lassoResource-promise/
│   │   │   │   ├── foo.txt
│   │   │   │   └── test.js
│   │   │   ├── myLasso-lassoPage-promise/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   └── test.js
│   │   │   ├── myLasso-lassoResource-promise/
│   │   │   │   ├── foo.txt
│   │   │   │   └── test.js
│   │   │   └── pollute-default-config/
│   │   │       └── test.js
│   │   ├── bundling/
│   │   │   ├── async-dependencies/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo-async.js
│   │   │   │   ├── foo-something-else.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-flags/
│   │   │   │   ├── DO_NOT_INCLUDE_ME.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-package/
│   │   │   │   ├── bar.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── bundle-getImageInfo-skip/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── bundles/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── d.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── bundling-strategy-default/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── bundling-strategy-lean/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── bundling-virtual-module/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── csp-nonce-inline-script/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── css-inline-resource-base64/
│   │   │   │   ├── expected.css
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── css-inline-resource-utf8/
│   │   │   │   ├── expected.css
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── css-resources-multiple-pages-no-bundling/
│   │   │   │   ├── foo.css
│   │   │   │   ├── foo.resource
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── custom-dependency-type-no-bundling/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── dedupe/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── d.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── dependency-code/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── escape-external-css-url/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── escape-external-js-url/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── external-js/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── external-js-inlined/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── external-js-integrity/
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── fingerprints/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── glob-patterns/
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   ├── require/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── foo.js
│   │   │   │   ├── style/
│   │   │   │   │   ├── style1.css
│   │   │   │   │   └── style2.css
│   │   │   │   └── test.js
│   │   │   ├── glob-patterns-relative-paths/
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   ├── require/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── foo.js
│   │   │   │   ├── style/
│   │   │   │   │   ├── style1.css
│   │   │   │   │   └── style2.css
│   │   │   │   └── test.js
│   │   │   ├── inline-async-script/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── inline-css-html-chars/
│   │   │   │   ├── expected.html
│   │   │   │   ├── package.json
│   │   │   │   ├── style.css
│   │   │   │   └── test.js
│   │   │   ├── inline-defer-script/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── inline-script-external-attrs/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── intersection/
│   │   │   │   ├── bar.js
│   │   │   │   ├── common.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── page1.browser.json
│   │   │   │   ├── page2.browser.json
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-100percent/
│   │   │   │   ├── a.browser.json
│   │   │   │   ├── a.js
│   │   │   │   ├── ab.browser.json
│   │   │   │   ├── abc.browser.json
│   │   │   │   ├── b.js
│   │   │   │   ├── bc.browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-2/
│   │   │   │   ├── a.browser.json
│   │   │   │   ├── a.js
│   │   │   │   ├── ab.browser.json
│   │   │   │   ├── abc.browser.json
│   │   │   │   ├── b.js
│   │   │   │   ├── bc.browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-2-require/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── main.browser.json
│   │   │   │   ├── package.json
│   │   │   │   ├── shared.js
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-2str/
│   │   │   │   ├── a.browser.json
│   │   │   │   ├── a.js
│   │   │   │   ├── ab.browser.json
│   │   │   │   ├── abc.browser.json
│   │   │   │   ├── b.js
│   │   │   │   ├── bc.browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-3/
│   │   │   │   ├── a.browser.json
│   │   │   │   ├── a.js
│   │   │   │   ├── ab.browser.json
│   │   │   │   ├── abc.browser.json
│   │   │   │   ├── b.js
│   │   │   │   ├── bc.browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── intersection-threshold-50percent/
│   │   │   │   ├── a.browser.json
│   │   │   │   ├── a.js
│   │   │   │   ├── ab.browser.json
│   │   │   │   ├── abc.browser.json
│   │   │   │   ├── b.js
│   │   │   │   ├── bc.browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── modules-ready-lastSlot/
│   │   │   │   ├── body.js
│   │   │   │   ├── head.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── no-bundles/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── recurseInto-all/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── recurseInto-dir/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── recurseInto-dirtree/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── recurseInto-module/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── registerRequireExtension-not-cacheable/
│   │   │   │   ├── foo.js
│   │   │   │   ├── hello.dynamic
│   │   │   │   ├── hello.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── resource-absolute-path/
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots/
│   │   │   │   ├── foo.css
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots-inline-beginning/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots-inline-end/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots-inline-false/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots-inline-in-place/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── c.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── slots-inline-true/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── slots-override/
│   │   │       ├── foo.css
│   │   │       ├── foo.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-require/
│   │   │   ├── async/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── builtin/
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── globals-custom/
│   │   │   │   ├── expected.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── globals-jquery/
│   │   │   │   ├── expected.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── main-custom/
│   │   │   │   ├── bar/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── package.json
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── main-index/
│   │   │   │   ├── bar/
│   │   │   │   │   └── index.js
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── module-no-dependencies/
│   │   │   │   │   ├── expected.json
│   │   │   │   │   ├── foo.js
│   │   │   │   │   ├── package.json
│   │   │   │   │   └── test.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── main-require-redefined/
│   │   │   │   ├── bar/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── package.json
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── remap-browser-override/
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo-browser.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed/
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed-scoped/
│   │   │   │   ├── expected.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-search-path/
│   │   │   │   ├── app-modules/
│   │   │   │   │   └── bar/
│   │   │   │   │       ├── index.js
│   │   │   │   │       └── package.json
│   │   │   │   ├── expected.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transitive/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transitive-resolved/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── virtual-module/
│   │   │       ├── expected.json
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-define/
│   │   │   ├── async/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── builtin/
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── globals-foo/
│   │   │   │   ├── expected.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── globals-jquery/
│   │   │   │   ├── expected.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── main-custom/
│   │   │   │   ├── bar/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── package.json
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── main-index/
│   │   │   │   ├── bar/
│   │   │   │   │   └── index.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── module-no-dependencies/
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── remap-void/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed/
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed-scoped/
│   │   │   │   ├── expected.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-search-path/
│   │   │   │   ├── app-modules/
│   │   │   │   │   └── bar/
│   │   │   │   │       ├── index.js
│   │   │   │   │       └── package.json
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-browserify/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-browserify-config/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-multiple/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   ├── transform-a.js
│   │   │   │   ├── transform-b.js
│   │   │   │   └── transform-c.js
│   │   │   ├── transform-promise/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-stream/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-stream-config/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-stream-no-config/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-synchronous/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-synchronous-config/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── my-transform.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transitive/
│   │   │   │   ├── bar.js
│   │   │   │   ├── expected.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── transitive-resolved/
│   │   │       ├── bar.js
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-installed/
│   │   │   └── simple/
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-main/
│   │   │   └── simple/
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-ready/
│   │   │   └── simple/
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-remap/
│   │   │   └── simple/
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dep-transport-run/
│   │   │   ├── no-wait/
│   │   │   │   ├── expected.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── wait/
│   │   │       ├── expected.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── dependency-walker/
│   │   │   ├── flat/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected.txt
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── globs/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected.txt
│   │   │   │   ├── package.json
│   │   │   │   ├── require/
│   │   │   │   │   ├── bar.js
│   │   │   │   │   └── foo.js
│   │   │   │   ├── style/
│   │   │   │   │   ├── style1.css
│   │   │   │   │   └── style2.css
│   │   │   │   └── test.js
│   │   │   ├── lasso-issue-136/
│   │   │   │   ├── browser.json
│   │   │   │   ├── common.js
│   │   │   │   ├── expected.txt
│   │   │   │   ├── foo1.js
│   │   │   │   ├── foo2.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected.txt
│   │   │   │   ├── foo.js
│   │   │   │   ├── nested/
│   │   │   │   │   └── index.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-mixed/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected.txt
│   │   │   │   ├── foo.js
│   │   │   │   ├── hello.css
│   │   │   │   ├── hello.js
│   │   │   │   ├── nested/
│   │   │   │   │   └── index.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── transitive-package/
│   │   │       ├── browser.json
│   │   │       ├── expected.txt
│   │   │       ├── foo.js
│   │   │       ├── nested/
│   │   │       │   ├── bar.js
│   │   │       │   └── browser.json
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── flags/
│   │   │   ├── bundling-enabled/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── desktop-a.js
│   │   │   │   ├── desktop-b.js
│   │   │   │   ├── mobile-a.js
│   │   │   │   ├── mobile-b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── if-flag-dependencies/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── desktop-a.js
│   │   │   │   ├── desktop-b.js
│   │   │   │   ├── mobile-a.js
│   │   │   │   ├── mobile-b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── if-not-flag/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── c.js
│   │   │   │   ├── desktop-a.js
│   │   │   │   ├── desktop-b.js
│   │   │   │   ├── mobile-a.js
│   │   │   │   ├── mobile-b.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── long-flags/
│   │   │   │   ├── a.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── simple/
│   │   │       ├── a.js
│   │   │       ├── b.js
│   │   │       ├── browser.json
│   │   │       ├── c.js
│   │   │       ├── desktop-a.js
│   │   │       ├── desktop-b.js
│   │   │       ├── mobile-a.js
│   │   │       ├── mobile-b.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── inspect/
│   │   │   ├── buffer/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── complex/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── first-mate/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── global-late-def/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── globals/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── lasso-loader-var/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── parse-error/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── process1/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── process2/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── process3/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   ├── process4/
│   │   │   │   ├── expected.json
│   │   │   │   └── input.js
│   │   │   └── simple/
│   │   │       ├── expected.json
│   │   │       └── input.js
│   │   ├── load-prebuild/
│   │   │   ├── error-invalid-path/
│   │   │   │   └── test.js
│   │   │   ├── error-no-build/
│   │   │   │   ├── page.prebuild.json
│   │   │   │   └── test.js
│   │   │   ├── load-valid-prebuild/
│   │   │   │   ├── page.prebuild.json
│   │   │   │   └── test.js
│   │   │   ├── load-valid-prebuild-multi-flags/
│   │   │   │   ├── page.prebuild.json
│   │   │   │   └── test.js
│   │   │   └── load-valid-prebuild-multi-no-flags/
│   │   │       ├── page.prebuild.json
│   │   │       └── test.js
│   │   ├── modules/
│   │   │   ├── async/
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-flags/
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-intersection/
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main1-helper.js
│   │   │   │   ├── main1.js
│   │   │   │   ├── main2-helper.js
│   │   │   │   ├── main2.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-package/
│   │   │   │   ├── bar.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── something.js
│   │   │   │   └── test.js
│   │   │   ├── async-package-css/
│   │   │   │   ├── browser.json
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── something.css
│   │   │   │   └── test.js
│   │   │   ├── async-raptor-loader/
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── async-unnecessary/
│   │   │   │   ├── foo.js
│   │   │   │   ├── lasso-loader-patch.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── browser.json-tilde/
│   │   │   │   ├── browser.json
│   │   │   │   ├── nested/
│   │   │   │   │   ├── browser.json
│   │   │   │   │   └── nested.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── browserify-transform/
│   │   │   │   ├── foo-transform.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── browserify-transforms/
│   │   │   │   ├── bar-transform.js
│   │   │   │   ├── foo-transform.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── duplicate-name-browser-json/
│   │   │   │   ├── bar/
│   │   │   │   │   ├── browser.json
│   │   │   │   │   └── hello.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo/
│   │   │   │   │   ├── browser.json
│   │   │   │   │   └── hello.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── mask-define-vanilla-js/
│   │   │   │   ├── define-global.js
│   │   │   │   ├── library.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── missing-module/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── no-conflict/
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── registerRequireExtension-getDependencies/
│   │   │   │   ├── extra.js
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   └── world.foo
│   │   │   ├── registerRequireType/
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   └── world.foo
│   │   │   ├── registerRequireType-getDependencies-callback/
│   │   │   │   ├── extra.js
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   └── world.foo
│   │   │   ├── registerRequireType-getDependencies-promise/
│   │   │   │   ├── extra.js
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   └── world.foo
│   │   │   ├── registerRequireType-getDependencies-value/
│   │   │   │   ├── extra.js
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   └── world.foo
│   │   │   ├── require-builtin-core/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-css/
│   │   │   │   ├── foo.css
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-custom-ext/
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   ├── require-foo-plugin.js
│   │   │   │   └── test.js
│   │   │   ├── require-custom-ext-no-plugin/
│   │   │   │   ├── hello.foo
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-custom-type/
│   │   │   │   ├── foo.json
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-globals/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-installed-scoped-package/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-json/
│   │   │   │   ├── foo.json
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-relative/
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-flag/
│   │   │   │   ├── bar-desktop.js
│   │   │   │   ├── bar.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo-mobile.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-flag-caching/
│   │   │   │   ├── bar-desktop.js
│   │   │   │   ├── bar.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo-mobile.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-local-to-installed/
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-local-to-local/
│   │   │   │   ├── foo-browser.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-void-installed/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-remap-void-relative/
│   │   │   │   ├── foo.js
│   │   │   │   ├── foo2.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-resolve/
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── require-virtual-module/
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── requireRemap-not-conditional/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo-browser.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── requireRemap-plus-package-browser/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo-browser-lasso.js
│   │   │   │   ├── foo-browser.js
│   │   │   │   ├── foo.js
│   │   │   │   ├── main.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── simple/
│   │   │       ├── main.js
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   ├── plugins/
│   │   │   ├── custom-dependency-type-callback/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── custom-dependency-type-promise/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── events/
│   │   │   │   ├── async-foo.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-events.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── global-dependency-prop/
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   ├── something.foo
│   │   │   │   └── test.js
│   │   │   ├── inline-all-for-slot/
│   │   │   │   ├── bar.js
│   │   │   │   ├── baz.js
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-my-inline-slot.html
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-context-event-bundle-written/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-events.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-context-event-resource-written/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-events.json
│   │   │   │   ├── fonts/
│   │   │   │   │   └── fonts.css
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-writer-event-bundle-written/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-events.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── lasso-writer-event-resource-written/
│   │   │   │   ├── browser.json
│   │   │   │   ├── expected-events.json
│   │   │   │   ├── fonts/
│   │   │   │   │   └── fonts.css
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   └── test.js
│   │   │   ├── registerRequireExtension/
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   ├── something.foo
│   │   │   │   └── test.js
│   │   │   ├── registerRequireType/
│   │   │   │   ├── browser.json
│   │   │   │   ├── package.json
│   │   │   │   ├── plugin.js
│   │   │   │   ├── something.foo
│   │   │   │   └── test.js
│   │   │   └── write-bundle/
│   │   │       ├── browser.json
│   │   │       ├── foo.js
│   │   │       ├── package.json
│   │   │       ├── plugin.js
│   │   │       └── test.js
│   │   ├── prebuild-page/
│   │   │   ├── invalid-prebuild-config/
│   │   │   │   └── test.js
│   │   │   ├── multi-prebuild/
│   │   │   │   ├── a.js
│   │   │   │   ├── b.js
│   │   │   │   ├── page.prebuild.expected.json
│   │   │   │   ├── page1.prebuild.expected.json
│   │   │   │   └── test.js
│   │   │   ├── prebuild-resource/
│   │   │   │   ├── test-page.prebuild.expected.json
│   │   │   │   └── test.js
│   │   │   └── valid-prebuild/
│   │   │       ├── a.js
│   │   │       ├── test-page-1.prebuild.expected.json
│   │   │       └── test.js
│   │   ├── require-no-op/
│   │   │   ├── enable/
│   │   │   │   ├── test.js
│   │   │   │   ├── test.xbar
│   │   │   │   ├── test.xfoo
│   │   │   │   ├── test.ybar
│   │   │   │   └── test.yfoo
│   │   │   ├── enable-ignore-null-extension/
│   │   │   │   ├── test.js
│   │   │   │   ├── test.xbar
│   │   │   │   ├── test.xfoo
│   │   │   │   ├── test.ybar
│   │   │   │   └── test.yfoo
│   │   │   └── enable-throw-invalid-extension-type/
│   │   │       ├── test.js
│   │   │       ├── test.xbar
│   │   │       ├── test.xfoo
│   │   │       ├── test.ybar
│   │   │       └── test.yfoo
│   │   ├── resource-transforms/
│   │   │   ├── filter/
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   ├── transform.bar
│   │   │   │   └── transform.foo
│   │   │   └── stream/
│   │   │       ├── package.json
│   │   │       ├── test.js
│   │   │       ├── transform.bar
│   │   │       └── transform.foo
│   │   ├── transforms/
│   │   │   ├── minify-js/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.js
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── output-transforms/
│   │   │   │   ├── browser.json
│   │   │   │   ├── css-transform1.js
│   │   │   │   ├── css-transform2.js
│   │   │   │   ├── js-transform1-async.js
│   │   │   │   ├── js-transform2-async.js
│   │   │   │   ├── package.json
│   │   │   │   ├── test.js
│   │   │   │   ├── transformsA.css
│   │   │   │   └── transformsA.js
│   │   │   ├── resolve-font-urls/
│   │   │   │   ├── browser.json
│   │   │   │   ├── fonts/
│   │   │   │   │   └── fonts.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-custom-resolver/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-custom-type/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-fingerprints/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-no-bundling/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-no-fingerprints/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   ├── transform-css-urls-no-relative/
│   │   │   │   ├── browser.json
│   │   │   │   ├── foo.css
│   │   │   │   ├── package.json
│   │   │   │   └── test.js
│   │   │   └── transform-css-urls-require/
│   │   │       ├── browser.json
│   │   │       ├── foo.css
│   │   │       ├── package.json
│   │   │       └── test.js
│   │   └── util/
│   │       └── caching-replay-stream/
│   │           ├── .gitignore
│   │           ├── hello.txt
│   │           └── test.js
│   ├── builtins-test.js
│   ├── bundling-test.js
│   ├── dep-require-test.js
│   ├── dep-transport-define-test.js
│   ├── dep-transport-installed-test.js
│   ├── dep-transport-main-test.js
│   ├── dep-transport-ready-test.js
│   ├── dep-transport-remap-test.js
│   ├── dep-transport-run-test.js
│   ├── dependency-walker-test.js
│   ├── fixtures/
│   │   ├── builtin-foo.js
│   │   ├── file.json
│   │   ├── foo-shim.js
│   │   └── inspect-cache/
│   │       ├── bar.js
│   │       └── foo.js
│   ├── flags-test.js
│   ├── inspect-cache-test.js
│   ├── inspect-test.js
│   ├── lasso-image-test.js
│   ├── load-prebuild-test.js
│   ├── mock/
│   │   ├── LassoManifest.js
│   │   ├── MockDependency.js
│   │   ├── MockLassoContext.js
│   │   ├── MockMemoryCache.js
│   │   ├── MockRequireHandler.js
│   │   ├── condition.js
│   │   ├── create-lasso-context.js
│   │   ├── dependency-factory.js
│   │   ├── fingerprint-stream.js
│   │   ├── manifest-loader.js
│   │   └── mock-lasso.js
│   ├── modules-test.js
│   ├── plugins-test.js
│   ├── prebuild-page-test.js
│   ├── require-no-op-test.js
│   ├── resource-transforms-test.js
│   ├── transforms-test.js
│   ├── unit/
│   │   ├── AsyncPackage-test.js
│   │   ├── LassoPageResult-test.js
│   │   └── hash-test.js
│   ├── util/
│   │   ├── WriterTracker.js
│   │   ├── index.js
│   │   ├── module-search-path.js
│   │   ├── normalizeOutput.js
│   │   ├── patch-module.js
│   │   └── test-init.js
│   └── util-test.js
└── test-loop.sh
Download .txt
SYMBOL INDEX (610 symbols across 177 files)

FILE: src/AsyncPackage.js
  function AsyncPackage (line 1) | function AsyncPackage(name) {

FILE: src/BundleMappings.js
  function safeRelativePath (line 7) | function safeRelativePath(path) {
  function BundleMappings (line 11) | function BundleMappings(config, pageName) {

FILE: src/BundleSetConfig.js
  function BundleSetConfig (line 3) | function BundleSetConfig(name) {

FILE: src/Config.js
  function createFilterFromContentType (line 9) | function createFilterFromContentType(contentType) {
  constant MAX_FINGERPRINT_DEPTH (line 34) | const MAX_FINGERPRINT_DEPTH = 4;
  function calculateConfigFingerprint (line 36) | function calculateConfigFingerprint(config) {
  function Config (line 97) | function Config(params) {
  method outputDir (line 139) | get outputDir() {
  method urlPrefix (line 143) | get urlPrefix() {
  method getResolver (line 219) | getResolver () {
  method setResolver (line 306) | setResolver (resolver) {
  method setCacheKey (line 385) | setCacheKey (value) {
  method setLoadPrebuild (line 392) | setLoadPrebuild (value) {
  method getLoadPrebuild (line 396) | getLoadPrebuild () {

FILE: src/DependencyList.js
  function DependencyList (line 4) | function DependencyList(dependencies, dependencyRegistry, dirname, filen...
  method normalize (line 36) | async normalize () {
  method inspect (line 50) | inspect() {

FILE: src/DependencyTree.js
  function Node (line 3) | function Node(dependency, parent) {
  function DependencyTree (line 9) | function DependencyTree() {
  function copyNodes (line 43) | function copyNodes(node) {
  function toStringHelper (line 77) | function toStringHelper(node, indent) {

FILE: src/FlagSet.js
  function FlagSet (line 29) | function FlagSet(flags) {

FILE: src/Lasso.js
  method calculateKey (line 43) | calculateKey (data, theLasso, lassoContext, options) {
  method calculateKey (line 54) | calculateKey (data, theLasso, lassoContext, options) {
  function isExternalUrl (line 74) | function isExternalUrl(path) {
  function getLassoManifestFromOptions (line 78) | async function getLassoManifestFromOptions (options, dependencyRegistry) {
  function doLassoPage (line 182) | async function doLassoPage (theLasso, options, lassoContext) {
  function resolvePath (line 361) | function resolvePath(path, from) {
  function doLassoResourceString (line 405) | async function doLassoResourceString (theLasso, path, cacheKey, options,...
  function doLassoResourceBuffer (line 498) | async function doLassoResourceBuffer (theLasso, buff, cacheKey, options,...
  function _buildResourceCacheKey (line 515) | function _buildResourceCacheKey (cacheKey, theLasso, lassoContext) {
  function Lasso (line 526) | function Lasso(config) {
  method createAppBundleMappings (line 570) | async createAppBundleMappings (bundleSetConfig, lassoContext) {
  method buildPageBundles (line 596) | async buildPageBundles (options, lassoContext) {
  method getAppBundleMappingsCached (line 629) | async getAppBundleMappingsCached (bundleSetConfig, lassoContext) {
  function cacheKeyAdd (line 647) | function cacheKeyAdd (str) {
  method lassoPage (line 781) | async lassoPage (options) {
  method prebuildPage (line 808) | async prebuildPage (pageConfig, { writeToDisk = true } = {}) {
  method loadPrebuild (line 843) | async loadPrebuild (options = {}) {
  method lassoResource (line 898) | async lassoResource (data, options) {
  method getDependencyRegistry (line 957) | getDependencyRegistry() {

FILE: src/LassoCache.js
  constant DEFAULT_BASE_CACHE_DIR (line 4) | const DEFAULT_BASE_CACHE_DIR = nodePath.join(require('app-root-dir').get...
  function safeFilename (line 10) | function safeFilename(name) {
  function waitImmediate (line 14) | function waitImmediate() {
  constant CACHE_DEFAULTS (line 18) | const CACHE_DEFAULTS = {
  class SyncCache (line 61) | class SyncCache {
    method constructor (line 62) | constructor() {
    method getSync (line 66) | getSync(key) {
    method putSync (line 70) | putSync(key, value) {
  function LassoCache (line 75) | function LassoCache(key, options) {
  method flushAll (line 153) | flushAll () {
  method getLassoPageResult (line 157) | async getLassoPageResult(cacheKey, options) {
  method getBundleMappings (line 161) | async getBundleMappings (id, builder) {
  method getLassoedResource (line 171) | async getLassoedResource (path, builder) {
  method getDependencyFingerprint (line 181) | async getDependencyFingerprint (cacheKey, lastModified, builder) {

FILE: src/LassoContext.js
  class LassoContext (line 11) | class LassoContext extends EventEmitter {
    method constructor (line 12) | constructor() {
    method deferredStream (line 27) | deferredStream(startFn, options) {
    method createReadStream (line 35) | createReadStream(func) {
    method clearData (line 39) | clearData() {
    method getData (line 43) | getData(name) {
    method setData (line 47) | setData(name, value) {
    method getFileLastModified (line 51) | async getFileLastModified (filePath) {
    method setPhase (line 56) | setPhase(phaseName) {
    method isPageBundlingPhase (line 61) | isPageBundlingPhase() {
    method isAppBundlingPhase (line 65) | isAppBundlingPhase() {
    method isAsyncBundlingPhase (line 69) | isAsyncBundlingPhase() {
    method readPackageFile (line 73) | readPackageFile(path) {
    method createFingerprintStream (line 81) | createFingerprintStream() {
    method getClientPath (line 85) | getClientPath(file) {
    method getResolver (line 89) | getResolver() {
    method resolve (line 96) | resolve(targetModule, fromDir, options) {
    method resolveCached (line 100) | resolveCached(targetModule, fromDir, options) {
    method getProjectRoot (line 104) | getProjectRoot() {

FILE: src/LassoManifest.js
  function resolveBrowserPath (line 17) | function resolveBrowserPath(dir, path) {
  function LassoManifest (line 32) | function LassoManifest(options) {
  method getDependencies (line 120) | async getDependencies (options) {

FILE: src/LassoPageResult.js
  constant EMPTY_OBJECT (line 2) | const EMPTY_OBJECT = {};
  function LassoPageResult (line 5) | function LassoPageResult () {
  method htmlBySlot (line 62) | get htmlBySlot() {
  method getOutputFilesWithInfo (line 161) | getOutputFilesWithInfo() {
  method getFilePathsByContentType (line 206) | getFilePathsByContentType(contentType) {
  method toLassoPrebuild (line 256) | toLassoPrebuild (name, flags) {

FILE: src/LassoPrebuildResult.js
  class LassoPrebuildResult (line 13) | class LassoPrebuildResult {
    method constructor (line 14) | constructor () {
    method addBuild (line 18) | addBuild (path, build) {
    method write (line 26) | async write () {
    method serializeBuild (line 35) | serializeBuild (path) {
    method getBuildByPath (line 40) | getBuildByPath (path) {
    method getBuildsByPath (line 44) | getBuildsByPath () {

FILE: src/LoaderMetadata.js
  function LoaderMetadata (line 2) | function LoaderMetadata() {

FILE: src/PageConfig.js
  function PageConfig (line 1) | function PageConfig() {

FILE: src/Slot.js
  function Slot (line 4) | function Slot(contentType) {
  function inlineScript (line 58) | function inlineScript(content, data) {
  function inlineStyle (line 77) | function inlineStyle(content, data) {
  function externalScript (line 81) | function externalScript(attrs, data) {
  function externalStyle (line 85) | function externalStyle(attrs, data) {
  function wrapInDocumentLoaded (line 89) | function wrapInDocumentLoaded(code, isAsync) {

FILE: src/SlotTracker.js
  function SlotTracker (line 4) | function SlotTracker() {
  function addCode (line 36) | function addCode(slotList, key) {

FILE: src/bundle-builder.js
  function checkDir (line 54) | function checkDir(dependency) {
  function checkDir (line 88) | function checkDir(dependency) {
  function shouldIncludeDependency (line 113) | function shouldIncludeDependency (lassoContext, rootDependency, recurseH...
  function shouldRecurseIntoPackageDependency (line 124) | function shouldRecurseIntoPackageDependency (rootDependency, recurseHand...
  function buildBundle (line 133) | async function buildBundle(bundleMappings, dependencyRegistry, bundleCon...

FILE: src/config-loader.js
  function findRootDir (line 17) | function findRootDir(dirname) {
  function load (line 37) | function load(options, baseDir, filename, configDefaults) {

FILE: src/dependencies/Dependency.js
  constant CONTENT_TYPE_CSS (line 4) | const CONTENT_TYPE_CSS = require('../content-types').CSS;
  constant CONTENT_TYPE_JS (line 5) | const CONTENT_TYPE_JS = require('../content-types').JS;
  constant CONTENT_TYPE_NONE (line 6) | const CONTENT_TYPE_NONE = require('../content-types').NONE;
  constant NON_KEY_PROPERTIES (line 18) | const NON_KEY_PROPERTIES = {
  function getPackagePath (line 26) | function getPackagePath(d) {
  function doCalculateFingerprint (line 30) | function doCalculateFingerprint (dependency, lassoContext) {
  function DependencyReadable (line 68) | function DependencyReadable() {
  function Dependency (line 78) | function Dependency(dependencyConfig, dirname, filename) {
  method init (line 124) | async init (lassoContext) {
  method doInit (line 135) | async doInit (lassoContext) {}
  method getPackageManifest (line 238) | async getPackageManifest (lassoContext) {
  method calculateKey (line 334) | calculateKey (lassoContext) {
  method doCalculateKey (line 390) | doCalculateKey (lassoContext) {
  method getLastModified (line 480) | async getLastModified (lassoContext) {
  method doGetLastModified (line 494) | async doGetLastModified (lassoContext, callback) {
  method getFileLastModified (line 503) | async getFileLastModified (path) {
  method toString (line 539) | toString() {

FILE: src/dependencies/DependencyRegistry.js
  constant CONTENT_TYPE_CSS (line 5) | const CONTENT_TYPE_CSS = require('../content-types').CSS;
  constant CONTENT_TYPE_JS (line 6) | const CONTENT_TYPE_JS = require('../content-types').JS;
  function createDefaultNormalizer (line 18) | function createDefaultNormalizer(registry) {
  function DependencyRegistry (line 69) | function DependencyRegistry() {
  function Ctor (line 192) | function Ctor(dependencyConfig, dirname, filename) {
  method init (line 281) | async init(lassoContext) {
  method getSourceFile (line 284) | getSourceFile() {
  method getDependencies (line 287) | async getDependencies (lassoContext) {
  method getRequireExtensionNames (line 299) | getRequireExtensionNames() {
  method createRequireHandler (line 322) | createRequireHandler(path, lassoContext, userOptions) {
  method normalizeDependencies (line 400) | async normalizeDependencies (dependencies, dirname, filename) {
  method createResourceTransformType (line 478) | createResourceTransformType (transformFunc) {

FILE: src/dependencies/RequireHandler.js
  constant EMPTY_ARRAY_PROMISE (line 4) | const EMPTY_ARRAY_PROMISE = Promise.resolve([]);
  class RequireHandler (line 6) | class RequireHandler {
    method constructor (line 7) | constructor(userOptions, lassoContext, path) {
    method init (line 29) | init() {
    method createReadStream (line 52) | createReadStream() {
    method getLastModified (line 76) | getLastModified() {
    method getDependencies (line 112) | async getDependencies() {
    method getDefaultBundleName (line 122) | getDefaultBundleName(pageBundleName, lassoContext) {

FILE: src/dependencies/dependency-comment.js
  method calculateKey (line 14) | calculateKey () {

FILE: src/dependencies/dependency-dependencies.js
  method init (line 6) | async init (lassoContext) {}
  method getDependencies (line 8) | async getDependencies (lassoContext) {
  method calculateKey (line 12) | calculateKey () {

FILE: src/dependencies/dependency-intersection.js
  function onDependency (line 7) | function onDependency (tracking, strictIntersection, firstSet, i) {
  method init (line 40) | async init (lassoContext) {
  method getDependencies (line 80) | async getDependencies (lassoContext) {
  method calculateKey (line 160) | calculateKey () {

FILE: src/dependencies/dependency-package.js
  method init (line 11) | async init (lassoContext) {
  method loadPackageManifest (line 41) | async loadPackageManifest (lassoContext) {
  method calculateKey (line 45) | calculateKey () {

FILE: src/dependencies/dependency-resource.js
  function maskDefine (line 8) | function maskDefine(code) {
  method init (line 23) | async init (lassoContext) {
  method read (line 51) | async read (context) {
  method getLastModified (line 84) | async getLastModified (lassoContext) {

FILE: src/dependencies/glob.js
  function globNormalizer (line 6) | async function globNormalizer (dependency, context) {

FILE: src/dependency-walker.js
  function walk (line 12) | async function walk(options) {

FILE: src/flags.js
  function isFlagSet (line 3) | function isFlagSet(o) {
  function createFlagSet (line 7) | function createFlagSet(flags) {

FILE: src/index.js
  function create (line 32) | function create(config, baseDir, filename) {
  function getDefaultLasso (line 60) | function getDefaultLasso() {
  function setDevelopmentMode (line 79) | function setDevelopmentMode() {
  constant NODE_ENV (line 87) | const NODE_ENV = process.env.NODE_ENV && process.env.NODE_ENV.toLowerCas...
  function configure (line 93) | function configure(config, baseDir, filename) {
  function lassoPage (line 112) | async function lassoPage(pageConfig) {
  function lassoResource (line 134) | async function lassoResource (path, context) {
  function clearCaches (line 138) | function clearCaches() {

FILE: src/manifest-loader.js
  function readManifest (line 20) | function readManifest(path) {
  function tryManifest (line 61) | function tryManifest(dirname, manifestPath) {
  function tryExtensionManifest (line 69) | function tryExtensionManifest(dirname, manifestPath) {
  function tryQualified (line 77) | function tryQualified(dirname, manifestPath) {
  function tryAll (line 82) | function tryAll(dirname, manifestPath) {
  function _resolve (line 91) | function _resolve(path, from) {
  function load (line 138) | function load(path, from) {

FILE: src/middleware/koa/serveStatic.js
  function notFound (line 5) | function notFound() {

FILE: src/middleware/serveStatic.js
  function notFound (line 5) | function notFound() {

FILE: src/node-require-no-op/index.js
  function requireNoOp (line 1) | function requireNoOp(module, filename) { /* no-op */ }
  function enableForExtension (line 3) | function enableForExtension(extension) {

FILE: src/page-bundles-builder.js
  function build (line 11) | async function build (options, config, bundleMappings, lassoContext) {

FILE: src/path.js
  function absUnix (line 24) | function absUnix (p) {
  function absWin (line 28) | function absWin (p) {

FILE: src/plugins/lasso-image/index.js
  constant IMAGE_SIZE_WHITELIST (line 4) | const IMAGE_SIZE_WHITELIST = {
  function plugin (line 12) | function plugin(lasso, config) {
  method builder (line 84) | async builder () {

FILE: src/plugins/lasso-minify-css/index.js
  function isInline (line 3) | function isInline(lassoContext) {
  method transform (line 21) | transform (code, lassoContext) {

FILE: src/plugins/lasso-minify-js/index.js
  function isInline (line 5) | function isInline(lassoContext) {

FILE: src/plugins/lasso-resolve-css-urls/index.js
  constant REQUIRE_PREFIX (line 5) | const REQUIRE_PREFIX = 'require:';
  function defaultUrlResolver (line 7) | async function defaultUrlResolver (url, lassoContext) {
  function replaceUrls (line 54) | function replaceUrls (code, lassoContext, urlResolver) {
  method transform (line 96) | async transform (code, lassoContext) {

FILE: src/reader.js
  function createReadDependencyStream (line 11) | function createReadDependencyStream(dependency, lassoContext, transforme...
  function createReadBundleStream (line 99) | function createReadBundleStream(bundle, lassoContext, transformerAsyncVa...
  function createBundleReader (line 182) | function createBundleReader(bundle, lassoContext) {
  function createResourceReader (line 249) | function createResourceReader(path, lassoContext) {

FILE: src/require/build-plugin-config.js
  function resolveGlobals (line 11) | function resolveGlobals(config) {
  function buildPluginConfig (line 33) | function buildPluginConfig(userConfig, defaultProjectRoot) {

FILE: src/require/dep-require-remap.js
  function create (line 3) | function create(config, lasso) {

FILE: src/require/dep-require.js
  constant VAR_REQUIRE_PROCESS (line 4) | const VAR_REQUIRE_PROCESS = 'process=require("process")';
  constant VAR_REQUIRE_BUFFER (line 5) | const VAR_REQUIRE_BUFFER = 'Buffer=require("buffer").Buffer';
  function buildAsyncInfo (line 15) | function buildAsyncInfo(path, asyncBlocks, lassoContext) {
  function create (line 53) | function create(config, lasso) {

FILE: src/require/dep-runtime.js
  method read (line 15) | async read (lassoContext) {
  method calculateKey (line 33) | calculateKey () {

FILE: src/require/dep-transport-builtin.js
  method init (line 11) | async init(lassoContext) {}
  method getLastModified (line 26) | async getLastModified (lassoContext) {
  method calculateKey (line 42) | calculateKey () {

FILE: src/require/dep-transport-define.js
  function shouldPreresolvePath (line 7) | function shouldPreresolvePath(path) {
  function preresolvePath (line 30) | function preresolvePath(require, stringTransformer) {
  function transformRequires (line 44) | function transformRequires(code, inspected, asyncBlocks, lassoContext) {
  method getLastModified (line 182) | async getLastModified (lassoContext) {
  method getUnbundledTarget (line 190) | getUnbundledTarget(lassoContext) {
  method calculateKey (line 194) | calculateKey () {
  method toString (line 198) | toString() {

FILE: src/require/dep-transport-installed.js
  method init (line 12) | async init(lassoContext) {}
  method getLastModified (line 28) | async getLastModified (lassoContext) {
  method calculateKey (line 44) | calculateKey () {

FILE: src/require/dep-transport-loader-metadata.js
  method init (line 7) | async init(lassoContext) {}
  method calculateKey (line 31) | calculateKey () {
  method getLastModified (line 39) | async getLastModified (lassoContext) {

FILE: src/require/dep-transport-main.js
  method init (line 11) | async init() {}
  method getLastModified (line 26) | async getLastModified (lassoContext) {
  method calculateKey (line 34) | calculateKey () {

FILE: src/require/dep-transport-ready.js
  method init (line 8) | async init() {
  method calculateKey (line 24) | calculateKey () {
  method getLastModified (line 28) | async getLastModified (lassoContext) {

FILE: src/require/dep-transport-remap.js
  method init (line 12) | async init (lassoContext) {}
  method getLastModified (line 27) | async getLastModified (lassoContext) {
  method calculateKey (line 35) | calculateKey () {

FILE: src/require/dep-transport-run.js
  method init (line 12) | async init(lassoContext) {}
  method getLastModified (line 36) | async getLastModified (lassoContext) {
  method calculateKey (line 56) | calculateKey () {

FILE: src/require/dep-transport-search-path.js
  method init (line 10) | async init () {
  method getLastModified (line 30) | async getLastModified (lassoContext) {
  method calculateKey (line 42) | calculateKey () {

FILE: src/require/index.js
  function registerExtension (line 43) | function registerExtension(ext) {
  method getLastModified (line 64) | getLastModified (path, lassoContext) {

FILE: src/require/inspect-cache.js
  function resolveInspectedRequires (line 24) | function resolveInspectedRequires(inspectResult) {
  function readSource (line 70) | function readSource() {
  function cacheBuilder (line 87) | function cacheBuilder () {
  function afterInspect (line 95) | function afterInspect (inspectResult) {
  function doInspect (line 138) | function doInspect(cacheKey) {
  function buildCacheKeyFromFingerprint (line 155) | function buildCacheKeyFromFingerprint() {

FILE: src/require/util/Deduper.js
  constant REQUIRE_DEDUPER_CONTEXT_KEY (line 4) | const REQUIRE_DEDUPER_CONTEXT_KEY = 'dependency-require';
  class Deduper (line 7) | class Deduper {
    method constructor (line 8) | constructor(lassoContext, dependencies) {
    method addDependency (line 36) | addDependency(key, d) {
    method defKey (line 42) | defKey(path) {
    method hasDef (line 46) | hasDef(key) {
    method runKey (line 51) | runKey(path, wait) {
    method hasRun (line 55) | hasRun(key) {
    method installedKey (line 60) | installedKey(parentPath, childName, childVersion) {
    method hasInstalled (line 64) | hasInstalled(key) {
    method mainKey (line 69) | mainKey(dir, main) {
    method hasMain (line 73) | hasMain(key) {
    method remapKey (line 78) | remapKey(from, to) {
    method hasRemap (line 82) | hasRemap(key) {
    method requireKey (line 87) | requireKey(path, from, run, wait) {
    method hasRequire (line 95) | hasRequire(key) {
    method builtinKey (line 100) | builtinKey(name, target) {
    method hasBuiltin (line 104) | hasBuiltin(key) {
    method searchPathKey (line 109) | searchPathKey(path) {
    method hasSearchPath (line 113) | hasSearchPath(key) {
    method addRuntime (line 117) | addRuntime(runtimeDependency) {
    method addReady (line 124) | addReady(readyDependency) {
    method addProcess (line 134) | addProcess(d) {

FILE: src/require/util/DeduperContext.js
  class DeduperContext (line 1) | class DeduperContext {
    method constructor (line 2) | constructor() {

FILE: src/require/util/StringTransformer.js
  function StringTransformer (line 1) | function StringTransformer() {

FILE: src/require/util/Transforms.js
  class TransformAdaptorStream (line 10) | class TransformAdaptorStream extends stream.Transform {
    method constructor (line 11) | constructor(transform, lassoContext) {
    method _transform (line 19) | _transform(buf, enc, callback) {
    method _flush (line 26) | _flush(callback) {
  function resolvePath (line 63) | function resolvePath(path, projectRoot) {
  class Transforms (line 81) | class Transforms {
    method constructor (line 82) | constructor(transforms, projectRoot) {
    method apply (line 163) | apply(path, inStream, lassoContext) {

FILE: src/require/util/inspect.js
  function isRequire (line 16) | function isRequire(node) {
  function isRequireResolve (line 25) | function isRequireResolve(node) {
  function isRequireFor (line 36) | function isRequireFor(node, moduleName) {
  function isRequireForAsyncLoader (line 45) | function isRequireForAsyncLoader(node) {
  function isAsyncNode (line 50) | function isAsyncNode(node, scope) {
  function parseAsyncNode (line 74) | function parseAsyncNode(node, scope) {
  function recordGlobalsHelper (line 144) | function recordGlobalsHelper(node, scope, foundGlobals) {
  function recordGlobals (line 166) | function recordGlobals(node, parentNode, scope, foundGlobals) {

FILE: src/require/util/normalizeFSPath.js
  function normalizeFSPath (line 3) | function normalizeFSPath(path) {

FILE: src/resolve/builtins.js
  function resolveBuiltin (line 4) | function resolveBuiltin(target) {
  function addBuiltins (line 29) | function addBuiltins(builtins) {

FILE: src/resolve/index.js
  function resolve (line 27) | function resolve(targetModule, fromDir, options) {
  function resolveCached (line 117) | function resolveCached(targetModule, fromDir, options) {

FILE: src/transforms.js
  function Transformer (line 7) | function Transformer(transforms) {
  function handleNonStreamTransform (line 11) | function handleNonStreamTransform(inStream, transform, applyTransform, h...
  method hasTransforms (line 45) | hasTransforms () {
  method transform (line 49) | transform (inStream, lassoContext) {
  function filterTransform (line 116) | async function filterTransform (lassoContext, transformConfig) {

FILE: src/util/CombinedStream.js
  function CombinedStream (line 5) | function CombinedStream(options) {

FILE: src/util/DeferredReadable.js
  function DeferredReadable (line 4) | function DeferredReadable(startFn, options) {

FILE: src/util/caching-stream.js
  function ReplayStream (line 7) | function ReplayStream(cachingStream, options) {
  function CachingStream (line 40) | function CachingStream(options) {

FILE: src/util/fingerprint-stream.js
  function FingerprintStream (line 5) | function FingerprintStream(options) {

FILE: src/util/index.js
  function merge (line 7) | function merge(src, dest) {
  function streamToString (line 27) | function streamToString(stream, callback) {
  function readStream (line 42) | function readStream(func) {

FILE: src/util/url-reader.js
  function createUrlReadStream (line 5) | function createUrlReadStream(url) {

FILE: src/writers/Writer.js
  function initWriter (line 11) | async function initWriter (writer, lassoContext) {
  function Writer (line 18) | function Writer(impl) {
  method writeBundle (line 78) | async writeBundle (bundle, onBundleWrittenCallback, lassoContext) {
  method writeResource (line 173) | async writeResource (path, lassoContext) {
  method writeResourceBuffer (line 225) | async writeResourceBuffer (buff, path, lassoContext) {
  method checkBundleUpToDate (line 252) | async checkBundleUpToDate (bundle, lassoContext) {
  method writeBundles (line 282) | async writeBundles (iteratorFunc, onBundleWrittenCallback, lassoContext) {
  method buildResourceCacheKey (line 299) | buildResourceCacheKey(cacheKey, lassoContext) {

FILE: src/writers/file-writer.js
  constant MAX_FILE_LENGTH (line 1) | const MAX_FILE_LENGTH = 255;
  function filePathToUrlWindows (line 14) | function filePathToUrlWindows(path) {
  function filePathToUrlUnix (line 18) | function filePathToUrlUnix(path) {
  function enforceFileLengthLimits (line 22) | function enforceFileLengthLimits(path) {
  function randomStr (line 41) | function randomStr(len) {
  function getBundleUrl (line 55) | function getBundleUrl(lassoContext) {
  function writeFile (line 98) | async function writeFile (inStream, outputFile, calculateFingerprint, fi...
  function getOutputFileForBundle (line 241) | function getOutputFileForBundle(bundle) {
  function getOutputFileFromFileName (line 264) | function getOutputFileFromFileName (path, relativePath) {
  function getOutputFileForResource (line 272) | function getOutputFileForResource(path, fingerprintsEnabled, lassoContex...
  function buildResourceCacheKey (line 298) | function buildResourceCacheKey(cacheKey, lassoContext) {
  function getOutputFile (line 309) | function getOutputFile(relativePath, filename, targetExt, slotName) {
  function getResourceUrlForHashed (line 351) | function getResourceUrlForHashed (path, lassoContext) {
  function getResourceUrl (line 372) | function getResourceUrl (path, lassoContext) {
  method checkBundleUpToDate (line 389) | async checkBundleUpToDate (bundle, lassoContext) {
  method sourceLastModified (line 406) | async sourceLastModified () {
  method outputLastModified (line 409) | async outputLastModified (callback) {
  method writeBundle (line 435) | async writeBundle (reader, lassoContext) {
  method writeResource (line 473) | async writeResource (reader, lassoContext) {
  method writeResourceBuffer (line 510) | async writeResourceBuffer (buff, lassoContext) {

FILE: src/writers/index.js
  function createWriter (line 3) | function createWriter(writerImpl) {

FILE: test/autotest.js
  function compareHelper (line 24) | function compareHelper(dir, actual, suffix) {
  function autoTest (line 49) | function autoTest (name, dir, run, options) {

FILE: test/autotests/bundling/async-dependencies/test.js
  method check (line 18) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/async-flags/test.js
  method check (line 18) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/async-package/test.js
  method check (line 31) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/bundles/test.js
  method check (line 37) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/bundling-virtual-module/test.js
  method read (line 18) | read (lassoContext) {

FILE: test/autotests/bundling/csp-nonce-inline-script/test.js
  method check (line 23) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/css-inline-resource-base64/test.js
  method check (line 19) | check(lassoPageResult, writerTracker, helpers) {

FILE: test/autotests/bundling/css-inline-resource-utf8/test.js
  method check (line 19) | check(lassoPageResult, writerTracker, helpers) {

FILE: test/autotests/bundling/css-resources-multiple-pages-no-bundling/test.js
  method check (line 21) | check(lassoPageResult, writerTracker) {
  method check (line 37) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/custom-dependency-type-no-bundling/test.js
  method init (line 15) | async init (lassoContext) {}
  method check (line 35) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/dedupe/test.js
  method check (line 37) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/escape-external-css-url/test.js
  method check (line 22) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/escape-external-js-url/test.js
  method check (line 22) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/external-js-inlined/test.js
  method check (line 21) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/external-js-integrity/test.js
  method check (line 23) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/external-js/test.js
  method check (line 19) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/fingerprints/test.js
  method check (line 18) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/glob-patterns-relative-paths/test.js
  method check (line 18) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/glob-patterns/test.js
  method check (line 18) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/inline-async-script/test.js
  method check (line 23) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/inline-css-html-chars/test.js
  method check (line 22) | check(lassoPageResult, writerTracker, helpers) {

FILE: test/autotests/bundling/inline-defer-script/test.js
  method check (line 23) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/inline-script-external-attrs/test.js
  method check (line 23) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/intersection-threshold-100percent/test.js
  method check (line 36) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/intersection-threshold-2-require/test.js
  method check (line 31) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/intersection-threshold-2/test.js
  method check (line 36) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/intersection-threshold-2str/test.js
  method check (line 36) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/intersection-threshold-3/test.js
  method check (line 36) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/intersection-threshold-50percent/test.js
  method check (line 36) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/intersection/test.js
  method check (line 32) | check(lassoPageResult, writerTracker) {
  method check (line 50) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/modules-ready-lastSlot/test.js
  method check (line 33) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/registerRequireExtension-not-cacheable/test.js
  method check (line 35) | check(lassoPageResult, writerTracker) {
  method check (line 51) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/resource-absolute-path/test.js
  method check (line 18) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/slots-inline-beginning/test.js
  method check (line 23) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/slots-inline-end/test.js
  method check (line 23) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/slots-inline-false/test.js
  method check (line 23) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/slots-inline-in-place/test.js
  method check (line 24) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/slots-inline-true/test.js
  method check (line 23) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/slots-override/test.js
  method check (line 27) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/bundling/slots/test.js
  method check (line 20) | check(lassoPageResult, writerTracker) {

FILE: test/autotests/dep-require/virtual-module/test.js
  method read (line 6) | read(lassoContext, callback) {

FILE: test/autotests/dep-transport-define/transform-browserify-config/my-transform.js
  class MyTransform (line 5) | class MyTransform extends stream.Transform {
    method constructor (line 6) | constructor(file, opts) {
    method _transform (line 13) | _transform(buf, enc, callback) {
    method _flush (line 20) | _flush(callback) {

FILE: test/autotests/dep-transport-define/transform-browserify/my-transform.js
  class MyTransform (line 5) | class MyTransform extends stream.Transform {
    method constructor (line 6) | constructor(file) {
    method _transform (line 12) | _transform(buf, enc, callback) {
    method _flush (line 19) | _flush(callback) {

FILE: test/autotests/dep-transport-define/transform-multiple/transform-a.js
  class MyTransform (line 6) | class MyTransform extends stream.Transform {
    method constructor (line 7) | constructor(file) {
    method _transform (line 13) | _transform(buf, enc, callback) {
    method _flush (line 20) | _flush(callback) {
  method createTransform (line 29) | createTransform() {

FILE: test/autotests/dep-transport-define/transform-multiple/transform-b.js
  class MyTransform (line 5) | class MyTransform extends stream.Transform {
    method constructor (line 6) | constructor(file) {
    method _transform (line 12) | _transform(buf, enc, callback) {
    method _flush (line 19) | _flush(callback) {

FILE: test/autotests/dep-transport-define/transform-multiple/transform-c.js
  method createTransform (line 4) | createTransform(transformConfig) {

FILE: test/autotests/dep-transport-define/transform-promise/my-transform.js
  method createTransform (line 4) | createTransform(transformConfig) {

FILE: test/autotests/dep-transport-define/transform-stream-config/my-transform.js
  class MyTransform (line 6) | class MyTransform extends stream.Transform {
    method constructor (line 7) | constructor(file, opts) {
    method _transform (line 14) | _transform(buf, enc, callback) {
    method _flush (line 21) | _flush(callback) {
  method createTransform (line 31) | createTransform(transformConfig) {

FILE: test/autotests/dep-transport-define/transform-stream-no-config/my-transform.js
  class MyTransform (line 6) | class MyTransform extends stream.Transform {
    method constructor (line 7) | constructor(file) {
    method _transform (line 13) | _transform(buf, enc, callback) {
    method _flush (line 20) | _flush(callback) {
  method createTransform (line 29) | createTransform() {

FILE: test/autotests/dep-transport-define/transform-stream/my-transform.js
  class MyTransform (line 6) | class MyTransform extends stream.Transform {
    method constructor (line 7) | constructor(file) {
    method _transform (line 13) | _transform(buf, enc, callback) {
    method _flush (line 20) | _flush(callback) {
  method createTransform (line 29) | createTransform() {

FILE: test/autotests/dep-transport-define/transform-synchronous-config/my-transform.js
  method createTransform (line 4) | createTransform(transformConfig) {

FILE: test/autotests/dep-transport-define/transform-synchronous/my-transform.js
  method createTransform (line 4) | createTransform(transformConfig) {

FILE: test/autotests/inspect/buffer/input.js
  function typedArraySupport (line 50) | function typedArraySupport () {
  function kMaxLength (line 62) | function kMaxLength () {
  function Buffer (line 77) | function Buffer (arg) {
  function fromNumber (line 109) | function fromNumber (that, length) {
  function fromString (line 119) | function fromString (that, string, encoding) {
  function fromObject (line 130) | function fromObject (that, object) {
  function fromBuffer (line 153) | function fromBuffer (that, buffer) {
  function fromArray (line 160) | function fromArray (that, array) {
  function fromTypedArray (line 170) | function fromTypedArray (that, array) {
  function fromArrayBuffer (line 182) | function fromArrayBuffer (that, array) {
  function fromArrayLike (line 196) | function fromArrayLike (that, array) {
  function fromJsonObject (line 207) | function fromJsonObject (that, object) {
  function allocate (line 240) | function allocate (that, length) {
  function checked (line 256) | function checked (length) {
  function SlowBuffer (line 266) | function SlowBuffer (subject, encoding) {
  function byteLength (line 345) | function byteLength (string, encoding) {
  function slowToString (line 382) | function slowToString (encoding, start, end) {
  function arrayIndexOf (line 482) | function arrayIndexOf (arr, val, byteOffset) {
  function hexWrite (line 498) | function hexWrite (buf, string, offset, length) {
  function utf8Write (line 525) | function utf8Write (buf, string, offset, length) {
  function asciiWrite (line 529) | function asciiWrite (buf, string, offset, length) {
  function binaryWrite (line 533) | function binaryWrite (buf, string, offset, length) {
  function base64Write (line 537) | function base64Write (buf, string, offset, length) {
  function ucs2Write (line 541) | function ucs2Write (buf, string, offset, length) {
  function base64Slice (line 624) | function base64Slice (buf, start, end) {
  function utf8Slice (line 632) | function utf8Slice (buf, start, end) {
  function decodeCodePointsArray (line 710) | function decodeCodePointsArray (codePoints) {
  function asciiSlice (line 728) | function asciiSlice (buf, start, end) {
  function binarySlice (line 738) | function binarySlice (buf, start, end) {
  function hexSlice (line 748) | function hexSlice (buf, start, end) {
  function utf16leSlice (line 761) | function utf16leSlice (buf, start, end) {
  function checkOffset (line 811) | function checkOffset (offset, ext, length) {
  function checkInt (line 972) | function checkInt (buf, value, offset, ext, max, min) {
  function objectWriteUInt16 (line 1019) | function objectWriteUInt16 (buf, value, offset, littleEndian) {
  function objectWriteUInt32 (line 1053) | function objectWriteUInt32 (buf, value, offset, littleEndian) {
  function checkIEEE754 (line 1197) | function checkIEEE754 (buf, value, offset, ext, max, min) {
  function writeFloat (line 1202) | function writeFloat (buf, value, offset, littleEndian, noAssert) {
  function writeDouble (line 1218) | function writeDouble (buf, value, offset, littleEndian, noAssert) {
  function base64clean (line 1319) | function base64clean (str) {
  function stringtrim (line 1331) | function stringtrim (str) {
  function toHex (line 1336) | function toHex (n) {
  function utf8ToBytes (line 1341) | function utf8ToBytes (string, units) {
  function asciiToBytes (line 1421) | function asciiToBytes (str) {
  function utf16leToBytes (line 1430) | function utf16leToBytes (str, units) {
  function base64ToBytes (line 1446) | function base64ToBytes (str) {
  function blitBuffer (line 1450) | function blitBuffer (src, dst, offset, length) {

FILE: test/autotests/inspect/complex/input.js
  function loadModule (line 30) | function loadModule(name, callback) {

FILE: test/autotests/inspect/first-mate/input.js
  function Grammar (line 27) | function Grammar(registry, options) {
  function TokenizeLineResult (line 347) | function TokenizeLineResult(line, openScopeTags, tags, ruleStack, regist...

FILE: test/autotests/inspect/global-late-def/input.js
  function Foo (line 3) | function Foo() {

FILE: test/autotests/inspect/process4/input.js
  function test (line 1) | function test() {

FILE: test/autotests/modules/async-flags/lasso-loader-patch.js
  function _handleMissingAsync (line 5) | function _handleMissingAsync(asyncId) {

FILE: test/autotests/modules/async-intersection/lasso-loader-patch.js
  function _handleMissingAsync (line 5) | function _handleMissingAsync(asyncId) {

FILE: test/autotests/modules/async-intersection/test.js
  method check (line 29) | check (window) {
  method check (line 58) | check (window) {

FILE: test/autotests/modules/async-package-css/lasso-loader-patch.js
  function _handleMissingAsync (line 5) | function _handleMissingAsync(asyncId) {

FILE: test/autotests/modules/async-package/lasso-loader-patch.js
  function _handleMissingAsync (line 5) | function _handleMissingAsync(asyncId) {

FILE: test/autotests/modules/async-raptor-loader/lasso-loader-patch.js
  function _handleMissingAsync (line 5) | function _handleMissingAsync(asyncId) {

FILE: test/autotests/modules/async-unnecessary/lasso-loader-patch.js
  function _handleMissingAsync (line 5) | function _handleMissingAsync(asyncId) {

FILE: test/autotests/modules/async/lasso-loader-patch.js
  function _handleMissingAsync (line 5) | function _handleMissingAsync(asyncId) {

FILE: test/autotests/modules/browserify-transform/foo-transform.js
  class MyTransform (line 5) | class MyTransform extends Transform {
    method constructor (line 6) | constructor(options) {
    method _transform (line 11) | _transform(data, encoding, callback) {
    method _flush (line 16) | _flush(callback) {

FILE: test/autotests/modules/browserify-transforms/bar-transform.js
  class MyTransform (line 5) | class MyTransform extends Transform {
    method constructor (line 6) | constructor(options) {
    method _transform (line 11) | _transform(data, encoding, callback) {
    method _flush (line 16) | _flush(callback) {

FILE: test/autotests/modules/browserify-transforms/foo-transform.js
  class MyTransform (line 5) | class MyTransform extends Transform {
    method constructor (line 6) | constructor(options) {
    method _transform (line 11) | _transform(data, encoding, callback) {
    method _flush (line 16) | _flush(callback) {

FILE: test/autotests/modules/registerRequireExtension-getDependencies/test.js
  method getDependencies (line 13) | async getDependencies (lassoContext) {
  method read (line 17) | async read (path, lassoContext) {

FILE: test/autotests/modules/registerRequireType-getDependencies-callback/test.js
  method init (line 17) | async init (lassoContext) {
  method getDependencies (line 25) | async getDependencies (lassoContext) {
  method read (line 29) | read (lassoContext) {

FILE: test/autotests/modules/registerRequireType-getDependencies-promise/test.js
  method init (line 17) | async init (lassoContext) {
  method getDependencies (line 25) | async getDependencies (lassoContext) {
  method read (line 29) | read (lassoContext) {

FILE: test/autotests/modules/registerRequireType-getDependencies-value/test.js
  method init (line 19) | async init (lassoContext) {
  method getDependencies (line 28) | async getDependencies (lassoContext) {
  method read (line 33) | read (lassoContext) {

FILE: test/autotests/modules/registerRequireType/test.js
  method init (line 17) | async init (lassoContext) {
  method read (line 25) | read (lassoContext) {

FILE: test/autotests/modules/require-custom-ext/require-foo-plugin.js
  method read (line 7) | async read (path, lassoContext) {
  method lastModified (line 13) | async lastModified (path, lassoContext) {

FILE: test/autotests/modules/require-custom-type/test.js
  function fooPlugins (line 3) | function fooPlugins(lasso, config) {

FILE: test/autotests/modules/require-virtual-module/test.js
  method read (line 12) | read (lassoContext) {

FILE: test/autotests/plugins/custom-dependency-type-callback/plugin.js
  method init (line 11) | async init () {
  method read (line 19) | async read (lassoContext) {
  method lastModified (line 29) | async lastModified (lassoContext) {
  method init (line 41) | async init () {
  method read (line 49) | async read (lassoContext) {
  method lastModified (line 60) | async lastModified (lassoContext) {

FILE: test/autotests/plugins/custom-dependency-type-promise/plugin.js
  method init (line 11) | async init () {
  method read (line 19) | async read (lassoContext) {
  method lastModified (line 29) | async lastModified (lassoContext) {
  method init (line 41) | async init () {
  method read (line 49) | async read (lassoContext) {
  method lastModified (line 60) | async lastModified (lassoContext) {

FILE: test/autotests/plugins/registerRequireType/plugin.js
  method init (line 9) | async init (lassoContext) {
  method read (line 19) | read (lassoContext) {
  method getLastModified (line 27) | async getLastModified (lassoContext) {

FILE: test/autotests/plugins/write-bundle/plugin.js
  method init (line 3) | async init (lassoContext) {
  method writeBundle (line 8) | async writeBundle (reader, lassoContext) {
  method writeResource (line 14) | async writeResource (reader, lassoContext) {

FILE: test/autotests/resource-transforms/filter/test.js
  method filter (line 12) | async filter (lassoContext) {
  method check (line 49) | check(result) {
  method check (line 57) | check(result) {

FILE: test/autotests/resource-transforms/stream/test.js
  method check (line 65) | check(result) {
  method check (line 73) | check(result) {

FILE: test/autotests/transforms/minify-js/foo.js
  function hello (line 4) | function hello(name) {

FILE: test/autotests/transforms/transform-css-urls-custom-resolver/test.js
  method urlResolver (line 8) | async urlResolver (url, lassoContext) {

FILE: test/autotests/transforms/transform-css-urls-custom-type/test.js
  method init (line 18) | async init (lassoContext) {
  method read (line 22) | async read (lassoContext) {
  method getLastModified (line 31) | async getLastModified (lassoContext) {

FILE: test/inspect-cache-test.js
  function createReadStream (line 28) | function createReadStream() {
  function getLastModified (line 34) | function getLastModified() {
  function createReadStream (line 62) | function createReadStream() {
  function getLastModified (line 69) | function getLastModified() {

FILE: test/lasso-image-test.js
  class Writer (line 110) | class Writer {
    method writeResource (line 111) | async writeResource (reader, lassoContext) {
    method writeBundles (line 119) | writeBundles() {
    method writeResource (line 160) | async writeResource (reader, lassoContext) {
  class Writer (line 159) | class Writer {
    method writeResource (line 111) | async writeResource (reader, lassoContext) {
    method writeBundles (line 119) | writeBundles() {
    method writeResource (line 160) | async writeResource (reader, lassoContext) {

FILE: test/mock/LassoManifest.js
  function resolveBrowserPath (line 6) | function resolveBrowserPath(dir, path) {
  function LassoManifest (line 21) | function LassoManifest(options) {

FILE: test/mock/MockDependency.js
  class MockDependency (line 3) | class MockDependency{
    method getParentManifestDir (line 4) | getParentManifestDir() {
    method getParentManifestPath (line 8) | getParentManifestPath() {

FILE: test/mock/MockLassoContext.js
  function noop (line 18) | function noop() {}
  function DeferredStream (line 20) | function DeferredStream(startFn, options) {
  class MockLassoContext (line 75) | class MockLassoContext {
    method constructor (line 76) | constructor() {
    method isMockLassoContext (line 146) | get isMockLassoContext() {
    method createReadStream (line 154) | createReadStream(func) {
    method mockEnableCachingForCache (line 218) | mockEnableCachingForCache(cacheName) {
    method uniqueId (line 222) | uniqueId() {
    method getFileLastModified (line 226) | async getFileLastModified(path) {
    method isAsyncBundlingPhase (line 230) | isAsyncBundlingPhase() {
    method cachingFs (line 234) | get cachingFs() {
    method deferredStream (line 238) | deferredStream(startFn, options) {
    method createFingerprintStream (line 242) | createFingerprintStream() {
    method readPackageFile (line 246) | readPackageFile(path) {
    method getResolver (line 254) | getResolver() {
    method resolve (line 261) | resolve(targetModule, fromDir, options) {
    method resolveCached (line 265) | resolveCached(targetModule, fromDir, options) {

FILE: test/mock/MockMemoryCache.js
  class MockMemoryCache (line 3) | class MockMemoryCache {
    method constructor (line 4) | constructor() {
    method get (line 8) | get(key, options) {
    method getSync (line 36) | getSync() {

FILE: test/mock/MockRequireHandler.js
  class RequireHandler (line 9) | class RequireHandler {
    method constructor (line 10) | constructor(userOptions, lassoContext, path) {
    method init (line 31) | async init() {
    method createReadStream (line 54) | createReadStream() {
    method getLastModified (line 79) | async getLastModified() {
    method getDependencies (line 116) | getDependencies() {
    method getDefaultBundleName (line 127) | getDefaultBundleName(pageBundleName, lassoContext) {

FILE: test/mock/create-lasso-context.js
  class SyncCache (line 38) | class SyncCache {
    method constructor (line 39) | constructor() {
    method getSync (line 43) | getSync(key) {
    method putSync (line 47) | putSync(key, value) {
  method init (line 91) | async init() {
  method getDependencies (line 95) | async getDependencies() {
  method getRequireExtensionNames (line 111) | getRequireExtensionNames() {
  method getCache (line 119) | getCache(name) {
  method getSyncCache (line 122) | getSyncCache(name) {

FILE: test/mock/dependency-factory.js
  function removeDashes (line 11) | function removeDashes(str) {
  function removeExt (line 17) | function removeExt(filename) {
  function createDependencyFactory (line 25) | function createDependencyFactory(mixinsFactory) {

FILE: test/mock/fingerprint-stream.js
  function FingerprintStream (line 7) | function FingerprintStream(options) {

FILE: test/mock/manifest-loader.js
  function readManifest (line 16) | function readManifest(path) {
  function tryManifest (line 59) | function tryManifest(dirname, manifestPath) {
  function tryExtensionManifest (line 67) | function tryExtensionManifest(dirname, manifestPath) {
  function tryQualified (line 75) | function tryQualified(dirname, manifestPath) {
  function tryAll (line 80) | function tryAll(dirname, manifestPath) {
  function _resolve (line 89) | function _resolve(path, from) {
  function load (line 133) | function load(path, from) {

FILE: test/prebuild-page-test.js
  function replaceLassoVersion (line 10) | function replaceLassoVersion (str) {
  function replaceLassoSlotURLS (line 14) | function replaceLassoSlotURLS (slot) {
  function replaceLasstAssetURLS (line 25) | function replaceLasstAssetURLS (asset) {
  function replaceLassoSlotVersion (line 31) | function replaceLassoSlotVersion (prebuild) {

FILE: test/util/WriterTracker.js
  function WriterTracker (line 5) | function WriterTracker(writer) {

FILE: test/util/index.js
  function rmdirRecursive (line 5) | function rmdirRecursive(dir) {
  function sandboxLoad (line 29) | function sandboxLoad(lassoPageResult, modulesRuntimeGlobal) {
  function writeTestHtmlPage (line 74) | function writeTestHtmlPage(lassoPageResult, outputFile) {

FILE: test/util/normalizeOutput.js
  function normalizeOutput (line 2) | function normalizeOutput(o, dir, options) {

FILE: test/util/patch-module.js
  function buildPath (line 15) | function buildPath (request, beginPath) {
Condensed preview — 1072 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,000K chars).
[
  {
    "path": ".editorconfig",
    "chars": 301,
    "preview": "# top-most EditorConfig file\nroot = true\n\n# Unix-style newlines with a newline ending every file\n[*]\nend_of_line = lf\nin"
  },
  {
    "path": ".eslintrc",
    "chars": 239,
    "preview": "{\n  \"extends\": \"standard\",\n  \"rules\": {\n    \"indent\": [\"error\", 4],\n    \"semi\": [\"error\", \"always\"],\n    \"space-before-f"
  },
  {
    "path": ".gitignore",
    "chars": 276,
    "preview": "/work\n/build\n/.idea/\n/npm-debug.log\n/node_modules\n/*.sublime-workspace\n*.orig\n.DS_Store\ncoverage\n/test/build\n/test/stati"
  },
  {
    "path": ".npmignore",
    "chars": 205,
    "preview": "/work\n/build\n/.idea/\n/npm-debug.log\n/node_modules\n/*.sublime-workspace\n*.orig\n.DS_Store\ncoverage\n/test/build\n*.actual.js"
  },
  {
    "path": ".travis.yml",
    "chars": 137,
    "preview": "node_js:\n- 10\n- 8\n- 6\n\nsudo: false\nlanguage: node_js\n# Use latest version of npm\nbefore_install: npm install -g npm@*\nsc"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 10819,
    "preview": "Changelog\n=========\n\n# 4.0.3\n- Fix issue where the internal lasso context data was missing for image/resource assets.\n\n#"
  },
  {
    "path": "README.md",
    "chars": 71182,
    "preview": "Lasso.js\n==================\n\n[![Build Status](https://travis-ci.org/lasso-js/lasso.svg?branch=master)](https://travis-ci"
  },
  {
    "path": "browser-refresh/index.js",
    "chars": 52,
    "preview": "module.exports = require('../src/browser-refresh');\n"
  },
  {
    "path": "docs/amd.md",
    "chars": 1297,
    "preview": "# AMD Compatibility\n\nLasso.js does not support the AMD module syntax. You can, however, use the [deamdify](https://githu"
  },
  {
    "path": "docs/bundling.md",
    "chars": 6396,
    "preview": "Lasso.js Bundling\n====================================\n\nBundling can either be enabled or disabled during page optimizat"
  },
  {
    "path": "docs/javascript-api.md",
    "chars": 5483,
    "preview": "JavaScript API\n==============\n\n## require('lasso')\n\n### Methods\n\n#### configure(config)\n\nConfigures the default lasso in"
  },
  {
    "path": "docs/migration-optimizer-to-lasso.md",
    "chars": 784,
    "preview": "Optimizer.js to Lasso.js Upgrade Guide\n======================================\n\n- Uninstall old modules:\n  - `npm uninsta"
  },
  {
    "path": "getImageInfo.js",
    "chars": 68,
    "preview": "module.exports = require('./src/plugins/lasso-image').getImageInfo;\n"
  },
  {
    "path": "index.js",
    "chars": 35,
    "preview": "module.exports = require('./src');\n"
  },
  {
    "path": "middleware/index.js",
    "chars": 47,
    "preview": "module.exports = require('../src/middleware');\n"
  },
  {
    "path": "middleware/koa/serveStatic.js",
    "chars": 66,
    "preview": "module.exports = require('../../src/middleware/koa/serveStatic');\n"
  },
  {
    "path": "middleware/serveStatic.js",
    "chars": 59,
    "preview": "module.exports = require('../src/middleware/serveStatic');\n"
  },
  {
    "path": "node-require-no-op.js",
    "chars": 54,
    "preview": "module.exports = require('./src/node-require-no-op');\n"
  },
  {
    "path": "package.json",
    "chars": 2607,
    "preview": "{\n  \"name\": \"lasso\",\n  \"description\": \"Lasso.js is a build tool and runtime library for building and bundling all of the"
  },
  {
    "path": "src/AsyncPackage.js",
    "chars": 1596,
    "preview": "function AsyncPackage(name) {\n    this.name = name;\n    this.bundles = [];\n    this.bundlesByKey = {};\n}\n\nAsyncPackage.p"
  },
  {
    "path": "src/Bundle.js",
    "chars": 4557,
    "preview": "const contentTypes = require('./content-types');\n\nconst Bundle = function(name) {\n    this.name = name;\n    this.depende"
  },
  {
    "path": "src/BundleConfig.js",
    "chars": 1113,
    "preview": "const ok = require('assert').ok;\nconst DependencyList = require('./DependencyList');\n\nconst BundleConfig = function(dirn"
  },
  {
    "path": "src/BundleMappings.js",
    "chars": 10015,
    "preview": "const Bundle = require('./Bundle');\nconst InlinePos = require('./InlinePos');\nconst EventEmitter = require('events').Eve"
  },
  {
    "path": "src/BundleSetConfig.js",
    "chars": 413,
    "preview": "let nextId = 0;\n\nfunction BundleSetConfig(name) {\n    this._id = nextId++;\n    this.name = name;\n    this.bundleConfigs "
  },
  {
    "path": "src/Config.js",
    "chars": 10451,
    "preview": "const extend = require('raptor-util').extend;\nconst BundleSetConfig = require('./BundleSetConfig');\nconst flags = requir"
  },
  {
    "path": "src/DependencyList.js",
    "chars": 1872,
    "preview": "const dependenciesModule = require('./dependencies');\nconst ok = require('assert').ok;\n\nfunction DependencyList(dependen"
  },
  {
    "path": "src/DependencyTree.js",
    "chars": 2723,
    "preview": "const hasOwn = Object.prototype.hasOwnProperty;\n\nfunction Node(dependency, parent) {\n    this.dependency = dependency;\n "
  },
  {
    "path": "src/FlagSet.js",
    "chars": 3952,
    "preview": "/*\n * Copyright 2011 eBay Software Foundation\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * y"
  },
  {
    "path": "src/InlinePos.js",
    "chars": 98,
    "preview": "module.exports = require('raptor-util').makeEnum([\n    'IN_PLACE',\n    'BEGINNING',\n    'END'\n]);\n"
  },
  {
    "path": "src/Lasso.js",
    "chars": 31247,
    "preview": "const assert = require('assert');\nconst nodePath = require('path');\nconst LassoCache = require('./LassoCache');\nconst La"
  },
  {
    "path": "src/LassoCache.js",
    "chars": 5536,
    "preview": "const raptorCache = require('raptor-cache');\nconst nodePath = require('path');\nconst LassoPageResult = require('./LassoP"
  },
  {
    "path": "src/LassoContext.js",
    "chars": 2864,
    "preview": "const EventEmitter = require('events').EventEmitter;\nconst lastModified = require('./last-modified');\nconst cachingFs = "
  },
  {
    "path": "src/LassoManifest.js",
    "chars": 4184,
    "preview": "const extend = require('raptor-util').extend;\nconst DependencyList = require('./DependencyList');\nconst ok = require('as"
  },
  {
    "path": "src/LassoPageResult.js",
    "chars": 7596,
    "preview": "const Slot = require('./Slot');\nconst EMPTY_OBJECT = {};\nconst hasOwn = Object.prototype.hasOwnProperty;\n\nfunction Lasso"
  },
  {
    "path": "src/LassoPrebuildResult.js",
    "chars": 1381,
    "preview": "const fs = require('fs');\n\n/**\n* We may want to store the prebuild in the same directory as the page\n* file instead of t"
  },
  {
    "path": "src/LoaderMetadata.js",
    "chars": 1399,
    "preview": "const AsyncPackage = require('./AsyncPackage');\nfunction LoaderMetadata() {\n    this._packageNames = Object.create(null)"
  },
  {
    "path": "src/PageBundles.js",
    "chars": 1299,
    "preview": "const forEachEntry = require('raptor-util').forEachEntry;\n\n/**\n *\n */\nconst PageBundles = function() {\n    this.bundles "
  },
  {
    "path": "src/PageConfig.js",
    "chars": 834,
    "preview": "function PageConfig() {\n    this.name = null;\n    this.bundleSetConfig = null;\n    this.packageManifest = null;\n}\n\nPageC"
  },
  {
    "path": "src/Slot.js",
    "chars": 2794,
    "preview": "const ok = require('assert').ok;\nconst stringifyAttrs = require('./util/stringify-attrs');\n\nfunction Slot(contentType) {"
  },
  {
    "path": "src/SlotTracker.js",
    "chars": 1726,
    "preview": "const Slot = require('./Slot');\nconst InlinePos = require('./InlinePos');\n\nfunction SlotTracker() {\n    this.slots = {};"
  },
  {
    "path": "src/browser-refresh/index.js",
    "chars": 1675,
    "preview": "const browserRefreshClient = require('browser-refresh-client');\nconst nodePath = require('path');\n\nconst styleExtensions"
  },
  {
    "path": "src/bundle-builder.js",
    "chars": 7236,
    "preview": "const dependencyWalker = require('./dependency-walker');\nconst DependencyTree = require('./DependencyTree');\nconst logge"
  },
  {
    "path": "src/bundling-strategies.js",
    "chars": 7569,
    "preview": "const logger = require('raptor-logging').logger(module);\n\nmodule.exports = {\n    default: function(options, config, bund"
  },
  {
    "path": "src/caching-fs.js",
    "chars": 46,
    "preview": "module.exports = require('lasso-caching-fs');\n"
  },
  {
    "path": "src/condition.js",
    "chars": 987,
    "preview": "exports.ifCondition = function(condition) {\n    // This is a hack because we moved from \"flags\" to \"extensions\"\n    // W"
  },
  {
    "path": "src/config-loader.js",
    "chars": 13355,
    "preview": "const Config = require('./Config');\nconst BundleSetConfig = require('./BundleSetConfig');\nconst BundleConfig = require('"
  },
  {
    "path": "src/content-types.js",
    "chars": 63,
    "preview": "exports.CSS = 'css';\nexports.JS = 'js';\nexports.NONE = 'none';\n"
  },
  {
    "path": "src/dependencies/Dependency.js",
    "chars": 20599,
    "preview": "const nodePath = require('path');\nconst condition = require('../condition');\n\nconst CONTENT_TYPE_CSS = require('../conte"
  },
  {
    "path": "src/dependencies/DependencyRegistry.js",
    "chars": 18331,
    "preview": "const nodePath = require('path');\nconst extend = require('raptor-util').extend;\nconst inherit = require('raptor-util').i"
  },
  {
    "path": "src/dependencies/RequireHandler.js",
    "chars": 4299,
    "preview": "const nodePath = require('path');\nconst ok = require('assert').ok;\n\nconst EMPTY_ARRAY_PROMISE = Promise.resolve([]);\n\ncl"
  },
  {
    "path": "src/dependencies/dependency-comment.js",
    "chars": 267,
    "preview": "module.exports = {\n\n    properties: {\n        path: 'string'\n    },\n\n    // we don't actually produce JavaScript or CSS\n"
  },
  {
    "path": "src/dependencies/dependency-dependencies.js",
    "chars": 299,
    "preview": "module.exports = {\n    properties: {\n        dependencies: 'array'\n    },\n\n    async init (lassoContext) {},\n\n    async "
  },
  {
    "path": "src/dependencies/dependency-intersection.js",
    "chars": 5355,
    "preview": "const dependencyWalker = require('../dependency-walker');\nconst DependencyList = require('../DependencyList');\n\nconst th"
  },
  {
    "path": "src/dependencies/dependency-package.js",
    "chars": 1505,
    "preview": "const ok = require('assert').ok;\nconst manifestLoader = require('../manifest-loader');\nconst nodePath = require('path');"
  },
  {
    "path": "src/dependencies/dependency-resource.js",
    "chars": 2237,
    "preview": "const nodePath = require('path');\n\nconst urlReader = require('../util/url-reader');\nconst urlRegExp = /^(http:|https:)?\\"
  },
  {
    "path": "src/dependencies/glob.js",
    "chars": 1079,
    "preview": "const nodePath = require('path');\nconst glob = require('util').promisify(require('glob'));\n\nconst globRegExp = /[*?+{}]/"
  },
  {
    "path": "src/dependencies/index.js",
    "chars": 514,
    "preview": "const Dependency = require('./Dependency');\nconst DependencyRegistry = require('./DependencyRegistry');\n\nexports.Depende"
  },
  {
    "path": "src/dependency-walker.js",
    "chars": 5079,
    "preview": "const EventEmitter = require('events').EventEmitter;\nconst forEachEntry = require('raptor-util/forEachEntry');\nconst per"
  },
  {
    "path": "src/flags.js",
    "chars": 231,
    "preview": "const FlagSet = require('./FlagSet');\n\nfunction isFlagSet(o) {\n    return o && o.__FlagSet;\n}\n\nfunction createFlagSet(fl"
  },
  {
    "path": "src/index.js",
    "chars": 5063,
    "preview": "require('raptor-logging');\n\nconst nodePath = require('path');\nconst configLoader = require('./config-loader');\nconst fla"
  },
  {
    "path": "src/last-modified.js",
    "chars": 313,
    "preview": "const cachingFs = require('./caching-fs');\n\n// TODO: Change in lasso-caching-fs\nexports.forFile = async function (filePa"
  },
  {
    "path": "src/manifest-loader.js",
    "chars": 5011,
    "preview": "const ok = require('assert').ok;\nconst nodePath = require('path');\nconst Module = require('module').Module;\nconst fs = r"
  },
  {
    "path": "src/middleware/index.js",
    "chars": 48,
    "preview": "exports.serveStatic = require('./serveStatic');\n"
  },
  {
    "path": "src/middleware/koa/serveStatic.js",
    "chars": 1589,
    "preview": "const lasso = require('../');\nconst send = require('send');\nconst extend = require('raptor-util/extend');\n\nfunction notF"
  },
  {
    "path": "src/middleware/serveStatic.js",
    "chars": 1553,
    "preview": "const lasso = require('../');\nconst send = require('send');\nconst extend = require('raptor-util/extend');\n\nfunction notF"
  },
  {
    "path": "src/node-require-no-op/index.js",
    "chars": 705,
    "preview": "function requireNoOp(module, filename) { /* no-op */ }\n\nfunction enableForExtension(extension) {\n    if (extension == nu"
  },
  {
    "path": "src/page-bundles-builder.js",
    "chars": 9843,
    "preview": "const PageBundles = require('./PageBundles');\nconst dependencyWalker = require('./dependency-walker');\nconst assert = re"
  },
  {
    "path": "src/path.js",
    "chars": 1952,
    "preview": "// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person"
  },
  {
    "path": "src/plugins/lasso-image/index.js",
    "chars": 2974,
    "preview": "const imageSize = require('util').promisify(require('image-size'));\nconst nodePath = require('path');\n\nconst IMAGE_SIZE_"
  },
  {
    "path": "src/plugins/lasso-image/lasso-image-browser.js",
    "chars": 197,
    "preview": "exports.getImageInfo = function(path, options, callback) {\n    if (typeof options === 'function') {\n        callback = o"
  },
  {
    "path": "src/plugins/lasso-image/package.json",
    "chars": 68,
    "preview": "{\n  \"browser\": {\n    \"./index.js\": \"./lasso-image-browser.js\"\n  }\n}\n"
  },
  {
    "path": "src/plugins/lasso-minify-css/index.js",
    "chars": 897,
    "preview": "const CleanCSS = require('clean-css');\n\nfunction isInline(lassoContext) {\n    if (lassoContext.inline === true) {\n      "
  },
  {
    "path": "src/plugins/lasso-minify-js/index.js",
    "chars": 1754,
    "preview": "const Terser = require('terser');\nconst codeFrame = require('@babel/code-frame');\nconst hasOwn = Object.prototype.hasOwn"
  },
  {
    "path": "src/plugins/lasso-resolve-css-urls/index.js",
    "chars": 3239,
    "preview": "const cssParser = require('raptor-css-parser');\nconst nodePath = require('path');\nconst lassoResolveFrom = require('lass"
  },
  {
    "path": "src/reader.js",
    "chars": 9957,
    "preview": "const transforms = require('./transforms');\nconst through = require('through');\nconst logger = require('raptor-logging')"
  },
  {
    "path": "src/require/build-plugin-config.js",
    "chars": 2790,
    "preview": "const ok = require('assert').ok;\nconst Transforms = require('./util/Transforms');\nconst extend = require('raptor-util')."
  },
  {
    "path": "src/require/dep-require-remap.js",
    "chars": 876,
    "preview": "const nodePath = require('path');\n\nfunction create(config, lasso) {\n    return {\n        properties: {\n            from:"
  },
  {
    "path": "src/require/dep-require.js",
    "chars": 22896,
    "preview": "const nodePath = require('path');\nconst ok = require('assert').ok;\nconst equal = require('assert').equal;\nconst VAR_REQU"
  },
  {
    "path": "src/require/dep-runtime.js",
    "chars": 1009,
    "preview": "const nodePath = require('path');\nconst fs = require('fs');\n\nconst lassoModulesClientMainPath = require.resolve('lasso-m"
  },
  {
    "path": "src/require/dep-transport-builtin.js",
    "chars": 1138,
    "preview": "const transport = require('lasso-modules-client/transport');\nconst nodePath = require('path');\n\nexports.create = functio"
  },
  {
    "path": "src/require/dep-transport-define.js",
    "chars": 7131,
    "preview": "const ok = require('assert').ok;\nconst nodePath = require('path');\nconst streamToString = require('./util/streamToString"
  },
  {
    "path": "src/require/dep-transport-installed.js",
    "chars": 1245,
    "preview": "const transport = require('lasso-modules-client/transport');\n\nexports.create = function(config, lasso) {\n    return {\n  "
  },
  {
    "path": "src/require/dep-transport-loader-metadata.js",
    "chars": 1087,
    "preview": "const transport = require('lasso-modules-client/transport');\n\nexports.create = function(config, lasso) {\n    return {\n  "
  },
  {
    "path": "src/require/dep-transport-main.js",
    "chars": 1111,
    "preview": "const transport = require('lasso-modules-client/transport');\nconst nodePath = require('path');\n\nexports.create = functio"
  },
  {
    "path": "src/require/dep-transport-ready.js",
    "chars": 675,
    "preview": "const transport = require('lasso-modules-client/transport');\n\nexports.create = function(config, lasso) {\n    return {\n  "
  },
  {
    "path": "src/require/dep-transport-remap.js",
    "chars": 1180,
    "preview": "const transport = require('lasso-modules-client/transport');\nconst nodePath = require('path');\n\nexports.create = functio"
  },
  {
    "path": "src/require/dep-transport-run.js",
    "chars": 1747,
    "preview": "const nodePath = require('path');\nconst transport = require('lasso-modules-client/transport');\n\nexports.create = functio"
  },
  {
    "path": "src/require/dep-transport-search-path.js",
    "chars": 1089,
    "preview": "const transport = require('lasso-modules-client/transport');\n\nexports.create = function(config, lasso) {\n    return {\n  "
  },
  {
    "path": "src/require/index.js",
    "chars": 5067,
    "preview": "const fs = require('fs');\nconst depRequire = require('./dep-require');\nconst depRequireRemap = require('./dep-require-re"
  },
  {
    "path": "src/require/inspect-cache.js",
    "chars": 7752,
    "preview": "const ok = require('assert').ok;\nconst logger = require('raptor-logging').logger(module);\nconst streamToString = require"
  },
  {
    "path": "src/require/util/Deduper.js",
    "chars": 3850,
    "preview": "const DeduperContext = require('./DeduperContext');\nconst ok = require('assert').ok;\n\nconst REQUIRE_DEDUPER_CONTEXT_KEY "
  },
  {
    "path": "src/require/util/DeduperContext.js",
    "chars": 423,
    "preview": "class DeduperContext {\n    constructor() {\n        this.lookups = {\n            def: {},\n            run: {},\n          "
  },
  {
    "path": "src/require/util/StringTransformer.js",
    "chars": 1921,
    "preview": "function StringTransformer() {\n    this.modifications = [];\n}\n\nStringTransformer.prototype = {\n    transform: function(s"
  },
  {
    "path": "src/require/util/Transforms.js",
    "chars": 7959,
    "preview": "const logger = require('raptor-logging').logger(module);\nconst crypto = require('crypto');\nconst ok = require('assert')."
  },
  {
    "path": "src/require/util/inspect.js",
    "chars": 11064,
    "preview": "const path = require('path');\nconst espree = require('espree');\nconst codeFrame = require('@babel/code-frame').default;\n"
  },
  {
    "path": "src/require/util/normalizeFSPath.js",
    "chars": 210,
    "preview": "const lassoModulesClientTransport = require('lasso-modules-client/transport');\n\nfunction normalizeFSPath(path) {\n    ret"
  },
  {
    "path": "src/require/util/streamToString.js",
    "chars": 382,
    "preview": "module.exports = function(stream) {\n    return new Promise((resolve, reject) => {\n        let str = '';\n        stream\n "
  },
  {
    "path": "src/resolve/builtins.js",
    "chars": 1423,
    "preview": "const lassoResolveFrom = require('lasso-resolve-from');\nconst extend = require('raptor-util/extend');\n\nfunction resolveB"
  },
  {
    "path": "src/resolve/getRequireRemapFromDir.js",
    "chars": 390,
    "preview": "const nodePath = require('path');\n\nmodule.exports = function(fromDir, lassoContext) {\n    const lassoJsonPath = nodePath"
  },
  {
    "path": "src/resolve/index.js",
    "chars": 5140,
    "preview": "const builtinsModule = require('./builtins');\nconst parseRequire = require('./parseRequire');\nconst nodePath = require('"
  },
  {
    "path": "src/resolve/parseRequire.js",
    "chars": 649,
    "preview": "module.exports = function parseRequire(path) {\n    const typeSeparatorIndex = path.indexOf(':');\n\n    // NOTE: Windows p"
  },
  {
    "path": "src/transforms.js",
    "chars": 4673,
    "preview": "const inspect = require('util').inspect;\nconst ok = require('assert').ok;\nconst DeferredReadable = require('./util').Def"
  },
  {
    "path": "src/util/CombinedStream.js",
    "chars": 3398,
    "preview": "const Readable = require('stream').Readable;\n\nconst inherit = require('raptor-util/inherit');\n\nfunction CombinedStream(o"
  },
  {
    "path": "src/util/DeferredReadable.js",
    "chars": 2735,
    "preview": "const Readable = require('stream').Readable;\nconst inherit = require('raptor-util/inherit');\n\nfunction DeferredReadable("
  },
  {
    "path": "src/util/caching-stream.js",
    "chars": 1949,
    "preview": "const inherit = require('raptor-util/inherit');\n\nconst Transform = require('stream').Transform;\nconst Readable = require"
  },
  {
    "path": "src/util/fingerprint-stream.js",
    "chars": 1050,
    "preview": "const crypto = require('crypto');\nconst inherit = require('raptor-util/inherit');\nconst Transform = require('stream').Tr"
  },
  {
    "path": "src/util/hash.js",
    "chars": 270,
    "preview": "const crypto = require('crypto');\n\nexports.HASH_OVERFLOW_LENGTH = 8;\n\nexports.generate = function (str, len) {\n    let h"
  },
  {
    "path": "src/util/index.js",
    "chars": 4121,
    "preview": "const cachingStream = require('./caching-stream');\nconst fingerprintStream = require('./fingerprint-stream');\nconst Defe"
  },
  {
    "path": "src/util/prebuild.js",
    "chars": 395,
    "preview": "const nodePath = require('path');\n\nexports.buildPrebuildFileName = function (file) {\n    return `${file}.prebuild.json`;"
  },
  {
    "path": "src/util/stringify-attrs.js",
    "chars": 345,
    "preview": "module.exports = function stringifyAttributes (obj) {\n    let str = '';\n    for (const key in obj) {\n        const val ="
  },
  {
    "path": "src/util/url-reader.js",
    "chars": 1463,
    "preview": "const http = require('http');\nconst https = require('https');\nconst DeferredReadable = require('./DeferredReadable');\n\nf"
  },
  {
    "path": "src/writers/Writer.js",
    "chars": 9829,
    "preview": "const nodePath = require('path');\nconst fileSep = nodePath.sep;\nconst logger = require('raptor-logging').logger(module);"
  },
  {
    "path": "src/writers/file-writer.js",
    "chars": 19865,
    "preview": "const MAX_FILE_LENGTH = 255;\n\nconst util = require('../util');\nconst nodePath = require('path');\nconst fs = require('fs'"
  },
  {
    "path": "src/writers/index.js",
    "chars": 220,
    "preview": "const Writer = require('./Writer');\n\nfunction createWriter(writerImpl) {\n    return new Writer(writerImpl);\n}\n\nexports.W"
  },
  {
    "path": "test/.eslintrc",
    "chars": 113,
    "preview": "{\n  \"globals\": {\n    \"it\": 1,\n    \"describe\": 1,\n    \"context\": 1,\n    \"beforeEach\": 1,\n    \"afterEach\": 1\n  }\n}\n"
  },
  {
    "path": "test/.gitignore",
    "chars": 42,
    "preview": "*.marko.js\n*.dust.js\n~*/\nactual.*\nactual-*"
  },
  {
    "path": "test/api-test.js",
    "chars": 899,
    "preview": "'use strict';\nrequire('./util/test-init');\n\nvar nodePath = require('path');\nrequire('chai').config.includeStack = true;\n"
  },
  {
    "path": "test/autotest.js",
    "chars": 2443,
    "preview": "'use strict';\n\nvar fs = require('fs');\nvar enabledTest = process.env.TEST;\nvar path = require('path');\nvar assert = requ"
  },
  {
    "path": "test/autotests/api/config-fingerprint/foo.js",
    "chars": 20,
    "preview": "console.log('Foo!');"
  },
  {
    "path": "test/autotests/api/config-fingerprint/test.js",
    "chars": 495,
    "preview": "const expect = require('chai').expect;\n\nexports.check = function (lasso, helpers) {\n    var config = {\n        bundles: "
  },
  {
    "path": "test/autotests/api/lasso-lassoPage-promise/browser.json",
    "chars": 50,
    "preview": "{\n    \"dependencies\": [\n        \"./foo.js\"\n    ]\n}"
  },
  {
    "path": "test/autotests/api/lasso-lassoPage-promise/foo.js",
    "chars": 3,
    "preview": "foo"
  },
  {
    "path": "test/autotests/api/lasso-lassoPage-promise/test.js",
    "chars": 526,
    "preview": "const nodePath = require('path');\nconst expect = require('chai').expect;\n\nexports.check = async function (lasso, helpers"
  },
  {
    "path": "test/autotests/api/lasso-lassoResource-buffer/test.js",
    "chars": 567,
    "preview": "'use strict';\n\nconst fs = require('fs');\nconst nodePath = require('path');\nconst expect = require('chai').expect;\n\nexpor"
  },
  {
    "path": "test/autotests/api/lasso-lassoResource-buffer-name/test.js",
    "chars": 594,
    "preview": "'use strict';\n\nconst fs = require('fs');\nconst nodePath = require('path');\nconst expect = require('chai').expect;\n\nexpor"
  },
  {
    "path": "test/autotests/api/lasso-lassoResource-promise/foo.txt",
    "chars": 3,
    "preview": "foo"
  },
  {
    "path": "test/autotests/api/lasso-lassoResource-promise/test.js",
    "chars": 410,
    "preview": "const nodePath = require('path');\nconst expect = require('chai').expect;\n\nexports.check = async function (lasso, helpers"
  },
  {
    "path": "test/autotests/api/myLasso-lassoPage-promise/browser.json",
    "chars": 50,
    "preview": "{\n    \"dependencies\": [\n        \"./foo.js\"\n    ]\n}"
  },
  {
    "path": "test/autotests/api/myLasso-lassoPage-promise/foo.js",
    "chars": 3,
    "preview": "foo"
  },
  {
    "path": "test/autotests/api/myLasso-lassoPage-promise/test.js",
    "chars": 535,
    "preview": "var nodePath = require('path');\nvar expect = require('chai').expect;\n\nexports.check = async function (lasso, helpers) {\n"
  },
  {
    "path": "test/autotests/api/myLasso-lassoResource-promise/foo.txt",
    "chars": 3,
    "preview": "foo"
  },
  {
    "path": "test/autotests/api/myLasso-lassoResource-promise/test.js",
    "chars": 425,
    "preview": "const nodePath = require('path');\nconst expect = require('chai').expect;\n\nexports.check = async function (lasso, helpers"
  },
  {
    "path": "test/autotests/api/pollute-default-config/test.js",
    "chars": 643,
    "preview": "const expect = require('chai').expect;\n\nexports.check = function (lasso, helpers) {\n    const myLasso1 = lasso.create({\n"
  },
  {
    "path": "test/autotests/bundling/async-dependencies/a.js",
    "chars": 4,
    "preview": "a.js"
  },
  {
    "path": "test/autotests/bundling/async-dependencies/b.js",
    "chars": 4,
    "preview": "b.js"
  },
  {
    "path": "test/autotests/bundling/async-dependencies/browser.json",
    "chars": 59,
    "preview": "{\n    \"dependencies\": [\n        \"require: ./foo.js\"\n    ]\n}"
  },
  {
    "path": "test/autotests/bundling/async-dependencies/foo-async.js",
    "chars": 58,
    "preview": "console.log('foo-async');\nrequire('./foo-something-else');"
  },
  {
    "path": "test/autotests/bundling/async-dependencies/foo-something-else.js",
    "chars": 34,
    "preview": "console.log('foo-something-else');"
  },
  {
    "path": "test/autotests/bundling/async-dependencies/foo.js",
    "chars": 130,
    "preview": "console.log('foo');\n\nrequire('lasso-loader').async([\n    './a.js',\n    './b.js'\n], function(err) {\n    require('./foo-as"
  },
  {
    "path": "test/autotests/bundling/async-dependencies/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/async-dependencies/test.js",
    "chars": 1422,
    "preview": "var expect = require('chai').expect;\nvar path = require('path');\n\nexports.getLassoConfig = function() {\n    return {\n   "
  },
  {
    "path": "test/autotests/bundling/async-flags/DO_NOT_INCLUDE_ME.js",
    "chars": 17,
    "preview": "DO_NOT_INCLUDE_ME"
  },
  {
    "path": "test/autotests/bundling/async-flags/browser.json",
    "chars": 262,
    "preview": "{\n    \"dependencies\": [\n        \"./foo.js\"\n    ],\n    \"async\": {\n        \"foo\": [\n            {\n                \"if-flag"
  },
  {
    "path": "test/autotests/bundling/async-flags/foo.js",
    "chars": 3,
    "preview": "foo"
  },
  {
    "path": "test/autotests/bundling/async-flags/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/async-flags/test.js",
    "chars": 705,
    "preview": "var expect = require('chai').expect;\nvar path = require('path');\n\nexports.getLassoConfig = function() {\n    return {\n   "
  },
  {
    "path": "test/autotests/bundling/async-package/bar.js",
    "chars": 19,
    "preview": "console.log('bar');"
  },
  {
    "path": "test/autotests/bundling/async-package/browser.json",
    "chars": 144,
    "preview": "{\n    \"async\": {\n        \"foo\": [\n            \"require: ./foo.js\"\n        ],\n\n        \"bar\": [\n            \"require: ./b"
  },
  {
    "path": "test/autotests/bundling/async-package/foo.js",
    "chars": 19,
    "preview": "console.log('foo');"
  },
  {
    "path": "test/autotests/bundling/async-package/main.js",
    "chars": 233,
    "preview": "var packageId = 'foo';\n\nconsole.log('main');\nrequire('lasso-loader').async(packageId, function(err) {\n    require('./foo"
  },
  {
    "path": "test/autotests/bundling/async-package/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/async-package/test.js",
    "chars": 1378,
    "preview": "var expect = require('chai').expect;\n\nexports.getLassoConfig = function() {\n    return {\n        fingerprintsEnabled: fa"
  },
  {
    "path": "test/autotests/bundling/bundle-getImageInfo-skip/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/bundle-getImageInfo-skip/test.js",
    "chars": 606,
    "preview": "var expect = require('chai').expect;\n\nexports.getLassoConfig = function() {\n    return {\n        fingerprintsEnabled: fa"
  },
  {
    "path": "test/autotests/bundling/bundles/a.js",
    "chars": 1,
    "preview": "a"
  },
  {
    "path": "test/autotests/bundling/bundles/b.js",
    "chars": 1,
    "preview": "b"
  },
  {
    "path": "test/autotests/bundling/bundles/browser.json",
    "chars": 71,
    "preview": "{\n    \"dependencies\": [\n        \"./foo.js\",\n        \"./foo.css\"\n    ]\n}"
  },
  {
    "path": "test/autotests/bundling/bundles/c.js",
    "chars": 1,
    "preview": "c"
  },
  {
    "path": "test/autotests/bundling/bundles/d.js",
    "chars": 1,
    "preview": "d"
  },
  {
    "path": "test/autotests/bundling/bundles/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/bundles/test.js",
    "chars": 1401,
    "preview": "var expect = require('chai').expect;\nvar path = require('path');\n\nexports.getLassoConfig = function() {\n    return {\n   "
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-default/a.js",
    "chars": 2,
    "preview": "a\n"
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-default/b.js",
    "chars": 2,
    "preview": "b\n"
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-default/browser.json",
    "chars": 46,
    "preview": "{\n    \"dependencies\": [\n        \"a.js\"\n    ]\n}"
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-default/c.js",
    "chars": 2,
    "preview": "c\n"
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-default/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-default/test.js",
    "chars": 657,
    "preview": "var expect = require('chai').expect;\n\nexports.getLassoConfig = function() {\n    return {\n        fingerprintsEnabled: fa"
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-lean/a.js",
    "chars": 2,
    "preview": "a\n"
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-lean/b.js",
    "chars": 2,
    "preview": "b\n"
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-lean/browser.json",
    "chars": 46,
    "preview": "{\n    \"dependencies\": [\n        \"a.js\"\n    ]\n}"
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-lean/c.js",
    "chars": 2,
    "preview": "c\n"
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-lean/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/bundling-strategy-lean/test.js",
    "chars": 717,
    "preview": "var expect = require('chai').expect;\n\nexports.getLassoConfig = function() {\n    return {\n        fingerprintsEnabled: fa"
  },
  {
    "path": "test/autotests/bundling/bundling-virtual-module/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/bundling-virtual-module/test.js",
    "chars": 888,
    "preview": "var expect = require('chai').expect;\n\nexports.getLassoConfig = function() {\n    return {\n        fingerprintsEnabled: fa"
  },
  {
    "path": "test/autotests/bundling/csp-nonce-inline-script/a.js",
    "chars": 1,
    "preview": "a"
  },
  {
    "path": "test/autotests/bundling/csp-nonce-inline-script/b.js",
    "chars": 1,
    "preview": "b"
  },
  {
    "path": "test/autotests/bundling/csp-nonce-inline-script/browser.json",
    "chars": 71,
    "preview": "{\n    \"dependencies\": [\n        \"./foo.js\",\n        \"./foo.css\"\n    ]\n}"
  },
  {
    "path": "test/autotests/bundling/csp-nonce-inline-script/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/csp-nonce-inline-script/test.js",
    "chars": 1187,
    "preview": "var expect = require('chai').expect;\nvar path = require('path');\n\nexports.getLassoConfig = function() {\n    return {\n   "
  },
  {
    "path": "test/autotests/bundling/css-inline-resource-base64/expected.css",
    "chars": 8169,
    "preview": ".foo {\n    background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE8AAAAeCAYAAABt5kPUAAAAGXRFWHRTb2Z0d2Fy"
  },
  {
    "path": "test/autotests/bundling/css-inline-resource-base64/foo.css",
    "chars": 57,
    "preview": ".foo {\n    background-image: url(ebay-logo.png?base64);\n}"
  },
  {
    "path": "test/autotests/bundling/css-inline-resource-base64/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/css-inline-resource-base64/test.js",
    "chars": 820,
    "preview": "var expect = require('chai').expect;\nvar path = require('path');\n\nexports.getLassoConfig = function() {\n    return {\n   "
  },
  {
    "path": "test/autotests/bundling/css-inline-resource-utf8/expected.css",
    "chars": 216,
    "preview": ".foo {\n    background-image: url('data:image/svg+xml;utf8,<?xml version=\"1.0\"?>%0A<svg viewBox=\"0 0 120 120\" version=\"1."
  },
  {
    "path": "test/autotests/bundling/css-inline-resource-utf8/foo.css",
    "chars": 54,
    "preview": ".foo {\n    background-image: url(./circle.svg?utf8);\n}"
  },
  {
    "path": "test/autotests/bundling/css-inline-resource-utf8/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/css-inline-resource-utf8/test.js",
    "chars": 823,
    "preview": "var expect = require('chai').expect;\nvar path = require('path');\n\nexports.getLassoConfig = function() {\n    return {\n   "
  },
  {
    "path": "test/autotests/bundling/css-resources-multiple-pages-no-bundling/foo.css",
    "chars": 53,
    "preview": ".foo {\n    background-image: url('./foo.resource');\n}"
  },
  {
    "path": "test/autotests/bundling/css-resources-multiple-pages-no-bundling/foo.resource",
    "chars": 3,
    "preview": "foo"
  },
  {
    "path": "test/autotests/bundling/css-resources-multiple-pages-no-bundling/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/css-resources-multiple-pages-no-bundling/test.js",
    "chars": 1484,
    "preview": "var expect = require('chai').expect;\nvar path = require('path');\n\nexports.getLassoConfig = function() {\n    return {\n   "
  },
  {
    "path": "test/autotests/bundling/custom-dependency-type-no-bundling/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  },
  {
    "path": "test/autotests/bundling/custom-dependency-type-no-bundling/test.js",
    "chars": 1263,
    "preview": "var expect = require('chai').expect;\nvar path = require('path');\n\nexports.getLassoConfig = function() {\n    return {\n   "
  },
  {
    "path": "test/autotests/bundling/dedupe/a.js",
    "chars": 1,
    "preview": "a"
  },
  {
    "path": "test/autotests/bundling/dedupe/b.js",
    "chars": 1,
    "preview": "b"
  },
  {
    "path": "test/autotests/bundling/dedupe/browser.json",
    "chars": 71,
    "preview": "{\n    \"dependencies\": [\n        \"./foo.js\",\n        \"./foo.css\"\n    ]\n}"
  },
  {
    "path": "test/autotests/bundling/dedupe/c.js",
    "chars": 1,
    "preview": "c"
  },
  {
    "path": "test/autotests/bundling/dedupe/d.js",
    "chars": 1,
    "preview": "d"
  },
  {
    "path": "test/autotests/bundling/dedupe/package.json",
    "chars": 64,
    "preview": "{\n    \"name\": \"test-bundling-project\",\n    \"version\": \"0.0.0\"\n}\n"
  }
]

// ... and 872 more files (download for full content)

About this extraction

This page contains the full source code of the lasso-js/lasso GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1072 files (857.7 KB), approximately 242.8k tokens, and a symbol index with 610 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!