diff --git a/scripts/build.js b/scripts/build.js index 07fe74dbf7..09124a3bf1 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -17,14 +17,15 @@ if (require.main === module) { .concat(dirs.map(d => `${d}/**`)) .concat([`!${formatDirsForMatcher(dirs)}/**/*.js`]) .concat([`!${formatDirsForMatcher(dirs)}/**/*.jsx`]) - .concat([`!${formatDirsForMatcher(copyDirs)}/**`]) + .concat([`!${formatDirsForMatcher(dirs)}/**/*.scss`]) + .concat([`!${formatDirsForMatcher(copyDirs)}/**`]); const signatures = await getSignatures(); const results = await Promise.all([ getBrowserify(signatures), getCopy(copyDirs.map(d => `${d}/**`), { ignore: ignoreMask }, signatures), getJS(jsFiles, { ignore: ignoreMask }, signatures), - getSass(scssFiles, { ignore: ignoreMask }, signatures), + ...scssFiles.map(scf => getSass(scf, { ignore: ignoreMask }, signatures)), getSymlinks(symlinks, { nodir: true, ignore: ignoreMask }, signatures), getSymlinks(symlinkDirs, { ignore: ignoreMask }, signatures), cleanUp(signatures) diff --git a/scripts/config.js b/scripts/config.js index 920efaa561..257c29b137 100644 --- a/scripts/config.js +++ b/scripts/config.js @@ -50,7 +50,8 @@ const symlinkFiles = [ 'resource/ace/theme-chrome.js', 'resource/ace/theme-monokai.js', 'resource/ace/worker-javascript.js', - 'update.rdf' + 'update.rdf', + '!chrome/skin/default/zotero/**/*.scss' ]; @@ -89,7 +90,6 @@ const browserifyConfigs = [ // exclude mask used for js, copy, symlink and sass tasks const ignoreMask = [ '**/#*', - '**/_*.scss', 'resource/schema/global/schema.json.gz' ]; diff --git a/scripts/sass.js b/scripts/sass.js index 185e06e307..6e3e457607 100644 --- a/scripts/sass.js +++ b/scripts/sass.js @@ -1,4 +1,4 @@ -'use strict'; +/* eslint-disable no-await-in-loop */ const universalify = require('universalify'); const sass = require('sass'); @@ -6,56 +6,59 @@ const globby = require('globby'); const path = require('path'); const fs = require('fs-extra'); const { getSignatures, writeSignatures, cleanUp, compareSignatures, getFileSignature, onSuccess, onError, onProgress, getPathRelativeTo } = require('./utils'); -const { ignoreMask } = require('./config'); +const { scssFiles, ignoreMask } = require('./config'); const sassRender = universalify.fromCallback(sass.render); const ROOT = path.resolve(__dirname, '..'); async function getSass(source, options, signatures={}) { const t1 = Date.now(); - const files = await globby(source, Object.assign({ cwd: ROOT }, options )); + const files = await globby(source, Object.assign({ cwd: ROOT }, options)); const totalCount = files.length; - var count = 0; - var f; + var count = 0, shouldRebuild = false; - while ((f = files.pop()) != null) { + for (const f of files) { + // if any file changed, rebuild all onSuccess let newFileSignature = await getFileSignature(f); - let destFile = getPathRelativeTo(f, 'scss'); - destFile = path.join(path.dirname(destFile), path.basename(destFile, '.scss') + '.css'); - let dest = path.join.apply(this, ['build', 'chrome', 'skin', 'default', 'zotero', destFile]); - if (['win', 'mac', 'unix'].some(platform => f.endsWith(`-${platform}.scss`))) { - let platform = f.slice(f.lastIndexOf('-')+1, f.lastIndexOf('.')); - destFile = destFile.slice(0, destFile.lastIndexOf('-')) - + destFile.slice(destFile.lastIndexOf('-')+1+platform.length); - dest = path.join.apply(this, ['build', 'chrome', 'content', 'zotero-platform', platform, destFile]); - } - - if (f in signatures) { - if (compareSignatures(newFileSignature, signatures[f])) { - try { - await fs.access(dest, fs.constants.F_OK); - // TODO: Doesn't recompile on partial scss file changes, so temporarily disabled - // continue; - } catch (_) { - // file does not exists in build, fallback to browserifing - } - } - } - try { - const sass = await sassRender({ - file: f, - outFile: dest, - sourceMap: true, - outputStyle: 'compressed' - }); - - await fs.outputFile(dest, sass.css); - await fs.outputFile(`${dest}.map`, sass.map); - onProgress(f, dest, 'sass'); + if (!compareSignatures(newFileSignature, signatures[f])) { signatures[f] = newFileSignature; - count++; - } catch (err) { - throw new Error(`Failed on ${f}: ${err}`); + shouldRebuild = true; + } + } + + var f; + if (shouldRebuild) { + const filesToBuild = files.filter(f => !path.basename(f).startsWith('_')); + while ((f = filesToBuild.pop())) { + let newFileSignature = await getFileSignature(f); + let destFile = getPathRelativeTo(f, 'scss'); + destFile = path.join(path.dirname(destFile), path.basename(destFile, '.scss') + '.css'); + let dest = path.join.apply(this, ['build', 'chrome', 'skin', 'default', 'zotero', destFile]); + + if (['win', 'mac', 'unix'].some(platform => f.endsWith(`-${platform}.scss`))) { + let platform = f.slice(f.lastIndexOf('-') + 1, f.lastIndexOf('.')); + destFile = destFile.slice(0, destFile.lastIndexOf('-')) + + destFile.slice(destFile.lastIndexOf('-') + 1 + platform.length); + dest = path.join.apply(this, ['build', 'chrome', 'content', 'zotero-platform', platform, destFile]); + } + + try { + const sass = await sassRender({ + file: f, + outFile: dest, + sourceMap: true, + outputStyle: 'compressed' + }); + + await fs.outputFile(dest, sass.css); + await fs.outputFile(`${dest}.map`, sass.map); + onProgress(f, dest, 'sass'); + signatures[f] = newFileSignature; + count++; + } + catch (err) { + throw new Error(`Failed on ${f}: ${err}`); + } } } @@ -74,13 +77,16 @@ if (require.main === module) { (async () => { try { const signatures = await getSignatures(); - onSuccess(await getSass('scss/*.scss', { root: 'scss', ignore: ignoreMask }, signatures)); + for (var i = 0; i < scssFiles.length; i++) { + onSuccess(await getSass(scssFiles[i], { ignore: ignoreMask }, signatures)); + } onSuccess(await cleanUp(signatures)); await writeSignatures(signatures); - } catch (err) { + } + catch (err) { process.exitCode = 1; global.isError = true; onError(err); } })(); -} \ No newline at end of file +} diff --git a/scripts/symlinks.js b/scripts/symlinks.js index 5e15748a09..a43301bc1d 100644 --- a/scripts/symlinks.js +++ b/scripts/symlinks.js @@ -70,6 +70,8 @@ if (require.main === module) { const source = symlinkFiles .concat(dirs.map(d => `${d}/**`)) .concat([`!${formatDirsForMatcher(dirs)}/**/*.js`]) + .concat([`!${formatDirsForMatcher(dirs)}/**/*.jsx`]) + .concat([`!${formatDirsForMatcher(dirs)}/**/*.scss`]) .concat([`!${formatDirsForMatcher(copyDirs)}/**`]); const signatures = await getSignatures(); diff --git a/scripts/utils.js b/scripts/utils.js index 682bb55100..969711b1c1 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -17,7 +17,7 @@ function onError(err) { function onSuccess(result) { var msg = `${green('Success:')} ${blue(`[${result.action}]`)} ${result.count} files processed`; if (result.totalCount) { - msg += ` (out of total ${result.totalCount} matched)`; + msg += ` | ${result.totalCount} checked`; } msg += ` [${yellow(`${result.processingTime}ms`)}]`; diff --git a/scripts/watch.js b/scripts/watch.js index b9e215c682..a341de2dda 100644 --- a/scripts/watch.js +++ b/scripts/watch.js @@ -35,6 +35,7 @@ const symlinks = symlinkFiles .concat(dirs.map(d => `${d}/**`)) .concat([`!${formatDirsForMatcher(dirs)}/**/*.js`]) .concat([`!${formatDirsForMatcher(dirs)}/**/*.jsx`]) + .concat([`!${formatDirsForMatcher(dirs)}/**/*.scss`]) .concat([`!${formatDirsForMatcher(copyDirs)}/**`]); var signatures; @@ -48,24 +49,33 @@ function getWatch() { let watcher = chokidar.watch(source, { cwd: ROOT }) .on('change', async (path) => { try { + var matched = false; if (multimatch(path, jsFiles).length && !multimatch(path, ignoreMask).length) { onSuccess(await getJS(path, { ignore: ignoreMask }, signatures)); - } else if (multimatch(path, scssFiles).length) { - if (multimatch(path, '**/_*.scss').length) { - onSuccess(await getSass(scssFiles, { ignore: ignoreMask })); - } else { - onSuccess(await getSass(path, {}, signatures)); - } - } else if (multimatch(path, copyDirs.map(d => `${d}/**`)).length) { - onSuccess(await getCopy(path, {}, signatures)); - } else if (multimatch(path, symlinks).length) { - onSuccess(await getSymlinks(path, { nodir: true }, signatures)); + onSuccess(await cleanUp(signatures)); + return; } - onSuccess(await cleanUp(signatures)); - } catch (err) { + for (var i = 0; i < scssFiles.length; i++) { + if (multimatch(path, scssFiles[i])) { + onSuccess(await getSass(scssFiles[i], { ignore: ignoreMask })); + onSuccess(await cleanUp(signatures)); + return; + } + } + if (multimatch(path, copyDirs.map(d => `${d}/**`)).length) { + onSuccess(await getCopy(path, {}, signatures)); + onSuccess(await cleanUp(signatures)); + return; + } + if (multimatch(path, symlinks).length) { + onSuccess(await getSymlinks(path, { nodir: true }, signatures)); + onSuccess(await cleanUp(signatures)); + return; + } + } + catch (err) { onError(err); } - }) .on('unlink', async () => { const signatures = await getSignatures();