Skip to content
Permalink
Browse files

feat(spa auto inject): the build will automatically inject scripts an…

…d styles into your spa.html

It will also inject clickjacking, moduleName and ngCloakStyles. See rapid-build.io build options page under spa.autoInject for more info. This feature can be turned off by providing option spa.autoInject false. Also if you are using the build placeholders, they will function the same. Lastly, there is a new spa placeholder available, ngCloakStyles (if you are using build placeholders in your spa.html).

BREAKING CHANGE:
The build will now automatically inject scripts and styles into your spa.html unless you are using build placeholders in your spa.html. You can disable this feature.
  • Loading branch information
jyounce committed Jun 3, 2016
1 parent e941118 commit 2b5a5563a72bcff87189dd663149b4904271dea3
@@ -2,7 +2,7 @@
**Requirements**: [npm](http://npmjs.org/) and [Node.js](http://nodejs.org/) version >= 4.0.0

Releases are documented here [changelog](https://github.com/jyounce/rapid-build/blob/master/CHANGELOG.md).
More and better documentation *coming real soon*!
Documentation: [http://rapid-build.io/](http://rapid-build.io/)

## Installation
If installing globally you may need to set your [NODE_PATH](https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders).
@@ -159,11 +159,12 @@ package.json
# angular.templateCache.urlPrefix = (string) prefix for template urls
# angular.templateCache.useAbsolutePaths = (boolean) defaults to false = prefix template urls with a '/'
# angular.ngFormify = (boolean) defaults to false = set to true to replace all html form tags with ng:form in client dist, useful if your application is going to be wrapped in a global form
# spa.autoInject = (array of strings) defaults to ['all'] = the build will automatically inject the following into your spa.html: ['clickjacking', 'moduleName', 'ngCloakStyles', 'scripts', 'styles'], set to false to disable or provide options you want injected
# spa.title = (string) defaults to package.json name or 'Application' = html title tag value
# spa.description = (string) defaults to package.json description = html meta description tag value
# spa.src.filePath = (string) set if you want to use your own spa file and not the build system's (file must be located in your client src directory)
# spa.dist.fileName = (string) defaults to file name of spa.src.filePath or 'spa.html' = provide if you want the dist spa file to be named differently, example: 'index.html'
# spa.placeholders = (array of strings) = set to retain spa file placeholders, optional values are: ['clickjacking', 'description', 'moduleName', 'scripts', 'styles', 'title'] or ['all']
# spa.placeholders = (array of strings) = set to retain spa file placeholders, optional values are: ['clickjacking', 'description', 'moduleName', 'ngCloakStyles', 'scripts', 'styles', 'title'] or ['all']
# minify.css.styles = (boolean) defaults to true = for prod build, minify the css
# minify.css.fileName = (string) defaults to 'styles.min.css'
# minify.css.splitMinFile = (boolean) defaults to true = for prod build, task for ie9 and below, split styles.min.css into multiple files if selector count > 4,095
@@ -194,7 +195,7 @@ package.json
# extra.compile.server[less|sass] = (array of strings) = file paths: additional files to compile to dist/server that the build didn't compile
# extra.minify.client[css|js] = (array of strings) = file paths: additional files to minify in dist/client that the build didn't minify (by default, the build does not minify files in libs or bower_components)
# security.client.clickjacking = (boolean) defaults to true = includes a clickjacking defense script in the default spa.html (set to false to disable)
# =====================================================================================================================================================================================================================================
# ======================================================================================================================================================================================================================================================================================================
```

## Build Modes
@@ -640,7 +640,7 @@ angular.module('rapid-build').constant 'BUILD_OPTS',
description: [
"The build will include a
<a target=\"_blank\" href=\"https://www.owasp.org/index.php/Clickjacking\">clickjacking</a>
defense script in the default spa.html (set to false to disable)."
defense script in the your spa.html (set to false to disable)."
]
]
example: """
@@ -671,6 +671,35 @@ angular.module('rapid-build').constant 'BUILD_OPTS',

spa:
opts: [
name: 'autoInject'
info: "@type array of strings, @default ['all']"
description: [
"The build will automatically
inject the following into your spa.html:
<ul>
<li>
<a href=\"#security.client.clickjacking\" rb-scroll>clickjacking</a>
</li>
<li>
<a href=\"#angular.moduleName\" rb-scroll>moduleName</a>
<em class=\"sub sep parens\">ng-app attribute</em>
</li>
<li>
<a target=\"_blank\" href=\"https://docs.angularjs.org/api/ng/directive/ngCloak\">ngCloakStyles</a>
</li>
<li>
scripts <em class=\"sub sep parens\">all your js files</em>
</li>
<li>
styles <em class=\"sub sep parens\">all your css files</em>
</li>
</ul>
"
"Or provide to the array the options you want."
"<rb:icon kind=\"fa-exclamation-circle\"></rb:icon>
Disable auto injection by setting to false <em class=\"sub parens\">boolean</em>."
]
,
name: 'description'
info: "@type string, @default package.json description"
description: [
@@ -687,7 +716,8 @@ angular.module('rapid-build').constant 'BUILD_OPTS',
all or
</li>
<li>
clickjacking, description, moduleName, scripts, styles and title
clickjacking, description, moduleName,
ngCloakStyles, scripts, styles and title
</li>
</ul>"
]
@@ -719,6 +749,7 @@ angular.module('rapid-build').constant 'BUILD_OPTS',
example: """
var opts = {
spa: {
autoInject: false,
description: 'Documentation website for rapid-build.',
placeholders: ['all'],
title: 'Rapid Build',
@@ -13,8 +13,8 @@
<!--#include clickjacking-->

<!--#include styles-->
<!-- When you load angular at the bottom, you need to create the "ng-cloak" rules yourself -->
<style>[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\:form{display:block;}</style>

<!--#include ngCloakStyles-->
</head>
<body ng-cloak class="ng-cloak" ng-include="'/views/layout/main-layout.html'">

@@ -43,7 +43,7 @@
color: lightslategrey;
ul {
list-style: none;
margin: 3px 0 -5px;
margin: 3px 0 5px;
> li {
position: relative;
&::before {
@@ -40,7 +40,7 @@ module.exports = (config, options) ->
angular: getAngularFiles()

# init order
# =========
# ==========
order =
rb:
scripts: first: [], last: []
@@ -18,19 +18,24 @@ module.exports = (config, options) ->

# defaults
# ========
customSrcPath = options.spa.src.filePath
isCustom = !!customSrcPath
srcFilePath = getSrcFilePath isCustom, customSrcPath
srcFile = path.basename srcFilePath
srcDir = path.dirname srcFilePath
distFile = options.spa.dist.fileName or srcFile
distFilePath = path.join config.dist.app.client.dir, distFile
customSrcPath = options.spa.src.filePath
isCustom = !!customSrcPath
srcFilePath = getSrcFilePath isCustom, customSrcPath
srcFile = path.basename srcFilePath
srcDir = path.dirname srcFilePath
distFile = options.spa.dist.fileName or srcFile
distFilePath = path.join config.dist.app.client.dir, distFile
distFileAbsPath = path.join config.app.dir, distFilePath

# init spa
# ========
spa = {}
spa.custom = isCustom

# autoInject
# ==========
spa.autoInject = if options.spa.autoInject is null then ['all'] else options.spa.autoInject

# placeholders
# ============
spa.title = options.spa.title or config.app.name or 'Application'
@@ -39,8 +44,9 @@ module.exports = (config, options) ->
# dist
# ====
spa.dist =
file: distFile
path: distFilePath
file: distFile
path: distFilePath
absPath: distFileAbsPath

# src
# ===
@@ -31,7 +31,8 @@ module.exports = (config) ->
config.src.rb.client.scripts.dir
)

templates.clickjacking = getInfo 'clickjacking.tpl'
templates.clickjacking = getInfo 'clickjacking.tpl'
templates.ngCloakStyles = getInfo 'ng-cloak-styles.tpl'

# add templates to config
# =======================
@@ -5,6 +5,7 @@ module.exports = (config, options) ->
# ================
spa = options.spa
spa = {} unless isType.object spa
spa.autoInject = null if not isType.array(spa.autoInject) and spa.autoInject isnt false
spa.title = null unless isType.string spa.title
spa.description = null unless isType.string spa.description
spa.src = {} unless isType.object spa.src
@@ -17,8 +17,11 @@ module.exports = (gulp, config) ->
taskHelp.addTask 'build-files', '/build/build-files', deps: ['clean-files']
taskHelp.addTask 'build-prod-files', '/build/build-prod-files'
taskHelp.addTask 'build-prod-files-blueprint', '/build/build-prod-files-blueprint'
taskHelp.addTask 'build-spa', '/build/build-spa'
taskHelp.addTask 'build-spa:prod', '/build/build-spa', env: 'prod'
taskHelp.addTask 'build-spa', '/build/build-spa', taskCB: true
taskHelp.addTask 'build-spa:prod', '/build/build-spa', taskCB: true, env: 'prod'
taskHelp.addTask 'build-spa-file', '/build/build-spa-file'
taskHelp.addTask 'build-spa-file:prod', '/build/build-spa-file', env: 'prod'
taskHelp.addTask 'build-spa-placeholders', '/build/build-spa-placeholders'

# clean
# =====
@@ -62,6 +65,7 @@ module.exports = (gulp, config) ->
taskHelp.addTask 'copy-server-config', '/copy/copy-server-config'
taskHelp.addTask 'copy-server-info', '/copy/copy-server-info'
taskHelp.addTask 'copy-server-node_modules', '/copy/copy-server-node_modules'
taskHelp.addTask 'copy-spa', '/copy/copy-spa'
taskHelp.addTask 'copy-views', '/copy/copy-views', taskCB: true

# extra
@@ -9,8 +9,7 @@
<!--#include clickjacking-->

<!--#include styles-->
<!-- When you load angular at the bottom, you need to create the "ng-cloak" rules yourself -->
<style>[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak{display:none;}ng\:form{display:block;}</style>
<!--#include ngCloakStyles-->
</head>
<body ng-cloak class="ng-cloak">
<div ng-view></div>
@@ -0,0 +1,96 @@
module.exports = (config, gulp, taskOpts={}) ->
q = require 'q'
fs = require 'fs'
path = require 'path'
gulpif = require 'gulp-if'
replace = require 'gulp-replace'
template = require 'gulp-template'
pathHelp = require "#{config.req.helpers}/path"
moduleHelp = require "#{config.req.helpers}/module"
format = require("#{config.req.helpers}/format")()

# helpers
# =======
runReplace = (type) ->
newKey = "<%= #{type} %>"
key = "<!--#include #{type}-->"
placeholders = config.spa.placeholders
replacePH = true # PH = placeholder
if placeholders.indexOf('all') isnt -1
replacePH = false
else if placeholders.indexOf(type) isnt -1
replacePH = false
gulpif replacePH, replace key, newKey

# task
# ====
buildTask = (src, dest, file, data={}) ->
defer = q.defer()
gulp.src src
.pipe runReplace 'clickjacking'
.pipe runReplace 'description'
.pipe runReplace 'moduleName'
.pipe runReplace 'ngCloakStyles'
.pipe runReplace 'scripts'
.pipe runReplace 'styles'
.pipe runReplace 'title'
.pipe template data
.pipe gulp.dest dest
.on 'end', ->
# console.log "built #{file}".yellow
defer.resolve()
defer.promise

# helpers
# =======
getFilesJson = (jsonEnvFile) ->
jsonEnvFile = path.join config.generated.pkg.files.path, jsonEnvFile
moduleHelp.cache.delete jsonEnvFile
files = require(jsonEnvFile).client
files = pathHelp.removeLocPartial files, config.dist.app.client.dir
files.styles = format.paths.to.html files.styles, 'styles', join: true, lineEnding: '\n\t'
files.scripts = format.paths.to.html files.scripts, 'scripts', join: true, lineEnding: '\n\t'
files

getClickjackingTpl = ->
return '' unless config.security.client.clickjacking
fs.readFileSync(config.templates.clickjacking.src.path).toString()

getNgCloakStylesTpl = ->
fs.readFileSync(config.templates.ngCloakStyles.src.path).toString()

getData = (jsonEnvFile) ->
files = getFilesJson jsonEnvFile
data =
clickjacking: getClickjackingTpl()
description: config.spa.description
moduleName: config.angular.moduleName
ngCloakStyles: getNgCloakStylesTpl()
scripts: files.scripts
styles: files.styles
title: config.spa.title

# API
# ===
api =
runTask: (env) -> # synchronously
defer = q.defer()
json = if env is 'prod' then 'prod-files.json' else 'files.json'
data = getData json
tasks = [
-> buildTask(
config.spa.dist.absPath
config.dist.app.client.dir
config.spa.dist.file
data
)
]
tasks.reduce(q.when, q()).done -> defer.resolve()
defer.promise

# return
# ======
api.runTask taskOpts.env



0 comments on commit 2b5a556

Please sign in to comment.
You can’t perform that action at this time.