@tangelo/tangelo-configuration-toolkit 1.18.0 → 1.20.0

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
@@ -1,10 +1,7 @@
1
1
  global._appStartTime = new Date();
2
2
 
3
- require('./src/lib/style-string-getters');
4
-
5
- String.prototype.toFws = function(){
6
- return this.replace(/\\/g, '/');
7
- };
3
+ require('./src/lib/set-string-getters.js');
4
+ require('./src/lib/set-global-functions.js');
8
5
 
9
6
 
10
7
  const {execSync} = require('child_process');
@@ -17,51 +14,12 @@ const execGitCommand = require('./src/lib/exec-git-command');
17
14
  const memoize = require('./src/lib/memoize');
18
15
 
19
16
 
20
- const appname = 'tangelo-configuration-toolkit';
21
-
22
-
23
- global._write = (...msg) => {
24
- msg = msg.map(m => typeof m == 'object' ? JSON.stringify(m, null, 2).cyan : m);
25
- console.log(msg.join(' ').replace(/^/gm, ' ')); // indent each line
26
- };
27
-
28
- global._info = (msg, time = false) => {
29
- if (time) {
30
- const tzDiff = new Date().getTimezoneOffset() * 60000;
31
- const time = new Date(Date.now() - tzDiff).toISOString().match(/\d\d:\d\d:\d\d/)[0];
32
- msg = `[${time}] ${msg}`;
33
- }
34
- console.log(msg.lgreen);
35
- };
36
-
37
- global._warn = msg => {
38
- console.log(msg.lyellow);
39
- };
40
-
41
- global._error = msg => {
42
- console.log(msg.red, '\n');
43
- process.exit();
44
- };
45
-
46
- global._perf = t1 => {
47
- const t2 = new Date();
48
- console.log(`\nExecution time: ${t2 - t1}ms`.blue);
49
- };
50
-
51
- global._formatDate = date =>
52
- date?.toLocaleDateString('en-gb', {day: 'numeric', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit'})
53
- ;
17
+ global._package = require('./package.json');
54
18
 
55
19
 
56
20
  global._devmode = !__dirname.includes('node_modules');
57
21
 
58
22
 
59
- global._packages = {
60
- TCT: {name: '@tangelo/tangelo-configuration-toolkit', version: require('./package.json')?.version},
61
- FDT: {name: '@fontoxml/fontoxml-development-tools'}
62
- };
63
-
64
-
65
23
  global._paths = {
66
24
  app: __dirname,
67
25
  apphome: path.join(homedir, '.tct'),
@@ -71,8 +29,7 @@ global._paths = {
71
29
  };
72
30
  _paths.appdata = path.join(_paths.apphome, 'appdata.json');
73
31
  _paths.appconfig = path.join(_paths.apphome, 'appconfig.json');
74
- _paths.repoconfig = path.join(_paths.repo, appname+'-repoconfig.json');
75
- _paths.apply = process.cwd().replace(_paths.repo, '').substr(1);
32
+ _paths.apply = process.cwd().replace(_paths.repo, '').slice(1);
76
33
 
77
34
 
78
35
  global._appdata = fs.readJsonSync(_paths.appdata, {throws: false}) || {};
@@ -105,7 +62,8 @@ catch({code, message}) {
105
62
  global._repoconfig = require('./src/lib/get-repoconfig')(_paths.repo);
106
63
 
107
64
 
108
- _appconfig.sharedConfigPath = path.resolve(_paths.appconfig, '..', _appconfig.sharedConfigPath || '', appname+'-appconfig.json');
65
+ const filenameSC = _package.name.split('/').pop() + '-appconfig.json';
66
+ _appconfig.sharedConfigPath = path.resolve(_paths.appconfig, '..', _appconfig.sharedConfigPath || '', filenameSC);
109
67
  _appconfig.shared = fs.readJsonSync(_appconfig.sharedConfigPath, {throws: false}) || {};
110
68
 
111
69
 
@@ -134,29 +92,32 @@ global._isPre51 = () => !fs.existsSync(path.join(_paths.repo, _paths.tdi, 'src')
134
92
 
135
93
  global._modulesTdi = {
136
94
  absolutePathTdi: path.join(_paths.repo, _paths.tdi),
137
- ensureDepsUpToDate() {
95
+ ensureDepsUpToDate(message) {
138
96
  if (this.depsUpToDate) return;
139
97
  try {
140
- _info('Checking installed dependencies in submodule');
98
+ if (message) _info('Checking installed dependencies in submodule');
141
99
  execSync('npm list', {cwd: this.absolutePathTdi, stdio: 'ignore'});
142
100
  } catch (e) {
143
- _info('Updating dependencies in submodule');
101
+ if (message) _info('Updating dependencies in submodule');
144
102
  execSync('npm update', {cwd: this.absolutePathTdi, stdio: 'ignore'});
145
103
  }
146
104
  this.depsUpToDate = true;
147
105
  },
148
- require(module) {
106
+ require(module, {throws = true, message = true} = {}) {
149
107
  if (path.extname(module) !== '.json') this.ensureDepsUpToDate();
150
- _info(`Loading ${path.join(_paths.tdi, 'tct', module)}\n`);
108
+ if (message) _info(`Loading ${path.join(_paths.tdi, 'tct', module)}\n`);
151
109
  try {
152
110
  return require(path.join(this.absolutePathTdi, 'tct', module));
153
111
  }
154
112
  catch (e) {
155
- _error('Module could not be loaded');
113
+ if (throws) _error('Module could not be loaded: ' + module);
114
+ else return undefined;
156
115
  }
157
116
  }
158
117
  };
159
118
 
119
+ global._settingsTdi = memoize(() => Object.assign(_package.settingsTdiDefault, _modulesTdi.require('settings.json', {throws: false, message: false}) ?? {}));
120
+
160
121
 
161
122
  process.on('beforeExit', () => {
162
123
  _write(); // print empty line before and after update check
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangelo/tangelo-configuration-toolkit",
3
- "version": "1.18.0",
3
+ "version": "1.20.0",
4
4
  "engines": {
5
5
  "node": ">=14.0.0"
6
6
  },
@@ -46,15 +46,20 @@
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": {
56
57
  "type": "git",
57
58
  "url": "git+ssh://git@bitbucket.org/tangelosoftware/tangelo-configuration-toolkit.git"
58
59
  },
59
- "homepage": "https://bitbucket.org/tangelosoftware/tangelo-configuration-toolkit#readme"
60
+ "homepage": "https://bitbucket.org/tangelosoftware/tangelo-configuration-toolkit#readme",
61
+ "settingsTdiDefault": {
62
+ "#": "Defaults for tangelo-default-implementation/tct/settings.json",
63
+ "transpileToES5": true
64
+ }
60
65
  }
package/src/cli.js CHANGED
@@ -6,7 +6,7 @@ module.exports = function cli () {
6
6
  _write();
7
7
 
8
8
  const txtTitle = 'Tangelo Configuration Toolkit'.bold.underline.cyan;
9
- const txtVersion = `v${_packages.TCT.version}`.lblack;
9
+ const txtVersion = `v${_package.version}`.lblack;
10
10
 
11
11
  yargs
12
12
  .scriptName('tct')
@@ -77,7 +77,7 @@ module.exports = function cli () {
77
77
  clone: {alias: 'c', desc: 'Clone a client repository and do basic setup', conflicts: ['i', 'r', 'u']},
78
78
  'update-repo': {alias: 'ur', desc: 'Update repository', conflicts: ['i', 'r', 'c']},
79
79
  'update-submodule': {alias: 'us', desc: 'Update TDI submodule, optionally pass release branch (without "release/")', conflicts: ['i', 'r', 'c']},
80
- dates: {alias: 'd', desc: '[hidden] Use i.c.w. update-submodule, pass 2 dates in format dd-mm-yyyy', conflicts: ['i', 'r', 'c'], implies: 'update-submodule', requiresArg: true, array: true, hidden: !_devmode}
80
+ dates: {alias: 'd', desc: '[hidden] Use i.c.w. update-submodule, pass 2 dates in format yyyy-mm-dd', conflicts: ['i', 'r', 'c'], implies: 'update-submodule', requiresArg: true, array: true, hidden: !_devmode}
81
81
  },
82
82
  handler: require('./modules/git')
83
83
  })
@@ -14,9 +14,9 @@ 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
- file.destination = path.join(remotedir, file.relative).toFws();
19
+ file.destination = path.join(remotedir, file.relative).toFws;
20
20
  files.push(file); // collect all files in array
21
21
  return cb();
22
22
  },
@@ -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
+ };
@@ -2,12 +2,14 @@ const {compare} = require('compare-versions');
2
2
  const exec = require('util').promisify(require('child_process').exec);
3
3
 
4
4
 
5
+ const packages = {TCT: _package};
6
+
5
7
  const doUpdateCheck = (pkg) => (
6
- exec(`npm view -g ${_packages[pkg].name} version`)
8
+ exec(`npm view -g ${packages[pkg].name} version`)
7
9
  .then(r => {
8
10
  const versionAvailable = r.stdout.match(/([\d/.]+)/)[1];
9
- if (!_packages[pkg].version) _warn(`${pkg} is not installed! Run ` + `npm i -g ${_packages[pkg].name}`.white);
10
- else if (compare(_packages[pkg].version, versionAvailable, '<')) {
11
+ if (!packages[pkg].version) _warn(`${pkg} is not installed! Run ` + `npm i -g ${packages[pkg].name}`.white);
12
+ else if (compare(packages[pkg].version, versionAvailable, '<')) {
11
13
  _appdata._update({[`updateCheck${pkg}`]: {executed: new Date(), versionAvailable}});
12
14
  return versionAvailable;
13
15
  }
@@ -25,14 +27,14 @@ module.exports = function packageUpdateCheck () {
25
27
  checkUpdatesDone = true;
26
28
 
27
29
  ['TCT'].forEach(pkg => {
28
- const updateMsg = (va) => `| Update ${pkg} to ${va} | ` + `npm i -g ${_packages[pkg].name}`.white;
30
+ const updateMsg = (va) => `| Update ${pkg} to ${va} | ` + `npm i -g ${packages[pkg].name}`.white;
29
31
  const {versionAvailable} = _appdata[`updateCheck${pkg}`] || {};
30
32
 
31
33
  if (new Date() - new Date(_appdata[`updateCheck${pkg}`]?.executed || 0) > 1000*3600*24*1) { // check every day
32
34
  doUpdateCheck(pkg).then(r => r && _warn(updateMsg(r)));
33
35
  }
34
36
  else if (versionAvailable) {
35
- if (compare(_packages[pkg].version, versionAvailable, '<')) _warn(updateMsg(versionAvailable));
37
+ if (compare(packages[pkg].version, versionAvailable, '<')) _warn(updateMsg(versionAvailable));
36
38
  else _appdata._update({[`updateCheck${pkg}`]: {executed: new Date()}});
37
39
  }
38
40
  });
@@ -0,0 +1,24 @@
1
+ global._write = (...msg) => {
2
+ msg = msg.map(m => typeof m == 'object' ? JSON.stringify(m, null, 2).cyan : m);
3
+ console.log(msg.join(' ').replace(/^/gm, ' ')); // indent each line
4
+ };
5
+ global._info = (msg, time = false) => {
6
+ if (time) {
7
+ const tzDiff = new Date().getTimezoneOffset() * 60000;
8
+ const time = new Date(Date.now() - tzDiff).toISOString().match(/\d\d:\d\d:\d\d/)[0];
9
+ msg = `[${time}] ${msg}`;
10
+ }
11
+ console.log(msg.lgreen);
12
+ };
13
+ global._warn = msg => {
14
+ console.log(msg.lyellow);
15
+ };
16
+ global._error = msg => {
17
+ console.log(msg.red, '\n');
18
+ process.exit();
19
+ };
20
+ global._perf = t1 => {
21
+ const t2 = new Date();
22
+ console.log(`\nExecution time: ${t2 - t1}ms`.blue);
23
+ };
24
+ global._formatDate = date => date?.toLocaleDateString('en-gb', {day: 'numeric', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit'});
@@ -15,4 +15,10 @@ Object.defineProperty(String.prototype, 'nostyle', {
15
15
  get () {
16
16
  return this.replace(/[\u001b\u009b][[()#;?]*(?:\d{1,4}(?:;\d{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');
17
17
  }
18
+ });
19
+
20
+ Object.defineProperty(String.prototype, 'toFws', {
21
+ get () {
22
+ return this.replace(/\\/g, '/');
23
+ }
18
24
  });
@@ -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
+ };
@@ -5,7 +5,7 @@ const path = require('path');
5
5
 
6
6
  function getRemotePath (...arr) {
7
7
  const fp = path.join(this.server.remotedir, ...arr);
8
- return this.server.remotedir.includes(':') ? fp : fp.toFws();
8
+ return this.server.remotedir.includes(':') ? fp : fp.toFws;
9
9
  }
10
10
 
11
11
 
@@ -82,7 +82,7 @@ function prepareForCopy (filter) {
82
82
  .map(p => '!' + (p.match(/^config/) ? p : '**/' + p.split('**/').pop()) + (p.match(/\/$/) ? '**' : '')) // negate expressions, remove base dir, suffix folders with **
83
83
  ;
84
84
 
85
- let transferPattern = path.join(_paths.apply, filter).toFws();
85
+ let transferPattern = path.join(_paths.apply, filter).toFws;
86
86
 
87
87
  // test if 'cmscustom/tdi' would be included, then add specifically, because following symlinks doesnt work with glob stars
88
88
  const tdiIncRegex = /^(config\/)?((\{\w*,?)?cmscustom(,?\w*\})?\/|\*\/)?\*\*/;
@@ -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
 
@@ -120,9 +121,10 @@ const createDeliveryPack = () => { // create install scripts if necessary, zip o
120
121
 
121
122
 
122
123
  const transfer = (paths, lrServer) => {
124
+ const jsFGlob = _settingsTdi().transpileToES5 ? ['**/*.js', '!**/hce/**/template_*', '!**/fonto/**', '!**/vendor/**', '!**/*.min.js'] : [];
125
+ const jsF = g_filter(jsFGlob, {restore: true});
123
126
  const xpsF = g_filter(['**/xopus/**/*.x*'], {restore: true});
124
127
  const sassF = g_filter(['**/*.scss'], {restore: true});
125
- const jsF = g_filter(['**/*.js', '!**/hce/**/template_*', '!**/fonto/**', '!**/vendor/**', '!**/*.min.js'], {restore: true});
126
128
  const shF = g_filter(['**/*.sh'], {restore: true});
127
129
  const srcset = s.create(paths);
128
130
  const files = [];
@@ -159,6 +161,7 @@ const transfer = (paths, lrServer) => {
159
161
  .pipe(xpsF)
160
162
  .pipe(g_resolveIncl())
161
163
  .pipe(xpsF.restore)
164
+ .pipe(g_tcl())
162
165
  .pipe(jsF)
163
166
  .pipe(g_sourcemaps.init())
164
167
  .pipe(g_babel({presets: [[babel_pe, {modules: false}]], comments: false, minified: true})) // function must be executed here, otherwise second execution during watch fails
@@ -77,7 +77,7 @@ module.exports = function deploy (argv) {
77
77
  // the "dist" folder isn't watched properly: it does not detect "assets" anymore after building once
78
78
  !/cmscustom.+fonto[\\/]/.test(filepath) ||
79
79
  /fonto[\\/]dist[\\/]/.test(filepath) ||
80
- (/fonto[\\/]dev[\\/]/.test(filepath)) ||
80
+ (/fonto[\\/]dev[\\/]/.test(filepath) && c.envDev) ||
81
81
  /fonto[\\/]packages[\\/]sx-shell-.*?[\\/]assets[\\/]schemas[\\/]/.test(filepath)
82
82
  )
83
83
  ) {
@@ -3,7 +3,7 @@ const globby = require('globby');
3
3
  const path = require('path');
4
4
 
5
5
 
6
- const relPath = (d, p) => path.relative(d, p).toFws();
6
+ const relPath = (d, p) => path.relative(d, p).toFws;
7
7
  const resolveBind = (d, p) => p.replace('#{cmscustompath}', 'cmscustom/').replace('{$rsrcPath}', (d.replace('stylesheets', 'resources')+'/'));
8
8
 
9
9
 
@@ -98,11 +98,11 @@ module.exports = {
98
98
  },
99
99
 
100
100
  addToCache (filepath) {
101
- if (this.potentialBaseFilesCache) this.potentialBaseFilesCache.push(filepath.toFws());
101
+ if (this.potentialBaseFilesCache) this.potentialBaseFilesCache.push(filepath.toFws);
102
102
  },
103
103
 
104
104
  removeFromCache (filepath) {
105
- if (this.potentialBaseFilesCache) this.potentialBaseFilesCache = this.potentialBaseFilesCache.filter(fp => fp != filepath.toFws());
105
+ if (this.potentialBaseFilesCache) this.potentialBaseFilesCache = this.potentialBaseFilesCache.filter(fp => fp != filepath.toFws);
106
106
  }
107
107
 
108
108
  };
@@ -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
  })
@@ -5,23 +5,25 @@ const globby = require('globby');
5
5
  const path = require('path');
6
6
 
7
7
 
8
- const fdtCommand = fv => `npx -y ${_packages.FDT.name}@${fv.replace(/^(7\.|8\.[012]\.).*/, '3.12.0')}`;
8
+ const fdtPackage = '@fontoxml/fontoxml-development-tools';
9
+ const fdtCommand = fv => `npx -y ${fdtPackage}@${fv.replace(/^(7\.|8\.[012]\.).*/, '3.12.0')}`;
9
10
 
10
11
  module.exports = function fonto (argv) {
11
12
 
12
13
  const allowedFontoVersionRegex = (() => {
13
- const cvRegex = _modulesTdi.require('fonto/compatibleVersions.json')?.regex;
14
+ const cvRegex = _settingsTdi().compatibleFontoVersions ?? _modulesTdi.require('fonto/compatibleVersions.json', {throws: false})?.regex;
14
15
  if (cvRegex) return RegExp(cvRegex);
15
16
 
16
17
  // old way: a regex for each basecommit is stored in global._git.commitTdi
18
+ _info('Fallback to list of commits for determining compatible Fonto versions\n');
17
19
  for (const fv of _git.commitTdi.fontoVersions) {
18
20
  if (_git.commitTdi.after(fv.commitHash)) return fv.regex;
19
21
  }
20
22
  })();
21
23
 
22
24
  // check if FDT is not installed globally, because then it won't be possible to use specific versions with npx
23
- if (fs.pathExistsSync(path.join(_appdata.npmPath, 'node_modules', _packages.FDT.name))) {
24
- _error(`A global installation of FDT has been found! Remove it first.\nExecute: npm r -g ${_packages.FDT.name}`);
25
+ if (fs.pathExistsSync(path.join(_appdata.npmPath, 'node_modules', fdtPackage))) {
26
+ _error(`A global installation of FDT has been found! Remove it first.\nExecute: npm r -g ${fdtPackage}`);
25
27
  }
26
28
 
27
29
  process.chdir(_paths.apply || '.');
@@ -50,7 +52,7 @@ module.exports = function fonto (argv) {
50
52
 
51
53
  if (fontoVersionNew === 'latest') {
52
54
  const data = execSync(`${fdtCommand(fontoVersionCurrent)} editor versions`, {encoding: 'UTF-8'});
53
- fontoVersionNew = data.match(/\d+\.\d+\.\d+/g).filter(v => allowedFontoVersionRegex.test(v))[0];
55
+ fontoVersionNew = data.match(/\d+\.\d+\.\d+/g).find(v => allowedFontoVersionRegex.test(v));
54
56
  }
55
57
  else if (!allowedFontoVersionRegex.test(fontoVersionNew)) {
56
58
  _error(`Fonto version ${fontoVersionNew} is not compatible with the current TDI submodule commit!\nExecute: ${'tct fonto --init latest'.cyan}`);
@@ -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'],
@@ -123,6 +123,7 @@ function updateRepo () {
123
123
  const fontoLocations = globby.sync('*/*/fonto/manifest.json', {cwd: path.join(_paths.repo, 'config/cmscustom')});
124
124
  const fontoVersions = {};
125
125
  fontoLocations.forEach(p => {fontoVersions[p] = readFontoVersionFromFile(p);});
126
+ const tdiLogBeforeUpdate = _git.commitTdi.local();
126
127
 
127
128
  _info(`Fetch all`);
128
129
  const cmdFetch = execGitCommand('fetch -pf --all', _paths.repo);
@@ -138,11 +139,24 @@ function updateRepo () {
138
139
 
139
140
  if (fontoLocations.find(p => fontoVersions[p] !== readFontoVersionFromFile(p))) _warn(`\nChanges in Fonto instance versions have been pulled. Therefore you must execute ${'tct fonto --init'.cyan} before building and deploying Fonto.`);
140
141
 
141
- _info(`\nRetrieve submodules that belong to this repo-commit`); // update submodule recursively (set to version that belongs to repo)
142
- _write(execGitCommand(`submodule update --recursive`, _paths.repo));
143
- _info(`Submodule checked out at commit:`);
142
+ // update submodule recursively (set to version that belongs to repo)
143
+ execGitCommand(`submodule update --recursive`, _paths.repo);
144
+
145
+ // clear memoize cache; which is filled with the old TDI data due to tdiLogBeforeUpdate
146
+ _git.commitTdi.local.clear();
144
147
  const tdiLog = _git.commitTdi.local();
145
- _write([_formatDate(tdiLog.date), tdiLog.tags, tdiLog.hash].filter(v=>v).join(' - '));
148
+
149
+ _info(`\nTDI submodule:`);
150
+ _write(`Submodule in repo-commit: ${[_formatDate(tdiLog.date), tdiLog.tags, tdiLog.hash].filter(v=>v).join(' - ')}`);
151
+
152
+ if (tdiLog.date < tdiLogBeforeUpdate.date) {
153
+ _write(`Restore TDI submodule because it was newer before the repository update:`);
154
+ execGitCommand(`checkout ${tdiLogBeforeUpdate.hash}`, path.join(_paths.repo, _paths.tdi));
155
+ _write(`Submodule checked out: ${[_formatDate(tdiLogBeforeUpdate.date), tdiLogBeforeUpdate.tags, tdiLogBeforeUpdate.hash].filter(v=>v).join(' - ')}\n`);
156
+ }
157
+ else {
158
+ _write(`Submodule in repo-commit is checked out\n`);
159
+ }
146
160
 
147
161
  const tdiBranch = getTdiBranch();
148
162
  _info(`\nTDI branch ${tdiBranch.name} is ${tdiBranch.commitsBehind} commits behind.\nUpdate TDI submodule to latest version with ${'tct git --update-submodule'.cyan}`);
@@ -51,7 +51,7 @@ module.exports = function migrate (argv) {
51
51
  a.script = cmdlScript.value;
52
52
  }
53
53
 
54
- let filter = path.join(_paths.apply, argv.filter??'**').toFws(); // Default set filter with filter added to the command argument -f
54
+ let filter = path.join(_paths.apply, argv.filter??'**').toFws; // Default set filter with filter added to the command argument -f
55
55
 
56
56
  if (a.filter === 'projects' && _repoconfig.length > a.projects.length) {
57
57
  // push paths of chosen active documents to projectFolders (only if not all projects are chosen)
@@ -61,10 +61,7 @@ module.exports = function sql (argv) {
61
61
  .prompt([
62
62
  {
63
63
  message: 'Choose projects: ', name: 'projects', type: 'checkbox', validate: v => !!v[0],
64
- choices:
65
- _repoconfig.projects
66
- ? _repoconfig.projects.map(p => ({name: p.name, value: p})) // when using repoconfig file (old)
67
- : _repoconfig.map(p => ({name: `${p.customer_name} ${p.project_name}`, value: p}))
64
+ choices: _repoconfig.map(p => ({name: `${p.customer_name} ${p.project_name}`, value: p}))
68
65
  },
69
66
  {message: 'Database TNS name: ', name: 'db', default: _appconfig.defaultDatabase},
70
67
  {message: 'TANCMS password: ', name: 'pw', default: 'tancms'}