@fontoxml/fontoxml-development-tools 3.9.0-beta.1 → 3.9.0-beta.2

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.
Files changed (24) hide show
  1. package/npm-shrinkwrap.json +17998 -9575
  2. package/package.json +14 -12
  3. package/src/editorVersions.js +23 -0
  4. package/src/modules/editor/src/commands/command.run.controller.js +7 -12
  5. package/src/modules/editor/src/getWebpackConfig.js +178 -33
  6. package/src/modules/editor/src/getWebpackDevMiddlewareConfig.js +16 -9
  7. package/src/modules/editor/src/templates/app-entry.cjs +69 -0
  8. package/src/modules/editor/src/webpackLoaders/generatedLoader.cjs +61 -79
  9. package/src/modules/editor/src/webpackLoaders/platformSourceMapLoader.cjs +7 -4
  10. package/src/modules/editor/src/webpackLoaders/symbolLoader.cjs +7 -7
  11. package/src/modules/editor/src/webpackLoaders/vendorsSourceMapLoader.cjs +5 -3
  12. package/src/modules/editor/src/webpackPlugins/CopyPlugin.js +172 -224
  13. package/src/modules/editor/src/webpackPlugins/DependenciesInLoadOrderPlugin.js +2 -11
  14. package/src/modules/editor/src/webpackPlugins/FdtOutputPlugin.js +102 -95
  15. package/src/modules/editor/src/webpackPlugins/RemoveExplicitExtensionResolvePlugin.js +19 -18
  16. package/src/modules/editor/src/webpackPlugins/ResolveImportAliasPlugin.js +10 -18
  17. package/src/modules/editor/src/webpackPlugins/UnitTestPlugin.js +13 -23
  18. package/src/modules/editor-pre-7-7-0/src/api/init/createConfigConfiguration.js +39 -10
  19. package/src/modules/editor-pre-7-7-0/src/api/schema/buildElementConfigurations.js +70 -0
  20. package/src/modules/editor-pre-7-7-0/src/api/schema/createSchemaExperiencePackages.js +31 -53
  21. package/src/modules/editor-pre-7-7-0/src/command.init.controller.js +4 -2
  22. package/src/modules/editor-pre-7-7-0/test/api/init/createConfigConfiguration.test.js +47 -0
  23. package/src/modules/editor-pre-7-7-0/test/api/schema/buildElementConfigurations.test.js +119 -0
  24. package/src/modules/editor/src/templates/app-entry.ts +0 -66
@@ -1,6 +1,23 @@
1
1
  import os from 'os';
2
+ import DirectoryWatcher from 'watchpack/lib/DirectoryWatcher.js';
2
3
  import webpack from 'webpack';
3
4
 
5
+ // Monkey patch watchpack to output any chokidar errors.
6
+ let response;
7
+ let watchErrorDebounceTimeout;
8
+
9
+ const originalOnWatcherError = DirectoryWatcher.prototype.onWatcherError;
10
+ DirectoryWatcher.prototype.onWatcherError = function (_error) {
11
+ clearTimeout(watchErrorDebounceTimeout);
12
+ watchErrorDebounceTimeout = setTimeout(() => {
13
+ (response || console).error(
14
+ '\nSomething went wrong while watching for file changes. Try closing applications, such as other development servers or IDEs, and restarting the development server to resolve this issue.'
15
+ );
16
+ }, 500);
17
+
18
+ return originalOnWatcherError.apply(this, arguments);
19
+ };
20
+
4
21
  const BUILD_MESSAGE_DEBOUNCE_IN_MS = 100;
5
22
 
6
23
  function getEndTimestamp(stats) {
@@ -9,156 +26,146 @@ function getEndTimestamp(stats) {
9
26
  ).toLocaleTimeString();
10
27
  }
11
28
 
