@tangelo/tangelo-configuration-toolkit 1.19.0 → 1.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -92,13 +92,13 @@ global._isPre51 = () => !fs.existsSync(path.join(_paths.repo, _paths.tdi, 'src')
92
92
 
93
93
  global._modulesTdi = {
94
94
  absolutePathTdi: path.join(_paths.repo, _paths.tdi),
95
- ensureDepsUpToDate() {
95
+ ensureDepsUpToDate(message) {
96
96
  if (this.depsUpToDate) return;
97
97
  try {
98
- _info('Checking installed dependencies in submodule');
98
+ if (message) _info('Checking installed dependencies in submodule');
99
99
  execSync('npm list', {cwd: this.absolutePathTdi, stdio: 'ignore'});
100
100
  } catch (e) {
101
- _info('Updating dependencies in submodule');
101
+ if (message) _info('Updating dependencies in submodule');
102
102
  execSync('npm update', {cwd: this.absolutePathTdi, stdio: 'ignore'});
103
103
  }
104
104
  this.depsUpToDate = true;
@@ -110,7 +110,10 @@ global._modulesTdi = {
110
110
  return require(path.join(this.absolutePathTdi, 'tct', module));
111
111
  }
112
112
  catch (e) {
113
- if (throws) _error('Module could not be loaded: ' + module);
113
+ if (throws) {
114
+ _debug(`${e}`);
115
+ _error('Module could not be loaded: ' + module);
116
+ }
114
117
  else return undefined;
115
118
  }
116
119
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangelo/tangelo-configuration-toolkit",
3
- "version": "1.19.0",
3
+ "version": "1.20.1",
4
4
  "engines": {
5
5
  "node": ">=14.0.0"
6
6
  },
@@ -46,10 +46,11 @@
46
46
  "p-limit": "^3.1.0",
47
47
  "replace-in-file": "^6.3.2",
48
48
  "sass": "^1.43.5",
49
- "saxon-js": "^2.3.0",
49
+ "saxon-js": "^2.5.0",
50
50
  "ssh2-sftp-client": "^9.1.0",
51
51
  "through2": "^4.0.2",
52
52
  "tiny-lr": "^2.0.0",
53
+ "xml2js": "^0.6.2",
53
54
  "yargs": "^17.7.2"
54
55
  },
55
56
  "repository": {
@@ -17,12 +17,15 @@ module.exports = function getRepoconfig(repoPath) {
17
17
  const path_cmscustom = xpiDir.replace(/\/[^/]+$/, '').split(/\//);
18
18
  const path_dbconfig = p.replace(/.*\/database\/config\/(.*)\/[^/]+/, '$1').split(/[/\\]/);
19
19
  const dnRegex = [path_cmscustom[0].replace(/[_'"]/g, '.'), path_dbconfig[0].replace(/[_'"]/g, '.')].sort((a, b) => b.length - a.length).join('|');
20
- const customer_name = (dtDisplayName.match(RegExp(dnRegex, 'i')) || dtDisplayName.split(/ (.+)/))[0];
20
+ /* Get customer name based on txd_document_types.display_name; if that match fails fallback to customername defined in path */
21
+ const customer_name = (dtDisplayName.match(RegExp(dnRegex, 'i')) || [path_cmscustom[0].split(/[\s_]/g).map(s => s[0].toUpperCase() + s.substring(1)).join(' ')])[0];
22
+ const customer_name_regex = RegExp(customer_name.replace(/(\W)/g, '\\$1?'), 'gi'); // match customer name; allow differences in special characters / match case insensitive
21
23
 
22
24
  return {
23
25
  customer_name,
24
26
  customer_abbr: ntName.split('_')[0],
25
- project_name: dtDisplayName.split(RegExp(customer_name.replace(/(\W)/g, '\\$1')))[1].trim() || '',
27
+ /* if display name matches the customer name; strip customer name from display name to get the project name; otherwise use the complete display name as projectname */
28
+ project_name: dtDisplayName.match(customer_name_regex) ? dtDisplayName.replace(customer_name_regex, '').trim() : dtDisplayName,
26
29
  project_abbr: ntName.split('_')[1],
27
30
  path_cmscustom,
28
31
  path_dbconfig,
@@ -14,7 +14,7 @@ module.exports = function(ftpConfig, remotedir) {
14
14
 
15
15
  function transform (file, _, cb) {
16
16
  if (file.isStream()) return cb(new Error('Streaming not supported.'));
17
- if (file.stat.isDirectory()) return cb();
17
+ if (file.stat?.isDirectory()) return cb();
18
18
 
19
19
  file.destination = path.join(remotedir, file.relative).toFws;
20
20
  files.push(file); // collect all files in array
@@ -0,0 +1,40 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const TclConfig = require('./tcl-config');
4
+ const through2 = require('through2');
5
+ const Vinyl = require('vinyl');
6
+
7
+
8
+ function createAddToStreamFn(stream) {
9
+ return (path, content) => stream.push(new Vinyl({
10
+ path: path,
11
+ contents: Buffer.from(content)
12
+ }));
13
+ }
14
+
15
+ module.exports = function() {
16
+ const tclFileDirs = [];
17
+
18
+ return through2.obj(
19
+
20
+ function transform (file, _, cb) {
21
+ if (file.isStream()) return cb(new Error('Streaming not supported.'));
22
+
23
+ if (file.extname == '.tcl') tclFileDirs.push(path.dirname(file.relative));
24
+ return cb(null, file);
25
+ },
26
+
27
+ function flush(cb) {
28
+ for (const tclFileDir of tclFileDirs) {
29
+ const tclConfig = new TclConfig(tclFileDir, createAddToStreamFn(this));
30
+ tclConfig.outputJson(path.resolve(tclFileDir, 'fonto/assets'));
31
+ tclConfig.outputCss(path.resolve(tclFileDir, 'fonto'));
32
+ const esefCssDir = path.resolve(tclFileDir, 'export/esef/esef_out/css');
33
+ if (fs.existsSync(esefCssDir)) tclConfig.outputCss(esefCssDir);
34
+ }
35
+ cb();
36
+ }
37
+
38
+ )
39
+ .resume(); // required for triggering 'end' event
40
+ };
@@ -10,6 +10,9 @@ global._info = (msg, time = false) => {
10
10
  }
11
11
  console.log(msg.lgreen);
12
12
  };
13
+ global._debug = msg => {
14
+ if (global._devmode) console.log(`[DEBUG]: ${msg}`.yellow);
15
+ };
13
16
  global._warn = msg => {
14
17
  console.log(msg.lyellow);
15
18
  };
@@ -0,0 +1,101 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const sass = require('sass');
4
+ const SaxonJS = require('saxon-js');
5
+
6
+
7
+ module.exports = class TclConfig {
8
+
9
+ static #SEF_FILE_PATH = 'tcl/configToJson.sef.json';
10
+ static #JSON_TO_SCSS_FILE_PATH = 'tcl/configJsonToScss';
11
+ static #TCL_FILE_NAME = 'project.tcl';
12
+ static #TCL_JSON_FILE_NAME = 'tcl-config.json';
13
+ static #TCL_CSS_FILE_NAME = 'tcl-styles.css';
14
+ static #FONTO_HTML_FILE_NAME = 'index.html';
15
+
16
+ static #sefFile;
17
+ static #jsonToScssFile;
18
+
19
+ static #transformTclConfigToJson(tclFilePathRel) {
20
+ this.#sefFile ??= _modulesTdi.require(this.#SEF_FILE_PATH, {message: false});
21
+
22
+ const messages = [` Warnings from transformation of ${tclFilePathRel}`];
23
+ const transformation = SaxonJS.transform({
24
+ stylesheetText: JSON.stringify(this.#sefFile),
25
+ sourceFileName: tclFilePathRel,
26
+ destination: 'raw',
27
+ deliverMessage(messageNode) {
28
+ messages.push(messageNode.textContent);
29
+ }
30
+ });
31
+
32
+ if (messages[1]) _warn(messages.join('\n '));
33
+ return transformation.principalResult ?? _error(`No result from transformation of ${tclFilePathRel}`);
34
+ }
35
+
36
+ static #transformJsonToCss(tclFilePathRel, json, moduleName) {
37
+ this.#jsonToScssFile ??= _modulesTdi.require(this.#JSON_TO_SCSS_FILE_PATH, {message: false});
38
+ const scss = this.#jsonToScssFile(json.project, moduleName);
39
+ const url = new URL(path.join('file://', path.resolve(tclFilePathRel)));
40
+ return sass.compileString(scss, {url, style: 'compressed'}).css;
41
+ }
42
+
43
+ static #addCssImportToHtml(dir) {
44
+ const filepath = path.join(dir, this.#FONTO_HTML_FILE_NAME);
45
+
46
+ if (fs.existsSync(filepath)) {
47
+ const html = fs.readFileSync(filepath).toString();
48
+
49
+ if (!RegExp(`<link[^>]*${this.#TCL_CSS_FILE_NAME}[^>]*>`).test(html)) {
50
+ const newHtml = html.replace(/((\s+<link.*")[^"]+\.css(.*))/, `$1$2${this.#TCL_CSS_FILE_NAME}$3`);
51
+ fs.outputFileSync(filepath, newHtml);
52
+ }
53
+ }
54
+ }
55
+
56
+ #outputFn;
57
+ #doModifyFontoHtml;
58
+ #tclFilePathRel;
59
+ #tclFileExists;
60
+ #resultJson;
61
+ #resultCss = {};
62
+
63
+ constructor(tclFileRelDir, addToStreamFn) {
64
+ this.#tclFilePathRel = path.join(tclFileRelDir, TclConfig.#TCL_FILE_NAME);
65
+ this.#tclFileExists = fs.existsSync(this.#tclFilePathRel);
66
+ this.#outputFn = addToStreamFn ?? fs.outputFileSync;
67
+ this.#doModifyFontoHtml = !addToStreamFn;
68
+ }
69
+
70
+ #getJson() {
71
+ return this.#resultJson ??= TclConfig.#transformTclConfigToJson(this.#tclFilePathRel);
72
+ }
73
+
74
+ #getCss(moduleName) {
75
+ return this.#resultCss[moduleName] ??= TclConfig.#transformJsonToCss(this.#tclFilePathRel, this.#getJson(), moduleName);
76
+ }
77
+
78
+ outputJson(dir) {
79
+ if (this.#tclFileExists) {
80
+ const filepath = path.join(dir, TclConfig.#TCL_JSON_FILE_NAME);
81
+ this.#outputFn(filepath, JSON.stringify(this.#getJson()));
82
+ }
83
+ return this;
84
+ }
85
+
86
+ outputCss(dir) {
87
+ if (this.#tclFileExists) {
88
+ const filepath = path.join(dir, TclConfig.#TCL_CSS_FILE_NAME);
89
+ const moduleName = dir.includes('esef') ? 'ESEF' : 'FONTO';
90
+ this.#outputFn(filepath, this.#getCss(moduleName));
91
+ this.modifyFontoHtml(dir);
92
+ }
93
+ return this;
94
+ }
95
+
96
+ modifyFontoHtml(dir) {
97
+ if (this.#tclFileExists && this.#doModifyFontoHtml) TclConfig.#addCssImportToHtml(dir);
98
+ return this;
99
+ }
100
+
101
+ };
@@ -4,6 +4,7 @@ const fs = require('fs-extra');
4
4
  const globby = require('globby');
5
5
  const gulp = require('gulp');
6
6
  const {NodeSSH} = require('node-ssh');
7
+ const g_tcl = require('../../lib/gulp-tcl-config');
7
8
  const through2 = require('through2');
8
9
  const {spawnSync} = require('child_process');
9
10
 
@@ -119,13 +120,13 @@ const createDeliveryPack = () => { // create install scripts if necessary, zip o
119
120
  };
120
121
 
121
122
 
122
- const transfer = (paths, lrServer) => {
123
+ const transfer = (paths, {watch, lrServer}) => {
123
124
  const jsFGlob = _settingsTdi().transpileToES5 ? ['**/*.js', '!**/hce/**/template_*', '!**/fonto/**', '!**/vendor/**', '!**/*.min.js'] : [];
124
125
  const jsF = g_filter(jsFGlob, {restore: true});
125
126
  const xpsF = g_filter(['**/xopus/**/*.x*'], {restore: true});
126
127
  const sassF = g_filter(['**/*.scss'], {restore: true});
127
128
  const shF = g_filter(['**/*.sh'], {restore: true});
128
- const srcset = s.create(paths);
129
+ const srcset = s.create(paths, {watch});
129
130
  const files = [];
130
131
 
131
132
  // local git repo must be on latest commit containing fonto changes, and fonto build files must be newer than that commit, unless that commit belongs to the current user
@@ -160,6 +161,7 @@ const transfer = (paths, lrServer) => {
160
161
  .pipe(xpsF)
161
162
  .pipe(g_resolveIncl())
162
163
  .pipe(xpsF.restore)
164
+ .pipe(g_tcl())
163
165
  .pipe(jsF)
164
166
  .pipe(g_sourcemaps.init())
165
167
  .pipe(g_babel({presets: [[babel_pe, {modules: false}]], comments: false, minified: true})) // function must be executed here, otherwise second execution during watch fails
@@ -33,7 +33,7 @@ module.exports = function deploy (argv) {
33
33
  // execute chosen option
34
34
 
35
35
  if (argv.test) {
36
- s.create([...c.transferPatterns, '!**/fonto/{*.*,!(dist)/**}'], true);
36
+ s.create([...c.transferPatterns, '!**/fonto/{*.*,!(dist)/**}'], {test: true});
37
37
  }
38
38
 
39
39
  if (argv.copy) {
@@ -52,7 +52,7 @@ module.exports = function deploy (argv) {
52
52
  this.queue = this.queue.map(p => p.replace(/fonto(.)(?:dist|dev).assets.schemas(.sx-shell-.*?).json/, 'fonto$1packages$2$1src$1assets$1schemas$2.json')); // fonto schema changes can be detected in different paths at the same time, rewrite paths to original package-path because files in build folders can be removed before transfer starts
53
53
  this.queue = [...new Set(this.queue)]; // remove duplicates
54
54
  this.queue.forEach(v => s.addToCache(v));
55
- transfer(this.queue, lrServer);
55
+ transfer(this.queue, {watch: true, lrServer});
56
56
  this.queue = [];
57
57
  },
58
58
  add (fp) {
@@ -9,12 +9,12 @@ const resolveBind = (d, p) => p.replace('#{cmscustompath}', 'cmscustom/').replac
9
9
 
10
10
  module.exports = {
11
11
 
12
- create (pattern, test) {
12
+ create (paths, {test, watch}) {
13
13
  const startTime = new Date();
14
14
 
15
- this.filesToTransfer = globby.sync(pattern, {nodir: true}); // get list of files to transfer
16
- this.potentialBaseFilesCache = this.potentialBaseFilesCache || globby.sync('**/*.{xml,xsd,xsl,scss}'); // get list of potential base files, if not previously done
17
- this.potentialBaseFiles = this.potentialBaseFilesCache
15
+ this.filesToTransfer = watch ? paths : globby.sync(paths, {nodir: true}); // get list of files to transfer
16
+ this.potentialBaseFilesCache ??= globby.sync('**/*.{xml,xsd,xsl,scss}'); // get list of potential base files, if not previously done
17
+ this.potentialBaseFiles = this.potentialBaseFilesCache
18
18
  .filter(p => !this.filesToTransfer.includes(p)) // subtract files to transfer from list of potential base files
19
19
  .map(path => [path]); // make array so file contents can be added later
20
20
 
@@ -1,12 +1,13 @@
1
- const del = require('del');
2
- const {exec} = require('child_process');
3
- const fs = require('fs-extra');
4
- const globby = require('globby');
5
- const gulp = require('gulp');
6
- const g_print = require('gulp-print');
7
- const path = require('path');
8
- const sass = require('gulp-sass')(require('sass'));
9
- const wws = require('../../lib/worker-with-spinner');
1
+ const del = require('del');
2
+ const {exec} = require('child_process');
3
+ const fs = require('fs-extra');
4
+ const globby = require('globby');
5
+ const gulp = require('gulp');
6
+ const g_print = require('gulp-print');
7
+ const path = require('path');
8
+ const sass = require('gulp-sass')(require('sass'));
9
+ const TclConfig = require('../../lib/tcl-config');
10
+ const wws = require('../../lib/worker-with-spinner');
10
11
 
11
12
 
12
13
  g_print.setLogFunction((filepath) => _write(filepath.nostyle));
@@ -261,6 +262,11 @@ module.exports = {
261
262
  _write('Done.\n');
262
263
  })
263
264
  .then(() => cmdExec(`${fdt} editor build`))
265
+ .then(() => {
266
+ _info('Read project configuration and create json and css for Fonto:');
267
+ new TclConfig('..').outputJson('dist/assets').outputCss('dist');
268
+ _write('Done.\n');
269
+ })
264
270
  .then(() => [fdt])
265
271
  ;
266
272
  },
@@ -268,14 +274,27 @@ module.exports = {
268
274
  run ([fdt]) {
269
275
  return compileSass()
270
276
  .then(() => {
271
- _info('Starting sass watch:');
272
- gulp.watch('**/*.scss')
277
+ _info('Read project configuration and create json and css for Fonto:');
278
+ new TclConfig('..').outputJson('dev/assets').outputCss('dev');
279
+ _write('Done.\n');
280
+ })
281
+ .then(() => {
282
+ _info('Starting watch for tcl and sass files:');
283
+ gulp.watch(['**/*.scss', '../*.tcl', 'dev/index.html'])
273
284
  .on('all', (event, filepath) => {
274
285
  _write(event + ':', filepath);
275
- gulp.src('**/*.scss')
276
- .pipe(sass().on('error', sass.logError))
277
- .pipe(gulp.dest('.'))
278
- ;
286
+ if (filepath.endsWith('.scss')) {
287
+ gulp.src('**/*.scss')
288
+ .pipe(sass().on('error', sass.logError))
289
+ .pipe(gulp.dest('.'))
290
+ ;
291
+ }
292
+ else if (filepath.endsWith('.html')) {
293
+ new TclConfig('..').modifyFontoHtml('dev');
294
+ }
295
+ else if (filepath.endsWith('.tcl')) {
296
+ new TclConfig('..').outputJson('dev/assets').outputCss('dev');
297
+ }
279
298
  });
280
299
  _write('Done.\n');
281
300
  })
@@ -71,9 +71,9 @@ function init () {
71
71
  ])
72
72
  .then(() => {
73
73
  _info(`Next steps:
74
- 1. Go to https://bitbucket.org/repo/create?workspace=tangelosoftware and create a repository named "${path.basename(process.cwd()).replace(/\W/, '-')}", with options for including README/.gitignore disabled.
75
- 2. Open this folder in Sourcetree (ctrl+O), and push master branch to origin.
76
- `.replace(/^\s{8}/gm, ''));
74
+ 1. Go to https://bitbucket.org/repo/create?workspace=tangelosoftware and create a repository named "${path.basename(process.cwd()).replace(/\W/, '-')}", with options for including README/.gitignore disabled.
75
+ 2. Open this folder in Sourcetree (ctrl+O), and push master branch to origin.
76
+ `.replace(/^\s{8}/gm, ''));
77
77
  });
78
78
  });
79
79
  }
@@ -101,7 +101,7 @@ function clone ({clone: repoName}) {
101
101
  // Change directory for the next commands, it should have the same name as the clone argument from commandline at this point
102
102
  process.chdir('./' + repoName);
103
103
  cmdExec([
104
- // Retrieve TDI submodule for this client
104
+ // Retrieve TDI submodule for this client
105
105
  ['git submodule update --init', 'Fetch submodules such as TDI'],
106
106
  // Create symlinks for TDI
107
107
  ['tct b -s', 'Create TDI symlinks'],