neft
Version:
JavaScript. Everywhere.
164 lines (130 loc) • 5.67 kB
text/coffeescript
'use strict'
fs = require 'fs-extra'
pathUtils = require 'path'
coffee = require 'coffee-script'
createBundle = require './styles/bundle'
{utils, log, Document} = Neft
cliUtils = require '../../../utils'
IN_DIR = './styles'
OUT_DIR = './build/styles'
QUERIES = './build/styles/queries.json'
getQueryPriority = (val) ->
Document.Element.Tag.query.getSelectorCommandsLength val
queriesSortFunc = (a, b) ->
a.dirPriority - b.dirPriority or getQueryPriority(b.query) - getQueryPriority(a.query)
module.exports = (platform, app, callback) ->
fs.ensureDir OUT_DIR
filesToLoad = 0
files = []
filesByFilename = {}
inputDirPriorities = {}
inputDirs = [path: IN_DIR, prefix: '']
packageConfig = JSON.parse fs.readFileSync('./package.json', 'utf-8')
for key of packageConfig.dependencies
stylesPath = "node_modules/#{key}/styles"
if /^neft\-/.test(key) and fs.existsSync(stylesPath)
inputDirs.push path: stylesPath, prefix: "#{key}/"
if utils.isObject(packageConfig.styles)
for key, val of packageConfig.styles
inputDirs.push path: val, prefix: "#{key}/"
for dir, i in inputDirs then do (dir) ->
if dir.prefix
inputDirPriorities[dir.prefix] = i
filesToLoad++
cliUtils.forEachFileDeep dir.path, (path, stat) ->
unless pathUtils.extname(path) in ['.js', '.nml']
return
filesToLoad++
filename = dir.prefix + path.slice(dir.path.length+1)
filename = filename.slice 0, filename.lastIndexOf('.')
destPath = "#{OUT_DIR}/#{filename}.js"
fs.stat destPath, (destErr, destStat) ->
if destErr or (new Date(stat.mtime)).valueOf() > (new Date(destStat.mtime)).valueOf()
fs.readFile path, 'utf-8', (err, data) ->
if err
return callback err
files.push file =
dir: dir
filename: filename
path: path
destPath: destPath
data: data
filesByFilename[filename] = file
if files.length is filesToLoad
onFilesReady()
else
files.push file =
filename: filename
path: path
destPath: destPath
filesByFilename[filename] = file
if files.length is filesToLoad
onFilesReady()
, ->
filesToLoad--
if files.length is filesToLoad
onFilesReady()
writeFile = (path, data, callback) ->
data = coffee.compile data
fs.outputFile path, data, callback
onFilesReady = ->
newQueries = {}
stack = new utils.async.Stack
for file in files
if file.data?
compileLogtime = log.time "Compile '#{file.path}'"
try
createBundle file
catch err
console.error "\u001b[1mError in `#{file.path}`\u001b[22m\n\n#{err.message or err}"
log.end compileLogtime
continue
log.end compileLogtime
newQueries[file.filename] = file.queries
stack.add writeFile, null, [file.destPath, file.data]
app.styles.push
name: ///^\./build/styles/(.+)\.[a-z]+$///.exec(file.destPath)[1]
path: file.destPath
writeLogtime = log.time 'Save styles'
stack.runAllSimultaneously ->
log.end writeLogtime
currentQueries = null
mergeQueries = ->
utils.merge currentQueries, newQueries
for filename, fileQueries of currentQueries
unless cliUtils.isPlatformFilePath(platform, "#{filename}.js")
continue
dirPriority = do ->
for dir, dirPriority of inputDirPriorities
if filename.indexOf(dir) is 0
return dirPriority
return 0
for query, val of fileQueries
val = "styles:#{filename}:#{val}"
splitQuery = query.split ','
for query in splitQuery
app.styleQueries.push
query: query
style: val
dirPriority: dirPriority
app.styleQueries.sort queriesSortFunc
queriesJson = JSON.stringify currentQueries, null, 4
fs.writeFile QUERIES, queriesJson, callback
fs.exists QUERIES, (exists) ->
if exists
fs.readFile QUERIES, (err, json) ->
if err?
return callback err
currentQueries = JSON.parse json
for filename of currentQueries
unless filesByFilename[filename]
delete currentQueries[filename]
mergeQueries()
else
currentQueries = {}
mergeQueries()
return
return