12
- /**
13
- * This plugin wraps webpack's output to ensure only the import stuff gets
14
- * outputted to the command line.
15
- */
16
29
  export default class FdtOutputPlugin {
17
30
  constructor(options) {
18
31
  this.res = options.res;
19
- this.inDevelopmentMode = !!options.inDevelopmentMode;
32
+ this.inDevelopmentMode = options.inDevelopmentMode;
20
33
 
21
34
  this.hasClearLine =
22
35
  typeof this.res.config.stdout.clearLine === 'function';
23
36
 
24
37
  this.resetState();
38
+
39
+ response = this.res;
25
40
  }
26
41
 
27
42
  resetState() {
28
43
  this.previousBuildMessageTimestamp = 0;
44
+ this.previousBuildProgressIsMinify = false;
29
45
  this.previousProgressIsBuild = false;
30
46
  this.previousRoundedPercentage = null;
31
47
  }
32
48
 
33
- /**
34
- * @param {number} percentage
35
- * @param {string} message
36
- * @param {...string} args
37
- */
38
- progressHandler(percentage, _message, ..._args) {
39
- if (percentage >= 0.99) {
40
- return;
41
- }
49
+ handler(percentage, message, ...args) {
50
+ if (message === 'doneWithStats') {
51
+ this.previousProgressIsBuild = false;
52
+ const stats = args[0];
53
+ const endTimestamp = getEndTimestamp(stats);
54
+ const statusPrefix = stats
55
+ ? `Build done at ${endTimestamp} in ${
56
+ stats.endTime - stats.startTime
57
+ }ms`
58
+ : `Build done at ${endTimestamp}`;
59
+
60
+ if (stats && (stats.hasErrors() || stats.hasWarnings())) {
61
+ this.res.needsClearing = true;
62
+ this.res[stats.hasErrors() ? 'error' : 'notice'](
63
+ stats.hasErrors() && stats.hasWarnings()
64
+ ? `${statusPrefix}, with errors and warnings:`
65
+ : stats.hasErrors()
66
+ ? `${statusPrefix}, with errors:`
67
+ : `${statusPrefix}, with warnings:`,
68
+ false
69
+ );
42
70
 
43
- if (this.hasClearLine || !this.previousProgressIsBuild) {
71
+ const errorsAndWarnings = stats.toString({
72
+ all: false,
73
+ colors: true,
74
+ errors: true,
75
+ moduleTrace: true,
76
+ warnings: true,
77
+ });
78
+
79
+ this.res.raw(errorsAndWarnings);
80
+ this.res.raw(os.EOL + os.EOL);
81
+
82
+ this.res.needsClearing = false;
83
+ if (this.inDevelopmentMode) {
84
+ this.res.log(
85
+ 'Waiting for new changes...',
86
+ this.hasClearLine
87
+ );
88
+ }
89
+ } else {
90
+ this.res.needsClearing = true;
91
+ if (this.inDevelopmentMode) {
92
+ this.res.success(
93
+ `${statusPrefix}, waiting for new changes...`,
94
+ this.hasClearLine
95
+ );
96
+ } else {
97
+ this.res.success(
98
+ `${statusPrefix}.
99
+ `,
100
+ false
101
+ );
102
+ }
103
+ }
104
+ } else if (message === 'failedWithError') {
105
+ this.previousProgressIsBuild = false;
106
+ this.res.needsClearing = true;
107
+ const error = args[0];
108
+ const endTimestamp = getEndTimestamp();
109
+ this.res.error(
110
+ `Failed at ${endTimestamp} with error: ${
111
+ error && error.message ? error.message : error
112
+ }`,
113
+ this.hasClearLine
114
+ );
115
+ } else if (this.hasClearLine || !this.previousProgressIsBuild) {
44
116
  const roundedPercentage = Math.floor(percentage * 100);
45
117
  const buildMessageTimestamp = Date.now();
118
+ const buildProgressIsMinify =
119
+ message === 'chunk asset optimization';
46
120
 
47
121
  // Relax outputting of progress based on previous state.
48
122
  if (
49
123
  !this.previousProgressIsBuild ||
124
+ this.previousBuildProgressIsMinify !== buildProgressIsMinify ||
50
125
  (roundedPercentage > this.previousRoundedPercentage &&
51
126
  buildMessageTimestamp >
52
127
  this.previousBuildMessageTimestamp +
53
128
  BUILD_MESSAGE_DEBOUNCE_IN_MS)
54
129
  ) {
55
130
  this.previousBuildMessageTimestamp = buildMessageTimestamp;
131
+ this.previousBuildProgressIsMinify = buildProgressIsMinify;
56
132
  this.previousProgressIsBuild = true;
57
133
  this.previousRoundedPercentage = roundedPercentage;
58
134
 
59
135
  this.res.needsClearing = true;
60
136
 
137
+ const statusPrefix = buildProgressIsMinify
138
+ ? 'Minifying'
139
+ : 'Building';
61
140
  this.res.log(
62
141
  this.hasClearLine
63
- ? `Building... ${roundedPercentage}%`
64
- : `Building...`,
142
+ ? `${statusPrefix}... ${roundedPercentage}%`
143
+ : `${statusPrefix}...`,
65
144
  true
66
145
  );
67
146
  }
68
147
  }
69
148
  }
70
149
 
71
- /**
72
- * @param {webpack.Stats} stats
73
- */
74
- doneHandler(stats) {
75
- this.previousProgressIsBuild = false;
76
- const endTimestamp = getEndTimestamp(stats);
77
- const statusPrefix = stats
78
- ? `Build done at ${endTimestamp} in ${
79
- stats.endTime - stats.startTime
80
- }ms`
81
- : `Build done at ${endTimestamp}`;
82
-
83
- if (stats && (stats.hasErrors() || stats.hasWarnings())) {
84
- this.res.needsClearing = true;
85
- this.res.clearIfNeeded();
86
-
87
- const errorsAndWarnings = stats.toString({
88
- all: false,
89
- colors: true,
90
- errors: true,
91
- moduleTrace: true,
92
- warnings: true,
93
- });
94
- this.res.raw(errorsAndWarnings);
95
- this.res.raw(os.EOL + os.EOL);
96
-
97
- this.res[stats.hasErrors() ? 'error' : 'notice'](
98
- stats.hasErrors() && stats.hasWarnings()
99
- ? `${statusPrefix}, with errors and warnings.`
100
- : stats.hasErrors()
101
- ? `${statusPrefix}, with errors.`
102
- : `${statusPrefix}, with warnings.`,
103
- false
104
- );
105
- this.res.break();
106
-
107
- this.res.needsClearing = false;
108
- if (this.inDevelopmentMode) {
109
- this.res.log('Waiting for new changes...', this.hasClearLine);
110
- }
111
- } else {
112
- this.res.needsClearing = true;
113
- if (this.inDevelopmentMode) {
114
- this.res.success(
115
- `${statusPrefix}, waiting for new changes...`,
116
- this.hasClearLine
117
- );
118
- } else {
119
- this.res.success(
120
- `${statusPrefix}.
121
- `,
122
- false
123
- );
124
- }
125
- }
126
- }
127
-
128
- failedHandler(error) {
129
- this.previousProgressIsBuild = false;
130
- this.res.needsClearing = true;
131
- const endTimestamp = getEndTimestamp();
132
- this.res.error(
133
- `Failed at ${endTimestamp} with error: ${
134
- error && error.message ? error.message : error
135
- }`,
136
- this.hasClearLine
137
- );
138
- }
139
-
140
- /**
141
- * @param {webpack.Compiler} compiler
142
- */
143
150
  apply(compiler) {
144
151
  // Listen to compile hook before the webpack ProgressPlugin, to reset state.
145
- compiler.hooks.compile.tap(FdtOutputPlugin.name, () => {
152
+ compiler.hooks.compile.tap('FdtOutputPlugin', (_compilationParams) => {
146
153
  this.resetState();
147
154
  });
148
155
 
149
156
  // Use ProgressPlugin to handle most hooks.
150
157
  new webpack.ProgressPlugin({
151
- handler: this.progressHandler.bind(this),
158
+ handler: this.handler.bind(this),
152
159
  }).apply(compiler);
153
160
 
154
161
  // Listen to done hook and call handler WITH stats, which ProgressPlugin does not do.
155
- compiler.hooks.done.tap(FdtOutputPlugin.name, (stats) => {
156
- this.doneHandler(stats);
162
+ compiler.hooks.done.tap('FdtOutputPlugin', (stats) => {
163
+ this.handler(1, 'doneWithStats', stats);
157
164
  });
158
165
 
159
166
  // Listen to failed hook and call handler, which ProgressPlugin does not do.
160
- compiler.hooks.failed.tap(FdtOutputPlugin.name, (error) => {
161
- this.failedHandler(error);
167
+ compiler.hooks.failed.tap('FdtOutputPlugin', (error) => {
168
+ this.handler(1, 'failedWithError', error);
162
169
  });
163
170
  }
164
171
  }
@@ -1,35 +1,35 @@
1
- /** @typedef {import('enhanced-resolve').Resolver} Resolver */
2
-
3
1
  import getPaths from 'enhanced-resolve/lib/getPaths.js';
4
2
  import path from 'path';
5
3
 
6
- /**
7
- * This plugin ensures that import paths with an extension are always resolved
8
- * as if they were extensionless.
9
- */
4
+ /** @typedef {import('enhanced-resolve').Resolver} Resolver */
5
+
10
6
  export default class RemoveExplicitExtensionResolvePlugin {
11
7
  constructor(options = {}) {
12
8
  this.options = options;
9
+
10
+ // Performing this plugin as early as possible. An alternative is to do it in the raw-file
11
+ // step (which is the same stap as the AppendPlugin runs, used for resolve.extensions).
12
+ this.source = 'resolve';
13
+ this.target = 'resolve';
13
14
  }
14
15
 
15
16
  /**
16
17
  * @param {Resolver} resolver
17
18
  */
18
19
  apply(resolver) {
19
- const target = resolver.ensureHook('resolve');
20
+ const target = resolver.ensureHook(this.target);
20
21
  resolver
21
- .getHook('resolve')
22
+ .getHook(this.source)
22
23
  .tapAsync(
23
- RemoveExplicitExtensionResolvePlugin.name,
24
+ 'RemoveExplicitExtensionResolvePlugin',
24
25
  (request, resolveContext, callback) => {
25
26
  const basename = getPaths.basename(request.request);
26
27
  if (!basename) {
27
28
  return callback();
28
29
  }
29
30
 
30
- // If there is no extension, or the extension is not in the
31
- // list of extensions, do not try to resolve with different
32
- // extensions.
31
+ // If there is no extension, or the extension is not in the list of extensions, do
32
+ // not try to resolve with different extensions.
33
33
  const extension = path.extname(basename);
34
34
  const extensions = this.options.extensions || [];
35
35
  if (!extension || !extensions.includes(extension)) {
@@ -43,17 +43,18 @@ export default class RemoveExplicitExtensionResolvePlugin {
43
43
  );
44
44
  const dirPath = path.dirname(request.request);
45
45
  if (!request.request.startsWith(dirPath)) {
46
- return callback(
47
- new Error(
48
- `Failed to remove explicit extension for "${request.request}" to "${fileNameWithoutExtension}".`
49
- )
46
+ throw new Error(
47
+ `Failed to remove explicit extension for "${request.request}" to "${fileNameWithoutExtension}".`
50
48
  );
51
49
  }
52
50
  const obj = {
53
51
  ...request,
54
- request: `${dirPath}/${fileNameWithoutExtension}`,
52
+ request: resolver.join(
53
+ dirPath,
54
+ fileNameWithoutExtension
55
+ ),
55
56
  };
56
- return resolver.doResolve(
57
+ resolver.doResolve(
57
58
  target,
58
59
  obj,
59
60
  `removing extension ${extension}`,
@@ -1,37 +1,28 @@
1
- /** @typedef {import('webpack').Compiler} Compiler */
2
-
3
1
  import { importAliases as legacyImportAliases } from '../config.js';
4
2
 
5
- /**
6
- * This plugin resolves special import aliases to their actual location on disk,
7
- * e.g. 'fds/components' to 'fontoxml-vendors/src/fds/components'.
8
- */
9
3
  export default class ResolveImportAliasPlugin {
10
- inDevelopmentMode;
4
+ #inDevelopmentMode;
11
5
 
12
6
  constructor(options) {
13
- this.inDevelopmentMode = options.inDevelopmentMode || false;
7
+ this.#inDevelopmentMode = options.inDevelopmentMode || false;
14
8
  }
15
9
 
16
10
  _addImportAlias(importAliases, importAlias) {
17
11
  importAliases.set(
18
12
  importAlias.alias,
19
- (this.inDevelopmentMode && importAlias.devImport) ||
13
+ (this.#inDevelopmentMode && importAlias.devImport) ||
20
14
  importAlias.import
21
15
  );
22
16
  }
23
17
 
24
- /**
25
- * @param {Compiler} compiler
26
- */
27
18
  apply(compiler) {
28
19
  const importAliases = new Map();
29
20
 
30
21
  // On each compilation, gather all import aliases as early as possible
31
22
  // and store them so they can be used in the resolver plugin below.
32
23
  compiler.hooks.thisCompilation.tap(
33
- ResolveImportAliasPlugin.name,
34
- (compilation) => {
24
+ 'ResolveImportAliasPlugin',
25
+ (compilation, _compilationParams) => {
35
26
  // Start with a clean slate for each compilation.
36
27
  importAliases.clear();
37
28
 
@@ -86,12 +77,13 @@ export default class ResolveImportAliasPlugin {
86
77
 
87
78
  compiler.resolverFactory.hooks.resolver
88
79
  .for('normal')
89
- .tap(ResolveImportAliasPlugin.name, (resolver) => {
80
+ .tap('ResolveImportAliasPlugin', (resolver) => {
90
81
  const target = resolver.ensureHook('resolve');
82
+
91
83
  resolver.getHook('resolve').tapAsync(
92
84
  // Loosely based on Webpack's own alias resolve plugin.
93
85
  // See: https://github.com/webpack/enhanced-resolve/blob/main/lib/AliasPlugin.js
94
- ResolveImportAliasPlugin.name,
86
+ 'ResolveImportAliasPlugin',
95
87
  (request, resolveContext, callback) => {
96
88
  const innerRequest = request.request || request.path;
97
89
 
@@ -121,10 +113,10 @@ export default class ResolveImportAliasPlugin {
121
113
 
122
114
  // Don't allow other aliasing or raw request.
123
115
  if (result === undefined) {
124
- return callback(undefined, null);
116
+ return callback(null, null);
125
117
  }
126
118
 
127
- callback(undefined, result);
119
+ callback(null, result);
128
120
  }
129
121
  );
130
122
  }
@@ -1,26 +1,20 @@
1
- /** @typedef {import('webpack').Compiler} Compiler */
2
-
3
1
  import {
4
2
  addPackageDependencies,
5
3
  getPackageManifest,
6
4
  orderPackages,
7
5
  } from '../getDependenciesInLoadOrder.js';
8
6
 
9
- /**
10
- * This plugin fakes a proper dependency tree for unit tests.
11
- */
7
+ const plugin = { name: 'UnitTestPlugin' };
8
+
12
9
  export default class UnitTestPlugin {
13
10
  constructor(options) {
14
11
  this.options = options;
15
12
  }
16
13
 
17
- /**
18
- * @param {Compiler} compiler
19
- */
20
14
  apply(compiler) {
21
15
  compiler.hooks.thisCompilation.tap(
22
- UnitTestPlugin.name,
23
- (compilation) => {
16
+ plugin,
17
+ (compilation, _compilationParams) => {
24
18
  try {
25
19
  const packageRootFolders =
26
20
  this.options.paths.packageRootFolders;
@@ -30,14 +24,13 @@ export default class UnitTestPlugin {
30
24
  if (!compilation.packagesInfoInLoadOrder) {
31
25
  compilation.errors.push(
32
26
  new Error(
33
- `Could not get package load order information. Make sure the package exists, and ${UnitTestPlugin.name} runs after the dependencies in load order plugin.`
27
+ `Could not get package load order information. Make sure the package exists, and ${plugin.name} runs after the dependencies in load order plugin.`
34
28
  )
35
29
  );
36
30
  return;
37
31
  }
38
32
 
39
- // Map packagesInfoInLoadOrder back to
40
- // packageInfoByPackageName.
33
+ // Map packagesInfoInLoadOrder back to packageInfoByPackageName.
41
34
  const packageInfoByPackageName =
42
35
  compilation.packagesInfoInLoadOrder.reduce(
43
36
  (acc, packageInfo) => {
@@ -47,9 +40,8 @@ export default class UnitTestPlugin {
47
40
  Object.create(null)
48
41
  );
49
42
 
50
- // Add a virtual package for the tests, as devDependencies
51
- // may be circular if seen as dependencies of the package
52
- // itself.
43
+ // Add a virtual package for the tests, as devDependencies may be circular if seen as
44
+ // dependencies of the package itself.
53
45
  const manifest = getPackageManifest(rootPackagePath);
54
46
  const virtualTestPackageName = `${rootPackageName}-virtual-test-package`;
55
47
  const initialPackageInfo = {
@@ -70,8 +62,7 @@ export default class UnitTestPlugin {
70
62
  packageInfoByPackageName
71
63
  );
72
64
 
73
- // Now topologically sort everything again, and filter out
74
- // the virtual test package.
65
+ // Now topologically sort everything again, and filter out the virtual test package.
75
66
  compilation.packagesInfoInLoadOrder = orderPackages(
76
67
  packageInfoByPackageName
77
68
  ).filter(
@@ -81,13 +72,12 @@ export default class UnitTestPlugin {
81
72
 
82
73
  compilation.packagesInfoInLoadOrderError = null;
83
74
 
84
- // Set the package to unit test on the compilation for use
85
- // in the generated loader.
75
+ // Set the package to unit test on the compilation for use in the generated loader.
86
76
  compilation.unitTestPackageInfo =
87
77
  packageInfoByPackageName[rootPackageName];
88
78
  } catch (error) {
89
- // Do not directly push the error to compilation errors, but
90
- // let consumers handle errors themselves.
79
+ // Do not directly push the error to compilation errors, but let consumers
80
+ // handle errors themselves.
91
81
  compilation.packagesInfoInLoadOrder = null;
92
82
  compilation.packagesInfoInLoadOrderError = error;
93
83
  compilation.unitTestPackageInfo = null;
@@ -95,7 +85,7 @@ export default class UnitTestPlugin {
95
85
  }
96
86
  );
97
87
 
98
- compiler.hooks.done.tap(UnitTestPlugin.name, (stats) => {
88
+ compiler.hooks.done.tap(plugin, (stats) => {
99
89
  if (
100
90
  stats.compilation.errors &&
101
91
  stats.compilation.errors.length &&
@@ -4,6 +4,7 @@
4
4
  import babel from '@babel/core';
5
5
  import os from 'os';
6
6
 
7
+ import { isPre7170Editor } from '../../../../../editorVersions.js';
7
8
  import SchemaSummary from '../../../../schema/src/api/SchemaSummary.js';
8
9
  import addCommentToAstNode, {
9
10
  trickRecastIntoKeepingStatementsTogether,
@@ -27,9 +28,21 @@ const buildNamespaceManagerImport = template(
27
28
  const buildConfigurationSetUniqueIdConfigurations = template(
28
29
  `configurationManager.set('unique-id-configurations', CONFIGURATION_VALUE);`
29
30
  );
31
+
32
+ // Pre-7.17.0 versions had no xq template tags, so a different expression wil be used.
33
+ const buildConfigurationSetUniqueIdConfigurationsObjectPre7170 =
34
+ template.expression(
35
+ `{ selector: 'self::*', namespaceURI: null, localName: 'id', strategy: 'unique-for-document' }`
36
+ );
37
+
30
38
  const buildConfigurationSetUniqueIdConfigurationsObject = template.expression(
31
- `{ selector: 'self::*', namespaceURI: null, localName: 'id', strategy: 'unique-for-document' }`
39
+ `{ selector: xq\`self::*\`, namespaceURI: null, localName: 'id', strategy: 'unique-for-document' }`
32
40
  );
41
+
42
+ const buildXqImport = template(
43
+ `import xq from 'fontoxml-selectors/src/xq.js';`
44
+ );
45
+
33
46
  const buildNamespaceManagerAddNamespace = template(
34
47
  'namespaceManager.addNamespace(PREFIX, NAMESPACE_URI);'
35
48
  );
@@ -40,17 +53,29 @@ const buildParagraphNodeNameForPastingConfiguration = template(
40
53
  // Configuration constants.
41
54
  const PARAGRAPH_COUTERPART_ELEMENT_NAME = 'p';
42
55
 
56
+ export function buildConfigurationSetUniqueIdConfigurationStatement(version) {
57
+ return buildConfigurationSetUniqueIdConfigurations({
58
+ CONFIGURATION_VALUE: t.arrayExpression([
59
+ isPre7170Editor(version)
60
+ ? buildConfigurationSetUniqueIdConfigurationsObjectPre7170()
61
+ : buildConfigurationSetUniqueIdConfigurationsObject(),
62
+ ]),
63
+ });
64
+ }
65
+
43
66
  /**
44
67
  * Adds the configuration for unique id configurations.
45
68
  *
46
69
  * @param {Object} compiledSchemaResultsByXsdPath The compiled schema for a package by xsd path.
47
70
  * @param {ASTNode[]} statements The statements node array to add the configuration and/or comments to.
71
+ * @param {string} version The sdk version used to configure.
48
72
  *
49
73
  * @return {Promise}
50
74
  */
51
75
  async function addUniqueIdGenerationConfigurations(
52
76
  compiledSchemaResultsByXsdPath,
53
- statements
77
+ statements,
78
+ version
54
79
  ) {
55
80
  // Check if an id attribute exists in one of the schemas.
56
81
  const idAttributeExists = Object.values(
@@ -65,12 +90,7 @@ async function addUniqueIdGenerationConfigurations(
65
90
 
66
91
  // Generate configuration code.
67
92
  const configurationSetUniqueIdConfigurationStatement =
68
- buildConfigurationSetUniqueIdConfigurations({
69
- CONFIGURATION_VALUE: t.arrayExpression([
70
- buildConfigurationSetUniqueIdConfigurationsObject(),
71
- ]),
72
- });
73
-
93
+ buildConfigurationSetUniqueIdConfigurationStatement(version);
74
94
  const comments = [
75
95
  'Set to an array of objects to determine the identifying attributes for which a GUID will be',
76
96
  'generated automatically.',
@@ -113,6 +133,7 @@ async function addUniqueIdGenerationConfigurations(
113
133
  * @param {Object} prefixByNamespaceUri The namespace URIs with their prefix.
114
134
  * @param {Array} addons The selected addons for this editor instance.
115
135
  * @param {Object} compiledSchemaResultsByXsdPath The compiled schema for a package by xsd path.
136
+ * @param {string} version The sdk version used to configure.
116
137
  *
117
138
  * @return {Promise}
118
139
  */
@@ -120,7 +141,8 @@ export default async function createConfigConfiguration(
120
141
  configConfigurationJsFilePath,
121
142
  prefixByNamespaceUri,
122
143
  addons,
123
- compiledSchemaResultsByXsdPath
144
+ compiledSchemaResultsByXsdPath,
145
+ version
124
146
  ) {
125
147
  const importStatements = [];
126
148
  const statements = [];
@@ -209,10 +231,17 @@ export default async function createConfigConfiguration(
209
231
  }
210
232
  }
211
233
 
234
+ // Import xq for editor versions 7.17 or higher
235
+ if (!isPre7170Editor(version)) {
236
+ const xqImport = buildXqImport();
237
+ importStatements.push(xqImport);
238
+ }
239
+
212
240
  // Add unique id generation configuration.
213
241
  await addUniqueIdGenerationConfigurations(
214
242
  compiledSchemaResultsByXsdPath,
215
- statements
243
+ statements,
244
+ version
216
245
  );
217
246
 
218
247
  // Get all prefix and namespace entries, sorted naturally by prefix.
@@ -0,0 +1,70 @@
1
+ import babel from '@babel/core';
2
+
3
+ import { isPre7170Editor } from '../../../../../editorVersions.js';
4
+ import addCommentToAstNode from '../addCommentToAstNode.js';
5
+ import createCommentsForElement from './createCommentsForElement.js';
6
+
7
+ const t = babel.types;
8
+ const template = babel.template;
9
+
10
+ const buildConfigureAsRemoved = template(
11
+ 'configureAsRemoved(sxModule, SELECTOR);'
12
+ );
13
+ /**
14
+ * Builds an array of Babel templates containing the schema experience configuration for the given elements.
15
+ *
16
+ * @param {Object[]} elements The sx configuration elements for which to create Babel templates.
17
+ * @param {Object} prefixByNamespaceUri The namespace URIs with their prefix.
18
+ * @param {string} version The version of the editor. Pre-7.17.0 versions had no xq template tags, so a different declaration wil be generated.
19
+ *
20
+ * @return {Object}
21
+ */
22
+ export default function buildElementConfigurations(
23
+ elements,
24
+ prefixByNamespaceUri,
25
+ version
26
+ ) {
27
+ return (
28
+ elements
29
+ // Sort the elements ascending by the localName property.
30
+ .sort((a, b) =>
31
+ a.localName < b.localName
32
+ ? -1
33
+ : a.localName > b.localName
34
+ ? 1
35
+ : 0
36
+ )
37
+ .map((element) => {
38
+ const elementSelector = element.namespacePrefix
39
+ ? `self::${element.namespacePrefix}:${element.localName}`
40
+ : `self::${element.localName}`;
41
+ let stringTemplateExpression;
42
+ if (isPre7170Editor(version)) {
43
+ stringTemplateExpression = t.stringLiteral(elementSelector);
44
+ } else {
45
+ const tag = t.identifier('xq');
46
+
47
+ const quasi = t.templateLiteral(
48
+ [t.templateElement({ raw: elementSelector })],
49
+ []
50
+ );
51
+ stringTemplateExpression = t.taggedTemplateExpression(
52
+ tag,
53
+ quasi
54
+ );
55
+ }
56
+ const elementConfiguration = buildConfigureAsRemoved({
57
+ SELECTOR: stringTemplateExpression,
58
+ });
59
+
60
+ const comments = createCommentsForElement(
61
+ element,
62
+ prefixByNamespaceUri
63
+ );
64
+
65
+ // Add preceding comments to the element configuration.
66
+ addCommentToAstNode(elementConfiguration, comments);
67
+ return elementConfiguration;
68
+ })
69
+ );
70
+ }