X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=src%2Findex.js;h=f4a6dff29ba15171fb08eae6219739518f98fda4;hb=3a4eb6d4238f63ef526a6343de220ceb97671511;hp=7c296508a4e8b81cdb683d6351fd78b849f86984;hpb=45c62a2c766132a13c546b19025e9c1ef25bcd5b;p=github%2Ffretlink%2Fpurs-loader.git diff --git a/src/index.js b/src/index.js index 7c29650..f4a6dff 100644 --- a/src/index.js +++ b/src/index.js @@ -3,15 +3,14 @@ const debug = require('debug')('purs-loader') const loaderUtils = require('loader-utils') const Promise = require('bluebird') -const fs = Promise.promisifyAll(require('fs')) const path = require('path') -const jsStringEscape = require('js-string-escape') const PsModuleMap = require('./PsModuleMap'); const Psc = require('./Psc'); const PscIde = require('./PscIde'); +const toJavaScript = require('./to-javascript'); const dargs = require('./dargs'); - -const requireRegex = /require\(['"]\.\.\/([\w\.]+)['"]\)/g +const spawn = require('cross-spawn').sync +const eol = require('os').EOL module.exports = function purescriptLoader(source, map) { const callback = this.async() @@ -19,34 +18,58 @@ module.exports = function purescriptLoader(source, map) { const query = loaderUtils.parseQuery(this.query) const webpackOptions = this.options.purescriptLoader || {} - const options = Object.assign({ + const depsPaths = (pscPackage => { + if (pscPackage) { + debug('calling psc-package...') + + return spawn('psc-package', ['sources']).stdout.toString().split(eol).filter(v => v != '') + } + else { + return [ path.join('bower_components', 'purescript-*', 'src', '**', '*.purs') ] + } + }) + + let options = Object.assign(webpackOptions, query) + + const defaultDeps = depsPaths(options.pscPackage) + const defaultOptions = { context: config.context, psc: 'psc', pscArgs: {}, pscBundle: 'psc-bundle', pscBundleArgs: {}, pscIde: false, - pscIdeColors: webpackOptions.psc === 'psa' || query.psc === 'psa', + pscIdeColors: options.psc === 'psa', pscIdeArgs: {}, + pscPackage: false, bundleOutput: 'output/bundle.js', bundleNamespace: 'PS', bundle: false, warnings: true, + watch: false, output: 'output', src: [ path.join('src', '**', '*.purs'), - path.join('bower_components', 'purescript-*', 'src', '**', '*.purs') + ...defaultDeps ] - }, webpackOptions, query) + } this.cacheable && this.cacheable() let cache = config.purescriptLoaderCache = config.purescriptLoaderCache || { rebuild: false, deferred: [], - bundleModules: [] + bundleModules: [], + warnings: [], + errors: [] } + if (options.pscPackage && options.src) { + options.src = options.src.concat(defaultDeps) // append psc-package-provided source paths with users' + } + + options = Object.assign(defaultOptions, options) + if (!config.purescriptLoaderInstalled) { config.purescriptLoaderInstalled = true @@ -59,9 +82,24 @@ module.exports = function purescriptLoader(source, map) { deferred: [], bundleModules: [], ideServer: cache.ideServer, - psModuleMap: cache.psModuleMap + psModuleMap: cache.psModuleMap, + warnings: [], + errors: [] } - }) + }); + + // add psc warnings to webpack compilation warnings + this._compiler.plugin('after-compile', (compilation, callback) => { + cache.warnings.forEach(warning => { + compilation.warnings.push(warning); + }); + + cache.errors.forEach(error => { + compilation.errors.push(error); + }); + + callback() + }); } const psModuleName = PsModuleMap.match(source) @@ -74,8 +112,16 @@ module.exports = function purescriptLoader(source, map) { jsPath: path.resolve(path.join(options.output, psModuleName, 'index.js')), options: options, cache: cache, - emitWarning: warning => this.emitWarning(warning), - emitError: error => this.emitError(error) + emitWarning: warning => { + if (options.warnings && warning.length) { + cache.warnings.push(warning); + } + }, + emitError: error => { + if (error.length) { + cache.errors.push(error); + } + } } debug('loader called', psModule.name) @@ -116,59 +162,3 @@ module.exports = function purescriptLoader(source, map) { }) } } - -function updatePsModuleMap(psModule) { - const options = psModule.options - const cache = psModule.cache - const filePurs = psModule.srcPath - if (!cache.psModuleMap) { - debug('module mapping does not exist'); - return PsModuleMap.makeMap(options.src).then(map => { - cache.psModuleMap = map; - return cache.psModuleMap; - }); - } - else { - return PsModuleMap.makeMapEntry(filePurs).then(result => { - const map = Object.assign(cache.psModuleMap, result) - cache.psModuleMap = map; - return cache.psModuleMap; - }); - } -} - -// The actual loader is executed *after* purescript compilation. -function toJavaScript(psModule) { - const options = psModule.options - const cache = psModule.cache - const bundlePath = path.resolve(options.bundleOutput) - const jsPath = cache.bundle ? bundlePath : psModule.jsPath - - debug('loading JavaScript for', psModule.name) - - return Promise.props({ - js: fs.readFileAsync(jsPath, 'utf8'), - psModuleMap: updatePsModuleMap(psModule) - }).then(result => { - let js = '' - - if (options.bundle) { - // if bundling, return a reference to the bundle - js = 'module.exports = require("' - + jsStringEscape(path.relative(psModule.srcDir, options.bundleOutput)) - + '")["' + psModule.name + '"]' - } else { - // replace require paths to output files generated by psc with paths - // to purescript sources, which are then also run through this loader. - js = result.js - .replace(requireRegex, (m, p1) => { - return 'require("' + jsStringEscape(result.psModuleMap[p1].src) + '")' - }) - .replace(/require\(['"]\.\/foreign['"]\)/g, (m, p1) => { - return 'require("' + jsStringEscape(result.psModuleMap[psModule.name].ffi) + '")' - }) - } - - return js - }) -}