-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
becfd81
commit 6ab52e8
Showing
12 changed files
with
412 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
const Asset = require('../Asset'); | ||
const commandExists = require('command-exists'); | ||
const localRequire = require('../utils/localRequire'); | ||
const {minify} = require('terser'); | ||
const path = require('path'); | ||
const spawn = require('cross-spawn'); | ||
|
||
class ElmAsset extends Asset { | ||
constructor(name, options) { | ||
super(name, options); | ||
this.type = 'js'; | ||
this.hmrPageReload = true; | ||
} | ||
|
||
async parse() { | ||
let options = { | ||
cwd: path.dirname(this.name) | ||
}; | ||
|
||
// If elm is not installed globally, install it locally. | ||
try { | ||
await commandExists('elm'); | ||
} catch (err) { | ||
await localRequire('elm', this.name); | ||
options.pathToElm = path.join( | ||
path.dirname(require.resolve('elm')), | ||
'bin', | ||
'elm' | ||
); | ||
} | ||
|
||
this.elm = await localRequire('node-elm-compiler', this.name); | ||
|
||
// Ensure that an elm.json file exists, and initialize one if not. | ||
let elmConfig = await this.getConfig(['elm.json'], {load: false}); | ||
if (!elmConfig) { | ||
await this.createElmConfig(options); | ||
|
||
// Ensure we are watching elm.json for changes | ||
await this.getConfig(['elm.json'], {load: false}); | ||
} | ||
|
||
if (this.options.minify) { | ||
options.optimize = true; | ||
} | ||
|
||
let compiled = await this.elm.compileToString(this.name, options); | ||
this.contents = compiled.toString(); | ||
} | ||
|
||
async collectDependencies() { | ||
let dependencies = await this.elm.findAllDependencies(this.name); | ||
for (let dependency of dependencies) { | ||
this.addDependency(dependency, {includedInParent: true}); | ||
} | ||
} | ||
|
||
async createElmConfig(options) { | ||
let cp = spawn(options.pathToElm || 'elm', ['init']); | ||
cp.stdin.write('y\n'); | ||
|
||
return new Promise((resolve, reject) => { | ||
cp.on('error', reject); | ||
cp.on('close', function(code) { | ||
if (code !== 0) { | ||
return reject(new Error('elm init failed.')); | ||
} | ||
|
||
return resolve(); | ||
}); | ||
}); | ||
} | ||
|
||
async generate() { | ||
let output = this.contents; | ||
|
||
if (this.options.minify) { | ||
output = pack(output); | ||
} | ||
|
||
return { | ||
[this.type]: output | ||
}; | ||
|
||
// Recommended minification | ||
// Based on: | ||
// - http://elm-lang.org/0.19.0/optimize | ||
function pack(source) { | ||
let options = { | ||
compress: { | ||
keep_fargs: false, | ||
passes: 2, | ||
pure_funcs: [ | ||
'F2', | ||
'F3', | ||
'F4', | ||
'F5', | ||
'F6', | ||
'F7', | ||
'F8', | ||
'F9', | ||
'A2', | ||
'A3', | ||
'A4', | ||
'A5', | ||
'A6', | ||
'A7', | ||
'A8', | ||
'A9' | ||
], | ||
pure_getters: true, | ||
unsafe: true, | ||
unsafe_comps: true | ||
}, | ||
mangle: true, | ||
rename: false | ||
}; | ||
|
||
let result = minify(source, options); | ||
|
||
if (result.error) { | ||
throw result.error; | ||
} | ||
|
||
return result.code; | ||
} | ||
} | ||
} | ||
|
||
module.exports = ElmAsset; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
const assert = require('assert'); | ||
const fs = require('../src/utils/fs'); | ||
const {bundle, assertBundleTree, run} = require('./utils'); | ||
|
||
describe('elm', function() { | ||
it('should produce a basic Elm bundle', async function() { | ||
let b = await bundle(__dirname + '/integration/elm/index.js'); | ||
|
||
await assertBundleTree(b, { | ||
type: 'js', | ||
assets: ['Main.elm', 'index.js'] | ||
}); | ||
|
||
let output = await run(b); | ||
assert.equal(typeof output().Elm.Main.init, 'function'); | ||
}); | ||
|
||
it('should minify Elm in production mode', async function() { | ||
let b = await bundle(__dirname + '/integration/elm/index.js', { | ||
production: true | ||
}); | ||
|
||
let output = await run(b); | ||
assert.equal(typeof output().Elm.Main.init, 'function'); | ||
|
||
let js = await fs.readFile(__dirname + '/dist/index.js', 'utf8'); | ||
assert(!js.includes('elm$core')); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"type": "application", | ||
"source-directories": [ | ||
"src" | ||
], | ||
"elm-version": "0.19.0", | ||
"dependencies": { | ||
"direct": { | ||
"elm/browser": "1.0.0", | ||
"elm/core": "1.0.0", | ||
"elm/html": "1.0.0" | ||
}, | ||
"indirect": { | ||
"elm/json": "1.0.0", | ||
"elm/time": "1.0.0", | ||
"elm/url": "1.0.0", | ||
"elm/virtual-dom": "1.0.0" | ||
} | ||
}, | ||
"test-dependencies": { | ||
"direct": {}, | ||
"indirect": {} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
var local = require('./src/Main.elm'); | ||
|
||
module.exports = function () { | ||
return local; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
module Main exposing (main) | ||
|
||
import Browser | ||
import Html exposing (Html, button, div, text) | ||
import Html.Events exposing (onClick) | ||
|
||
|
||
type alias Model = | ||
{ count : Int } | ||
|
||
|
||
initialModel : Model | ||
initialModel = | ||
{ count = 0 } | ||
|
||
|
||
type Msg | ||
= Increment | ||
| Decrement | ||
|
||
|
||
update : Msg -> Model -> Model | ||
update msg model = | ||
case msg of | ||
Increment -> | ||
{ model | count = model.count + 1 } | ||
|
||
Decrement -> | ||
{ model | count = model.count - 1 } | ||
|
||
|
||
view : Model -> Html Msg | ||
view model = | ||
div [] | ||
[ button [ onClick Increment ] [ text "+1" ] | ||
, div [] [ text <| String.fromInt model.count ] | ||
, button [ onClick Decrement ] [ text "-1" ] | ||
] | ||
|
||
|
||
main : Program () Model Msg | ||
main = | ||
Browser.sandbox | ||
{ init = initialModel | ||
, view = view | ||
, update = update | ||
} |
Oops, something went wrong.