├── .gitignore
├── testdata
├── JavaScriptGetText
│ ├── name.txt
│ └── index.html.template
├── transforms
│ ├── buildProduction
│ │ ├── GetStaticUrlFlash
│ │ │ ├── swf
│ │ │ │ └── foo.swf
│ │ │ └── index.html
│ │ ├── initialHtmlFragments
│ │ │ ├── script.js
│ │ │ ├── js
│ │ │ │ └── script.js
│ │ │ ├── myTemplate.html
│ │ │ ├── foo.png
│ │ │ └── index.html
│ │ ├── inline
│ │ │ ├── script.js
│ │ │ ├── styles.css
│ │ │ └── index.html
│ │ ├── simple
│ │ │ ├── someTextFile.txt
│ │ │ ├── script1.js
│ │ │ ├── script2.js
│ │ │ ├── script3.js
│ │ │ ├── morescripts
│ │ │ │ ├── shimmed.js
│ │ │ │ ├── somethingElse.js
│ │ │ │ ├── amdDependency.js
│ │ │ │ ├── view
│ │ │ │ │ ├── styles.less
│ │ │ │ │ └── template.ko
│ │ │ │ └── main.js
│ │ │ ├── styles1.css
│ │ │ ├── styles3.css
│ │ │ ├── styles2.css
│ │ │ ├── myImage.gif
│ │ │ ├── index.i18n
│ │ │ └── index.html
│ │ ├── dataMainAndAlmondJs
│ │ │ ├── a.js
│ │ │ ├── d.js
│ │ │ ├── almond.js
│ │ │ ├── require.js
│ │ │ └── index.html
│ │ ├── bundlingInHtmlFragments
│ │ │ ├── a.js
│ │ │ ├── b.js
│ │ │ ├── a.css
│ │ │ ├── b.css
│ │ │ └── index.html
│ │ ├── duplicateImports
│ │ │ ├── one.css
│ │ │ ├── two.css
│ │ │ ├── imported.css
│ │ │ └── index.html
│ │ ├── issue58
│ │ │ ├── templates
│ │ │ │ └── header.html
│ │ │ ├── js
│ │ │ │ └── main.js
│ │ │ └── index.html
│ │ ├── lessPlugin
│ │ │ ├── b.less
│ │ │ ├── c.less
│ │ │ ├── a.less
│ │ │ ├── someModule.js
│ │ │ ├── main.js
│ │ │ ├── main2.js
│ │ │ ├── index.html
│ │ │ └── index2.html
│ │ ├── htmlDataMainWithI18n
│ │ │ ├── script.js
│ │ │ ├── webmail.i18n
│ │ │ └── index.html
│ │ ├── assetsThatShouldNotBeMoved
│ │ │ ├── .htaccess
│ │ │ ├── robots.txt
│ │ │ ├── humans.txt
│ │ │ ├── favicon.ico
│ │ │ └── index.html
│ │ ├── implicitBaseUrl
│ │ │ ├── src
│ │ │ │ ├── component.js
│ │ │ │ └── main.js
│ │ │ └── index.html
│ │ ├── requiredCssImport
│ │ │ ├── other.css
│ │ │ ├── foo.css
│ │ │ └── index.html
│ │ ├── issue60
│ │ │ ├── js
│ │ │ │ ├── config.js
│ │ │ │ ├── modules
│ │ │ │ │ └── utils.js
│ │ │ │ └── main.js
│ │ │ └── index.html
│ │ ├── knockoutJs
│ │ │ ├── templates
│ │ │ │ ├── bar.ko
│ │ │ │ └── foo.ko
│ │ │ ├── foo.png
│ │ │ ├── someModule.js
│ │ │ ├── main.js
│ │ │ ├── index.html
│ │ │ └── tpl.js
│ │ ├── styleSheetInTemplate
│ │ │ ├── style.css
│ │ │ ├── component.html
│ │ │ └── index.html
│ │ ├── gzip
│ │ │ ├── foo.js
│ │ │ ├── foo.png
│ │ │ ├── sockjs-0.3.4.js.gz
│ │ │ └── index.html
│ │ ├── requireJsConfigurationInExternalFile
│ │ │ ├── theCorrectBase
│ │ │ │ └── foo.js
│ │ │ ├── theRequireJsConfig.js
│ │ │ └── index.html
│ │ ├── GetStaticUrlSingleFileWildcard
│ │ │ ├── justThisOneFile.txt
│ │ │ └── index.html
│ │ ├── bootstrapperI18n
│ │ │ ├── bootstrapper.js
│ │ │ ├── index.i18n
│ │ │ └── index.html
│ │ ├── requireJsOrphans
│ │ │ ├── module1.js
│ │ │ ├── module2.js
│ │ │ ├── module4.js
│ │ │ ├── module3.js
│ │ │ ├── index.html
│ │ │ └── main.js
│ │ ├── GetStaticUrlSingleFileAndTwoWildcards
│ │ │ ├── dir
│ │ │ │ └── justThisOneFile.txt
│ │ │ └── index.html
│ │ ├── issue114
│ │ │ ├── a.js
│ │ │ └── index.html
│ │ ├── issue54
│ │ │ ├── js
│ │ │ │ ├── vendor
│ │ │ │ │ ├── deep-model.js
│ │ │ │ │ └── backbone-amd
│ │ │ │ │ │ └── backbone.js
│ │ │ │ └── app.js
│ │ │ └── index.html
│ │ ├── multiPageRequireJs
│ │ │ ├── common1.js
│ │ │ ├── common2.js
│ │ │ ├── main1.js
│ │ │ ├── main2.js
│ │ │ ├── index1.html
│ │ │ └── index2.html
│ │ ├── issue83
│ │ │ ├── script.js
│ │ │ └── index.html
│ │ ├── angularJs
│ │ │ ├── index.i18n
│ │ │ ├── bar.png
│ │ │ ├── foo.png
│ │ │ ├── partials
│ │ │ │ └── 1.html
│ │ │ ├── quux.png
│ │ │ └── index.html
│ │ ├── multipleHtmlsReferencingTheSameExternalRequireJsConfig
│ │ │ ├── requireJsConfig.js
│ │ │ ├── app
│ │ │ │ ├── someDependency.js
│ │ │ │ ├── main1.js
│ │ │ │ └── main2.js
│ │ │ ├── app1.html
│ │ │ └── app2.html
│ │ ├── rss
│ │ │ ├── foo.png
│ │ │ ├── index.html
│ │ │ └── rssFeed.xml
│ │ ├── initialAssetWithoutHtmlElement
│ │ │ └── index.html
│ │ ├── inkscape
│ │ │ ├── index.html
│ │ │ ├── styles.less
│ │ │ └── image.svg
│ │ ├── requireJsCdnPath
│ │ │ ├── main.js
│ │ │ └── index.html
│ │ ├── angularJsMultipleTemplateRefs
│ │ │ ├── partials
│ │ │ │ └── 1.html
│ │ │ └── index.html
│ │ ├── fragmentWithUnpopulatedRelation
│ │ │ ├── templates
│ │ │ │ └── myTemplate.html
│ │ │ └── index.html
│ │ ├── nonInitialAssetWithIncomingHtmlAnchor
│ │ │ ├── index2.html
│ │ │ └── index.html
│ │ ├── nonExistentFileWithoutExtension
│ │ │ └── index.html
│ │ ├── spriteAndProcessImages
│ │ │ ├── foo.png
│ │ │ └── index.html
│ │ ├── faviconOutsideRoot
│ │ │ ├── foo
│ │ │ │ └── favicon.ico
│ │ │ └── index.html
│ │ ├── GetStaticUrlImageOnCdn
│ │ │ ├── images
│ │ │ │ └── test.png
│ │ │ └── index.html
│ │ ├── existingSourceMap
│ │ │ └── index.html
│ │ ├── imagesWithWrongExtensions
│ │ │ ├── actuallyAPng.jpg
│ │ │ ├── actuallyAJpeg.png
│ │ │ ├── index.html
│ │ │ └── style.css
│ │ ├── issue69
│ │ │ ├── index.html
│ │ │ └── app
│ │ │ │ └── main.js
│ │ ├── JavaScriptGetStaticUrlWithProcessedImages
│ │ │ ├── images
│ │ │ │ ├── bar.png
│ │ │ │ └── foo.png
│ │ │ └── index.html
│ │ ├── missingDataBind
│ │ │ └── index.html
│ │ ├── ssi
│ │ │ ├── index.i18n
│ │ │ └── index.html
│ │ ├── noCompress
│ │ │ └── index.html
│ │ ├── lessCompiler
│ │ │ └── index.html
│ │ ├── emptyScriptsAndStylesheetsWithAttributes
│ │ │ └── index.html
│ │ ├── stripDebug
│ │ │ └── index.html
│ │ └── svgsWithIdenticalInlineStyle
│ │ │ ├── gears.svg
│ │ │ └── gears2.svg
│ ├── replaceDartWithJavaScript
│ │ ├── app.dart
│ │ ├── app.dart.js
│ │ └── index.html
│ ├── buildDevelopment
│ │ ├── simple
│ │ │ ├── script.js
│ │ │ ├── styles.css
│ │ │ ├── index.i18n
│ │ │ └── index.html.template
│ │ └── dataBindOnHtmlStyle
│ │ │ └── index.html.template
│ ├── autoprefixer
│ │ ├── userselect.css
│ │ ├── borderimage.css
│ │ ├── borderimage.png
│ │ └── index.html
│ ├── cloneForEachLocale
│ │ ├── css
│ │ │ ├── doesNotNeedLocalization.css
│ │ │ ├── bar.png
│ │ │ ├── foo.png
│ │ │ ├── index.html
│ │ │ └── needsLocalization.css
│ │ ├── knockoutTemplate
│ │ │ ├── templateWithoutI18n.ko
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── templateWithI18n.ko
│ │ │ └── index.i18n
│ │ ├── simple
│ │ │ ├── index.html.appcache
│ │ │ ├── style.css
│ │ │ ├── foo.png
│ │ │ ├── index.i18n
│ │ │ └── index.html
│ │ ├── localeCookieName
│ │ │ ├── localeCookieName.js
│ │ │ └── index.html
│ │ ├── multipleHtmls
│ │ │ ├── doesNotNeedLocalization.js
│ │ │ ├── needsLocalization.js
│ │ │ ├── index.i18n
│ │ │ ├── 1.html
│ │ │ └── 2.html
│ │ ├── JavaScriptTrHtmlAndJavaScriptGetText
│ │ │ ├── template.html
│ │ │ ├── index.i18n
│ │ │ └── index.html
│ │ ├── inlineScriptTemplateInKnockoutJsTemplate
│ │ │ ├── index.js
│ │ │ ├── template.ko
│ │ │ ├── index.i18n
│ │ │ └── index.html
│ │ ├── svg
│ │ │ ├── index.i18n
│ │ │ ├── index.html
│ │ │ └── image.svg
│ │ ├── trInHtmlDataBindAttributeInKoTemplate
│ │ │ ├── template.ko
│ │ │ ├── main.js
│ │ │ ├── index.i18n
│ │ │ └── index.html
│ │ ├── reusePlaceHolder
│ │ │ ├── index.i18n
│ │ │ └── index.html
│ │ ├── inlineCssCombo
│ │ │ ├── foo.png
│ │ │ └── index.html
│ │ ├── JavaScriptTrHtml
│ │ │ ├── index.i18n
│ │ │ └── index.html
│ │ ├── inlineScriptTemplate
│ │ │ ├── index.i18n
│ │ │ └── index.html
│ │ ├── relationInPlaceHolder
│ │ │ ├── index.i18n
│ │ │ ├── foo.png
│ │ │ └── index.html
│ │ ├── trInHtmlDataBindAttribute
│ │ │ ├── index.i18n
│ │ │ └── index.html
│ │ ├── globalVarUsageInJavaScript
│ │ │ ├── index.html
│ │ │ └── foo.js
│ │ └── multipleLocales
│ │ │ ├── index.html
│ │ │ └── index.i18n
│ ├── processImages
│ │ ├── jpeg
│ │ │ ├── style.css
│ │ │ └── turtle.jpg
│ │ ├── setFormat
│ │ │ ├── index.css
│ │ │ └── foo.png
│ │ ├── dot.in.path
│ │ │ ├── style.css
│ │ │ └── redalpha24bit.png
│ │ ├── html
│ │ │ ├── myImage.png
│ │ │ └── index.html
│ │ ├── css
│ │ │ ├── redalpha24bit.png
│ │ │ ├── purplealpha24bit.png
│ │ │ └── style.css
│ │ ├── devicePixelRatio
│ │ │ ├── foo.png
│ │ │ ├── foo@2x.png
│ │ │ ├── foo@8x.png
│ │ │ └── style.css
│ │ ├── pngs
│ │ │ ├── redalpha24bit.png
│ │ │ ├── purplealpha24bit.png
│ │ │ └── style.css
│ │ └── svg
│ │ │ ├── addBogusElement.js
│ │ │ └── index.html
│ ├── duplicateFavicon
│ │ ├── unreferencedFavicon
│ │ │ ├── noHead.html
│ │ │ ├── index.html
│ │ │ └── favicon.ico
│ │ └── referencedFavicon
│ │ │ ├── favicon.ico
│ │ │ └── index.html
│ ├── checkLanguageKeys
│ │ ├── duplicateLanguageKeys
│ │ │ ├── external.js
│ │ │ └── index.html
│ │ ├── neverEndingSpaceLoop
│ │ │ └── index.html
│ │ ├── pluralRule
│ │ │ ├── index.html
│ │ │ └── index.i18n
│ │ └── combo
│ │ │ └── index.html
│ ├── angularAnnotations
│ │ └── basic.js
│ └── runJavaScriptConditionalBlocks
│ │ └── index.html
├── resolvers
│ └── senchaJsBuilder
│ │ ├── dependentPackages
│ │ ├── js
│ │ │ ├── A1.js
│ │ │ ├── B1.js
│ │ │ └── C1.js
│ │ ├── index.html
│ │ ├── overlappingIncludes.html
│ │ └── foo.jsb2
│ │ └── rewriteBackgroundImageUrls
│ │ ├── index.html
│ │ ├── resources
│ │ ├── images
│ │ │ └── foo
│ │ │ │ └── bar
│ │ │ │ └── foo.png
│ │ └── css
│ │ │ └── subdir
│ │ │ └── foo.css
│ │ └── foo.jsb2
├── bin
│ ├── applyBabelJob
│ │ ├── index.someother.i18n
│ │ ├── translationjob
│ │ │ ├── en.txt
│ │ │ └── da.txt
│ │ ├── index.i18n
│ │ └── index.html
│ ├── makeBabelJobAndApplyBabelJob
│ │ ├── template.ko
│ │ ├── index.html
│ │ └── thething.i18n
│ └── makeBabelJob
│ │ ├── other.i18n
│ │ ├── index.i18n
│ │ └── index.html
└── findParentDirectory
│ ├── directory
│ └── quux.png
│ └── otherdirectory
│ └── onemorelevel
│ ├── bar.png
│ └── foo.png
├── .jshintignore
├── test
├── mocha.opts
├── unexpected-with-plugins.js
├── transforms
│ ├── angularAnnotations.js
│ ├── replaceDartWithJavaScript.js
│ ├── runJavaScriptConditionalBlocks.js
│ ├── autoprefixer.js
│ ├── buildDevelopment.js
│ └── duplicateFavicon.js
├── JavaScriptGetText.js
├── findParentDirectory.js
├── i18nTools.js
├── resolvers
│ └── senchaJsBuilder.js
└── bin
│ └── applyBabelJob.js
├── Dockerfile
├── lib
├── transforms
│ ├── removeNobundleAttribute.js
│ ├── omitFunctionCall.js
│ ├── setAsyncOrDeferOnHtmlScripts.js
│ ├── removeDuplicateHtmlStyles.js
│ ├── injectBootstrapper.js
│ ├── replaceDartWithJavaScript.js
│ ├── angularAnnotations.js
│ ├── autoprefixer.js
│ ├── duplicateFavicon.js
│ ├── addDataVersionAttributeToHtmlElement.js
│ ├── stripDebug.js
│ ├── gzip.js
│ ├── runJavaScriptConditionalBlocks.js
│ ├── buildDevelopment.js
│ └── registerLabelsAsCustomProtocols.js
├── resolvers
│ ├── index.js
│ ├── findParentDirectory.js
│ └── senchaJsBuilder.js
├── canonicalizeObject.js
├── mkpathSync.js
├── AssetGraph.js
├── loadAndInstantiateAutoprefixer.js
└── PngQuantWithHistogram.js
├── .travis.yml
├── bin
├── optimizeImage
├── buildDevelopment
├── flattenOneInclude
├── findUnusedSelectors
├── copyReferencedAssets
├── checkLanguageKeys
└── refreshI18n
├── LICENSE
├── package.json
└── .jshintrc
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 | /coverage/
3 |
--------------------------------------------------------------------------------
/testdata/JavaScriptGetText/name.txt:
--------------------------------------------------------------------------------
1 | Foobar
2 |
--------------------------------------------------------------------------------
/.jshintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | testdata
3 | coverage
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/GetStaticUrlFlash/swf/foo.swf:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/initialHtmlFragments/script.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/testdata/resolvers/senchaJsBuilder/dependentPackages/js/A1.js:
--------------------------------------------------------------------------------
1 | A1();
2 |
--------------------------------------------------------------------------------
/testdata/resolvers/senchaJsBuilder/dependentPackages/js/B1.js:
--------------------------------------------------------------------------------
1 | B1();
2 |
--------------------------------------------------------------------------------
/testdata/resolvers/senchaJsBuilder/dependentPackages/js/C1.js:
--------------------------------------------------------------------------------
1 | C1();
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/inline/script.js:
--------------------------------------------------------------------------------
1 | alert("script");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/someTextFile.txt:
--------------------------------------------------------------------------------
1 | someText
2 |
--------------------------------------------------------------------------------
/testdata/transforms/replaceDartWithJavaScript/app.dart:
--------------------------------------------------------------------------------
1 | 'I am Dart'
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildDevelopment/simple/script.js:
--------------------------------------------------------------------------------
1 | alert('script');
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/dataMainAndAlmondJs/a.js:
--------------------------------------------------------------------------------
1 | alert("a");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/dataMainAndAlmondJs/d.js:
--------------------------------------------------------------------------------
1 | alert("d");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/script1.js:
--------------------------------------------------------------------------------
1 | alert("script1");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/script2.js:
--------------------------------------------------------------------------------
1 | alert("script2");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/script3.js:
--------------------------------------------------------------------------------
1 | alert("script3");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/bundlingInHtmlFragments/a.js:
--------------------------------------------------------------------------------
1 | alert("a");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/bundlingInHtmlFragments/b.js:
--------------------------------------------------------------------------------
1 | alert("b");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/replaceDartWithJavaScript/app.dart.js:
--------------------------------------------------------------------------------
1 | 'I am JavaScript'
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/dataMainAndAlmondJs/almond.js:
--------------------------------------------------------------------------------
1 | alert("almond");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/dataMainAndAlmondJs/require.js:
--------------------------------------------------------------------------------
1 | alert("require");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/morescripts/shimmed.js:
--------------------------------------------------------------------------------
1 | alert('shimmed');
2 |
--------------------------------------------------------------------------------
/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --reporter spec
2 | --timeout 60000
3 | --recursive
4 | --check-leaks
5 |
--------------------------------------------------------------------------------
/testdata/transforms/autoprefixer/userselect.css:
--------------------------------------------------------------------------------
1 | body {
2 | user-select: none;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildDevelopment/simple/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: beige;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/bundlingInHtmlFragments/a.css:
--------------------------------------------------------------------------------
1 | body {color: #aaa;}
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/bundlingInHtmlFragments/b.css:
--------------------------------------------------------------------------------
1 | body {color: #bbb;}
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/duplicateImports/one.css:
--------------------------------------------------------------------------------
1 | @import url("imported.css");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/duplicateImports/two.css:
--------------------------------------------------------------------------------
1 | @import url("imported.css");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue58/templates/header.html:
--------------------------------------------------------------------------------
1 |
The header
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/lessPlugin/b.less:
--------------------------------------------------------------------------------
1 | body {
2 | color: tan;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/styles1.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: teal;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/styles3.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: tan;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/htmlDataMainWithI18n/script.js:
--------------------------------------------------------------------------------
1 | INCLUDE('webmail.i18n');
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/inline/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: maroon;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/lessPlugin/c.less:
--------------------------------------------------------------------------------
1 | body {
2 | text-indent: 10px;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/styles2.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: maroon;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/assetsThatShouldNotBeMoved/.htaccess:
--------------------------------------------------------------------------------
1 | AddType text/html .shtml
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/implicitBaseUrl/src/component.js:
--------------------------------------------------------------------------------
1 | define([], function () {});
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requiredCssImport/other.css:
--------------------------------------------------------------------------------
1 | span {
2 | color: green;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/morescripts/somethingElse.js:
--------------------------------------------------------------------------------
1 | alert('something else');
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/assetsThatShouldNotBeMoved/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
3 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/duplicateImports/imported.css:
--------------------------------------------------------------------------------
1 | body {
2 | color: white;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/implicitBaseUrl/src/main.js:
--------------------------------------------------------------------------------
1 | require(['component'], function () {});
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue60/js/config.js:
--------------------------------------------------------------------------------
1 | require.config({
2 | baseUrl: '/js'
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/knockoutJs/templates/bar.ko:
--------------------------------------------------------------------------------
1 |
2 |
bar.ko
3 |
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/lessPlugin/a.less:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: beige;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/styleSheetInTemplate/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: red;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/gzip/foo.js:
--------------------------------------------------------------------------------
1 | alert("this is a tiny script that's not worth gzipping");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/lessPlugin/someModule.js:
--------------------------------------------------------------------------------
1 | define(['less!b.less'], function () {
2 | });
3 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requireJsConfigurationInExternalFile/theCorrectBase/foo.js:
--------------------------------------------------------------------------------
1 | alert("foo");
2 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/css/doesNotNeedLocalization.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: red;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/knockoutTemplate/templateWithoutI18n.ko:
--------------------------------------------------------------------------------
1 | No i18n stuff here!
2 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/simple/index.html.appcache:
--------------------------------------------------------------------------------
1 | CACHE MANIFEST
2 | style.css
3 | foo.png
4 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/jpeg/style.css:
--------------------------------------------------------------------------------
1 | #turtle {
2 | background-image: url(turtle.jpg);
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/GetStaticUrlSingleFileWildcard/justThisOneFile.txt:
--------------------------------------------------------------------------------
1 | The contents of the file.
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/bootstrapperI18n/bootstrapper.js:
--------------------------------------------------------------------------------
1 | var keys = JSON.parse(GETTEXT('index.i18n'));
2 |
--------------------------------------------------------------------------------
/testdata/transforms/autoprefixer/borderimage.css:
--------------------------------------------------------------------------------
1 | body {
2 | border-image: url(borderimage.png) 30 30 repeat;
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/knockoutJs/templates/foo.ko:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requireJsOrphans/module1.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | return 'module1';
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requireJsOrphans/module2.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | return 'module2';
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requireJsOrphans/module4.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | return 'module4';
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requiredCssImport/foo.css:
--------------------------------------------------------------------------------
1 | @import "other.css";
2 | body {
3 | color: red;
4 | }
5 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/localeCookieName/localeCookieName.js:
--------------------------------------------------------------------------------
1 | var bar = LOCALECOOKIENAME;
2 | alert(bar);
3 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/GetStaticUrlSingleFileAndTwoWildcards/dir/justThisOneFile.txt:
--------------------------------------------------------------------------------
1 | The contents of the file.
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/initialHtmlFragments/js/script.js:
--------------------------------------------------------------------------------
1 | var myTemplateUrl = GETSTATICURL('myTemplate.html');
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue114/a.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | var aJS = true;
3 | console.log(aJS);
4 | }());
5 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue54/js/vendor/deep-model.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | return "deepmodel";
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multiPageRequireJs/common1.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | alert("common1");
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multiPageRequireJs/common2.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | alert("common2");
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/setFormat/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-image: url(foo.png?setFormat=gif);
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/bin/applyBabelJob/index.someother.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "KeyInSomeOtherI18nFile": {
3 | "en": "Woop"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/assetsThatShouldNotBeMoved/humans.txt:
--------------------------------------------------------------------------------
1 | /* SITE */
2 |
3 | This site was made by humans.
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue54/js/vendor/backbone-amd/backbone.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | return "backbone";
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue60/js/modules/utils.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | alert("These are the utils!");
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/lessPlugin/main.js:
--------------------------------------------------------------------------------
1 | require(['less!a.less', 'someModule', 'less!c.less'], function () {
2 | });
3 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/lessPlugin/main2.js:
--------------------------------------------------------------------------------
1 | require(['less!a.less', 'someModule', 'less!c.less'], function () {
2 | });
3 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/simple/style.css:
--------------------------------------------------------------------------------
1 | .bogus {
2 | color: red;
3 | background-image: url(foo.png);
4 | }
5 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue60/js/main.js:
--------------------------------------------------------------------------------
1 | require(['modules/utils'], function(Utils) {
2 | console.log('Ready.');
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue83/script.js:
--------------------------------------------------------------------------------
1 | function hey ($$super, foo, quux) {
2 | $$super.foo();
3 | quux.baz();
4 | }
5 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/morescripts/amdDependency.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | console.warn("here I AM(D)");
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/morescripts/view/styles.less:
--------------------------------------------------------------------------------
1 | body {
2 | & div {
3 | width: 100px;
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/multipleHtmls/doesNotNeedLocalization.js:
--------------------------------------------------------------------------------
1 | INCLUDE('needsLocalization.js');
2 |
3 | alert("hello");
4 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/multipleHtmls/needsLocalization.js:
--------------------------------------------------------------------------------
1 | INCLUDE('index.i18n');
2 |
3 | alert(TR('languageKey', 'yup'));
4 |
--------------------------------------------------------------------------------
/testdata/transforms/duplicateFavicon/unreferencedFavicon/noHead.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/dot.in.path/style.css:
--------------------------------------------------------------------------------
1 | #redalpha24bit {
2 | background-image: url(redalpha24bit.png?optipng);
3 | }
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multiPageRequireJs/main1.js:
--------------------------------------------------------------------------------
1 | require(['common1', 'common2'], function () {
2 | alert("main1");
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multiPageRequireJs/main2.js:
--------------------------------------------------------------------------------
1 | require(['common1', 'common2'], function () {
2 | alert("main2");
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requireJsOrphans/module3.js:
--------------------------------------------------------------------------------
1 | define(['module4'], function (module4) {
2 | return 'module3+' + module4;
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/styleSheetInTemplate/component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/JavaScriptTrHtmlAndJavaScriptGetText/template.html:
--------------------------------------------------------------------------------
1 | The default value
2 |
--------------------------------------------------------------------------------
/testdata/bin/makeBabelJobAndApplyBabelJob/template.ko:
--------------------------------------------------------------------------------
1 | Simple key in a Knockout.js template
2 |
--------------------------------------------------------------------------------
/testdata/findParentDirectory/directory/quux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/findParentDirectory/directory/quux.png
--------------------------------------------------------------------------------
/testdata/transforms/autoprefixer/borderimage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/autoprefixer/borderimage.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/angularJs/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "foo": {
3 | "da": "lige direkte",
4 | "en": "directly"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/gzip/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/gzip/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multipleHtmlsReferencingTheSameExternalRequireJsConfig/requireJsConfig.js:
--------------------------------------------------------------------------------
1 | var require = {
2 | baseUrl: '/'
3 | };
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/rss/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/rss/foo.png
--------------------------------------------------------------------------------
/testdata/bin/makeBabelJob/other.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "KeyAlreadyPartiallyTranslatedInOtherI18n": {
3 | "de": "Existing translation to German"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/bootstrapperI18n/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "TheTitle": {
3 | "en": "The title",
4 | "da": "Titelen"
5 | }
6 | }
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/morescripts/view/template.ko:
--------------------------------------------------------------------------------
1 | The link text
2 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/css/bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/cloneForEachLocale/css/bar.png
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/css/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/cloneForEachLocale/css/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/inlineScriptTemplateInKnockoutJsTemplate/index.js:
--------------------------------------------------------------------------------
1 | INCLUDE('index.i18n');
2 |
3 | var template = GETTEXT('template.ko');
4 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/multipleHtmls/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "languageKey": {
3 | "en": "yup",
4 | "da": "jeps"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/svg/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "keyName": {
3 | "da": "Dansk nøgle",
4 | "en": "English key"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/html/myImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/processImages/html/myImage.png
--------------------------------------------------------------------------------
/testdata/transforms/processImages/jpeg/turtle.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/processImages/jpeg/turtle.jpg
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/angularJs/bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/angularJs/bar.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/angularJs/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/angularJs/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/angularJs/partials/1.html:
--------------------------------------------------------------------------------
1 | 1: External template loaded asynchronously with templateUrl: 'partials/1.html'
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/htmlDataMainWithI18n/webmail.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "languageKey": {
3 | "da": "foo",
4 | "en": "bar"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/initialAssetWithoutHtmlElement/index.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/simple/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/cloneForEachLocale/simple/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/processImages/setFormat/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/processImages/setFormat/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/angularJs/quux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/angularJs/quux.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/initialHtmlFragments/myTemplate.html:
--------------------------------------------------------------------------------
1 |
2 |
Template with a relative image reference: 
3 |
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/inkscape/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/knockoutJs/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/knockoutJs/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requireJsCdnPath/main.js:
--------------------------------------------------------------------------------
1 | require(['jquery'], function ($) {
2 | $(function () {
3 | alert('Ready!');
4 | });
5 | });
6 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/myImage.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/simple/myImage.gif
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/trInHtmlDataBindAttributeInKoTemplate/template.ko:
--------------------------------------------------------------------------------
1 | foo
2 |
--------------------------------------------------------------------------------
/testdata/transforms/duplicateFavicon/unreferencedFavicon/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/css/redalpha24bit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/processImages/css/redalpha24bit.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/knockoutJs/someModule.js:
--------------------------------------------------------------------------------
1 | define(['tpl!templates/foo.ko'], function () {
2 | alert("The module that also requires foo.ko!");
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multipleHtmlsReferencingTheSameExternalRequireJsConfig/app/someDependency.js:
--------------------------------------------------------------------------------
1 | define(function () {
2 | return "some dependency";
3 | });
--------------------------------------------------------------------------------
/testdata/transforms/checkLanguageKeys/duplicateLanguageKeys/external.js:
--------------------------------------------------------------------------------
1 | alert(TR('AnotherSimpleAndIdentical1', 'Blah'));
2 | alert(TR('AnotherSimpleAndIdentical2', 'Blah'));
3 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/css/purplealpha24bit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/processImages/css/purplealpha24bit.png
--------------------------------------------------------------------------------
/testdata/transforms/processImages/devicePixelRatio/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/processImages/devicePixelRatio/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/processImages/pngs/redalpha24bit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/processImages/pngs/redalpha24bit.png
--------------------------------------------------------------------------------
/testdata/transforms/angularAnnotations/basic.js:
--------------------------------------------------------------------------------
1 | /*global angular*/
2 | angular.module('MyMod').controller('MyCtrl', function ($scope, $timeout) { return [$scope, $timeout]; });
3 |
--------------------------------------------------------------------------------
/testdata/transforms/buildDevelopment/simple/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "myLanguageKey": {
3 | "en": "The English value",
4 | "da": "Den danske værdi"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/gzip/sockjs-0.3.4.js.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/gzip/sockjs-0.3.4.js.gz
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/knockoutJs/main.js:
--------------------------------------------------------------------------------
1 | require(['tpl!templates/foo.ko', 'someModule', 'tpl!templates/bar.ko'], function () {
2 | alert("Alles klar!");
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/reusePlaceHolder/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "foo": {
3 | "en": "Some {0} thing",
4 | "da": "Some {0} {0} thing"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/pngs/purplealpha24bit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/processImages/pngs/purplealpha24bit.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/angularJsMultipleTemplateRefs/partials/1.html:
--------------------------------------------------------------------------------
1 | 1: External template loaded asynchronously with templateUrl: 'partials/1.html'
2 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/fragmentWithUnpopulatedRelation/templates/myTemplate.html:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/nonInitialAssetWithIncomingHtmlAnchor/index2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requireJsConfigurationInExternalFile/theRequireJsConfig.js:
--------------------------------------------------------------------------------
1 | var require = {
2 | paths: {
3 | foo: "theCorrectBase/foo"
4 | }
5 | };
6 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/inlineCssCombo/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/cloneForEachLocale/inlineCssCombo/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/processImages/devicePixelRatio/foo@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/processImages/devicePixelRatio/foo@2x.png
--------------------------------------------------------------------------------
/testdata/transforms/processImages/devicePixelRatio/foo@8x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/processImages/devicePixelRatio/foo@8x.png
--------------------------------------------------------------------------------
/testdata/transforms/processImages/dot.in.path/redalpha24bit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/processImages/dot.in.path/redalpha24bit.png
--------------------------------------------------------------------------------
/testdata/findParentDirectory/otherdirectory/onemorelevel/bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/findParentDirectory/otherdirectory/onemorelevel/bar.png
--------------------------------------------------------------------------------
/testdata/findParentDirectory/otherdirectory/onemorelevel/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/findParentDirectory/otherdirectory/onemorelevel/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/initialHtmlFragments/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/initialHtmlFragments/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/JavaScriptTrHtml/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "myLanguageKey": {
3 | "da": "Den danske værdi",
4 | "en": "The English value"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/inlineScriptTemplate/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "MyLanguageKey": {
3 | "da": "Min sprognøgle",
4 | "en": "My language key"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/relationInPlaceHolder/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "foo": {
3 | "en": "Some {0} thing",
4 | "da": "Et {0} eller {0} andet"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/simple/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "the.key.name": {
3 | "en_US": "The American English text",
4 | "da": "The Danish text"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/replaceDartWithJavaScript/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/initialHtmlFragments/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue58/js/main.js:
--------------------------------------------------------------------------------
1 | require([
2 | 'text!/templates/header.html'
3 | ], function (headerHtml) {
4 | alert("Got the header HTML: " + headerHtml);
5 | });
6 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue83/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/nonExistentFileWithoutExtension/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/spriteAndProcessImages/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/spriteAndProcessImages/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/knockoutTemplate/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/relationInPlaceHolder/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/cloneForEachLocale/relationInPlaceHolder/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/trInHtmlDataBindAttribute/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "keyname": {
3 | "en": "The English value",
4 | "da": "Den danske værdi"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/trInHtmlDataBindAttributeInKoTemplate/main.js:
--------------------------------------------------------------------------------
1 | require(['tpl!template.ko'], function () {
2 | // Here I am with my lovely template in scope...
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/duplicateFavicon/referencedFavicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/duplicateFavicon/referencedFavicon/favicon.ico
--------------------------------------------------------------------------------
/testdata/transforms/duplicateFavicon/unreferencedFavicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/duplicateFavicon/unreferencedFavicon/favicon.ico
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/faviconOutsideRoot/foo/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/faviconOutsideRoot/foo/favicon.ico
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/knockoutJs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/lessPlugin/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/lessPlugin/index2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/globalVarUsageInJavaScript/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/inlineScriptTemplateInKnockoutJsTemplate/template.ko:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/localeCookieName/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/JavaScriptGetText/index.html.template:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/multipleHtmls/1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | First HTML
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/trInHtmlDataBindAttributeInKoTemplate/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "keyname": {
3 | "en": "The English value",
4 | "da": "Den danske værdi"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/svg/addBogusElement.js:
--------------------------------------------------------------------------------
1 | var g = document.createElement('g');
2 | g.setAttribute('id', svgFilter.bogusElementId || 'blablaf');
3 | document.documentElement.appendChild(g);
4 |
--------------------------------------------------------------------------------
/testdata/resolvers/senchaJsBuilder/rewriteBackgroundImageUrls/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/GetStaticUrlImageOnCdn/images/test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/GetStaticUrlImageOnCdn/images/test.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/assetsThatShouldNotBeMoved/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/assetsThatShouldNotBeMoved/favicon.ico
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/htmlDataMainWithI18n/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multipleHtmlsReferencingTheSameExternalRequireJsConfig/app/main1.js:
--------------------------------------------------------------------------------
1 | require(['app/someDependency'], function (someDependency) {
2 | alert("main1 ready to go");
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multipleHtmlsReferencingTheSameExternalRequireJsConfig/app/main2.js:
--------------------------------------------------------------------------------
1 | require(['app/someDependency'], function (someDependency) {
2 | alert("main2 ready to go");
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/JavaScriptTrHtmlAndJavaScriptGetText/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "myLanguageKey": {
3 | "da": "Den danske værdi",
4 | "en": "The English value"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/inlineScriptTemplateInKnockoutJsTemplate/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "MyLanguageKey": {
3 | "da": "Min sprognøgle",
4 | "en": "My language key"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/multipleHtmls/2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Second HTML
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/resolvers/senchaJsBuilder/dependentPackages/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/bundlingInHtmlFragments/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/existingSourceMap/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/imagesWithWrongExtensions/actuallyAPng.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/imagesWithWrongExtensions/actuallyAPng.jpg
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue114/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Text
8 |
9 |
10 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue58/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue69/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/inlineScriptTemplateInKnockoutJsTemplate/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/imagesWithWrongExtensions/actuallyAJpeg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/imagesWithWrongExtensions/actuallyAJpeg.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/imagesWithWrongExtensions/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/nonInitialAssetWithIncomingHtmlAnchor/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | hello
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requireJsOrphans/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/knockoutTemplate/index.js:
--------------------------------------------------------------------------------
1 | INCLUDE('index.i18n');
2 |
3 | var templateWithoutI18n = GETTEXT('templateWithoutI18n.ko'),
4 | templateWithI18n = GETTEXT('templateWithI18n.ko');
5 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requireJsOrphans/main.js:
--------------------------------------------------------------------------------
1 | require(['module1', 'module2', 'module3'], function (module1, module2, module3) {
2 | alert("got " + module1 + ", " + module2 + ', and ' + module3);
3 | });
4 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/globalVarUsageInJavaScript/foo.js:
--------------------------------------------------------------------------------
1 | alert(LOCALEID);
2 | alert(DEFAULTLOCALEID);
3 | alert(LOCALECOOKIENAME);
4 | alert(SUPPORTEDLOCALEIDS);
5 | LOCALEID="foo"; // Shouldn't be replaced
6 |
--------------------------------------------------------------------------------
/testdata/transforms/duplicateFavicon/referencedFavicon/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/GetStaticUrlFlash/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue54/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multiPageRequireJs/index1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multiPageRequireJs/index2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/duplicateImports/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/GetStaticUrlImageOnCdn/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/JavaScriptGetStaticUrlWithProcessedImages/images/bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/JavaScriptGetStaticUrlWithProcessedImages/images/bar.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/JavaScriptGetStaticUrlWithProcessedImages/images/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/transforms/buildProduction/JavaScriptGetStaticUrlWithProcessedImages/images/foo.png
--------------------------------------------------------------------------------
/testdata/resolvers/senchaJsBuilder/rewriteBackgroundImageUrls/resources/images/foo/bar/foo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/podio/assetgraph-builder/master/testdata/resolvers/senchaJsBuilder/rewriteBackgroundImageUrls/resources/images/foo/bar/foo.png
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/rss/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/faviconOutsideRoot/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/resolvers/senchaJsBuilder/dependentPackages/overlappingIncludes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/inline/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/svg/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/missingDataBind/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/svg/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/css/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/trInHtmlDataBindAttributeInKoTemplate/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/ssi/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "title": {
3 | "en": "Yes, {0} like that",
4 | "da": "Ja, {0} sådan"
5 | },
6 | "somethingelse": {
7 | "en": "{0} is the thing",
8 | "da": "{0} er tingen"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/pngs/style.css:
--------------------------------------------------------------------------------
1 | #redalpha24bit {
2 | background-image: url(redalpha24bit.png);
3 | _background-image: url(redalpha24bit.png?pngquant=256);
4 | }
5 |
6 | #purplealpha24bit {
7 | background-image: url(purplealpha24bit.png?pngcrush);
8 | }
9 |
--------------------------------------------------------------------------------
/testdata/bin/applyBabelJob/translationjob/en.txt:
--------------------------------------------------------------------------------
1 | foo=FooProofRead
2 | bar=BarProofRead
3 | placeholders=This proofread key has {0} proofread placeholders
4 | WeirdlyFormattedKey=that comes back the same in the translation job
5 | ComplexKey[that]=also comes
6 | ComplexKey[back]=the same
7 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/trInHtmlDataBindAttribute/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | foo
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/reusePlaceHolder/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Some foo thing
6 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/GetStaticUrlSingleFileWildcard/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requiredCssImport/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/styleSheetInTemplate/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/relationInPlaceHolder/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Some

thing
6 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/css/style.css:
--------------------------------------------------------------------------------
1 | #redalpha24bit {
2 | background-image: url(redalpha24bit.png?irrelevant);
3 | _background-image: url(redalpha24bit.png?pngquant=128);
4 | }
5 |
6 | #purplealpha24bit {
7 | background-image: url(purplealpha24bit.png?pngquant=256);
8 | }
9 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/fragmentWithUnpopulatedRelation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/bootstrapperI18n/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Default title
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/unexpected-with-plugins.js:
--------------------------------------------------------------------------------
1 | var expect = require('unexpected')
2 | .clone()
3 | .installPlugin(require('unexpected-sinon'))
4 | .installPlugin(require('assetgraph/test/unexpectedAssetGraph'));
5 |
6 | // expect.output.installPlugin(require('magicpen-prism'));
7 |
8 | module.exports = expect;
9 |
--------------------------------------------------------------------------------
/testdata/bin/applyBabelJob/translationjob/da.txt:
--------------------------------------------------------------------------------
1 | foo=FooOversat
2 | bar=BarOversat
3 | placeholders=Denne oversatte nøgle har {0} pladsholdere
4 | WeirdlyFormattedKey=der kommer uændret retur i oversættelsesjobbet
5 | ComplexKey[that]=også kommer
6 | ComplexKey[back]=det samme
7 | KeyInSomeOtherI18nFile=Jubii
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/GetStaticUrlSingleFileAndTwoWildcards/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multipleHtmlsReferencingTheSameExternalRequireJsConfig/app1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/multipleHtmlsReferencingTheSameExternalRequireJsConfig/app2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/noCompress/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/inlineCssCombo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ...
5 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/testdata/bin/applyBabelJob/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "foo": {
3 | "en": "Foo",
4 | "da": null
5 | },
6 | "bar": {
7 | "en": "Bar",
8 | "da": null
9 | },
10 | "placeholders": {
11 | "en": "This key has {0} placeholders",
12 | "da": null
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/implicitBaseUrl/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue69/app/main.js:
--------------------------------------------------------------------------------
1 | require.config({
2 | baseUrl: 'app',
3 | enforceDefine: false,
4 | paths: {
5 | sockjs: '../vendor/sockjs/sockjs-0.3.4'
6 | }
7 | });
8 |
9 | require(['sockjs'], function (sockjs) {
10 | alert("got sockjs: " + sockjs);
11 | });
12 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node
2 |
3 | RUN apt-get update
4 | RUN apt-get install -y --no-install-recommends libcairo2-dev libgif-dev optipng pngcrush pngquant libpango1.0-dev graphicsmagick libjpeg-progs inkscape libvips-dev libgsf-1-dev
5 | RUN npm install -g assetgraph-builder
6 |
7 | ENTRYPOINT ["/usr/local/bin/buildProduction"]
8 |
--------------------------------------------------------------------------------
/testdata/transforms/buildDevelopment/dataBindOnHtmlStyle/index.html.template:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
My Shop
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/JavaScriptGetStaticUrlWithProcessedImages/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/JavaScriptTrHtmlAndJavaScriptGetText/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/gzip/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/JavaScriptTrHtml/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/simple/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue54/js/app.js:
--------------------------------------------------------------------------------
1 | require.config({
2 | paths: {
3 | backbone: 'vendor/backbone-amd/backbone',
4 | deepmodel: 'vendor/deep-model'
5 | }
6 | });
7 |
8 | require(['backbone', 'deepmodel'], function (backbone, deepmodel) {
9 | alert("Yup, got " + backbone + " and " + deepmodel);
10 | });
11 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/inlineScriptTemplate/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/testdata/transforms/autoprefixer/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Document
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/issue60/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/lessCompiler/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/ssi/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Yes, like that
5 |
6 |
7 | is the thing
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/imagesWithWrongExtensions/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-image: url(actuallyAJpeg.png?sprite=foo);
3 | }
4 |
5 | .quux {
6 | background-image: url(actuallyAPng.jpg?sprite=foo);
7 | }
8 |
9 | .bar {
10 | background-image: url(actuallyAJpeg.png);
11 | }
12 |
13 | .baz {
14 | background-image: url(actuallyAPng.jpg);
15 | }
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "documentTitle": {
3 | "en": "The English title",
4 | "da": "Den danske titel"
5 | },
6 | "linkText": {
7 | "en": "The English link text",
8 | "da": "Den danske linktekst"
9 | },
10 | "greeting": {
11 | "en": "Hello!",
12 | "da": "Hej!"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requireJsConfigurationInExternalFile/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/morescripts/main.js:
--------------------------------------------------------------------------------
1 | require.config({
2 | shim: {
3 | shimmed: ['somethingElse']
4 | }
5 | });
6 |
7 | require([
8 | 'shimmed',
9 | 'amdDependency',
10 | 'tpl!view/template.ko',
11 | 'less!view/styles.less'
12 | ], function (shimmedDependency, amdDependency) {
13 | alert(TR('greeting', 'Hello!'));
14 | });
15 |
--------------------------------------------------------------------------------
/testdata/transforms/buildDevelopment/simple/index.html.template:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The default title
5 |
6 |
7 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/testdata/transforms/checkLanguageKeys/neverEndingSpaceLoop/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/testdata/resolvers/senchaJsBuilder/rewriteBackgroundImageUrls/foo.jsb2:
--------------------------------------------------------------------------------
1 | {
2 | "licenseText": "Ext JS Library 3.0.0 <-- This is the trigger for fixing background-image urls",
3 | "pkgs": [{
4 | "name": "CSS stuff",
5 | "file": "resources/css/stuff.css",
6 | "fileIncludes": [{
7 | "text": "foo.css",
8 | "path": "resources/css/subdir/"
9 | }]
10 | }]
11 | }
12 |
--------------------------------------------------------------------------------
/lib/transforms/removeNobundleAttribute.js:
--------------------------------------------------------------------------------
1 | module.exports = function (queryObj) {
2 | return function removeNobundleAttribute(assetGraph) {
3 | assetGraph.findRelations(queryObj).forEach(function (relation) {
4 | if (relation.node.hasAttribute('nobundle')) {
5 | relation.node.removeAttribute('nobundle');
6 | relation.from.markDirty();
7 | }
8 | });
9 | };
10 | };
11 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/assetsThatShouldNotBeMoved/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Here's my .htaccess file, grab it if you can!
9 | If you're a robot, please refer to robots.txt.
10 |
11 |
12 |
--------------------------------------------------------------------------------
/testdata/transforms/runJavaScriptConditionalBlocks/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/requireJsCdnPath/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/dataMainAndAlmondJs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/spriteAndProcessImages/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/inkscape/styles.less:
--------------------------------------------------------------------------------
1 | body {
2 | background-image: url("image.svg?inkscape=--export-width=70,--export-area=0:0:70:12");
3 | background-size: 70px;
4 | background-repeat: no-repeat;
5 | background-position: center center;
6 | }
7 | @media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 1.5dppx), (min-resolution: 144dpi) {
8 | body {
9 | background-image: url("image.svg?inkscape=--export-width=105,--export-area=0:0:70:12");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/emptyScriptsAndStylesheetsWithAttributes/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/knockoutTemplate/templateWithI18n.ko:
--------------------------------------------------------------------------------
1 |
2 |
foo
3 |
bar
4 |
quux
5 |
baz
6 |
Here is a Nice and beautiful nested i18n construct
7 |
8 |
--------------------------------------------------------------------------------
/lib/resolvers/index.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 |
3 | // Start with AssetGraph's built-in resolvers:
4 |
5 | _.extend(exports, require('assetgraph').resolvers);
6 |
7 | // Install getters for all resolvers in this directory:
8 |
9 | require('fs').readdirSync(__dirname).forEach(function (fileName) {
10 | if (/\.js$/.test(fileName) && fileName !== 'index.js') {
11 | exports.__defineGetter__(fileName.replace(/\.js$/, ''), function () {
12 | return require('./' + fileName);
13 | });
14 | }
15 | });
16 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/svg/image.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/inkscape/image.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/stripDebug/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/angularJsMultipleTemplateRefs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | My AngularJS App
5 |
6 |
7 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/lib/canonicalizeObject.js:
--------------------------------------------------------------------------------
1 | module.exports = function canonicalizeObject(obj, numLevels) {
2 | if (typeof numLevels !== 'number') {
3 | numLevels = Infinity;
4 | }
5 | if (Array.isArray(obj)) {
6 | return obj.map(canonicalizeObject, numLevels - 1);
7 | } else if (typeof obj === 'object' && obj !== null && numLevels > 0) {
8 | var sortedObj = {};
9 | Object.keys(obj).sort().forEach(function (key) {
10 | sortedObj[key] = canonicalizeObject(obj[key], numLevels - 1);
11 | });
12 | return sortedObj;
13 | } else {
14 | return obj;
15 | }
16 | };
17 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/css/needsLocalization.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-weight: bold;
3 | }
4 |
5 | html[lang=da] .theThing {
6 | width: 128px;
7 | background-image: url(foo.png);
8 | }
9 |
10 | html[lang="de"].anotherClassOnHtml .theGermanThing {
11 | width: 130px;
12 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC);
13 | }
14 |
15 | html[lang="sv"] .theSwedishThing {
16 | width: 128px;
17 | background-image: url(bar.png);
18 | }
19 |
--------------------------------------------------------------------------------
/lib/transforms/omitFunctionCall.js:
--------------------------------------------------------------------------------
1 | // GETSTATICURL(fileNameOrHash) => fileNameOrHash
2 | // TRHTML(htmlString) => htmlString
3 | // Saves bytes, but makes it impossible to recognize the relations again.
4 |
5 | module.exports = function (queryObj) {
6 | return function omitFunctionCall(assetGraph) {
7 | assetGraph.findRelations(queryObj).filter(function (relation) {
8 | return relation.type === 'JavaScriptTrHtml' || relation.type === 'JavaScriptGetStaticUrl';
9 | }).forEach(function (relation) {
10 | relation.omitFunctionCall = true;
11 | relation.inline();
12 | });
13 | };
14 | };
15 |
--------------------------------------------------------------------------------
/testdata/transforms/checkLanguageKeys/pluralRule/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/lib/mkpathSync.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs'),
2 | path = require('path');
3 |
4 | function mkpathSync(p, permissions) {
5 | if (typeof permissions === 'undefined') {
6 | permissions = '0777';
7 | }
8 | if (!/^\//.test(p)) {
9 | p = process.cwd() + '/' + p;
10 | }
11 | p = path.normalize(p).replace(/\/$/, '');
12 | if (!(fs.existsSync || path.existsSync)(p)) {
13 | var fragments = p.split('/');
14 | if (fragments.length > 1) {
15 | mkpathSync(fragments.slice(0, fragments.length - 1).join('/'), permissions);
16 | fs.mkdirSync(p, permissions);
17 | }
18 | }
19 | }
20 |
21 | module.exports = mkpathSync;
22 |
--------------------------------------------------------------------------------
/testdata/transforms/processImages/devicePixelRatio/style.css:
--------------------------------------------------------------------------------
1 | .p1 {
2 | background-image: url(foo.png);
3 | }
4 |
5 | .p2 {
6 | background-image: url(foo@2x.png);
7 | }
8 |
9 | .p3 {
10 | background-image: url(foo.png?dpr=3);
11 | }
12 |
13 | .p4 {
14 | background-image: url(foo.png?resize=,200);
15 | }
16 |
17 | .p5 {
18 | background-image: url(foo.png?resize=,200&dpr=5);
19 | }
20 |
21 | .p6 {
22 | background-image: url(foo.png?dpr=6&resize=,200);
23 | }
24 |
25 | .p7 {
26 | background-image: url(foo.png?dpr=7&foo=bar);
27 | }
28 |
29 | .p8 {
30 | background-image: url(foo@8x.png?dpr=1);
31 | }
32 |
33 | .p9 {
34 | background-image: url(foo.png?setFormat=jpg&dpr=9);
35 | }
36 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "0.10"
4 | before_install: "sudo apt-get update && sudo apt-get install -y libcairo2-dev libjpeg8-dev libgif-dev optipng pngcrush pngquant libpango1.0-dev graphicsmagick libjpeg-turbo-progs inkscape && npm install -g npm && npm cache clean"
5 | script: "npm run-script travis"
6 | after_success: "
2 |
3 |
4 |
5 |
6 | Bla bla
7 | A beautiful text with lovely placeholders in it
8 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/rss/rssFeed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RSS Title
5 | This is an example of an RSS feed
6 | index.html
7 | Mon, 06 Sep 2010 00:01:00 +0000
8 | Mon, 06 Sep 2009 16:20:00 +0000
9 | 1800
10 | -
11 | Example entry
12 | Here is some text containing an interesting description and an image: <img src="foo.png" />.
13 | http://www.wikipedia.org/
14 | unique string per item
15 | Mon, 06 Sep 2009 16:20:00 +0000
16 |
17 |
18 |
--------------------------------------------------------------------------------
/lib/transforms/removeDuplicateHtmlStyles.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 |
3 | // https://github.com/One-com/assetgraph/issues/82
4 |
5 | module.exports = function (queryObj) {
6 | return function removeDuplicateHtmlStyles(assetGraph) {
7 | assetGraph.findAssets(_.extend({type: 'Html'}, queryObj)).forEach(function (htmlAsset) {
8 | var seenCssAssetsById = {};
9 | assetGraph.findRelations({from: htmlAsset, type: 'HtmlStyle'}).forEach(function (htmlStyle) {
10 | if (seenCssAssetsById[htmlStyle.to.id]) {
11 | htmlStyle.detach();
12 | } else {
13 | seenCssAssetsById[htmlStyle.to.id] = true;
14 | }
15 | });
16 | });
17 | };
18 | };
19 |
--------------------------------------------------------------------------------
/testdata/resolvers/senchaJsBuilder/rewriteBackgroundImageUrls/resources/css/subdir/foo.css:
--------------------------------------------------------------------------------
1 | .x-html-editor-tb .x-edit-bold, .x-menu-item img.x-edit-bold {
2 | background-position:0 0;
3 | background-image:url(../images/foo/bar/foo.png);
4 | }
5 |
6 | .x-html-editor-tb .x-edit-italic, .x-menu-item img.x-edit-italic {
7 | background-position:-16px 0;
8 | background-image:url(../images/foo/bar/foo.png);
9 | }
10 |
11 | .x-html-editor-tb .x-edit-underline, .x-menu-item img.x-edit-underline {
12 | background-position:-32px 0;
13 | background-image:url(../images/foo/bar/foo.png);
14 | }
15 |
16 | .x-html-editor-tb .x-edit-forecolor, .x-menu-item img.x-edit-forecolor {
17 | background-position:-160px 0;
18 | background-image:url(../images/foo/bar/foo.png);
19 | }
20 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/simple/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The fancy title
5 |
6 |
7 |
8 |
9 |
10 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/lib/AssetGraph.js:
--------------------------------------------------------------------------------
1 | var Path = require('path'),
2 | AssetGraph = module.exports = require('assetgraph');
3 |
4 | // Get the spriteBackgroundImages transform from assetgraph-sprite if available:
5 | var spriteBackgroundImages;
6 | try {
7 | spriteBackgroundImages = require('assetgraph-sprite');
8 | } catch (e) {
9 | spriteBackgroundImages = function () {
10 | console.warn('assetgraph-sprite is not available, skipping the spriteBackgroundImages transform');
11 | return function spriteBackgroundImagesDisabled(assetGraph) {};
12 | };
13 | }
14 | AssetGraph.registerTransform(spriteBackgroundImages, 'spriteBackgroundImages');
15 |
16 | // Register ./transforms/*:
17 |
18 | require('fs').readdirSync(Path.resolve(__dirname, 'transforms')).forEach(function (fileName) {
19 | AssetGraph.registerTransform(Path.resolve(__dirname, 'transforms', fileName));
20 | });
21 |
--------------------------------------------------------------------------------
/bin/optimizeImage:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var AssetGraph = require('../lib/AssetGraph'),
4 | urlTools = require('urltools'),
5 | commandLineOptions = require('optimist')
6 | .usage('$0 image1 image2...')
7 | .demand(1)
8 | .argv;
9 |
10 | new AssetGraph({root: commandLineOptions.root})
11 | .logEvents({repl: commandLineOptions.repl, stopOnWarning: commandLineOptions.stoponwarning, suppressJavaScriptCommonJsRequireWarnings: true})
12 | .loadAssets(commandLineOptions._.map(urlTools.fsFilePathToFileUrl))
13 | .queue(function () {
14 | console.warn('BEFORE:');
15 | })
16 | .writeStatsToStderr()
17 | .processImages({isImage: true}, {autoLossless: true})
18 | .writeAssetsToDisc({url: /^file:/, isImage: true, isDirty: true})
19 | .queue(function () {
20 | console.warn('\nAFTER:');
21 | })
22 | .writeStatsToStderr()
23 | .run();
24 |
--------------------------------------------------------------------------------
/test/transforms/angularAnnotations.js:
--------------------------------------------------------------------------------
1 | /*global describe, it*/
2 | var expect = require('../unexpected-with-plugins');
3 | var AssetGraph = require('../../lib/AssetGraph');
4 |
5 | describe('angularAnnotations', function () {
6 | it('should annotate a basic example', function (done) {
7 | new AssetGraph({ root: __dirname + '/../../testdata/transforms/angularAnnotations' })
8 | .loadAssets('basic.js')
9 | .populate()
10 | .angularAnnotations()
11 | .queue(function (assetGraph) {
12 | expect(assetGraph, 'to contain assets', 'JavaScript', 1);
13 |
14 | var asset = assetGraph.findAssets()[0];
15 |
16 | expect(asset.text, 'to be', 'angular.module("MyMod").controller("MyCtrl",["$scope","$timeout",function($scope,$timeout){return[$scope,$timeout]}]);');
17 | })
18 | .run(done);
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/knockoutTemplate/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "MyLanguageKey": {
3 | "da": "Min sprognøgle",
4 | "en": "My language key"
5 | },
6 | "YetAnotherOne": {
7 | "da": "quux på dansk",
8 | "en": "quux in English"
9 | },
10 | "YetYetAnotherOne": {
11 | "da": "baz på dansk",
12 | "en": "baz in English"
13 | },
14 | "AndAnother": {
15 | "da": "blah på dansk",
16 | "en": "blah in English"
17 | },
18 | "MyOtherLanguageKey": {
19 | "da": "Min anden sprognøgle",
20 | "en": "My other language key"
21 | },
22 | "MyNestedLanguageKey": {
23 | "en": "Here is a {0} nested i18n construct in English",
24 | "da": "Her er en {0} dyb i18n-struktur på dansk"
25 | },
26 | "Nice": {
27 | "en": "nice and English",
28 | "da": "rar"
29 | },
30 | "Beautiful": {
31 | "en": "beautifully English",
32 | "da": "smuk"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/test/transforms/replaceDartWithJavaScript.js:
--------------------------------------------------------------------------------
1 | /*global describe, it*/
2 | var expect = require('../unexpected-with-plugins'),
3 | AssetGraph = require('../../lib/AssetGraph');
4 |
5 | describe('replaceDartWithJavaScript', function (done) {
6 | it('should handle a test case with 2 Dart assets', function (done) {
7 | new AssetGraph({root: __dirname + '/../../testdata/transforms/replaceDartWithJavaScript/'})
8 | .loadAssets('index.html')
9 | .populate()
10 | .queue(function (assetGraph) {
11 | expect(assetGraph, 'to contain relation', 'HtmlDart');
12 | expect(assetGraph, 'to contain no relations', 'HtmlScript');
13 | })
14 | .replaceDartWithJavaScript()
15 | .queue(function (assetGraph) {
16 | expect(assetGraph, 'to contain no relations', 'HtmlDart');
17 | expect(assetGraph, 'to contain relation', 'HtmlScript');
18 | })
19 | .run(done);
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/testdata/transforms/checkLanguageKeys/duplicateLanguageKeys/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/testdata/resolvers/senchaJsBuilder/dependentPackages/foo.jsb2:
--------------------------------------------------------------------------------
1 | {
2 | "pkgs": [
3 | {
4 | "name": "A",
5 | "file": "A.js",
6 | "fileIncludes": [
7 | {
8 | "text": "A1.js",
9 | "path": "js/"
10 | }
11 | ]
12 | },
13 | {
14 | "name": "B",
15 | "file": "B.js",
16 | "pkgDeps": [
17 | "A.js"
18 | ],
19 | "fileIncludes": [
20 | {
21 | "text": "B1.js",
22 | "path": "js/"
23 | }
24 | ]
25 | },
26 | {
27 | "name": "C",
28 | "file": "C.js",
29 | "pkgDeps": [
30 | "B.js"
31 | ],
32 | "fileIncludes": [
33 | {
34 | "text": "C1.js",
35 | "path": "js/"
36 | }
37 | ]
38 | }
39 | ]
40 | }
41 |
--------------------------------------------------------------------------------
/testdata/transforms/cloneForEachLocale/multipleLocales/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "theTitle": {
3 | "en": "The awesome document title",
4 | "en_GB": "The most delightful document title",
5 | "da": "Dokumentets vidunderlige titel"
6 | },
7 | "plainTr": {
8 | "en": "Plain English",
9 | "da": "Jævnt dansk"
10 | },
11 | "callTRPAT": {
12 | "en": "Boring {0} English pattern",
13 | "da": "Kedeligt {0} dansk mønster"
14 | },
15 | "nonInvokedTrPattern": {
16 | "en": "Welcome to an English-speaking country, Mr. {0}",
17 | "en_US": "Welcome to America, Mr. {0}",
18 | "da": "Velkommen til Danmark, hr. {0}"
19 | },
20 | "some.text.in.body": {
21 | "en": "Some text in body",
22 | "da": "Kropstekst"
23 | },
24 | "text.with.placeholders": {
25 | "en": "A {0} text with {1} placeholders in it",
26 | "en_GB": "A {0} text with oh so {1} placeholders in it",
27 | "da": "En {0} tekst med {1} pladsholdere i sig"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/testdata/bin/makeBabelJobAndApplyBabelJob/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Simple key in HTML
6 | ...
7 | Key with nice placeholders
8 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/testdata/transforms/checkLanguageKeys/pluralRule/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "EveryNWeeks": {
3 | "en": {
4 | "one": "Every week",
5 | "other": "Every {0} weeks"
6 | },
7 | "cs": {
8 | "one": "Každý týden",
9 | "other": "Každých {0} týdnů"
10 | },
11 | "da": {
12 | "one": "Hver uge",
13 | "other": "Hver {0}. uge",
14 | "many": "I should not be here"
15 | }
16 | },
17 | "DeeplyStructured": {
18 | "en": {
19 | "foo": {
20 | "one": "Every week",
21 | "other": "Every {0} weeks"
22 | }
23 | },
24 | "cs": {
25 | "foo": {
26 | "one": "Každý týden",
27 | "other": "Každých {0} týdnů"
28 | },
29 | "bar": 123
30 | },
31 | "da": {
32 | "foo": {
33 | "one": "Hver uge",
34 | "other": "Hver {0}. uge",
35 | "many": "I should not be here"
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lib/transforms/injectBootstrapper.js:
--------------------------------------------------------------------------------
1 | var bootstrapper = require('../bootstrapper');
2 |
3 | module.exports = function (queryObj, options) {
4 | if (!queryObj) {
5 | throw new Error('transforms.injectBootstrapper: The \'queryObj\' parameter is required.');
6 | }
7 | return function injectBootstrapper(assetGraph) {
8 | assetGraph.findAssets(queryObj).forEach(function (initialAsset) {
9 | var bootstrapAsset = new assetGraph.JavaScript({
10 | parseTree: bootstrapper.createAst(initialAsset, assetGraph, options)
11 | });
12 | assetGraph.addAsset(bootstrapAsset);
13 | if (initialAsset.type === 'Html') {
14 | new assetGraph.HtmlScript({to: bootstrapAsset})
15 | .attach(initialAsset, 'first')
16 | .inline()
17 | .node.setAttribute('id', 'bootstrapper');
18 | } else { // initialAsset.type === 'JavaScript'
19 | new assetGraph.JavaScriptInclude({to: bootstrapAsset}).attach(initialAsset, 'first');
20 | }
21 | });
22 | };
23 | };
24 |
--------------------------------------------------------------------------------
/test/JavaScriptGetText.js:
--------------------------------------------------------------------------------
1 | /*global describe, it*/
2 | var expect = require('./unexpected-with-plugins'),
3 | AssetGraph = require('../lib/AssetGraph');
4 |
5 | describe('GETTEXT', function () {
6 | it('should handle a simple test case', function (done) {
7 | new AssetGraph({root: __dirname + '/../testdata/JavaScriptGetText/'})
8 | .loadAssets('index.html.template')
9 | .populate()
10 | .injectBootstrapper({isInitial: true})
11 | .queue(function (assetGraph) {
12 | expect(assetGraph, 'to contain assets', {}, 4);
13 | expect(assetGraph, 'to contain relation', 'JavaScriptGetText');
14 | })
15 | .inlineRelations({type: 'JavaScriptGetText'})
16 | .removeRelations({type: 'JavaScriptGetText'}, {removeOrphan: true})
17 | .queue(function (assetGraph) {
18 | expect(assetGraph, 'to contain assets', {}, 3);
19 | expect(assetGraph.findAssets({type: 'JavaScript'})[0].text, 'to match', /\"Hello, my name is \"\s*\+\s*\"Foobar/);
20 | })
21 | .run(done);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/lib/transforms/replaceDartWithJavaScript.js:
--------------------------------------------------------------------------------
1 | var seq = require('seq');
2 |
3 | module.exports = function () {
4 | return function replaceDartWithJavaScript(assetGraph, cb) {
5 | seq(assetGraph.findRelations({type: 'HtmlDart'}))
6 | .parEach(function (dartRelation) {
7 | var self = this,
8 | url = dartRelation.to.url + '.js';
9 |
10 | assetGraph.resolveAssetConfig(url, assetGraph.root, function (err, config) {
11 | var jsAsset = assetGraph.createAsset(config),
12 | jsRelation = new assetGraph.HtmlScript({
13 | from: dartRelation.from,
14 | to: jsAsset
15 | });
16 |
17 | assetGraph.addAsset(jsAsset);
18 | jsRelation.attach(dartRelation.from, 'after', dartRelation);
19 | dartRelation.detach();
20 |
21 | jsAsset.load(self);
22 | });
23 | })
24 | .seq(function () {
25 | cb();
26 | })
27 | .catch(cb);
28 | };
29 | };
30 |
--------------------------------------------------------------------------------
/lib/loadAndInstantiateAutoprefixer.js:
--------------------------------------------------------------------------------
1 | var semver = require('semver');
2 |
3 | module.exports = function loadAndInstantiateAutoprefixer(browsersOrAutoprefixerInstance, errorMessageIfUnavailable) {
4 | if (browsersOrAutoprefixerInstance && browsersOrAutoprefixerInstance.process) {
5 | return browsersOrAutoprefixerInstance;
6 | } else if (browsersOrAutoprefixerInstance && !Array.isArray(browsersOrAutoprefixerInstance)) {
7 | browsersOrAutoprefixerInstance = String(browsersOrAutoprefixerInstance).split(/,\s*/);
8 | }
9 |
10 | var autoprefixer;
11 | try {
12 | autoprefixer = require('autoprefixer');
13 | } catch (e) {
14 | if (errorMessageIfUnavailable) {
15 | e.message = errorMessageIfUnavailable + '\n' + e.message;
16 | throw e;
17 | }
18 | }
19 |
20 | if (semver.satisfies(require('autoprefixer/package.json').version, '>= 3.0.0')) {
21 | autoprefixer = autoprefixer(browsersOrAutoprefixerInstance ? {browsers: browsersOrAutoprefixerInstance} : {});
22 | } else {
23 | autoprefixer = autoprefixer(browsersOrAutoprefixerInstance);
24 | }
25 | return autoprefixer;
26 | };
27 |
--------------------------------------------------------------------------------
/test/transforms/runJavaScriptConditionalBlocks.js:
--------------------------------------------------------------------------------
1 | /*global describe, it*/
2 | var expect = require('../unexpected-with-plugins'),
3 | AssetGraph = require('../../lib/AssetGraph');
4 |
5 | describe('runJavaScriptConditionalBlocks', function () {
6 | it('shold handle a simple test case with some code that alters the DOM', function (done) {
7 | new AssetGraph({root: __dirname + '/../../testdata/transforms/runJavaScriptConditionalBlocks'})
8 | .loadAssets('index.html')
9 | .populate()
10 | .queue(function (assetGraph) {
11 | expect(assetGraph, 'to contain asset', 'JavaScript');
12 | })
13 | .runJavaScriptConditionalBlocks({type: 'Html'}, 'THEENVIRONMENT')
14 | .queue(function (assetGraph) {
15 | var html = assetGraph.findAssets({type: 'Html'})[0],
16 | divs = html.parseTree.getElementsByTagName('div');
17 | expect(divs, 'to have length', 2);
18 | expect(divs[0].firstChild.nodeValue, 'to equal', 'Howdy');
19 | expect(divs[1].firstChild.nodeValue, 'to equal', 'there');
20 | })
21 | .run(done);
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/lib/transforms/angularAnnotations.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 |
3 | var annotate;
4 |
5 | module.exports = function (queryObj, annotateOptions) {
6 | queryObj = _.extend({ type: 'JavaScript', isLoaded: true }, queryObj);
7 | annotateOptions = _.extend(annotateOptions || {}, { add: true });
8 |
9 | return function angularAnnotations(assetGraph, cb) {
10 | if (!annotate) {
11 | try {
12 | annotate = require('ng-annotate');
13 | } catch (err) {
14 | assetGraph.emit('warn', new Error('angularAnnotations: ng-annotate not installed. Please install it to get angular annotations'));
15 | return cb();
16 | }
17 | }
18 |
19 | assetGraph.findAssets(queryObj).forEach(function (asset) {
20 | var res = annotate(asset.text, annotateOptions);
21 |
22 | if (res.errors) {
23 | var err = new Error('ng-annotate: ' + res.errors);
24 | err.asset = asset;
25 |
26 | assetGraph.emit('warn', err);
27 | } else {
28 | asset.text = res.src;
29 | }
30 | });
31 |
32 | return cb();
33 | };
34 | };
35 |
--------------------------------------------------------------------------------
/testdata/bin/makeBabelJob/index.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "KeyAlreadyPartiallyTranslatedInIndexI18n": {
3 | "de": "Existing translation to German"
4 | },
5 | "KeyAlreadyTranslatedToCzech": {
6 | "cs": {
7 | "one": "fzd",
8 | "few": "fzd",
9 | "many": "fzd",
10 | "other": "fzd"
11 | }
12 | },
13 | "KeyAlreadyTranslatedToCzech": {
14 | "cs": {
15 | "one": "fzd",
16 | "few": "fzd",
17 | "many": "fzd",
18 | "other": "fzd"
19 | }
20 | },
21 | "KeyAlreadyTranslatedToAllLanguages": {
22 | "cs": {
23 | "one": "fzd",
24 | "few": "fzd",
25 | "many": "fzd",
26 | "other": "fzd"
27 | },
28 | "da": {
29 | "one": "føø",
30 | "other": "føø"
31 | },
32 | "de": {
33 | "one": "voo",
34 | "other": "voo"
35 | },
36 | "en": {
37 | "one": "foo",
38 | "other": "foo"
39 | },
40 | "pl": {
41 | "one": "fzz",
42 | "few": "fzz",
43 | "many": "fzz",
44 | "other": "fzz"
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/transforms/autoprefixer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * autoprefixer transform
3 | *
4 | * - Runs autoprefixer with the supplied options on each css asset
5 | */
6 |
7 | var loadAndInstantiateAutoprefixer = require('../loadAndInstantiateAutoprefixer');
8 |
9 | module.exports = function (autoprefixerOrOptions) {
10 | return function autoprefixer(assetGraph) {
11 | var cssAssets = assetGraph.findAssets({type: 'Css'});
12 |
13 | if (cssAssets.length > 0) {
14 | // See https://github.com/ai/autoprefixer#browsers
15 | var autoprefix = loadAndInstantiateAutoprefixer(autoprefixerOrOptions, 'autoprefixer transform: Found ' + cssAssets.length + ' css asset(s), but no autoprefixer module is available. Please use npm to install autoprefixer in your project so the autoprefixer transform can require it.');
16 |
17 | cssAssets.forEach(function (cssAsset) {
18 | try {
19 | cssAsset.text = autoprefix.process(cssAsset.text).css;
20 | } catch (err) {
21 | console.log(cssAsset.urlOrDescription, err);
22 | err.asset = cssAsset;
23 |
24 | assetGraph.emit('warn', err);
25 | }
26 | });
27 | }
28 | };
29 | };
30 |
--------------------------------------------------------------------------------
/testdata/bin/applyBabelJob/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Foo
5 |
6 |
7 |
17 | This key has some placeholders
18 |
19 |
20 | that comes back the same
21 | in the translation job
22 |
23 | data-i18n specifying that the contents of the tag should not be translated
24 | data-i18n specifying that the contents of the tag should not be translated
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/lib/transforms/duplicateFavicon.js:
--------------------------------------------------------------------------------
1 | // If the graph contains a favicon.ico at the root, make sure that all Html assets reference it explicitly so that
2 | // it can be moved to the static dir and served with a far-future expires. Still, keep a copy at /favicon.ico for
3 | // old IE versions.
4 |
5 | var _ = require('lodash');
6 |
7 | module.exports = function (queryObj) {
8 | return function duplicateFavicon(assetGraph) {
9 | var rootFavicon = assetGraph.findAssets({url: assetGraph.root + 'favicon.ico'})[0];
10 | assetGraph.findAssets(_.extend({type: 'Html', isInline: false, isFragment: false}, queryObj)).forEach(function (htmlAsset) {
11 | if (rootFavicon && assetGraph.findRelations({from: htmlAsset, type: 'HtmlShortcutIcon'}).length === 0) {
12 | new assetGraph.HtmlShortcutIcon({to: rootFavicon}).attach(htmlAsset);
13 | }
14 | });
15 | if (rootFavicon) {
16 | var incomingRelations = assetGraph.findRelations({to: rootFavicon});
17 | if (incomingRelations.length > 0) {
18 | var rootFaviconCopy = rootFavicon.clone(incomingRelations);
19 | rootFaviconCopy.fileName = 'favicon.copy.ico';
20 | rootFaviconCopy.isInitial = false;
21 | }
22 | }
23 | };
24 | };
25 |
--------------------------------------------------------------------------------
/testdata/bin/makeBabelJob/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 | data-i18n specifying that the contents of the tag should not be translated
18 | data-i18n specifying that the contents of the tag should not be translated
19 |
20 |
21 |
--------------------------------------------------------------------------------
/testdata/bin/makeBabelJobAndApplyBabelJob/thething.i18n:
--------------------------------------------------------------------------------
1 | {
2 | "stringvalue": {
3 | "en": "value"
4 | },
5 | "arrayvalue": {
6 | "en": [5, "items", "in", "an", "array"]
7 | },
8 | "objectvalue": {
9 | "en": {
10 | "key1": "value1",
11 | "key2": "value2"
12 | }
13 | },
14 | "objectvaluewithsomemissingkeysinthestructure": {
15 | "en": {
16 | "foo": {
17 | "bar": "baz"
18 | }
19 | },
20 | "da": {
21 | "foo": {
22 | "bar": "baz"
23 | }
24 | }
25 | },
26 | "withexistingkeys": {
27 | "en": "the English value",
28 | "da": "the Danish value"
29 | },
30 | "simplekeyinhtml": {
31 | "en": "Simple key in HTML, English"
32 | },
33 | "simplekeyinhtmlattribute": {
34 | "en": "Simple key in HTML attribute, English"
35 | },
36 | "keywithplaceholdersinhtml": {
37 | "en": "Key with {0} placeholders in HTML, English"
38 | },
39 | "alreadyPartiallyTranslatedKey": {
40 | "en": {
41 | "theTranslatedOne": "yep"
42 | },
43 | "da": {
44 | "theTranslatedOne": "ja"
45 | },
46 | "de": {
47 | "theTranslatedOne": "Ja"
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/lib/transforms/addDataVersionAttributeToHtmlElement.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash'),
2 | childProcess = require('child_process');
3 |
4 | module.exports = function (queryObj, version) {
5 | return function addDataVersionAttributeToHtmlElement(assetGraph, cb) {
6 | function proceed() {
7 | if (version) {
8 | assetGraph.findAssets(_.extend({type: 'Html'}, queryObj)).forEach(function (htmlAsset) {
9 | var documentElement = htmlAsset.parseTree.documentElement;
10 | if (documentElement) {
11 | documentElement.setAttribute('data-version', version.replace(/\{0\}/g, documentElement.getAttribute('data-version') || ''));
12 | htmlAsset.markDirty();
13 | }
14 | });
15 | }
16 | cb();
17 | }
18 |
19 | if (typeof version === 'undefined') {
20 | // Try to derive a version tag from git:
21 | childProcess.exec('git describe --long --tags --always --dirty', function (err, stdout, stderr) {
22 | if (!err) {
23 | version = stdout.replace(/^[\s\n\r]+|[\s\r\n]+$/g, '');
24 | }
25 | proceed();
26 | });
27 | } else {
28 | proceed();
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/testdata/transforms/checkLanguageKeys/combo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | This should be translated, but there is no data-i18n attribute for the text contents
6 |
7 | This should be translated, but there is no data-i18n attribute for the text contents
8 | This is
9 | translated
10 | This should be translated, but there is no data-i18n attribute for the text contents, although there is one for the title attribute
11 | data-i18n specifying that the contents of the tag should not be translated
12 | data-i18n specifying that the contents of the tag should not be translated
13 |
14 | This is translated but with wrong content
15 |
16 |
17 |
--------------------------------------------------------------------------------
/lib/transforms/stripDebug.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash'),
2 | AssetGraph = require('../AssetGraph'),
3 | uglifyJs = AssetGraph.JavaScript.uglifyJs,
4 | uglifyAst = AssetGraph.JavaScript.uglifyAst;
5 |
6 | module.exports = function (queryObj) {
7 | return function stripDebug(assetGraph) {
8 | assetGraph.findAssets(_.extend({type: 'JavaScript'}, queryObj)).forEach(function (javaScript) {
9 | javaScript.parseTree.figure_out_scope(); // So that uglifyJs.AST_SymbolRef.undeclared() is available
10 | var walker = new uglifyJs.TreeWalker(function (node) {
11 | if (node instanceof uglifyJs.AST_SimpleStatement) {
12 | if (node.body instanceof uglifyJs.AST_Call &&
13 | node.body.expression instanceof uglifyJs.AST_Dot &&
14 | node.body.expression.expression instanceof uglifyJs.AST_SymbolRef &&
15 | node.body.expression.expression.name === 'console' &&
16 | node.body.expression.expression.undeclared()) {
17 | uglifyAst.replaceDescendantNode(walker.parent(), node, new uglifyJs.AST_EmptyStatement());
18 | } else if (node instanceof uglifyJs.AST_Debugger) {
19 | uglifyAst.replaceDescendantNode(walker.parent(), node, new uglifyJs.AST_EmptyStatement());
20 | }
21 | }
22 | });
23 | javaScript.parseTree.walk(walker);
24 | });
25 | };
26 | };
27 |
--------------------------------------------------------------------------------
/test/findParentDirectory.js:
--------------------------------------------------------------------------------
1 | /*global describe, it*/
2 | var expect = require('./unexpected-with-plugins'),
3 | passError = require('passerror'),
4 | AssetGraph = require('../lib/AssetGraph'),
5 | resolvers = require('../lib/resolvers'),
6 | Path = require('path'),
7 | assetGraphRoot = Path.resolve(__dirname, '..', 'testdata', 'findParentDirectory') + '/';
8 |
9 | function resolveAssetConfig(assetConfig, fromUrl, cb) {
10 | var assetGraph = new AssetGraph({root: assetGraphRoot});
11 | assetGraph.defaultResolver = resolvers.findParentDirectory();
12 | assetGraph.resolveAssetConfig(assetConfig, fromUrl || assetGraph.root, cb);
13 | }
14 |
15 | describe('findParentDirectory', function () {
16 | it('should resolve an a url with an unknown protocol', function (done) {
17 | resolveAssetConfig('directory:quux.png', null, passError(done, function (resolvedAssetConfig) {
18 | expect(resolvedAssetConfig, 'to have properties', {
19 | url: 'file://' + assetGraphRoot + 'directory/quux.png'
20 | });
21 | done();
22 | }));
23 | });
24 |
25 | it('should resolving a url with an unknown protocol and a wildcard', function (done) {
26 | resolveAssetConfig('otherdirectory:onemorelevel/*.png', 'file://' + assetGraphRoot + 'directory', passError(done, function (resolvedAssetConfigs) {
27 | expect(resolvedAssetConfigs, 'to be an array whose items satisfy', 'to have properties', {type: 'Png'});
28 | done();
29 | }));
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/lib/transforms/gzip.js:
--------------------------------------------------------------------------------
1 | var async = require('async'),
2 | _ = require('lodash'),
3 | AssetGraph = require('../AssetGraph');
4 |
5 | module.exports = function (queryObj) {
6 | return function gzip(assetGraph, cb) {
7 | var compress,
8 | gzipAssets = assetGraph.findAssets(_.extend({isInline: false}, queryObj));
9 |
10 | if (gzipAssets.length > 0) {
11 | try {
12 | compress = require('node-zopfli');
13 | } catch (e) {
14 | assetGraph.emit('info', new Error('node-zopfli is not available, using less efficient zlib compression'));
15 | compress = require('zlib');
16 | }
17 | }
18 |
19 | async.eachLimit(gzipAssets, 4, function (asset, cb) {
20 | // http://webmasters.stackexchange.com/questions/31750/what-is-recommended-minimum-object-size-for-gzip-performance-benefits
21 | if (asset.rawSrc.length <= 860) {
22 | return cb();
23 | }
24 |
25 | compress.gzip(asset.rawSrc, function (err, gzippedRawSrc) {
26 | if (err) {
27 | assetGraph.emit('error', err);
28 | } else if (gzippedRawSrc.length < asset.rawSrc.length) {
29 | assetGraph.addAsset(new AssetGraph.Asset({
30 | url: asset.url.replace(/(?=[\?#]|$)/, '.gz'),
31 | rawSrc: gzippedRawSrc
32 | }));
33 | }
34 | cb();
35 | });
36 | }, cb);
37 | };
38 | };
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011, One.com
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the
13 | distribution.
14 | * Neither the name of the author nor the names of contributors may
15 | be used to endorse or promote products derived from this
16 | software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
19 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
--------------------------------------------------------------------------------
/test/i18nTools.js:
--------------------------------------------------------------------------------
1 | /*global describe, it*/
2 | var unexpected = require('./unexpected-with-plugins'),
3 | i18nTools = require('../lib/i18nTools');
4 |
5 | describe('i18nTools', function () {
6 | var expect = unexpected.clone().addAssertion('to tokenize as', function (expect, subject, value) {
7 | expect(i18nTools.tokenizePattern(subject), 'to equal', value);
8 | });
9 |
10 | describe('#tokenizePattern()', function () {
11 | it('should recognize a simple text as one text token', function () {
12 | expect('foo bar', 'to tokenize as', [{type: 'text', value: 'foo bar'}]);
13 | });
14 |
15 | it('should allow backslash in text tokens', function () {
16 | expect('foo \\ bar', 'to tokenize as', [{type: 'text', value: 'foo \\ bar'}]);
17 | });
18 |
19 | it('should recognize a placeholder', function () {
20 | expect('foo {1} bar', 'to tokenize as', [{type: 'text', value: 'foo '}, {type: 'placeHolder', value: 1}, {type: 'text', value: ' bar'}]);
21 | });
22 |
23 | it('should support curly brace followed by non-number in text tokens', function () {
24 | expect('foo { bar', 'to tokenize as', [{type: 'text', value: 'foo { bar'}]);
25 | });
26 |
27 | it('should support curly brace followed by number followed by non-curly end brace in text tokens', function () {
28 | expect('foo {5 bar', 'to tokenize as', [{type: 'text', value: 'foo {5 bar'}]);
29 | });
30 |
31 | it('should work even with a space at the end of a string', function () {
32 | expect('foo bar ', 'to tokenize as', [{type: 'text', value: 'foo bar '}]);
33 | });
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/test/transforms/autoprefixer.js:
--------------------------------------------------------------------------------
1 | /*global describe, it*/
2 | var expect = require('../unexpected-with-plugins'),
3 | AssetGraph = require('../../lib/AssetGraph');
4 |
5 | describe('transforms.autoprefixer', function () {
6 | it('should handle an unprefixed test case', function (done) {
7 | new AssetGraph({root: __dirname + '/../../testdata/transforms/autoprefixer/'})
8 | .loadAssets('index.html')
9 | .populate()
10 | .queue(function (assetGraph) {
11 | expect(assetGraph, 'to contain relations', 'HtmlStyle', 2);
12 | expect(assetGraph, 'to contain relations', 'CssImage', 1);
13 | })
14 | .autoprefixer('last 100 versions')
15 | .queue(function (assetGraph) {
16 | expect(assetGraph, 'to contain relations', 'HtmlStyle', 2);
17 | expect(assetGraph, 'to contain relations', 'CssImage', 4);
18 | })
19 | .run(done);
20 | });
21 |
22 | it('should handle a simple option case', function (done) {
23 | expect(function () {
24 | new AssetGraph({root: __dirname + '/../../testdata/transforms/autoprefixer/'})
25 | .loadAssets('index.html')
26 | .populate()
27 | .autoprefixer('last 2 versions')
28 | .run(done);
29 | }, 'not to throw');
30 | });
31 |
32 | it('should handle a complex option case', function (done) {
33 | expect(function () {
34 | new AssetGraph({root: __dirname + '/../../testdata/transforms/autoprefixer/'})
35 | .loadAssets('index.html')
36 | .populate()
37 | .autoprefixer('last 2 versions, ie > 8,ff > 28')
38 | .run(done);
39 | }, 'not to throw');
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/angularJs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | My AngularJS App
5 |
6 |
7 |
8 |
14 |
15 |
16 |
17 |
18 |
51 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/bin/buildDevelopment:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var _ = require('lodash'),
4 | AssetGraph = require('../lib/AssetGraph'),
5 | i18nTools = require('../lib/i18nTools'),
6 | urlTools = require('urltools'),
7 | commandLineOptions = require('optimist')
8 | .usage('$0 --root [--label = ...] [--parentdir] [--locales ,...] [--defaultlocale ] [--localecookiename ] [--cssimports] [--inline ] [--watch] [--version ] ...')
9 | .boolean('cssimports', 'parentdir')
10 | .options('stoponwarning', {
11 | describe: 'Whether to stop with a non-zero exit code when a warning is encountered',
12 | type: 'boolean',
13 | default: false
14 | })
15 | .demand(['root'])
16 | .argv;
17 |
18 | new AssetGraph({root: commandLineOptions.root})
19 | .logEvents({repl: commandLineOptions.repl, stopOnWarning: commandLineOptions.stoponwarning, suppressJavaScriptCommonJsRequireWarnings: true})
20 | .if(commandLineOptions.watch)
21 | .startOverIfAssetSourceFilesChange()
22 | .endif()
23 | .registerRequireJsConfig({preventPopulationOfJavaScriptAssetsUntilConfigHasBeenFound: true})
24 | .registerLabelsAsCustomProtocols(commandLineOptions.label, {installFindParentDirectoryAsDefault: commandLineOptions.parentdir})
25 | .loadAssets(commandLineOptions._.map(urlTools.fsFilePathToFileUrl))
26 | .buildDevelopment({
27 | version: commandLineOptions.version,
28 | supportedLocaleIds: commandLineOptions.locales && _.flatten(_.flatten([commandLineOptions.locales]).map(function (localeId) {
29 | return localeId.split(',');
30 | })).map(i18nTools.normalizeLocaleId),
31 | defaultLocaleId: commandLineOptions.defaultlocale && i18nTools.normalizeLocaleId(commandLineOptions.defaultlocale),
32 | localeCookieName: commandLineOptions.localecookiename,
33 | cssImports: commandLineOptions.cssimports,
34 | inlineUrlWildCard: commandLineOptions.inline
35 | })
36 | .writeAssetsToDisc({isInitial: true})
37 | .run();
38 |
--------------------------------------------------------------------------------
/bin/flattenOneInclude:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var fs = require('fs'),
4 | seq = require('seq'),
5 | AssetGraph = require('../lib/AssetGraph'),
6 | urlTools = require('urltools'),
7 | commandLineOptions = require('optimist')
8 | .usage('$0 [--label = ...] [--parentdir] [--root ] [-o ] ')
9 | .boolean('parentdir')
10 | .check(function (argv) {
11 | if (argv._.length !== 1 || !/\.js$/.test(argv._[0])) {
12 | throw 'Please specify a single JavaScript file on the command line';
13 | }
14 | })
15 | .argv;
16 |
17 | new AssetGraph({root: commandLineOptions.root})
18 | .logEvents({repl: commandLineOptions.repl, stopOnWarning: commandLineOptions.stoponwarning, suppressJavaScriptCommonJsRequireWarnings: true})
19 | .registerLabelsAsCustomProtocols(commandLineOptions.label, {installFindParentDirectoryAsDefault: commandLineOptions.parentdir})
20 | .loadAssets(commandLineOptions._.map(urlTools.fsFilePathToFileUrl))
21 | .populate({followRelations: {type: 'JavaScriptInclude'}})
22 | .queue(function (assetGraph) {
23 | assetGraph.findAssets({isInitial: true}).forEach(function (initialAsset) {
24 | // Get the original text including comments etc.:
25 | seq(assetGraph.collectAssetsPostOrder(initialAsset, {to: {type: 'JavaScript'}}).filter(function (asset) {
26 | return !asset.isInline;
27 | }))
28 | .parMap(function (asset) {
29 | fs.readFile(urlTools.fileUrlToFsPath(asset.url), 'utf-8', this);
30 | })
31 | .unflatten()
32 | .seq(function (texts) {
33 | var flattenedText = texts.join('\n').replace(/INCLUDE\(([^\)]*)\);?\n?/g, '');
34 | if ('o' in commandLineOptions) {
35 | fs.writeFileSync(commandLineOptions.o, flattenedText, AssetGraph.assets.JavaScript.prototype.encoding);
36 | } else {
37 | console.log(flattenedText);
38 | }
39 | });
40 | });
41 | })
42 | .run();
43 |
--------------------------------------------------------------------------------
/bin/findUnusedSelectors:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var AssetGraph = require('../lib/AssetGraph'),
4 | _ = require('lodash'),
5 | urlTools = require('urltools'),
6 | commandLineOptions = require('optimist')
7 | .usage('$0 [--root ] ...')
8 | .demand(1)
9 | .argv;
10 |
11 | new AssetGraph({root: commandLineOptions.root})
12 | .logEvents({repl: commandLineOptions.repl, stopOnWarning: commandLineOptions.stoponwarning, suppressJavaScriptCommonJsRequireWarnings: true})
13 | .loadAssets(commandLineOptions._.map(urlTools.fsFilePathToFileUrl))
14 | .populate({
15 | followRelations: {type: ['HtmlStyle', 'CssImport'], to: {url: /^file:/}}
16 | })
17 | .queue(function (assetGraph) {
18 | var documents = _.pluck(assetGraph.findAssets({type: 'Html'}), 'parseTree');
19 | function isSelectorUsed(selector) {
20 | return documents.some(function (document) {
21 | return document.querySelectorAll(selector).length > 0;
22 | });
23 | }
24 | assetGraph.findAssets({type: 'Css'}).forEach(function (cssAsset) {
25 | cssAsset.constructor.eachRuleInParseTree(cssAsset.parseTree, function (cssRule) {
26 | if (cssRule.type === 1) { // STYLE_RULE
27 | if (isSelectorUsed(cssRule.selectorText)) {
28 | //console.warn('IN USE: ' + cssRule.cssText);
29 | if (cssRule.selectorText.indexOf(',') !== -1) {
30 | cssRule.selectorText.split(',').forEach(function (subSelector) {
31 | subSelector = subSelector.replace(/^\s+|\s+$/g, ''); // Trim
32 | if (!isSelectorUsed(subSelector)) {
33 | console.warn('Unused selector fragment "' + subSelector + '" in rule: ' + cssRule.cssText);
34 | }
35 | });
36 | }
37 | } else {
38 | console.warn('NOT IN USE: ' + cssRule.cssText);
39 | }
40 | }
41 | });
42 | });
43 | })
44 | .run();
45 |
--------------------------------------------------------------------------------
/lib/transforms/runJavaScriptConditionalBlocks.js:
--------------------------------------------------------------------------------
1 | var vm = require('vm'),
2 | _ = require('lodash'),
3 | AssetGraph = require('../AssetGraph'),
4 | uglifyJs = AssetGraph.JavaScript.uglifyJs,
5 | bootstrapper = require('../bootstrapper');
6 |
7 | module.exports = function (queryObj, environment, removeAfter) {
8 | if (!environment) {
9 | throw new Error('transforms.runJavaScriptConditionalBlocks: no \'environment\' option provided');
10 | }
11 | return function runJavaScriptConditionalBlocks(assetGraph) {
12 | assetGraph.findAssets(_.extend({type: 'Html'}, queryObj)).forEach(function (htmlAsset) {
13 | var contextProperties = {console: console};
14 | contextProperties[environment] = true;
15 | var context = bootstrapper.createContext(htmlAsset, assetGraph, contextProperties);
16 |
17 | assetGraph.collectAssetsPostOrder(htmlAsset, {type: ['HtmlScript', 'HtmlRequireJsMain', 'JavaScriptAmdRequire', 'JavaScriptAmdDefine', 'JavaScriptShimRequire', 'JavaScriptRequireJsCommonJsCompatibilityRequire', 'JavaScriptInclude']}).filter(function (asset) {
18 | return asset.isLoaded && asset.type === 'JavaScript';
19 | }).forEach(function (javaScript) {
20 | // Loop through top-level statements:
21 | var topLevelStatements = javaScript.parseTree.body;
22 | for (var i = 0 ; i < topLevelStatements.length ; i += 1) {
23 | var node = topLevelStatements[i];
24 | if (node instanceof uglifyJs.AST_If &&
25 | ((node.condition instanceof uglifyJs.AST_SymbolRef && node.condition.name === environment) ||
26 | (node.condition instanceof uglifyJs.AST_Dot && node.condition.property === environment &&
27 | node.condition.expression instanceof uglifyJs.AST_SymbolRef &&
28 | node.condition.expression.name === 'window'))) {
29 |
30 | var fileName = javaScript.url || assetGraph.findRelations({to: javaScript})[0].baseAsset.url;
31 | new vm.Script(node.body.print_to_string(), fileName).runInContext(context);
32 | if (removeAfter) {
33 | javaScript.parseTree.body.splice(i, 1);
34 | i -= 1;
35 | }
36 | }
37 | }
38 | });
39 | });
40 | };
41 | };
42 |
--------------------------------------------------------------------------------
/lib/transforms/buildDevelopment.js:
--------------------------------------------------------------------------------
1 | var urlTools = require('urltools');
2 |
3 | module.exports = function (options) {
4 | options = options || {};
5 | return function buildDevelopment(assetGraph, cb) {
6 | var query = assetGraph.query;
7 | assetGraph
8 | .populate({from: {type: 'Html'}, followRelations: {type: 'HtmlScript', to: {url: /^file:/}}})
9 | .assumeRequireJsConfigHasBeenFound()
10 | .moveAssets({isInitial: true}, function (asset) { return asset.url.replace(/\.template$/, ''); })
11 | .addDataVersionAttributeToHtmlElement({type: 'Html', isInitial: true}, options.version)
12 | .populate({
13 | followRelations: query.or({
14 | type: ['HtmlScript', 'HtmlRequireJsMain', 'JavaScriptAmdRequire', 'JavaScriptAmdDefine', 'JavaScriptShimRequire', 'JavaScriptRequireJsCommonJsCompatibilityRequire', 'JavaScriptInclude'],
15 | to: {url: assetGraph.query.not(/^https?:/)}
16 | },
17 | {
18 | to: {type: 'I18n'}
19 | })
20 | })
21 | .injectBootstrapper({isInitial: true}, {
22 | defaultLocaleId: options.defaultLocaleId,
23 | supportedLocaleIds: options.supportedLocaleIds,
24 | localeCookieName: options.localeCookieName
25 | })
26 | .flattenStaticIncludes({isInitial: true})
27 | .removeAssets({isLoaded: true, isEmpty: true, type: 'JavaScript'})
28 | .inlineRelations({type: 'HtmlStyle', from: {isInitial: true, type: 'Html'}, to: {fixedUpExtJS: true, isLoaded: true}})
29 | .if(options.cssImports)
30 | .convertHtmlStylesToInlineCssImports()
31 | .endif()
32 | .inlineRelations({type: 'HtmlScript', from: {isInitial: true, type: 'Html'}, to: {fixedUpExtJS: true, isLoaded: true}})
33 | .prettyPrintAssets({type: 'JavaScript', isLoaded: true, incoming: {type: 'HtmlScript', from: {isInitial: true, type: 'Html'}}})
34 | .prettyPrintAssets({type: 'Css', isLoaded: true, incoming: {type: 'HtmlStyle', from: {isInitial: true, type: 'Html'}}})
35 | .runJavaScriptConditionalBlocks({type: 'Html', isLoaded: true}, 'BUILDDEVELOPMENT')
36 | .if(options.inlineUrlWildCard)
37 | .inlineRelations({to: {isLoaded: true, url: urlTools.makeFileUrlMatcher(options.inlineUrlWildCard)}})
38 | .endif()
39 | .run(cb);
40 | };
41 | };
42 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/svgsWithIdenticalInlineStyle/gears.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/svgsWithIdenticalInlineStyle/gears2.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "assetgraph-builder",
3 | "description": "Build system for web sites and applications",
4 | "repository": "git://github.com/One-com/assetgraph-builder.git",
5 | "version": "3.0.2-podio",
6 | "keywords": [
7 | "assetgraph",
8 | "web",
9 | "build",
10 | "build system",
11 | "single page",
12 | "web application",
13 | "static html",
14 | "cache manifest",
15 | "appcache",
16 | "spriting",
17 | "html",
18 | "css",
19 | "javascript",
20 | "jsdom",
21 | "localization",
22 | "internationalization",
23 | "i18n",
24 | "l10n"
25 | ],
26 | "maintainers": [
27 | {
28 | "name": "Andreas Lind Petersen",
29 | "email": "andreas@one.com"
30 | },
31 | {
32 | "name": "Peter Müller",
33 | "email": "munter@fumle.dk"
34 | }
35 | ],
36 | "main": "lib/AssetGraph.js",
37 | "files": [
38 | "lib",
39 | "bin"
40 | ],
41 | "dependencies": {
42 | "assetgraph": "1.15.4",
43 | "async": "0.9.0",
44 | "chalk": "1.0.0",
45 | "express-processimage": "https://github.com/podio/express-processimage/archive/v2.1.1-podio.tar.gz",
46 | "extend": "1.2.1",
47 | "jpegtran": "0.1.0",
48 | "lodash": "2.4.1",
49 | "memoizesync": "0.5.0",
50 | "ng-annotate": "0.15.4",
51 | "optimist": "0.6.1",
52 | "optipng": "0.1.1",
53 | "passerror": "1.1.0",
54 | "plurals-cldr": "1.0.1",
55 | "pngcrush": "0.1.0",
56 | "pngquant": "https://github.com/podio/node-pngquant/archive/v0.4.1-podio.tar.gz",
57 | "semver": "4.3.1",
58 | "seq": "0.3.5",
59 | "temp": "0.8.1",
60 | "urltools": "0.2.0"
61 | },
62 | "optionalDependencies": {
63 | "assetgraph-sprite": "0.7.1",
64 | "histogram": "2.0.0",
65 | "node-zopfli": "1.2.1"
66 | },
67 | "devDependencies": {
68 | "autoprefixer": "3.1.0",
69 | "coveralls": "2.11.2",
70 | "gm": "1.17.0",
71 | "istanbul": "0.3.6",
72 | "jsdom": "0.11.0",
73 | "jshint": "2.6.0",
74 | "less": "1.6.3",
75 | "mocha": "2.1.0",
76 | "node-sass": "0.9.4",
77 | "sinon": "1.12.2",
78 | "unexpected": "5.9.3",
79 | "unexpected-jsdom": "5.1.0",
80 | "unexpected-sinon": "5.1.0"
81 | },
82 | "engines": {
83 | "node": ">=0.8.0"
84 | },
85 | "directories": {
86 | "lib": "./lib",
87 | "bin": "./bin"
88 | },
89 | "publishConfig": {
90 | "registry": "http://registry.npmjs.org/"
91 | },
92 | "scripts": {
93 | "lint": "jshint . bin/*",
94 | "test": "npm run lint && mocha",
95 | "travis": "npm run lint && npm run coverage",
96 | "coverage": "NODE_ENV=development ./node_modules/.bin/istanbul cover --include-all-sources -x '**/testdata/**' -x lib/i18nTools.js -x lib/bootstrapper.js ./node_modules/mocha/bin/_mocha -- --reporter dot"
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/testdata/transforms/buildProduction/knockoutJs/tpl.js:
--------------------------------------------------------------------------------
1 | /*global define, $, ko*/
2 | define({
3 | load: function (url, req, load, config) {
4 | if (!ko.templateSources.externalTemplate) {
5 | ko.templateSources.externalTemplate = function (template) {
6 | this.data = {};
7 | this.template = ko.externalTemplateEngine.templates[template];
8 | };
9 |
10 | ko.templateSources.externalTemplate.prototype.data = function (key, value) {
11 | if (value) {
12 | return this.data[key];
13 | } else {
14 | this.data[key] = value;
15 | }
16 | };
17 |
18 | ko.templateSources.externalTemplate.prototype.text = function (value) {
19 | if (value) {
20 | this.template = value;
21 | } else {
22 | return this.template;
23 | }
24 | };
25 |
26 | ko.externalTemplateEngine = function () {
27 | var nativeTemplateEngine = new ko.nativeTemplateEngine(),
28 | nativeMakeTemplateSource = nativeTemplateEngine.makeTemplateSource;
29 |
30 | nativeTemplateEngine.makeTemplateSource = function (template) {
31 | if (typeof template === 'string' && ko.externalTemplateEngine.templates[template]) {
32 | return new ko.templateSources.externalTemplate(template);
33 | } else {
34 | return nativeMakeTemplateSource(template);
35 | }
36 | };
37 |
38 | return nativeTemplateEngine;
39 | };
40 |
41 | ko.externalTemplateEngine.templates = {};
42 |
43 | ko.setTemplateEngine(new ko.externalTemplateEngine());
44 | }
45 |
46 | $.ajax({
47 | url: url,
48 | success: function (htmlString) {
49 | var templateId = url.split('/').pop().replace(/\.ko$/, '');
50 |
51 | if (templateId in ko.externalTemplateEngine.templates) {
52 | throw new Error("tpl plugin for require.js: More than one of the loaded templates have the file name " + templateId + ".ko, skipped " + url + ". Please disambiguate by changing at least one of the file names.");
53 | } else {
54 | // Translate the template if AssetGraph-builder's bootstrapper script is present and we're not using the default language:
55 | if (window.TRHTML && (!window.DEFAULTLOCALEID || LOCALEID !== DEFAULTLOCALEID) && window.TRANSLATE !== false) {
56 | htmlString = TRHTML(htmlString);
57 | }
58 | ko.externalTemplateEngine.templates[templateId] = htmlString;
59 | }
60 | load(htmlString);
61 | }
62 | });
63 | }
64 | });
65 |
--------------------------------------------------------------------------------
/lib/resolvers/findParentDirectory.js:
--------------------------------------------------------------------------------
1 | /*global setImmediate:true*/
2 | // node 0.8 compat
3 | if (typeof setImmediate === 'undefined') {
4 | setImmediate = process.nextTick;
5 | }
6 |
7 | var urlTools = require('urltools'),
8 | passError = require('passerror'),
9 | fs = require('fs'),
10 | seq = require('seq');
11 |
12 | // FIXME: Make flushable
13 | var dirExistsCache = {},
14 | dirExistsWaitingQueue = {};
15 |
16 | function dirExistsCached(fsPath, cb) {
17 | if (fsPath in dirExistsCache) {
18 | setImmediate(function () {
19 | cb(null, dirExistsCache[fsPath]);
20 | });
21 | } else if (fsPath in dirExistsWaitingQueue) {
22 | dirExistsWaitingQueue[fsPath].push(cb);
23 | } else {
24 | dirExistsWaitingQueue[fsPath] = [cb];
25 | fs.stat(fsPath, function (err, stats) {
26 | var isDirectory = !err && stats.isDirectory();
27 | dirExistsCache[fsPath] = isDirectory;
28 | dirExistsWaitingQueue[fsPath].forEach(function (waitingCallback) {
29 | waitingCallback(null, isDirectory);
30 | });
31 | delete dirExistsWaitingQueue[fsPath];
32 | });
33 | }
34 | }
35 |
36 | function findParentDirCached(fromPath, parentDirName, cb) {
37 | var candidatePaths = [],
38 | fromPathFragments = fromPath.replace(/\/$/, '').split('/');
39 |
40 | seq(fromPathFragments)
41 | .parMap(function (fromPathFragment, i) {
42 | // FIXME: Stop at caller's definition of root?
43 | var candidatePath = fromPathFragments.slice(0, i + 1).concat(parentDirName).join('/');
44 | candidatePaths.push(candidatePath);
45 | dirExistsCached(candidatePath, this);
46 | })
47 | .unflatten()
48 | .seq(function (dirExistsResults) {
49 | var bestCandidateIndex = dirExistsResults.lastIndexOf(true);
50 | if (bestCandidateIndex === -1) {
51 | return cb(new Error('findParentDirCached: Couldn\'t find a parent dir named ' + parentDirName + ' from ' + fromPath));
52 | }
53 | cb(null, candidatePaths[bestCandidateIndex]);
54 | })['catch'](cb);
55 | }
56 |
57 | module.exports = function () {
58 | return function findParentDirectory(assetConfig, fromUrl, cb) {
59 | if (/^file:/.test(fromUrl)) {
60 | var protocol = assetConfig.url.substr(0, assetConfig.url.indexOf(':')),
61 | pathname = assetConfig.url.replace(/^\w+:(?:\/\/)?/, ''); // Strip protocol and two leading slashes if present
62 | findParentDirCached(urlTools.fileUrlToFsPath(fromUrl), protocol, passError(cb, function (parentPath) {
63 | assetConfig.url = urlTools.fsFilePathToFileUrl(parentPath + '/' + pathname);
64 | cb(null, assetConfig);
65 | }));
66 | } else {
67 | setImmediate(function () {
68 | cb(new Error('resolvers.findParentDir: fromUrl must be file: ' + fromUrl));
69 | });
70 | }
71 | };
72 | };
73 |
--------------------------------------------------------------------------------
/test/transforms/buildDevelopment.js:
--------------------------------------------------------------------------------
1 | /*global describe, it*/
2 | var expect = require('../unexpected-with-plugins'),
3 | passError = require('passerror'),
4 | AssetGraph = require('../../lib/AssetGraph');
5 |
6 | describe('buildDevelopment', function () {
7 | it('should handle a simple test case', function (done) {
8 | new AssetGraph({root: __dirname + '/../../testdata/transforms/buildDevelopment/simple/'})
9 | .registerRequireJsConfig()
10 | .loadAssets('index.html.template')
11 | .populate()
12 | .buildDevelopment({
13 | version: 'The version number',
14 | supportedLocaleIds: ['en', 'da'],
15 | defaultLocaleId: 'en',
16 | localeCookieName: 'myLocaleCookie',
17 | cssImports: true,
18 | inlineUrlWildCard: false // Test it
19 | })
20 | .run(passError(done, function (assetGraph) {
21 | expect(assetGraph, 'to contain asset', 'Html', 1);
22 |
23 | expect(assetGraph.findAssets({type: 'Html'})[0].parseTree.title, 'to equal', 'The default title');
24 |
25 | expect(assetGraph, 'to contain relations', {
26 | type: 'HtmlScript',
27 | node: function (node) {
28 | return node.getAttribute('id') === 'bootstrapper';
29 | }
30 | }, 1);
31 |
32 | var bootstrapperText = assetGraph.findRelations({type: 'HtmlScript', node: function (node) {return node.getAttribute('id') === 'bootstrapper'; }})[0].to.text;
33 | expect(bootstrapperText, 'to match', /\bwindow\.SUPPORTEDLOCALEIDS\s*=\s*\[\s*(['"])en\1\s*,\s*\1da\1\s*\]\s*;/);
34 | expect(bootstrapperText, 'to match', /\bwindow\.DEFAULTLOCALEID\s*=\s*(['"])en\1\s*;/);
35 | expect(bootstrapperText, 'to match', /\bwindow\.LOCALECOOKIENAME\s*=\s*(['"])myLocaleCookie\1\s*;/);
36 | expect(bootstrapperText, 'to match', /\bwindow\.I18NKEYS\s*=\s*\{\s*myLanguageKey:\s*\{\s*en:\s*(['"])The English value\1\s*,\s*da:\s*\1Den danske værdi\1\s*\}\s*\}\s*;/);
37 |
38 | expect(assetGraph.findAssets({type: 'Html'})[0].parseTree.querySelectorAll('html[data-version="The version number"]'), 'to have length', 1);
39 | done();
40 | }));
41 | });
42 |
43 | it('should not mangle an inline stylesheet with a data-bind attribute', function (done) {
44 | new AssetGraph({root: __dirname + '/../../testdata/transforms/buildDevelopment/dataBindOnHtmlStyle/'})
45 | .registerRequireJsConfig()
46 | .loadAssets('index.html.template')
47 | .populate()
48 | .buildDevelopment({
49 | version: 'The version number'
50 | })
51 | .queue(function (assetGraph) {
52 | expect(assetGraph.findAssets({type: 'Html'})[0].text, 'to contain', '');
53 | })
54 | .run(done);
55 | });
56 | });
57 |
--------------------------------------------------------------------------------
/lib/transforms/registerLabelsAsCustomProtocols.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash'),
2 | resolvers = require('../resolvers'),
3 | seq = require('seq'),
4 | urlTools = require('urltools');
5 |
6 | module.exports = function (labelDefinitions, options) {
7 | options = options || {};
8 | if (!labelDefinitions) {
9 | labelDefinitions = [];
10 | } else if (_.isString(labelDefinitions)) {
11 | labelDefinitions = [labelDefinitions];
12 | }
13 | if (_.isArray(labelDefinitions)) {
14 | labelDefinitions = labelDefinitions.map(function (labelDefinition) {
15 | if (_.isString(labelDefinition)) {
16 | var matchNameTypeAndUrl = labelDefinition.match(/^([^:=]+)(?::([^=]+))?=(.*)$/);
17 | if (!matchNameTypeAndUrl) {
18 | throw new Error('transforms.registerLabelsAsCustomProtocols: Invalid label definition syntax: ' + labelDefinition);
19 | }
20 | labelDefinition = {
21 | name: matchNameTypeAndUrl[1],
22 | type: matchNameTypeAndUrl[2] || null,
23 | url: matchNameTypeAndUrl[3]
24 | };
25 | } else if (typeof labelDefinition !== 'object' || labelDefinition === null) {
26 | throw new Error('transforms.registerLabelsAsCustomProtocols: Invalid label definition: ' + labelDefinition);
27 | }
28 | if (!('url' in labelDefinition) || !('name' in labelDefinition)) {
29 | throw new Error('transforms.registerLabelsAsCustomProtocols: \'name\' and \'url\' options are mandatory.');
30 | }
31 | if (labelDefinition.type && !(labelDefinition.type in resolvers)) {
32 | throw new Error('transforms.registerLabelsAsCustomProtocols: Unknown resolver type: ' + labelDefinition.type);
33 | }
34 | return labelDefinition;
35 | });
36 | } else {
37 | throw new Error('transforms.registerLabelsAsCustomProtocols: Invalid label definitions: ' + labelDefinitions);
38 | }
39 |
40 | return function registerLabelsAsCustomProtocols(assetGraph, cb) {
41 | if (options.installFindParentDirectoryAsDefault) {
42 | assetGraph.defaultResolver = resolvers.findParentDirectory();
43 | }
44 |
45 | seq(labelDefinitions)
46 | .parEach(function (labelDefinition) {
47 | var resolverName = labelDefinition.type || (/\.jsb\d+$/.test(labelDefinition.url) ? 'senchaJsBuilder' : 'fixedDirectory');
48 |
49 | try {
50 | assetGraph.resolverByProtocol[labelDefinition.name] = resolvers[resolverName](urlTools.fsFilePathToFileUrl(labelDefinition.url));
51 | } catch (err) {
52 | err.message = 'transforms.registerLabelsAsCustomProtocols: Error initializing resolver: ' + err.message;
53 | return this(err);
54 | }
55 | this();
56 | })
57 | .seq(function () {
58 | cb();
59 | })['catch'](cb);
60 | };
61 | };
62 |
--------------------------------------------------------------------------------
/lib/PngQuantWithHistogram.js:
--------------------------------------------------------------------------------
1 | /*global setImmediate:true*/
2 | // node 0.8 compat
3 | if (typeof setImmediate === 'undefined') {
4 | setImmediate = process.nextTick;
5 | }
6 |
7 | var Stream = require('stream'),
8 | util = require('util'),
9 | PngQuant = require('pngquant'),
10 | histogram;
11 |
12 | try {
13 | histogram = require('histogram');
14 | } catch (err) {}
15 |
16 | function PngQuantWithHistogram() {
17 | // Fall back to quanting to 256 colors. If you don't want this behavior, check PngQuantWithHistogram.histogramAvailable
18 | if (!histogram) {
19 | return new PngQuant([256]);
20 | }
21 |
22 | Stream.call(this);
23 | this.bufferedChunks = [];
24 | }
25 |
26 | PngQuantWithHistogram.histogramAvailable = !!histogram;
27 |
28 | util.inherits(PngQuantWithHistogram, Stream);
29 |
30 | PngQuantWithHistogram.prototype.write = function (chunk) {
31 | this.bufferedChunks.push(chunk);
32 | };
33 |
34 | PngQuantWithHistogram.prototype.end = function (chunk) {
35 | if (chunk) {
36 | this.write(chunk);
37 | }
38 | var rawSrc = Buffer.concat(this.bufferedChunks);
39 | this.bufferedChunks = null;
40 | histogram(rawSrc, function (err, data) {
41 | if (err) {
42 | err.message = 'histogram: ' + err.message;
43 | return this.emit('error', err);
44 | }
45 | if (data.colors.rgba < 256) {
46 | // The image has fewer than 256 colors, run rawSrc through a PngQuant filter and proxy its events:
47 | this.pngQuant = new PngQuant([data.colors.rgba < 2 ? 2 : data.colors.rgba]);
48 | this.__defineGetter__('commandLine', function () {
49 | return this.pngQuant.commandLine;
50 | }.bind(this));
51 | ['data', 'end', 'error'].forEach(function (eventName) {
52 | this.pngQuant.on(eventName, function () { // ...
53 | this.emit.apply(this, eventName.concat(arguments));
54 | }.bind(this));
55 | }.bind(this));
56 | this.pngQuant.end(rawSrc);
57 | } else {
58 | // The image has too many colors. Emit all the buffered chunks at once when we aren't paused:
59 | var hasEnded = false,
60 | emitRawSrcAndEnd = function () {
61 | hasEnded = true;
62 | this.emit('data', rawSrc);
63 | this.emit('end');
64 | }.bind(this);
65 |
66 | if (this.isPaused) {
67 | this.resume = function () {
68 | setImmediate(function () {
69 | if (!this.isPaused && !hasEnded) {
70 | emitRawSrcAndEnd();
71 | }
72 | });
73 | }.bind(this);
74 | } else {
75 | emitRawSrcAndEnd();
76 | }
77 | }
78 | }.bind(this));
79 |
80 | };
81 |
82 | PngQuantWithHistogram.prototype.pause = function () {
83 | this.isPaused = true;
84 | if (this.pngQuant) {
85 | this.pngQuant.pause();
86 | }
87 | };
88 |
89 | PngQuantWithHistogram.prototype.resume = function () {
90 | this.isPaused = false;
91 | if (this.pngQuant) {
92 | this.pngQuant.resume();
93 | }
94 | };
95 |
96 | module.exports = PngQuantWithHistogram;
97 |
--------------------------------------------------------------------------------
/test/transforms/duplicateFavicon.js:
--------------------------------------------------------------------------------
1 | /*global describe, it*/
2 | var expect = require('../unexpected-with-plugins'),
3 | passError = require('passerror'),
4 | AssetGraph = require('../../lib/AssetGraph'),
5 | urlTools = require('urltools');
6 |
7 | describe('transforms.duplicateFavicon', function () {
8 | it('should handle a referenced favicon.ico', function (done) {
9 | new AssetGraph({root: __dirname + '/../../testdata/transforms/duplicateFavicon/referencedFavicon'})
10 | .loadAssets('index.html')
11 | .populate()
12 | .queue(function (assetGraph) {
13 | expect(assetGraph, 'to contain relations', 'HtmlShortcutIcon', 1);
14 | })
15 | .duplicateFavicon()
16 | .run(passError(done, function (assetGraph) {
17 | expect(assetGraph, 'to contain relation', 'HtmlShortcutIcon');
18 | expect(assetGraph, 'to contain relation', {type: 'HtmlShortcutIcon', href: 'favicon.copy.ico'});
19 | expect(assetGraph, 'to contain assets', 'Ico', 2);
20 | expect(assetGraph, 'to contain asset', {url: urlTools.resolveUrl(assetGraph.root, 'favicon.ico')});
21 | expect(assetGraph, 'to contain asset', {url: urlTools.resolveUrl(assetGraph.root, 'favicon.copy.ico')});
22 | expect(assetGraph.findAssets({type: 'Html'})[0].text, 'to equal',
23 | '\n' +
24 | '\n' +
25 | ' \n' +
26 | ' \n' +
27 | ' \n' +
28 | ' \n' +
29 | ' \n' +
30 | '\n');
31 | done();
32 | }));
33 | });
34 |
35 | it('should handle an unreferenced favicon.ico', function (done) {
36 | new AssetGraph({root: __dirname + '/../../testdata/transforms/duplicateFavicon/unreferencedFavicon'})
37 | .loadAssets('index.html', 'noHead.html', 'favicon.ico')
38 | .populate()
39 | .queue(function (assetGraph) {
40 | expect(assetGraph, 'to contain relations', 'HtmlShortcutIcon', 0);
41 | })
42 | .duplicateFavicon()
43 | .run(passError(done, function (assetGraph) {
44 | expect(assetGraph, 'to contain relation', 'HtmlShortcutIcon', 2);
45 | expect(assetGraph, 'to contain assets', 'Ico', 2);
46 | expect(assetGraph, 'to contain asset', {url: urlTools.resolveUrl(assetGraph.root, 'favicon.ico'), isInitial: true});
47 | expect(assetGraph, 'to contain asset', {url: urlTools.resolveUrl(assetGraph.root, 'favicon.copy.ico'), isInitial: function (isInitial) {return !isInitial; }});
48 | expect(assetGraph.findAssets({type: 'Html', fileName: 'index.html'})[0].text, 'to equal',
49 | '\n' +
50 | '\n' +
51 | ' \n' +
52 | ' \n' +
53 | ' \n' +
54 | ' \n' +
55 | '\n'
56 | );
57 | expect(assetGraph.findAssets({type: 'Html', fileName: 'noHead.html'})[0].text, 'to equal',
58 | '\n' +
59 | '\n' +
60 | ' \n' +
61 | ' \n' +
62 | '\n'
63 | );
64 | done();
65 | }));
66 | });
67 | });
68 |
--------------------------------------------------------------------------------
/test/resolvers/senchaJsBuilder.js:
--------------------------------------------------------------------------------
1 | /*global describe, it*/
2 | var expect = require('../unexpected-with-plugins'),
3 | _ = require('lodash'),
4 | AssetGraph = require('../../lib/AssetGraph');
5 |
6 | describe('resolvers/senchaJsBuilder', function () {
7 | it('should handle a test case with 3 assets', function (done) {
8 | new AssetGraph({root: __dirname + '/../../testdata/resolvers/senchaJsBuilder/rewriteBackgroundImageUrls/'})
9 | .registerLabelsAsCustomProtocols([
10 | {name: 'mylabel', url: __dirname + '/../../testdata/resolvers/senchaJsBuilder/rewriteBackgroundImageUrls/foo.jsb2'}
11 | ])
12 | .loadAssets('index.html')
13 | .populate()
14 | .flattenStaticIncludes({isInitial: true})
15 | .queue(function (assetGraph) {
16 | expect(assetGraph, 'to contain asset', 'Html');
17 | expect(assetGraph, 'to contain asset', {type: 'Css', isInline: false});
18 | expect(assetGraph, 'to contain asset', 'Png');
19 |
20 | var cssAsset = assetGraph.findAssets({type: 'Css'})[0],
21 | cssBackgroundImageRelations = assetGraph.findRelations({type: 'CssImage', to: assetGraph.findAssets({type: 'Png'})[0]});
22 | expect(cssBackgroundImageRelations, 'to have length', 4);
23 | cssBackgroundImageRelations.forEach(function (cssBackgroundImageRelation) {
24 | expect(cssBackgroundImageRelation.baseAsset, 'to be', cssAsset);
25 | });
26 | var src = assetGraph.findAssets({type: 'Css'})[0].text,
27 | matches = src.match(/url\(\.\.\/\.\.\/images\/foo\/bar\/foo\.png\)/g);
28 | expect(matches, 'to have length', 4);
29 | })
30 | .inlineRelations({type: 'HtmlStyle'})
31 | .queue(function (assetGraph) {
32 | // All the background-image urls should be relative to the Html
33 | assetGraph.findRelations({type: 'CssImage'}).forEach(function (relation) {
34 | expect(relation.cssRule.style[relation.propertyName], 'to equal', 'url(resources/images/foo/bar/foo.png)');
35 | });
36 | expect(assetGraph.findAssets({type: 'Html'})[0].text.match(/url\(resources\/images\/foo\/bar\/foo\.png\)/g), 'to have length', 4);
37 | })
38 | .run(done);
39 | });
40 |
41 | it('should handle an Html asset and a jsb2 describing packages that depend on each other', function (done) {
42 | new AssetGraph({root: __dirname + '/../../testdata/resolvers/senchaJsBuilder/dependentPackages/'})
43 | .registerLabelsAsCustomProtocols([
44 | {name: 'mylabel', url: __dirname + '/../../testdata/resolvers/senchaJsBuilder/dependentPackages/foo.jsb2'}
45 | ])
46 | .loadAssets('index.html')
47 | .populate()
48 | .queue(function (assetGraph) {
49 | expect(assetGraph, 'to contain asset', 'Html');
50 | expect(assetGraph, 'to contain asset', {type: 'JavaScript', isInline: true});
51 | expect(assetGraph, 'to contain relations', 'JavaScriptInclude', 3);
52 |
53 | expect(assetGraph.findAssets({type: 'JavaScript', isInline: true})[0].text.match(/INCLUDE/g), 'to have length', 3);
54 | })
55 | .flattenStaticIncludes({isInitial: true})
56 | .queue(function (assetGraph) {
57 | expect(assetGraph, 'to contain relations', 'HtmlScript', 4);
58 | expect(_.pluck(assetGraph.findRelations({type: 'HtmlScript'}), 'href'), 'to equal', [
59 | 'js/A1.js',
60 | 'js/B1.js',
61 | 'js/C1.js',
62 | undefined
63 | ]);
64 | })
65 | .run(done);
66 | });
67 |
68 | it('should handle overlapping jsb2 packages', function (done) {
69 | new AssetGraph({root: __dirname + '/../../testdata/resolvers/senchaJsBuilder/dependentPackages/'})
70 | .registerLabelsAsCustomProtocols([
71 | {name: 'mylabel', url: __dirname + '/../../testdata/resolvers/senchaJsBuilder/dependentPackages/foo.jsb2'}
72 | ])
73 | .loadAssets('overlappingIncludes.html')
74 | .populate()
75 | .queue(function (assetGraph) {
76 | expect(assetGraph, 'to contain asset', 'Html');
77 | expect(assetGraph, 'to contain asset', {type: 'JavaScript', isInline: true});
78 | expect(assetGraph, 'to contain relations', 'JavaScriptInclude', 4);
79 |
80 | expect(assetGraph.findAssets({type: 'JavaScript', isInline: true})[0].text.match(/INCLUDE/g), 'to have length', 4);
81 | })
82 | .flattenStaticIncludes({isInitial: true})
83 | .queue(function (assetGraph) {
84 | expect(assetGraph, 'to contain relations', 'HtmlScript', 4);
85 | expect(_.pluck(assetGraph.findRelations({type: 'HtmlScript'}), 'href'), 'to equal', [
86 | 'js/A1.js',
87 | 'js/B1.js',
88 | 'js/C1.js',
89 | undefined
90 | ]);
91 | })
92 | .run(done);
93 | });
94 | });
95 |
--------------------------------------------------------------------------------
/bin/copyReferencedAssets:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var optimist = require('optimist'),
4 | commandLineOptions = optimist
5 | .usage('$0 --root --outroot [options] ')
6 | .options('h', {
7 | alias: 'help',
8 | describe: 'Show this help',
9 | type: 'boolean',
10 | default: false
11 | })
12 | .options('root', {
13 | describe: 'Path to your web root (will be deduced from your input files if not specified)',
14 | type: 'string',
15 | demand: false
16 | })
17 | .options('outroot', {
18 | describe: 'Path to the output folder. Will be generated if non-existing',
19 | type: 'string',
20 | demand: true
21 | })
22 | .options('label', {
23 | describe: 'Registers labels as custom protocols for path resolving. You can create multiple of these: --label = --label =',
24 | type: 'string',
25 | demand: false
26 | })
27 | .options('parentdir', {
28 | describe: 'If an unknown label (scheme) is found, look for at parent dir of that name before failing (breaks custom protocols)',
29 | type: 'boolean',
30 | demand: false
31 | })
32 | .options('stoponwarning', {
33 | describe: 'Whether to stop with a non-zero exit code when a warning is encountered',
34 | type: 'boolean',
35 | default: false
36 | })
37 | .options('noless', {
38 | describe: 'Keep .less files as they are instead of automatically compiling them to CSS',
39 | type: 'boolean',
40 | default: false
41 | })
42 | .wrap(72)
43 | .argv;
44 |
45 | if (commandLineOptions.h) {
46 | optimist.showHelp();
47 | process.exit(1);
48 | }
49 |
50 | var AssetGraph = require('../lib/AssetGraph'),
51 | query = AssetGraph.query,
52 | urlTools = require('urltools'),
53 | outRoot = urlTools.fsDirToFileUrl(commandLineOptions.outroot),
54 | rootUrl = commandLineOptions.root && urlTools.urlOrFsPathToUrl(commandLineOptions.root, true),
55 | inputUrls;
56 |
57 | if (commandLineOptions._.length > 0) {
58 | inputUrls = commandLineOptions._.map(function (urlOrFsPath) {
59 | return urlTools.urlOrFsPathToUrl(urlOrFsPath, false);
60 | });
61 | if (!rootUrl) {
62 | rootUrl = urlTools.findCommonUrlPrefix(inputUrls.filter(function (inputUrl) {
63 | return (/^file:/).test(inputUrl);
64 | }));
65 | if (rootUrl) {
66 | console.warn('Guessing --root from input files: ' + rootUrl);
67 | }
68 | }
69 | } else if (rootUrl && /^file:/.test(rootUrl)) {
70 | inputUrls = [rootUrl + '**/*.html'];
71 | console.warn('No input files specified, defaulting to ' + inputUrls[0]);
72 | } else {
73 | throw new Error('No input files and no --root specified (or it isn\'t file:), cannot proceed');
74 | }
75 |
76 | var followRelationsQueryObj = query.or(
77 | {
78 | to: {type: 'I18n'}
79 | },
80 | {
81 | type: query.not(['JavaScriptInclude', 'JavaScriptExtJsRequire', 'JavaScriptCommonJsRequire', 'HtmlAnchor', 'HtmlMetaRefresh']),
82 | to: {url: query.not(/^https?:/)}
83 | }
84 | );
85 |
86 | new AssetGraph({root: rootUrl})
87 | .logEvents({repl: commandLineOptions.repl, stopOnWarning: commandLineOptions.stoponwarning, suppressJavaScriptCommonJsRequireWarnings: true})
88 | .registerRequireJsConfig({preventPopulationOfJavaScriptAssetsUntilConfigHasBeenFound: true})
89 | .registerLabelsAsCustomProtocols(commandLineOptions.label, {installFindParentDirectoryAsDefault: commandLineOptions.parentdir})
90 | .loadAssets(inputUrls)
91 | .populate({from: {type: 'Html'}, followRelations: {type: 'HtmlScript', to: {url: /^file:/}}})
92 | .assumeRequireJsConfigHasBeenFound()
93 | .populate({followRelations: followRelationsQueryObj})
94 | .queue(function fixBaseAssetsOfUnresolvedOutgoingRelationsFromHtmlFragments(assetGraph) {
95 | assetGraph.findRelations({from: {type: 'Html', isFragment: true, isInitial: true}}, true).forEach(function (relation) {
96 | if (relation._baseAssetPath === null) {
97 | delete relation._baseAssetPath;
98 | }
99 | });
100 | })
101 | .populate({followRelations: followRelationsQueryObj, startAssets: {type: 'Html', isFragment: true, isInitial: true}})
102 | .if(!commandLineOptions.noless)
103 | // Replace Less assets with their Css counterparts:
104 | .compileLessToCss({type: 'Less', isLoaded: true})
105 |
106 | // Remove the in-browser less compiler and its incoming relations,
107 | // even if it's included from a CDN and thus hasn't been populated:
108 | .removeRelations({to: {url: /\/less(?:-\d+\.\d+\.\d+)?(?:\.min)?\.js$/}}, {unresolved: true, detach: true, removeOrphan: true})
109 |
110 | // Find and populate CssImage relations from the compiled Less assets:
111 | .populate({from: {type: 'Css'}, followRelations: followRelationsQueryObj})
112 | .endif()
113 | .writeAssetsToDisc({url: /^file:/, isLoaded: true}, outRoot)
114 | .writeStatsToStderr()
115 | .run();
116 |
--------------------------------------------------------------------------------
/bin/checkLanguageKeys:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var optimist = require('optimist'),
4 | commandLineOptions = optimist
5 | .usage('$0 --root [options] ')
6 | .options('locales', {
7 | describe: 'Comma-separated list of locales to check',
8 | type: 'string',
9 | demand: true
10 | })
11 | .options('removeunused', {
12 | describe: 'Remove unused language keys from .i18n files',
13 | type: 'boolean'
14 | })
15 | .options('ignore', {
16 | describe: 'Type(s) of messages to suppress (supported: \'missing\', \'untranslated\', \'defaultValueMismatch\', \'whitespace\', \'unused\')',
17 | type: 'string'
18 | })
19 | .options('warn', {
20 | descrbe: 'Type(s) of messages that should be emitted with \'warning\' status (supported: \'missing\', \'untranslated\', \'defaultValueMismatch\', \'whitespace\', \'unused\'). Intended for use with --stoponwarning',
21 | type: 'string'
22 | })
23 | .options('stoponwarning', {
24 | describe: 'Whether to stop with a non-zero exit code when a warning is encountered',
25 | type: 'boolean',
26 | default: false
27 | })
28 | .options('defaultlocale', {
29 | describe: 'The locale of the default value in TR statements and tags with a data-i18n attribute',
30 | type: 'string',
31 | default: 'en'
32 | })
33 | .wrap(72)
34 | .argv;
35 |
36 | if (commandLineOptions.h) {
37 | optimist.showHelp();
38 | process.exit(1);
39 | }
40 |
41 | var _ = require('lodash'),
42 | AssetGraph = require('../lib/AssetGraph'),
43 | i18nTools = require('../lib/i18nTools'),
44 | query = AssetGraph.query,
45 | urlTools = require('urltools'),
46 | rootUrl = commandLineOptions.root && urlTools.urlOrFsPathToUrl(commandLineOptions.root, true),
47 | localeIds = commandLineOptions.locales && _.flatten(_.flatten([commandLineOptions.locales]).map(function (localeId) {
48 | return localeId.split(',');
49 | })).map(i18nTools.normalizeLocaleId),
50 | defaultLocaleId = commandLineOptions.defaultlocale && i18nTools.normalizeLocaleId(commandLineOptions.defaultlocale),
51 | ignoreMessageTypes = commandLineOptions.ignore && _.flatten(_.flatten([commandLineOptions.ignore]).map(function (ignoreMessageType) {
52 | return ignoreMessageType.split(',');
53 | })),
54 | warnMessageTypes = commandLineOptions.warn && _.flatten(_.flatten([commandLineOptions.warn]).map(function (warnMessageType) {
55 | return warnMessageType.split(',');
56 | })),
57 | includeAttributeNames = commandLineOptions.includeattribute && _.flatten(_.flatten([commandLineOptions.includeattribute]).map(function (attributeName) {
58 | return attributeName.split(',');
59 | })),
60 | excludeAttributeNames = commandLineOptions.excludeattribute && _.flatten(_.flatten([commandLineOptions.excludeattribute]).map(function (attributeName) {
61 | return attributeName.split(',');
62 | })),
63 | inputUrls;
64 |
65 | if (commandLineOptions._.length > 0) {
66 | inputUrls = commandLineOptions._.map(function (urlOrFsPath) {
67 | return urlTools.urlOrFsPathToUrl(urlOrFsPath, false);
68 | });
69 | if (!rootUrl) {
70 | rootUrl = urlTools.findCommonUrlPrefix(inputUrls.filter(function (inputUrl) {
71 | return /^file:/.test(inputUrl);
72 | }));
73 | if (rootUrl) {
74 | console.warn('Guessing --root from input files: ' + rootUrl);
75 | }
76 | }
77 | } else if (rootUrl && /^file:/.test(rootUrl)) {
78 | inputUrls = [rootUrl + '**/*.html'];
79 | console.warn('No input files specified, defaulting to ' + inputUrls[0]);
80 | } else {
81 | throw new Error('No input files and no --root specified (or it isn\'t file:), cannot proceed');
82 | }
83 |
84 | new AssetGraph({root: rootUrl})
85 | .logEvents({repl: commandLineOptions.repl, stopOnWarning: commandLineOptions.stoponwarning, suppressJavaScriptCommonJsRequireWarnings: true})
86 | .registerRequireJsConfig({preventPopulationOfJavaScriptAssetsUntilConfigHasBeenFound: true})
87 | .registerLabelsAsCustomProtocols(commandLineOptions.label, {installFindParentDirectoryAsDefault: commandLineOptions.parentdir})
88 | .loadAssets(inputUrls)
89 | .populate({from: {type: 'Html'}, followRelations: {type: 'HtmlScript', to: {url: /^file:/}}})
90 | .assumeRequireJsConfigHasBeenFound()
91 | .populate({
92 | followRelations: query.or(
93 | {
94 | to: {type: 'I18n'}
95 | },
96 | {
97 | type: query.not(['JavaScriptCommonJsRequire', 'HtmlAnchor', 'HtmlMetaRefresh', 'SvgAnchor', 'JavaScriptSourceMappingUrl', 'JavaScriptSourceUrl']),
98 | to: {url: query.not(/^https?:/)}
99 | }
100 | )
101 | })
102 | .checkLanguageKeys({
103 | supportedLocaleIds: localeIds,
104 | defaultLocaleId: defaultLocaleId,
105 | ignoreMessageTypes: ignoreMessageTypes,
106 | warnMessageTypes: warnMessageTypes,
107 | removeUnused: commandLineOptions.removeunused,
108 | includeAttributeNames: includeAttributeNames,
109 | excludeAttributeNames: excludeAttributeNames
110 | })
111 | .if(commandLineOptions.removeunused)
112 | .prettyPrintAssets({type: ['I18n'], isDirty: true})
113 | .writeAssetsToDisc({type: ['I18n'], isDirty: true})
114 | .endif()
115 | .run();
116 |
--------------------------------------------------------------------------------
/test/bin/applyBabelJob.js:
--------------------------------------------------------------------------------
1 | /*global describe, it*/
2 | var childProcess = require('child_process'),
3 | fs = require('fs'),
4 | Path = require('path'),
5 | expect = require('unexpected'),
6 | temp = require('temp');
7 |
8 | describe('applyBabelJob', function () {
9 | it('should handle a complex test case', function (done) {
10 | var babelDir = Path.resolve(__dirname, '..', '..', 'testdata', 'bin', 'applyBabelJob', 'translationjob'),
11 | tmpTestCaseCopyDir = temp.mkdirSync(),
12 | copyCommand = 'cp \'' + __dirname + '/../../testdata/bin/applyBabelJob\'/index.* ' + tmpTestCaseCopyDir;
13 | childProcess.exec(copyCommand, function (err, stdout, stderr) {
14 | if (err) {
15 | return done(new Error(copyCommand + ' failed: STDERR:' + stderr + '\nSTDOUT:' + stdout));
16 | }
17 | var applyBabelJobProcess = childProcess.spawn(__dirname + '/../../bin/applyBabelJob', [
18 | '--babeldir', babelDir,
19 | '--root', tmpTestCaseCopyDir,
20 | '--defaultlocale', 'en',
21 | '--locales', 'en,da',
22 | '--i18n', tmpTestCaseCopyDir + '/index.i18n',
23 | '--replace',
24 | tmpTestCaseCopyDir + '/index.html'
25 | ]);
26 |
27 | applyBabelJobProcess.on('exit', function (exitCode) {
28 | if (exitCode) {
29 | done(new Error('The applyBabelJob process ended with a non-zero exit code: ' + exitCode));
30 | } else {
31 | expect(JSON.parse(fs.readFileSync(tmpTestCaseCopyDir + '/index.i18n')), 'to equal', {
32 | ComplexKey: {
33 | da: {
34 | that: 'også kommer',
35 | back: 'det samme'
36 | },
37 | en: {
38 | that: 'also comes',
39 | back: 'the same'
40 | }
41 | },
42 | WeirdlyFormattedKey: {
43 | da: 'der kommer uændret retur i oversættelsesjobbet',
44 | en: 'that comes back the same in the translation job'
45 | },
46 | bar: {
47 | da: 'BarOversat',
48 | en: 'BarProofRead'
49 | },
50 | foo: {
51 | da: 'FooOversat',
52 | en: 'FooProofRead'
53 | },
54 | placeholders: {
55 | da: 'Denne oversatte nøgle har {0} pladsholdere',
56 | en: 'This proofread key has {0} proofread placeholders'
57 | }
58 | });
59 | expect(JSON.parse(fs.readFileSync(tmpTestCaseCopyDir + '/index.someother.i18n')), 'to equal', {
60 | KeyInSomeOtherI18nFile: {
61 | en: 'Woop',
62 | da: 'Jubii'
63 | }
64 | });
65 | expect(fs.readFileSync(tmpTestCaseCopyDir + '/index.html', 'utf-8'), 'to equal',
66 | '\n' +
67 | '\n' +
68 | ' \n' +
69 | ' FooProofRead\n' +
70 | ' \n' +
71 | ' \n' +
72 | ' \n' +
82 | ' This proofread key has some proofread placeholders\n' +
83 | ' \n' +
84 | ' \n' +
85 | ' that comes back the same\n' +
86 | ' in the translation job\n' +
87 | ' \n' +
88 | ' data-i18n specifying that the contents of the tag should not be translated\n' +
89 | ' data-i18n specifying that the contents of the tag should not be translated\n' +
90 | ' \n' +
91 | ' \n' +
92 | '\n'
93 | );
94 | done();
95 | }
96 | });
97 | });
98 | });
99 | });
100 |
--------------------------------------------------------------------------------
/bin/refreshI18n:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var _ = require('lodash'),
4 | AssetGraph = require('../lib/AssetGraph'),
5 | i18nTools = require('../lib/i18nTools'),
6 | uglifyAst = require('uglifyast'),
7 | urlTools = require('urltools'),
8 | fs = require('fs'),
9 | commandLineOptions = require('optimist')
10 | .usage('$0 [--label = ...] [--parentdir] --root --locales ,... ...')
11 | .boolean('parentdir')
12 | .demand(['root', 'locales'])
13 | .argv,
14 | localeIds = _.flatten(_.flatten([commandLineOptions.locales]).map(function (localeId) {
15 | return localeId.split(',');
16 | }));
17 |
18 | new AssetGraph({root: commandLineOptions.root})
19 | .logEvents({repl: commandLineOptions.repl, stopOnWarning: commandLineOptions.stoponwarning, suppressJavaScriptCommonJsRequireWarnings: true})
20 | .registerRequireJsConfig({preventPopulationOfJavaScriptAssetsUntilConfigHasBeenFound: true})
21 | .registerLabelsAsCustomProtocols(commandLineOptions.label, {installFindParentDirectoryAsDefault: commandLineOptions.parentdir})
22 | .loadAssets(commandLineOptions._.map(urlTools.fsFilePathToFileUrl))
23 | .populate({from: {type: 'Html'}, followRelations: {type: 'HtmlScript', to: {url: /^file:/}}})
24 | .assumeRequireJsConfigHasBeenFound()
25 | .populate({
26 | followRelations: {
27 | type: ['HtmlScript', 'HtmlRequireJsMain', 'JavaScriptInclude', 'JavaScriptAmdDefine', 'JavaScriptAmdRequire', 'JavaScriptGetText'],
28 | to: {url: AssetGraph.query.not(/^https?:/)}
29 | }
30 | })
31 | .queue(function (assetGraph) {
32 | // We don't want to overwrite the "initially dirty" assets, such as ext-base.js.
33 | assetGraph.findAssets({isDirty: true}).forEach(function (dirtyAsset) {
34 | dirtyAsset.isDirty = false;
35 | });
36 | var existingI18nRelations = assetGraph.findRelations({to: {type: 'I18n'}, from: {type: 'JavaScript'}}),
37 | occurrencesByKey = i18nTools.findOccurrences(assetGraph, assetGraph.findAssets({type: 'Html', isInitial: true}));
38 |
39 | _.keys(occurrencesByKey).forEach(function (key) {
40 | var occurrences = occurrencesByKey[key];
41 | if (occurrences.length > 1) {
42 | for (var i = 1 ; i < occurrences.length ; i += 1) {
43 | if (!_.isEqual(occurrences[0].defaultValue, occurrences[1].defaultValue)) {
44 | console.warn('Default values for ' + key + ' are different');
45 | }
46 | }
47 | }
48 | var i18nAsset = i18nTools.getOrCreateI18nAssetForKey(assetGraph, key, occurrencesByKey);
49 | localeIds.forEach(function (localeId) {
50 | var prioritizedLocaleIds = i18nTools.expandLocaleIdToPrioritizedList(localeId);
51 | if (key in i18nAsset.parseTree) {
52 | for (var i = 0 ; i < prioritizedLocaleIds.length ; i += 1) {
53 | if (prioritizedLocaleIds[i] in i18nAsset.parseTree[key]) {
54 | return; // Already found, don't do anything
55 | }
56 | }
57 | } else {
58 | i18nAsset.parseTree[key] = {};
59 | }
60 | var leastSpecificLocaleId = prioritizedLocaleIds[prioritizedLocaleIds.length - 1],
61 | value = null;
62 | if (leastSpecificLocaleId === 'en' && occurrences[0].defaultValue) {
63 | value = /^i18nTag/.test(occurrences[0].type) ? occurrences[0].defaultValue : uglifyAst.astToObj(occurrences[0].defaultValue);
64 | }
65 | i18nAsset.parseTree[key][leastSpecificLocaleId] = value;
66 | console.log(i18nAsset.url + ': ' + key + ' already found, added entry for ' + leastSpecificLocaleId);
67 | i18nAsset.markDirty();
68 | });
69 | });
70 |
71 | // Find the JavaScript => I18n relations that didn't exist when we started:
72 | var newI18nRelationsByJavaScriptId = {};
73 | assetGraph.findRelations({to: {type: 'I18n'}, from: {type: 'JavaScript'}}).forEach(function (i18nRelation) {
74 | if (existingI18nRelations.indexOf(i18nRelation) === -1) {
75 | (newI18nRelationsByJavaScriptId[i18nRelation.from.id] = newI18nRelationsByJavaScriptId[i18nRelation.from.id] || []).push(i18nRelation);
76 | }
77 | });
78 |
79 | // Hack: Inject the new relations at the top of the file
80 | _.each(newI18nRelationsByJavaScriptId, function (i18nRelations, javaScriptId) {
81 | var javaScript = assetGraph.idIndex[javaScriptId],
82 | originalText = fs.readFileSync(urlTools.fileUrlToFsPath(javaScript.url), javaScript.encoding),
83 | oneIncludeStatements = i18nRelations.map(function (i18nRelation) {
84 | return 'INCLUDE(\'' +
85 | urlTools.buildRelativeUrl(i18nRelation.from.url || assetGraph.findBaseAssetForRelation(i18nRelation).url, i18nRelation.to.url) +
86 | '\');\n';
87 | }).join(''),
88 | matchSplitAfterLastOneIncludeLine = originalText.match(/^([\s\S]*one\.include[^\n]*\n)([\s\S]*)$/),
89 | patchedText;
90 | if (matchSplitAfterLastOneIncludeLine) {
91 | patchedText = matchSplitAfterLastOneIncludeLine[1] + '\n' + oneIncludeStatements + matchSplitAfterLastOneIncludeLine[2];
92 | } else {
93 | patchedText = oneIncludeStatements + originalText;
94 | }
95 | fs.writeFileSync(urlTools.fileUrlToFsPath(javaScript.url), patchedText, javaScript.encoding);
96 | });
97 | })
98 | .prettyPrintAssets({type: 'I18n', isDirty: true})
99 | .writeStatsToStderr()
100 | .writeAssetsToDisc({type: 'I18n', isDirty: true})
101 | .run();
102 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | // JSHint Default Configuration File (as on JSHint website)
3 | // See http://jshint.com/docs/ for more details
4 |
5 | "maxerr" : 50, // {int} Maximum error before stopping
6 |
7 | // Enforcing
8 | "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
9 | "camelcase" : false, // true: Identifiers must be in camelCase
10 | "curly" : true, // true: Require {} for every new block or scope
11 | "eqeqeq" : true, // true: Require triple equals (===) for comparison
12 | "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty()
13 | "immed" : true, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
14 | "indent" : 4, // {int} Number of spaces to use for indentation
15 | "latedef" : true, // true: Require variables/functions to be defined before being used
16 | "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()`
17 | "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
18 | "noempty" : true, // true: Prohibit use of empty blocks
19 | "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
20 | "plusplus" : true, // true: Prohibit use of `++` & `--`
21 | "quotmark" : "single", // Quotation mark consistency:
22 | // false : do nothing (default)
23 | // true : ensure whatever is used is consistent
24 | // "single" : require single quotes
25 | // "double" : require double quotes
26 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
27 | "unused" : "vars", // true: Require all defined variables be used
28 | "strict" : false, // true: Requires all functions run in ES5 Strict Mode
29 | "trailing" : true, // true: Prohibit trailing whitespaces
30 | "maxparams" : false, // {int} Max number of formal params allowed per function
31 | "maxdepth" : false, // {int} Max depth of nested blocks (within functions)
32 | "maxstatements" : false, // {int} Max number statements per function
33 | "maxcomplexity" : false, // {int} Max cyclomatic complexity per function
34 | "maxlen" : false, // {int} Max number of characters per line
35 |
36 | // Relaxing
37 | "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
38 | "boss" : false, // true: Tolerate assignments where comparisons would be expected
39 | "debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
40 | "eqnull" : false, // true: Tolerate use of `== null`
41 | "es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
42 | "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
43 | // (ex: `for each`, multiple try/catch, function expression…)
44 | "evil" : false, // true: Tolerate use of `eval` and `new Function()`
45 | "expr" : false, // true: Tolerate `ExpressionStatement` as Programs
46 | "funcscope" : false, // true: Tolerate defining variables inside control statements"
47 | "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
48 | "iterator" : false, // true: Tolerate using the `__iterator__` property
49 | "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
50 | "laxbreak" : false, // true: Tolerate possibly unsafe line breakings
51 | "laxcomma" : false, // true: Tolerate comma-first style coding
52 | "loopfunc" : true, // true: Tolerate functions being defined in loops
53 | "multistr" : false, // true: Tolerate multi-line strings
54 | "proto" : false, // true: Tolerate using the `__proto__` property
55 | "scripturl" : false, // true: Tolerate script-targeted URLs
56 | "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment
57 | "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
58 | "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
59 | "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
60 | "validthis" : false, // true: Tolerate using this in a non-constructor function
61 |
62 | // Environments
63 | "browser" : false, // Web Browser (window, document, etc)
64 | "couch" : false, // CouchDB
65 | "devel" : true, // Development/debugging (alert, confirm, etc)
66 | "dojo" : false, // Dojo Toolkit
67 | "jquery" : true, // jQuery
68 | "mootools" : false, // MooTools
69 | "node" : true, // Node.js
70 | "nonstandard" : true, // Widely adopted globals (escape, unescape, etc)
71 | "prototypejs" : false, // Prototype and Scriptaculous
72 | "rhino" : false, // Rhino
73 | "worker" : false, // Web Workers
74 | "wsh" : false, // Windows Scripting Host
75 | "yui" : false, // Yahoo User Interface
76 |
77 | // Legacy
78 | "nomen" : false, // true: Prohibit dangling `_` in variables
79 | "onevar" : false, // true: Allow only one `var` statement per function
80 | "passfail" : false, // true: Stop on first error
81 | "white" : true, // true: Check against strict whitespace and indentation rules
82 |
83 | // Custom Globals
84 | "predef" : [ // additional predefined global variables
85 | "TR",
86 | "TRPAT",
87 | "GETTEXT",
88 | "GETSTATICURL",
89 | "INCLUDE",
90 | "define",
91 | "require"
92 | ]
93 | }
94 |
--------------------------------------------------------------------------------
/lib/resolvers/senchaJsBuilder.js:
--------------------------------------------------------------------------------
1 | /*global setImmediate:true*/
2 | // node 0.8 compat
3 | if (typeof setImmediate === 'undefined') {
4 | setImmediate = process.nextTick;
5 | }
6 |
7 | var fs = require('fs'),
8 | urlTools = require('urltools'),
9 | seq = require('seq'),
10 | _ = require('lodash'),
11 | passError = require('passerror');
12 |
13 | module.exports = function (fileUrl) {
14 | var matchJSBUrl = fileUrl.match(/^(.*\/)[^\/]*\.jsb([23])$/);
15 |
16 | if (!matchJSBUrl) {
17 | throw new Error('resolvers.SenchaJsBuilder: Url must end in .jsb2 or .jsb3: ' + fileUrl);
18 | }
19 | var baseUrl = matchJSBUrl[1],
20 | jsbVersion = parseInt(matchJSBUrl[2], 10),
21 | jsbBody = JSON.parse(fs.readFileSync(urlTools.fileUrlToFsPath(fileUrl), 'utf-8')),
22 | pkgIndex = {};
23 |
24 | if (jsbVersion === 2) {
25 | jsbBody.packages = jsbBody.pkgs;
26 | delete jsbBody.pkgs;
27 | }
28 |
29 | jsbBody.builds = jsbBody.builds || [];
30 |
31 | ['packages', 'builds'].forEach(function (sectionName) {
32 | if (sectionName in jsbBody) {
33 | jsbBody[sectionName].forEach(function (pkg) {
34 | if (jsbVersion === 2) {
35 | pkg.packages = pkg.pkgDeps;
36 | delete pkg.pkgDeps;
37 | pkg.target = pkg.file;
38 | delete pkg.file;
39 | pkg.files = pkg.fileIncludes.map(function (fileInclude) {
40 | return {
41 | path: fileInclude.path.replace(/^src\/ext-core/, '../ext-core'), // FIXME
42 | name: fileInclude.text
43 | };
44 | });
45 | delete pkg.fileIncludes;
46 | }
47 | pkgIndex[pkg.name] = pkgIndex[pkg.target] = pkg;
48 | if ('id' in pkg) {
49 | pkgIndex[pkg.id] = pkg;
50 | }
51 | });
52 | }
53 | });
54 |
55 | function fixupAssetConfig(assetConfig, cb) {
56 | if (/\bresources\/.*\.css$/.test(assetConfig.url) && /^Ext JS Library [23].\d.\d/.test(jsbBody.licenseText)) {
57 | // Stupid ExtJS 3 has Css url()s relative to the target paths of their
58 | // bundles, NOT the source files!
59 | // Issue reported here: http://www.extjs.com/forum/showthread.php?p=330222
60 | // Work around it by around by substituting the url()s:
61 |
62 | fs.readFile(urlTools.fileUrlToFsPath(assetConfig.url), 'utf-8', passError(cb, function (src) {
63 | assetConfig.type = 'Css';
64 | assetConfig.text = src.replace(/\/\*[\s\S]*?\*\//g, ' ').replace(/url\s*\(\s*/g, function () {
65 | assetConfig.isDirty = true;
66 | assetConfig.fixedUpExtJS = true;
67 | return 'url(../';
68 | });
69 | assetConfig.isResolved = true;
70 | cb(null, assetConfig);
71 | }));
72 | } else {
73 | setImmediate(function () {
74 | cb(null, assetConfig);
75 | });
76 | }
77 | }
78 |
79 | function resolveExtBase(pkg, fileNames, cb) {
80 | seq(fileNames)
81 | .parMap(function (url) {
82 | fs.readFile(urlTools.fileUrlToFsPath(url), 'utf-8', this);
83 | })
84 | .unflatten()
85 | .seq(function (texts) {
86 | cb(null, {
87 | type: 'JavaScript',
88 | isResolved: true,
89 | isDirty: true,
90 | fixedUpExtJS: true,
91 | text: texts.join('\n'),
92 | outgoingRelations: [], // Save the trouble of parsing it to find zero relations
93 | url: urlTools.resolveUrl(baseUrl, pkg.target)
94 | });
95 | })['catch'](cb);
96 | }
97 |
98 | function resolvePkg(pkg, cb) {
99 | var assetConfigs = [],
100 | fileNames = (pkg.files || []).map(function (fileDef) {
101 | return urlTools.resolveUrl(baseUrl, fileDef.path + fileDef.name);
102 | });
103 |
104 | if (pkg.name === 'Ext Base') {
105 | // Special case for the ext-base.js package, which doesn't work when included as individual files
106 | return resolveExtBase(pkg, fileNames, cb);
107 | }
108 |
109 | seq(pkg.packages || [])
110 | .parMap(function (dependentPkgTargetFileName) {
111 | if (!pkgIndex[dependentPkgTargetFileName] && dependentPkgTargetFileName === 'ext-base.js') {
112 | dependentPkgTargetFileName = 'adapter/ext/ext-base.js'; // pkgDeps bug in ExtJS 3.2
113 | }
114 | resolvePkg(pkgIndex[dependentPkgTargetFileName], this);
115 | })
116 | .seqEach(function (resolvedAssetConfigs) {
117 | if (_.isArray(resolvedAssetConfigs)) {
118 | Array.prototype.push.apply(assetConfigs, resolvedAssetConfigs);
119 | } else {
120 | assetConfigs.push(resolvedAssetConfigs);
121 | }
122 | this();
123 | })
124 | .set(fileNames)
125 | .parMap(function (url) {
126 | var assetConfig = {
127 | url: url
128 | };
129 | if (/\.js$/.test(url)) {
130 | assetConfig.outgoingRelations = [];
131 | }
132 | fixupAssetConfig(assetConfig, this);
133 | })
134 | .unflatten()
135 | .seq(function (fixedUpAssetConfigs) {
136 | cb(null, assetConfigs.concat(fixedUpAssetConfigs));
137 | })['catch'](cb);
138 | }
139 |
140 | return function senchaJsBuilder(assetConfig, fromUrl, cb) {
141 | var labelRelativePath = assetConfig.url.replace(/^[^:]*:/, '');
142 | if (labelRelativePath in pkgIndex) {
143 | resolvePkg(pkgIndex[labelRelativePath], cb);
144 | } else {
145 | fixupAssetConfig({url: urlTools.resolveUrl(baseUrl, labelRelativePath)}, cb);
146 | }
147 | };
148 | };
149 |
--------------------------------------------------------------------------------