diff --git a/README.md b/README.md
index 304ee41f..104409a0 100644
--- a/README.md
+++ b/README.md
@@ -49,17 +49,20 @@ mkdir myApp
cd myApp
```
-Then run the generator. If you installed from source or GitHub,
+Then run the generator:
+- If you installed from a fork or from GitHub.
-```bash
-yo exist
-```
+ ```bash
+ yo exist
+ ```
-or if you installed from npm:
+- If you installed from npm or from a clone of this repo.
-```bash
-yo @existdb/exist
-```
+ ```bash
+ yo @existdb/exist
+ ```
+
+If you are unsure about which command is right simply run `yo` to see the list of currently installed generators.
[![asciicast](https://asciinema.org/a/MqB6TyzdyBJImItHLsfC99Ufj.png)](https://asciinema.org/a/MqB6TyzdyBJImItHLsfC99Ufj)
@@ -264,7 +267,6 @@ Since if would be impractical to go through all possible combinations of option
│ ├── lib_demo-1.0.0-dev.xar
│ └── lib_demo-1.0.0.xar
├── build.xml
-├── collection.xconf
├── expath-pkg.xml
├── node_modules
│ └── pruned …
diff --git a/generators/app/index.js b/generators/app/index.js
index 5ba9711d..f223b85b 100644
--- a/generators/app/index.js
+++ b/generators/app/index.js
@@ -4,11 +4,7 @@ const chalk = require('chalk')
const yosay = require('yosay')
const prettyData = require('gulp-pretty-data')
const stripBom = require('gulp-stripbom')
-const pjson = require('../../package.json')
-// Var isodate = (new Date()).toISOString();
-
-// Potential location for teipub defaults. see https://github.com/enquirer/enquirer/issues/15
module.exports = class extends Generator {
initializing () {
this.props = {}
@@ -77,14 +73,6 @@ module.exports = class extends Generator {
value: ['empty', 'library']
}]
},
- // TODO: [yo] Make these options meaningful
- // {
- // type: 'checkbox',
- // choices: ['ant', 'gulp', 'maven', 'gradle'],
- // name: 'builder',
- // message: 'How would you like to build your app?',
- // default: 'ant'
- // },
{
when: response => {
return response.apptype[1] === 'application'
@@ -132,7 +120,14 @@ module.exports = class extends Generator {
message: 'Pick the release status',
default: 'SNAPSHOT'
},
- // TODO: [teipup] autoanswer pre,post, setperm, (license?) see#
+ {
+ type: 'list',
+ choices: ['ant', 'gulp', 'hybrid'],
+ name: 'builder',
+ message: 'How would you like to build your app?',
+ default: 'ant',
+ store: true
+ },
{
type: 'confirm',
name: 'pre',
@@ -270,7 +265,7 @@ module.exports = class extends Generator {
type: 'list',
choices: ['travis', 'GitHub Action'],
name: 'ci',
- message: 'Whats your CI service',
+ message: 'Pick a CI service provider',
default: 'GitHub Action',
store: true
},
@@ -329,9 +324,6 @@ module.exports = class extends Generator {
store: true
}]
- // TODO: [yo]: js, css, gulp, funcdoc,
- // TODO: [gulp] https://github.com/bnjjj/generator-gulpfile-advanced
-
return this.prompt(prompts).then(props => {
// To access props later use this.props.someAnswer;
this.props = props
@@ -354,7 +346,7 @@ module.exports = class extends Generator {
// try to clean invalid xml from streams
this.registerTransformStream(
stripBom({
- ext: ['xml', 'odd', 'xconf'],
+ ext: ['xml', 'odd', 'xconf', 'xhtml'],
showLog: false
}))
// minify xml first …
@@ -382,15 +374,6 @@ module.exports = class extends Generator {
homepage: '',
bugs: '',
keywords: ['exist', 'exist-db', 'xml', 'xql', 'xquery'],
- devDependencies: {
- chai: pjson.devDependencies.chai,
- 'chai-xml': pjson.devDependencies['chai-xml'],
- 'fs-extra': pjson.devDependencies['fs-extra'],
- mocha: pjson.devDependencies.mocha,
- supertest: pjson.devDependencies.supertest,
- xmldoc: pjson.devDependencies.xmldoc,
- 'yeoman-assert': pjson.devDependencies['yeoman-assert']
- },
author: {
name: this.props.author,
email: this.props.email
@@ -401,174 +384,237 @@ module.exports = class extends Generator {
},
repository: ''
}
- // TODO #56 html -> xhtml
+
+ this.npmInstall(['chai', 'chai-xml', 'fs-extra', 'mocha', 'supertest', 'xmldoc', 'yeoman-assert'], { 'save-dev': true })
+
+ // EXPATH
// Applies to all (build, expath-pkg, repo, xqs)
- this.fs.copyTpl(
- this.templatePath('build.xml'),
- this.destinationPath('build.xml'), {
- apptype: this.props.apptype[0],
- title: this.props.title,
- github: this.props.github,
- desc: this.props.desc,
- gitfiles: ', README.md, **/.git*/**'
- })
+ // TODO #56 html -> xhtml
this.fs.copyTpl(
this.templatePath('repo.xml'),
this.destinationPath('repo.xml'), {
- desc: this.props.desc,
- short: this.props.short,
- author: this.props.author,
apptype: this.props.apptype[1],
- status: this.props.status,
- pre: this.props.pre,
- prexq: 'pre-install.xql',
+ author: this.props.author,
+ desc: this.props.desc,
+ group: this.props.group,
+ license: this.props.license[0],
+ mode: this.props.mode,
+ owner: this.props.owner,
post: this.props.post,
postxq: 'post-install.xql',
+ pre: this.props.pre,
+ prexq: 'pre-install.xql',
setperm: this.props.setperm,
- website: this.props.website,
- license: this.props.license[0],
- owner: this.props.owner,
+ short: this.props.short,
+ status: this.props.status,
userpw: this.props.userpw,
- group: this.props.group,
- mode: this.props.mode
+ website: this.props.website
})
this.fs.copyTpl(
this.templatePath('expath-pkg.xml'),
this.destinationPath('expath-pkg.xml'), {
- short: this.props.short,
+ apptype: this.props.apptype[0],
defcoll: this.props.defcoll,
defuri: this.props.defuri,
- version: this.props.version,
desc: this.props.desc,
- apptype: this.props.apptype[0]
+ short: this.props.short,
+ version: this.props.version
})
+ // Unit Test
this.fs.copyTpl(
- this.templatePath('tests/xqs/test-suite.xql'),
+ this.templatePath('specs/xqs/test-suite.xql'),
this.destinationPath('test/xqs/test-suite.xql'), {
apptype: this.props.apptype[0],
- short: this.props.short,
+ author: this.props.author,
defcoll: this.props.defcoll,
defuri: this.props.defuri,
+ short: this.props.short,
+ title: this.props.title,
version: this.props.version,
- author: this.props.author,
- website: this.props.website,
- title: this.props.title
+ website: this.props.website
})
this.fs.copyTpl(
- this.templatePath('tests/xqs/test-runner.xq'),
+ this.templatePath('specs/xqs/test-runner.xq'),
this.destinationPath('test/xqs/test-runner.xq'), {
- short: this.props.short,
+ author: this.props.author,
defcoll: this.props.defcoll,
defuri: this.props.defuri,
- version: this.props.version,
- author: this.props.author,
- title: this.props.title
+ short: this.props.short,
+ title: this.props.title,
+ version: this.props.version
+ })
+
+ this.fs.copy(
+ this.templatePath('specs/mocha/app_spec.js'),
+ this.destinationPath('test/mocha/app_spec.js')
+ )
+
+ this.fs.copyTpl(
+ this.templatePath('specs/mocha/rest_spec.js'),
+ this.destinationPath('test/mocha/rest_spec.js'), {
+ apptype: this.props.apptype[0],
+ defcoll: this.props.defcoll,
+ short: this.props.short
+ })
+
+ this.fs.copyTpl(
+ this.templatePath('specs/xqs/xqSuite.js'),
+ this.destinationPath('test/xqs/xqSuite.js'), {
+ apptype: this.props.apptype[1],
+ defcoll: this.props.defcoll,
+ short: this.props.short,
+ version: this.props.version
})
- // all application packages (fixed)
+ // all application packages, …
if (this.props.apptype[1] === 'application') {
this.fs.copy(
this.templatePath('img/icon.png'),
this.destinationPath('icon.png')
)
+ this.fs.copy(
+ this.templatePath('specs/cypress/'),
+ this.destinationPath('test/cypress/')
+ )
+
+ this.fs.copy(
+ this.templatePath('specs/cypress.json'),
+ this.destinationPath('cypress.json')
+ )
+
+ this.fs.copy(
+ this.templatePath('github/.gitkeep'),
+ this.destinationPath('reports/screenshots/.gitkeep')
+ )
+
+ this.fs.copy(
+ this.templatePath('github/.gitkeep'),
+ this.destinationPath('reports/videos/.gitkeep')
+ )
+
+ this.fs.copyTpl(
+ this.templatePath('specs/integration/landing_spec.js'),
+ this.destinationPath('test/cypress/integration/landing_spec.js'), {
+ apptype: this.props.apptype[0],
+ defcoll: this.props.defcoll,
+ desc: this.props.desc,
+ mysec: this.props.mysec,
+ short: this.props.short
+ })
+
+ this.npmInstall(['cypress'], { 'save-dev': true })
+
+ Object.assign(pkgJson.scripts, {
+ cypress: 'cypress run'
+ })
}
- // not polymer (flexible)
+ // … except empty (flexible)
if (this.props.apptype[0] !== 'empty') {
this.fs.copyTpl(
this.templatePath('pages/error-page.html'),
this.destinationPath('error-page.html'), {
apptype: this.props.apptype[0]
})
- }
- // secure area (mysec)
- if (this.props.mysec) {
- this.fs.copy(
- this.templatePath('mysec/**'),
- this.destinationPath('')
- )
+
this.fs.copyTpl(
- this.templatePath('tests/integration/login-*_spec.js'),
- this.destinationPath('test/cypress/integration/'), {
- defcoll: this.props.defcoll,
- short: this.props.short
- }
+ this.templatePath('pages/index.html'),
+ this.destinationPath('index.html'), {
+ apptype: this.props.apptype[0]
+ })
+ this.fs.copyTpl(
+ this.templatePath('styles/style.css'),
+ this.destinationPath('resources/css/style.css'), {
+ apptype: this.props.apptype[0]
+ })
- )
- }
- // distinct contents (flexible)
- switch (this.props.apptype[0]) {
- case 'exist-design':
- this.fs.copy(
- this.templatePath('exist-design/images/**'),
- this.destinationPath('resources/images/')
- )
- break
- default:
- }
+ this.fs.copyTpl(
+ this.templatePath('collection.xconf'),
+ this.destinationPath('collection.xconf'), {
+ apptype: this.props.apptype[0],
+ index: this.props.index
+ })
- // Plain and exist design stuff
- if (this.props.apptype[0] !== 'empty') {
// XQuery
this.fs.copyTpl(
- this.templatePath('controller.xql'),
+ this.templatePath('xq/controller.xql'),
this.destinationPath('controller.xql'), {
apptype: this.props.apptype[0],
mysec: this.props.mysec
})
this.fs.copyTpl(
- this.templatePath('view.xql'),
+ this.templatePath('xq/view.xql'),
this.destinationPath('modules/view.xql'), {
- short: this.props.short,
+ apptype: this.props.apptype[0],
defcoll: this.props.defcoll,
defuri: this.props.defuri,
- apptype: this.props.apptype[0],
+ short: this.props.short,
version: this.props.version
})
this.fs.copyTpl(
- this.templatePath('app.xql'),
+ this.templatePath('xq/app.xql'),
this.destinationPath('modules/app.xql'), {
- short: this.props.short,
- defcoll: this.props.defcoll,
- defuri: this.props.defuri,
apptype: this.props.apptype[0],
- version: this.props.version,
author: this.props.author,
- website: this.props.website,
+ defcoll: this.props.defcoll,
+ defuri: this.props.defuri,
+ mysec: this.props.mysec,
+ short: this.props.short,
title: this.props.title,
- mysec: this.props.mysec
+ version: this.props.version,
+ website: this.props.website
})
this.fs.copyTpl(
- this.templatePath('config.xqm'),
+ this.templatePath('xq/config.xqm'),
this.destinationPath('modules/config.xqm'), {
- short: this.props.short,
+ apptype: this.props.apptype[0],
defcoll: this.props.defcoll,
defuri: this.props.defuri,
- apptype: this.props.apptype[0],
defview: this.props.defview,
index: this.props.index,
- dataloc: this.props.dataloc,
- datasrc: this.props.datasrc,
- odd: this.props.odd
+ short: this.props.short
})
+ // #36 shared-resources
+ this.fs.copy(
+ this.templatePath('img/exist_icon_16x16.ico'),
+ this.destinationPath('resources/images/exist_icon_16x16.ico')
+ )
+ this.fs.copy(
+ this.templatePath('img/powered-by.svg'),
+ this.destinationPath('resources/images/powered-by.svg')
+ )
+ this.fs.copy(
+ this.templatePath('js/**'),
+ this.destinationPath('resources/scripts/')
+ )
+
+ this.npmInstall(['jquery@1', 'bootstrap@3'])
- // Page.html
+ // distinct contents (flexible)
// see #28
switch (this.props.apptype[0]) {
case 'exist-design':
this.fs.copyTpl(
- this.templatePath('exist-design/page.html'),
+ this.templatePath('pages/exist-design/page.html'),
this.destinationPath('templates/page.html'), {
title: this.props.title,
mysec: this.props.mysec
})
+ this.fs.copy(
+ this.templatePath('img/exist-design/**'),
+ this.destinationPath('resources/images/')
+ )
+ this.fs.copy(
+ this.templatePath('styles/exist-2.2.css'),
+ this.destinationPath('resources/css/exist-2.2.css')
+ )
break
case 'plain':
this.fs.copyTpl(
- this.templatePath('exist-plain/page.html'),
+ this.templatePath('pages/plain/page.html'),
this.destinationPath('templates/page.html'), {
title: this.props.title,
mysec: this.props.mysec
@@ -576,50 +622,93 @@ module.exports = class extends Generator {
break
default:
}
- if (this.props.apptype[1] === 'application') {
- this.fs.copyTpl(
- this.templatePath('pages/index.html'),
- this.destinationPath('index.html'), {
- apptype: this.props.apptype[0]
- })
- this.fs.copyTpl(
- this.templatePath('style.css'),
- this.destinationPath('resources/css/style.css'), {
- apptype: this.props.apptype[0]
- })
- }
+ }
+
+ // Prompt based
+ // Builder
+
+ if (this.props.builder !== 'gulp') {
+ this.fs.copyTpl(
+ this.templatePath('builder/build.xml'),
+ this.destinationPath('build.xml'), {
+ apptype: this.props.apptype[0],
+ builder: this.props.builder,
+ desc: this.props.desc,
+ docker: this.props.docker,
+ dockerfiles: ', Dockerfile, .dockerignore',
+ github: this.props.github,
+ gitfiles: ', README.md, **/.git*/**',
+ title: this.props.title
+ })
+ }
+ if (this.props.builder !== 'ant') {
+ this.fs.copyTpl(
+ this.templatePath('builder/gulpfile.js'),
+ this.destinationPath('gulpfile.js'), {
+ apptype: this.props.apptype[1]
+ }
+ )
+ // TODO dotnev
+ this.npmInstall(['@existdb/gulp-exist', '@existdb/gulp-replace-tmpl', 'del', 'gulp', 'gulp-autoprefixer', 'gulp-concat', 'gulp-cssnano', 'gulp-flatmap', 'gulp-header', 'gulp-muxml', 'gulp-rename', 'gulp-sass', 'gulp-sourcemaps', 'gulp-svgmin', 'gulp-uglify', 'gulp-zip', 'lazypipe'], { 'save-dev': true })
+ Object.assign(pkgJson.scripts, {
+ build: 'gulp build',
+ deploy: 'gulp install'
+ })
+ Object.assign(pkgJson, {
+ browserslist: [
+ 'defaults',
+ 'not IE 11'
+ ]
+ })
}
// Pre-install
if (this.props.pre) {
this.fs.copyTpl(
- this.templatePath('pre-install.xql'),
+ this.templatePath('xq/pre-install.xql'),
this.destinationPath('pre-install.xql'), {
- version: this.props.version,
author: this.props.author,
+ version: this.props.version,
website: this.props.website
}
)
- this.fs.copyTpl(
- this.templatePath('collection.xconf'),
- this.destinationPath('collection.xconf'), {
- apptype: this.props.apptype[0],
- index: this.props.index
- })
}
// Post-install
if (this.props.post) {
this.fs.copyTpl(
- this.templatePath('post-install.xql'),
+ this.templatePath('xq/post-install.xql'),
this.destinationPath('post-install.xql'), {
apptype: this.props.apptype[0],
- version: this.props.version,
author: this.props.author,
+ version: this.props.version,
website: this.props.website
})
}
+ // Secure area (mysec)
+ if (this.props.mysec) {
+ this.fs.copy(
+ this.templatePath('pages/mysec/admin/*.html'),
+ this.destinationPath('admin/')
+ )
+ this.fs.copy(
+ this.templatePath('xq/admin/**'),
+ this.destinationPath('admin/')
+ )
+ this.fs.copy(
+ this.templatePath('pages/mysec/templates/*.html'),
+ this.destinationPath('templates/')
+ )
+ this.fs.copyTpl(
+ this.templatePath('specs/integration/login-*_spec.js'),
+ this.destinationPath('test/cypress/integration/'), {
+ defcoll: this.props.defcoll,
+ short: this.props.short
+ })
+ }
+
// Github
+ // TODO #601
if (this.props.github) {
this.fs.copy(
this.templatePath('github/__gitignore__'),
@@ -643,16 +732,16 @@ module.exports = class extends Generator {
this.templatePath('github/readme.md'),
this.destinationPath('README.md'), {
apptype: this.props.apptype[0],
- title: this.props.title,
- desc: this.props.desc,
- version: this.props.version,
- ghuser: this.props.ghuser,
- website: this.props.website,
author: this.props.author,
- license: this.props.license[0],
badge: this.props.license[1],
badgelink: this.props.license[2],
- ci: this.props.ci
+ ci: this.props.ci,
+ desc: this.props.desc,
+ ghuser: this.props.ghuser,
+ license: this.props.license[0],
+ title: this.props.title,
+ version: this.props.version,
+ website: this.props.website
})
this.fs.copyTpl(
this.templatePath('github/contributing.md'),
@@ -679,7 +768,12 @@ module.exports = class extends Generator {
}
// DOCKER
+ // #610 streamline CI configs based on this prompt
if (this.props.docker) {
+ this.fs.copy(
+ this.templatePath('.dockerignore'),
+ this.destinationPath('.dockerignore')
+ )
this.fs.copyTpl(
this.templatePath('Dockerfile'),
this.destinationPath('Dockerfile'), {
@@ -694,15 +788,16 @@ module.exports = class extends Generator {
this.fs.copyTpl(
this.templatePath('.existdb.json'),
this.destinationPath('.existdb.json'), {
- short: this.props.short,
- defcoll: this.props.defcoll,
- instance: this.props.instance,
admin: this.props.admin,
- adminpw: this.props.adminpw
+ adminpw: this.props.adminpw,
+ defcoll: this.props.defcoll,
+ short: this.props.short,
+ instance: this.props.instance
})
}
// CI
+ // TODO add more option Appveyor, CircleCI, …
switch (this.props.ci) {
case 'travis':
this.fs.copyTpl(
@@ -720,96 +815,31 @@ module.exports = class extends Generator {
)
}
- // no prompt
- // TODO these will need to be adapted for polymer apps
- // Mocha
- this.fs.copy(
- this.templatePath('tests/mocha/app_spec.js'),
- this.destinationPath('test/mocha/app_spec.js')
- )
-
- this.fs.copyTpl(
- this.templatePath('tests/mocha/rest_spec.js'),
- this.destinationPath('test/mocha/rest_spec.js'), {
- apptype: this.props.apptype[0],
- short: this.props.short,
- defcoll: this.props.defcoll
- })
-
- this.fs.copyTpl(
- this.templatePath('tests/xqs/xqSuite.js'),
- this.destinationPath('test/xqs/xqSuite.js'), {
- apptype: this.props.apptype[1],
- short: this.props.short,
- defcoll: this.props.defcoll,
- version: this.props.version
- })
-
- // Cypress
- switch (this.props.apptype[1]) {
- case 'application':
- if (this.props.apptype[0] === 'exist-design' || this.props.apptype[0] === 'plain' || this.props.apptype[0] === 'empty') {
- this.fs.copy(
- this.templatePath('tests/cypress/'),
- this.destinationPath('test/cypress/')
- )
-
- this.fs.copy(
- this.templatePath('tests/cypress.json'),
- this.destinationPath('cypress.json')
- )
-
- this.fs.copy(
- this.templatePath('github/.gitkeep'),
- this.destinationPath('reports/screenshots/.gitkeep')
- )
-
- this.fs.copy(
- this.templatePath('github/.gitkeep'),
- this.destinationPath('reports/videos/.gitkeep')
- )
-
- this.fs.copyTpl(
- this.templatePath('tests/integration/landing_spec.js'),
- this.destinationPath('test/cypress/integration/landing_spec.js'), {
- apptype: this.props.apptype[0],
- short: this.props.short,
- defcoll: this.props.defcoll,
- desc: this.props.desc,
- mysec: this.props.mysec
- })
-
- Object.assign(pkgJson.devDependencies, {
- cypress: pjson.devDependencies.cypress
- })
-
- Object.assign(pkgJson.scripts, {
- cypress: 'cypress run'
- })
- }
- break
- default:
- }
-
// Write the constructed pkgJson
this.fs.writeJSON(this.destinationPath('package.json'), pkgJson)
}
install () {
- this.installDependencies({
- npm: true,
- bower: false,
- yarn: false
- })
+ this.npmInstall()
}
end () {
+ // TODO insert new project layout here?
+ // #513 could even run cypress here after calling npm i
+
if (this.props.github) {
this.spawnCommandSync('git', ['init'])
this.spawnCommandSync('git', ['add', '--all'])
- this.spawnCommandSync('git', ['commit', '-q', '-m', '\'initial scaffolding by Yeoman\''])
+ this.spawnCommandSync('git', ['commit', '-q', '-m', '\'chore(init): scaffolding by Yeoman\''])
+ }
+
+ switch (this.props.builder) {
+ case 'gulp':
+ this.spawnCommandSync('gulp', 'xar')
+ break
+ default:
+ this.spawnCommandSync('ant', '-q')
}
- this.spawnCommandSync('ant', '-q')
console.log(yosay('I believe we\'re done here.'))
}
diff --git a/generators/app/templates/.dockerignore b/generators/app/templates/.dockerignore
new file mode 100644
index 00000000..5fea1ca4
--- /dev/null
+++ b/generators/app/templates/.dockerignore
@@ -0,0 +1,5 @@
+.git/
+
+.existdb.json
+
+yo-rc.json
\ No newline at end of file
diff --git a/generators/app/templates/.existdb.json b/generators/app/templates/.existdb.json
index d44528d6..c1730280 100644
--- a/generators/app/templates/.existdb.json
+++ b/generators/app/templates/.existdb.json
@@ -3,20 +3,19 @@
"localhost": {
"server": "<%- instance %>",
"user": "<%- admin %>",
- "password": "<%- adminpw %>"
+ "password": "<%- adminpw %>",
+ "root": "/db/<%- defcoll %>/<%- short %>"
}
},
"sync": {
"server": "localhost",
- "root": "/db/<%- defcoll %>/<%- short %>",
"active": true,
"ignore": [
".existdb.json",
".git/**",
"node_modules/**",
- "bower_components/**",
"build/**",
- "webtest/**",
+ ".vscode/**",
"README.md",
"yo-rc.json"
]
diff --git a/generators/app/templates/build.xml b/generators/app/templates/build.xml
deleted file mode 100644
index 119954c6..00000000
--- a/generators/app/templates/build.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
- <%- desc %>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/generators/app/templates/builder/build.xml b/generators/app/templates/builder/build.xml
new file mode 100644
index 00000000..ebc5f513
--- /dev/null
+++ b/generators/app/templates/builder/build.xml
@@ -0,0 +1,49 @@
+
+
+ <%- desc %>
+
+
+
+
+
+
+
+
+ <%_ if (builder === 'hybrid') { %>
+
+
+
+ <%_ } else { %>
+
+
+
+
+
+ <% } -%>
+
+
+
+
+ <%_ if (builder === 'hybrid') { %>
+
+
+
+
+ <%_ } else { %>
+
+ <% } -%>
+
+
+
+
+ <%_ if (builder === 'hybrid') { %>
+
+ <%_ } else { %>
+
+ <% } -%>
+
+
+
+
+
+
diff --git a/generators/app/templates/builder/gulpfile.js b/generators/app/templates/builder/gulpfile.js
new file mode 100644
index 00000000..a1745aaa
--- /dev/null
+++ b/generators/app/templates/builder/gulpfile.js
@@ -0,0 +1,300 @@
+// TODO: line-o tell me what you want what you really really …
+// see https://docs.google.com/document/d/1UdSWERC9rCSYIYjTGgCr3avce47h5OeLFR4tGKYXZlM/edit#heading=h.ei4sqy3ojpkl
+// see https://github.com/eeditiones/roaster/blob/master/gulpfile.js
+// see https://github.com/eXist-db/documentation/blob/master/Gulpfile.js
+// see #563
+
+/**
+ * Paths to adjust project layout
+ */
+
+// TODO flexible hybrid vs pure gulp for hybrid (no src) stick with old project layout ?
+const paths = {
+ input: 'src/main/',
+ output: 'dist/xar/',
+ scripts: {
+ input: 'src/main/js/*',
+ // polyfills: '.polyfill.js',
+ output: 'dist/xar/resources/scripts/'
+ },
+ styles: {
+ input: 'src/main/styles/sass/*.{scss,sass}',
+ output: 'dist/xar/resources/styles/'
+ },
+ svgs: {
+ input: 'src/main/img/*.svg',
+ output: 'dist/xar/resources/images/'
+ },
+ vendor: {
+ input: 'node_modules/'
+ },
+ static: {
+ input: 'src/main/**/*.{html,xq,xquery,xql,xqm}'
+ }
+}
+
+/**
+ * Gulp Packages
+ */
+
+// General
+const {
+ src,
+ dest,
+ watch,
+ series,
+ parallel,
+ lastRun
+} = require('gulp')
+const { createClient } = require('@existdb/gulp-exist')
+const del = require('del')
+const flatmap = require('gulp-flatmap')
+const header = require('gulp-header')
+const lazypipe = require('lazypipe')
+const muxml = require('gulp-muxml')
+const zip = require("gulp-zip")
+const rename = require('gulp-rename')
+const replace = require('@existdb/gulp-replace-tmpl') // Do we need this still when starting from here ?
+
+
+// Scripts
+const concat = require('gulp-concat')
+const uglify = require('gulp-uglify')
+
+// Styles
+const sass = require('gulp-sass')
+const prefix = require('gulp-autoprefixer')
+const minify = require('gulp-cssnano')
+const sourcemaps = require('gulp-sourcemaps')
+
+// SVGs
+const svgmin = require('gulp-svgmin')
+
+// read metadata from local files
+const pkg = require('./package.json')
+const { version, license } = pkg
+const existJSON = require('./.existdb.json')
+const replacements = [existJSON.package, { version, license }]
+
+// .tmpl replacements to include
+// first value wins
+const replacements = [pkg, { version, license }] // s.a.
+
+// Connection Info
+const packageUri = existJSON.package.ns
+const serverInfo = existJSON.servers.localhost
+const target = serverInfo.root
+
+const connectionOptions = {
+ basic_auth: {
+ user: serverInfo.user,
+ pass: serverInfo.password
+ }
+}
+const existClient = createClient(connectionOptions);
+
+// construct the current xar name from available data
+const packageName = () => `${existJSON.package.target}-${pkg.version}.xar`
+// TODO: check if this is really what we want, modifications in these need to trigger sync
+// - xml / xconf / odd should be prettied
+// - html should be...
+// - xq / xsl ... ?
+
+
+
+/**
+ * Use the `delete` module directly, instead of using gulp-rimraf
+ */
+function clean(cb) {
+ del([paths.output], cb);
+}
+exports.clean = clean
+
+/**
+* replace placeholders
+* in src/repo.xml.tmpl and
+* output to build/repo.xml
+*/
+function templates() {
+ return src('src/*.tmpl')
+ .pipe(replace(replacements, { debug: true }))
+ .pipe(rename(path => { path.extname = "" }))
+ .pipe(dest(paths.output))
+}
+exports.templates = templates
+
+function watchTemplates() {
+ watch('src/*.tmpl', series(templates))
+}
+exports["watch:tmpl"] = watchTemplates
+
+/**
+ * compile SCSS styles and output css
+ */
+function styles() {
+ return src(paths.styles.input)
+ .pipe(sourcemaps.init())
+ .pipe(sass({
+ outputStyle: 'expanded',
+ sourceComments: true
+ }).on('error', sass.logError))
+ .pipe(prefix({
+ browsers: ['last 2 version', '> 0.25%'],
+ cascade: true,
+ remove: true
+ }))
+ .pipe(rename({
+ suffix: '.min'
+ }))
+ .pipe(minify({
+ discardComments: {
+ removeAll: true
+ }
+ }))
+ .pipe(sourcemaps.write('.'))
+ .pipe(dest(paths.styles.output));
+}
+exports.styles = styles
+
+function watchStyles() {
+ watch(paths.styles.input, series(styles))
+}
+exports["watch:styles"] = watchStyles
+
+/**
+* minify EcmaSript files and put them into output dir
+*/
+function minifyEs() {
+ return src(paths.scripts.input)
+ .pipe(uglify())
+ .pipe(dest(paths.scripts.output))
+}
+exports.minify = minifyEs
+
+function watchEs() {
+ watch(paths.scripts.input, series(minifyEs))
+}
+exports["watch:es"] = watchEs
+
+
+/**
+* copy html templates, XSL stylesheet, XMLs and XQueries to 'build'
+*/
+function copyStatic() {
+ return src(paths.static.input).pipe(dest(paths.output))
+}
+exports.copy = parallel(copyXml, copyVendor, copyImg, copyStatic)
+
+function watchStatic() {
+ watch(paths.static.input, series(copyStatic, copyXML, copyVendor));
+}
+exports["watch:static"] = watchStatic
+
+function copyXml() {
+ return src(paths.input + '**/*.{odd,xq,xquery,xql,xqm,xml,xhtml,xconf,xsl}')
+ .pipe(muxml({
+ stripComments: false,
+ stripCdata: false,
+ stripInstruction: false,
+ saxOptions: {
+ trim: true,
+ normalize: true
+ }
+ }))
+ .pipe(dest(paths.output))
+}
+
+function copyImg () {
+ return src(paths.input + '**/*.svg', {base: paths.input})
+ .pipe(svgmin())
+ .pipe(dest(paths.output))
+ .pipe(src([paths.input + 'icon.png', paths.input + 'img/**/*.{*,!svg}'], {base: paths.input, allowEmpty: true}))
+ .pipe(dest(paths.output))
+}
+
+exports.copyImg = copyImg
+
+// TODO #36 flexible
+/**
+* copy vendored scripts and style into output
+*/
+<%_ if (apptype !== 'empty') { %>
+function copyVendorES() {
+ return src([paths.vendor.input + 'bootstrap/dist/js/bootstrap.min.*', paths.vendor.input + 'jquery/dist/jquery.min.*'], {allowEmpty: true})
+ .pipe(dest(paths.scripts.output))
+}
+
+function copyVendorStyle() {
+ return src(paths.vendor.input + 'bootstrap/dist/css/bootstrap.min.*', {allowEmpty: true})
+ .pipe(dest(paths.styles.output))
+}
+exports.copyVendor = parallel(copyVendorES, copyVendorStyle)
+
+function watchVendor() {
+ watch(paths.vendor.input, series(copyVendorES, copyVendorStyle))
+}
+exports["watch:vendor"] = watchVendor
+<% } -%>
+/**
+ * Upload all files in the build folder to existdb.
+ * This function will only upload what was changed
+ * since the last run (see gulp documentation for lastRun).
+ */
+
+ // Todo: # 563 conditional library package tasks go here
+
+function deploy() {
+ return src(paths.output + '**/*', {
+ base: paths.output,
+ since: lastRun(deploy)
+ })
+ .pipe(existClient.dest({ target }))
+}
+
+function watchBuild() {
+ watch(paths.output + '**/*', series(deploy))
+}
+
+/**
+ * create XAR package in repo root
+ */
+function xar() {
+ return src(paths.output + '**/*', { base: 'dist' })
+ .pipe(zip(packageName()))
+ .pipe(dest('.'))
+}
+
+/**
+* upload and install the latest built XAR
+*/
+function installXar() {
+ return src(packageName())
+ .pipe(existClient.install({ packageUri }))
+}
+
+// composed tasks
+const build = series(
+ clean,
+ styles,
+ minifyEs,
+ templates,
+ copyStatic
+)
+const watchAll = parallel(
+ watchStyles,
+ watchEs,
+ watchStatic,
+ watchTemplates,
+ watchVendor,
+ watchBuild
+)
+
+exports.build = build
+exports.watch = watchAll
+
+exports.deploy = series(build, deploy)
+exports.xar = series(build, xar)
+exports.install = series(build, xar, installXar)
+
+// main task for day to day development
+exports.default = series(build, deploy, watchAll)
diff --git a/generators/app/templates/expath-pkg.xml b/generators/app/templates/expath-pkg.xml
index d2a88d9e..88fd7028 100644
--- a/generators/app/templates/expath-pkg.xml
+++ b/generators/app/templates/expath-pkg.xml
@@ -3,5 +3,5 @@
abbrev="<%- short %>" version="<%- version %>" spec="1.0">
<%- desc %>
- <%_ if (apptype !== 'empty') { %><% } -%>
+ <%_ if (apptype !== 'empty') { %><% } -%>
diff --git a/generators/app/templates/github/__gitignore__ b/generators/app/templates/github/__gitignore__
index 9334c182..9376a56e 100644
--- a/generators/app/templates/github/__gitignore__
+++ b/generators/app/templates/github/__gitignore__
@@ -69,7 +69,7 @@ query-results
# =========================
# other
# =========================
-
+.env
.yo-rc.json
node_modules/
coverage
diff --git a/generators/app/templates/github/readme.md b/generators/app/templates/github/readme.md
index 9bcb831a..28c0f67f 100644
--- a/generators/app/templates/github/readme.md
+++ b/generators/app/templates/github/readme.md
@@ -7,7 +7,6 @@
<%_ } else { _%>
![exist-db CI](https://github.com/<%- ghuser %>/<%- title %>/workflows/exist-db%20CI/badge.svg)
<% } -%>
-[![Coverage percentage][coveralls-image]][coveralls-url]
@@ -108,5 +107,3 @@ You can take a look at the [Contribution guidelines for this project](.github/CO
[travis-image]: https://travis-ci.com/<%- ghuser %>/<%- title %>.svg?branch=master
[travis-url]: https://travis-ci.com/<%- ghuser %>/<%- title %>
<% } -%>
-[coveralls-image]: https://coveralls.io/repos/<%- ghuser %>/<%- title %>/badge.svg
-[coveralls-url]: https://coveralls.io/r/<%- ghuser %>/<%- title %>
diff --git a/generators/app/templates/exist-design/images/bgmenu.gif b/generators/app/templates/img/exist-design/bgmenu.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/bgmenu.gif
rename to generators/app/templates/img/exist-design/bgmenu.gif
diff --git a/generators/app/templates/exist-design/images/bgmenuhi.gif b/generators/app/templates/img/exist-design/bgmenuhi.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/bgmenuhi.gif
rename to generators/app/templates/img/exist-design/bgmenuhi.gif
diff --git a/generators/app/templates/exist-design/images/body-base.gif b/generators/app/templates/img/exist-design/body-base.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/body-base.gif
rename to generators/app/templates/img/exist-design/body-base.gif
diff --git a/generators/app/templates/exist-design/images/body.gif b/generators/app/templates/img/exist-design/body.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/body.gif
rename to generators/app/templates/img/exist-design/body.gif
diff --git a/generators/app/templates/exist-design/images/bold.gif b/generators/app/templates/img/exist-design/bold.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/bold.gif
rename to generators/app/templates/img/exist-design/bold.gif
diff --git a/generators/app/templates/exist-design/images/code.gif b/generators/app/templates/img/exist-design/code.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/code.gif
rename to generators/app/templates/img/exist-design/code.gif
diff --git a/generators/app/templates/exist-design/images/delete-icon.png b/generators/app/templates/img/exist-design/delete-icon.png
similarity index 100%
rename from generators/app/templates/exist-design/images/delete-icon.png
rename to generators/app/templates/img/exist-design/delete-icon.png
diff --git a/generators/app/templates/exist-design/images/existdb.png b/generators/app/templates/img/exist-design/existdb.png
similarity index 100%
rename from generators/app/templates/exist-design/images/existdb.png
rename to generators/app/templates/img/exist-design/existdb.png
diff --git a/generators/app/templates/exist-design/images/glyphicons-halflings.png b/generators/app/templates/img/exist-design/glyphicons-halflings.png
similarity index 100%
rename from generators/app/templates/exist-design/images/glyphicons-halflings.png
rename to generators/app/templates/img/exist-design/glyphicons-halflings.png
diff --git a/generators/app/templates/exist-design/images/grey-box-bot.gif b/generators/app/templates/img/exist-design/grey-box-bot.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/grey-box-bot.gif
rename to generators/app/templates/img/exist-design/grey-box-bot.gif
diff --git a/generators/app/templates/exist-design/images/grey-box-rpt.gif b/generators/app/templates/img/exist-design/grey-box-rpt.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/grey-box-rpt.gif
rename to generators/app/templates/img/exist-design/grey-box-rpt.gif
diff --git a/generators/app/templates/exist-design/images/grey-box-top.gif b/generators/app/templates/img/exist-design/grey-box-top.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/grey-box-top.gif
rename to generators/app/templates/img/exist-design/grey-box-top.gif
diff --git a/generators/app/templates/exist-design/images/header.gif b/generators/app/templates/img/exist-design/header.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/header.gif
rename to generators/app/templates/img/exist-design/header.gif
diff --git a/generators/app/templates/exist-design/images/horizontal.gif b/generators/app/templates/img/exist-design/horizontal.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/horizontal.gif
rename to generators/app/templates/img/exist-design/horizontal.gif
diff --git a/generators/app/templates/exist-design/images/italic.gif b/generators/app/templates/img/exist-design/italic.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/italic.gif
rename to generators/app/templates/img/exist-design/italic.gif
diff --git a/generators/app/templates/exist-design/images/nav-dropdown.gif b/generators/app/templates/img/exist-design/nav-dropdown.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/nav-dropdown.gif
rename to generators/app/templates/img/exist-design/nav-dropdown.gif
diff --git a/generators/app/templates/exist-design/images/nav-dropdown.png b/generators/app/templates/img/exist-design/nav-dropdown.png
similarity index 100%
rename from generators/app/templates/exist-design/images/nav-dropdown.png
rename to generators/app/templates/img/exist-design/nav-dropdown.png
diff --git a/generators/app/templates/exist-design/images/nav.gif b/generators/app/templates/img/exist-design/nav.gif
similarity index 100%
rename from generators/app/templates/exist-design/images/nav.gif
rename to generators/app/templates/img/exist-design/nav.gif
diff --git a/generators/app/templates/exist-design/images/page-edit-icon.png b/generators/app/templates/img/exist-design/page-edit-icon.png
similarity index 100%
rename from generators/app/templates/exist-design/images/page-edit-icon.png
rename to generators/app/templates/img/exist-design/page-edit-icon.png
diff --git a/generators/app/templates/img/exist_icon_16x16.ico b/generators/app/templates/img/exist_icon_16x16.ico
new file mode 100644
index 00000000..369b350f
Binary files /dev/null and b/generators/app/templates/img/exist_icon_16x16.ico differ
diff --git a/generators/app/templates/img/powered-by.svg b/generators/app/templates/img/powered-by.svg
new file mode 100644
index 00000000..75e4f325
--- /dev/null
+++ b/generators/app/templates/img/powered-by.svg
@@ -0,0 +1,58 @@
+
+
+
\ No newline at end of file
diff --git a/generators/app/templates/img/yoexist.svg b/generators/app/templates/img/yoexist.svg
new file mode 100644
index 00000000..2221c59e
--- /dev/null
+++ b/generators/app/templates/img/yoexist.svg
@@ -0,0 +1,91 @@
+
+
diff --git a/generators/app/templates/js/loadsource.js b/generators/app/templates/js/loadsource.js
new file mode 100644
index 00000000..1ce826ac
--- /dev/null
+++ b/generators/app/templates/js/loadsource.js
@@ -0,0 +1,45 @@
+$(document).ready(function () {
+ /*
+ * Open link or code snippet in eXide. Check if eXide is already open.
+ * Include this script if you use templates:load-source.
+ */
+ $('.eXide-open').click(function (ev) {
+ // try to retrieve existing eXide window
+ var exide = window.open('', 'eXide')
+ if (exide && !exide.closed) {
+ var snip = $(this).data('exide-create')
+ var path = $(this).data('exide-open')
+
+ // check if eXide is really available or it's an empty page
+ var app = exide.eXide
+ if (app) {
+ // eXide is there
+ if (snip) {
+ exide.eXide.app.newDocument(snip, 'xquery')
+ } else {
+ exide.eXide.app.findDocument(path)
+ }
+ exide.focus()
+ setTimeout(function () {
+ if ($.browser.msie ||
+ (typeof exide.eXide.app.hasFocus === 'function' && !exide.eXide.app.hasFocus())) {
+ alert('Opened code in existing eXide window.')
+ }
+ }, 200)
+ } else {
+ window.eXide_onload = function () {
+ console.log('onloaed called')
+ if (snip) {
+ exide.eXide.app.newDocument(snip, 'xquery')
+ } else {
+ exide.eXide.app.findDocument(path)
+ }
+ }
+ // empty page
+ exide.location = this.href.substring(0, this.href.indexOf('?'))
+ }
+ return false
+ }
+ return true
+ })
+})
diff --git a/generators/app/templates/exist-design/page.html b/generators/app/templates/pages/exist-design/page.html
similarity index 89%
rename from generators/app/templates/exist-design/page.html
rename to generators/app/templates/pages/exist-design/page.html
index 90560958..593c321d 100755
--- a/generators/app/templates/exist-design/page.html
+++ b/generators/app/templates/pages/exist-design/page.html
@@ -4,12 +4,12 @@
<%- title %>
-
-
+
+
-
-
-
+
+
+
diff --git a/generators/app/templates/mysec/admin/index.html b/generators/app/templates/pages/mysec/admin/index.html
similarity index 100%
rename from generators/app/templates/mysec/admin/index.html
rename to generators/app/templates/pages/mysec/admin/index.html
diff --git a/generators/app/templates/mysec/admin/security.html b/generators/app/templates/pages/mysec/admin/security.html
similarity index 100%
rename from generators/app/templates/mysec/admin/security.html
rename to generators/app/templates/pages/mysec/admin/security.html
diff --git a/generators/app/templates/mysec/templates/login-panel.html b/generators/app/templates/pages/mysec/templates/login-panel.html
similarity index 100%
rename from generators/app/templates/mysec/templates/login-panel.html
rename to generators/app/templates/pages/mysec/templates/login-panel.html
diff --git a/generators/app/templates/exist-plain/page.html b/generators/app/templates/pages/plain/page.html
similarity index 84%
rename from generators/app/templates/exist-plain/page.html
rename to generators/app/templates/pages/plain/page.html
index 89055527..aafc417e 100755
--- a/generators/app/templates/exist-plain/page.html
+++ b/generators/app/templates/pages/plain/page.html
@@ -4,12 +4,12 @@
<%- title %>
-
-
+
+
-
-
-
+
+
+