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 @@ + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + powered by + + + \ 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 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + 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 %> - - + + -