neft
Version:
Universal Platform
182 lines (144 loc) • 5.99 kB
text/coffeescript
'use strict'
moduleCache = require 'lib/module-cache'
moduleCache.registerTxt(['.pegjs'])
fs = require 'fs-extra'
pathUtils = require 'path'
coffee = require 'coffee-script'
utils = require 'src/utils'
log = require 'src/log'
Document = require 'src/document'
nmlParser = require 'src/nml-parser'
createBundle = nmlParser.bundle
cliUtils = require 'cli/utils'
IN_DIR = './styles'
OUT_DIR = 'build/styles'
QUERIES = './build/styles/queries.json'
DEFAULT_STYLES = pathUtils.join __dirname, '/styles/default'
getQueryPriority = (val) ->
Document.Element.Tag.query.getSelectorCommandsLength val
queriesSortFunc = (a, b) ->
b.dirPriority - a.dirPriority or
getQueryPriority(a.query) - getQueryPriority(b.query)
writeFile = (path, data, callback) ->
data = coffee.compile data, bare: true
fs.outputFile path, data, callback
getInputDirs = (app) ->
inputDirs = []
for ext in app.allExtensions
path = pathUtils.join ext.path, '/styles'
if fs.existsSync(path)
inputDirs.unshift path: path, prefix: "#{ext.name}/"
inputDirs.push {path: IN_DIR, prefix: ''}
unless fs.existsSync(pathUtils.join(IN_DIR, '/__view__.js'))
inputDirs.push {path: DEFAULT_STYLES, prefix: ''}
inputDirs
module.exports = (platform, app, callback) ->
fs.ensureDir OUT_DIR
inputDirs = getInputDirs app
filesToLoad = 0
files = []
filesByFilename = {}
filesByDestPaths = {}
inputDirPriorities = {}
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()
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 (err) ->
log.end writeLogtime
if err
return callback err
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