@pi-r/android 0.7.3 → 0.8.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.
@@ -4,18 +4,18 @@ const htmlparser2 = require("htmlparser2");
4
4
  const domhandler = require("domhandler");
5
5
  const domutils = require("domutils");
6
6
  const domserializer = require("dom-serializer");
7
- const util_1 = require("@e-mc/document/util");
8
7
  const types_1 = require("@e-mc/types");
8
+ const util_1 = require("@e-mc/document/util");
9
9
  const Parser = htmlparser2.Parser;
10
10
  const DomHandler = domhandler.DomHandler;
11
11
  const MANIFEST_ATTR = ['package', 'android:sharedUserId', 'android:sharedUserLabel', 'android:sharedUserMaxSdkVersion', 'android:versionCode', 'android:versionName', 'android:installLocation'];
12
- module.exports = function finalize(instance) {
12
+ function finalize(instance) {
13
13
  const config = instance.config;
14
14
  const manifest = config.manifest;
15
15
  if (!manifest) {
16
16
  return;
17
17
  }
18
- let { localUri, source, existing } = instance.findTemplate(path.join(this.baseDirectory, config.mainParentDir, config.mainSrcDir), "AndroidManifest.xml", { detect: this.incremental !== 'staging' });
18
+ let { localUri, source, existing } = instance.findTemplate(path.join(this.baseDirectory, config.mainParentDir, config.mainSrcDir), "AndroidManifest.xml", { detect: instance.detect(this) });
19
19
  if (localUri && source && instance.canWrite(localUri, { ownPermissionOnly: true })) {
20
20
  const { supportsRtl, label, theme, activity, metaData = [], activityName, fontProvider } = manifest.application || {};
21
21
  const profileable = config.profileable;
@@ -28,7 +28,7 @@ module.exports = function finalize(instance) {
28
28
  case 'label':
29
29
  return '@string/' + (label || 'app_name');
30
30
  case 'theme':
31
- return '@style/' + (theme || 'Theme.Android2');
31
+ return '@style/' + (theme || 'Theme.Android4');
32
32
  case 'activityName':
33
33
  return activityName || '';
34
34
  case 'profileable':
@@ -65,7 +65,7 @@ module.exports = function finalize(instance) {
65
65
  if (activityName) {
66
66
  for (const item of activities) {
67
67
  const intentFilter = domutils.findAll(elem => elem.tagName === 'intent-filter', [item]);
68
- if (intentFilter.length) {
68
+ if (intentFilter.length > 0) {
69
69
  const action = domutils.findOne(elem => elem.tagName === 'action' && elem.attribs['android:name'] === 'android.intent.action.MAIN', intentFilter);
70
70
  if (action) {
71
71
  const attribs = item.attribs;
@@ -131,14 +131,14 @@ module.exports = function finalize(instance) {
131
131
  metaData.push({ name: 'preloaded_fonts', resource: '@array/' + fontProvider });
132
132
  }
133
133
  const keys = Object.keys(manifest).map(attr => MANIFEST_ATTR.includes(attr) ? attr : attr !== 'package' && MANIFEST_ATTR.includes('android:' + attr) ? attr : '').filter(item => item);
134
- if (keys.length || (0, types_1.isArray)(metaData)) {
134
+ if (keys.length > 0 || (0, types_1.isArray)(metaData)) {
135
135
  new Parser(new DomHandler((err, dom) => {
136
136
  if (err) {
137
137
  instance.writeFail(['Unable to parse XML document', "AndroidManifest.xml"], err, 0);
138
138
  return;
139
139
  }
140
140
  let target = null;
141
- if (keys.length && (target = domutils.findOne(elem => elem.tagName === 'manifest', dom, true))) {
141
+ if (keys.length > 0 && (target = domutils.findOne(elem => elem.tagName === 'manifest', dom, true))) {
142
142
  for (let key of keys) {
143
143
  if (!key.startsWith('android:') && key !== 'package') {
144
144
  key = 'android:' + key;
@@ -182,4 +182,5 @@ module.exports = function finalize(instance) {
182
182
  }
183
183
  }
184
184
  }
185
- };
185
+ }
186
+ module.exports = finalize;
@@ -1,14 +1,20 @@
1
1
  "use strict";
2
2
  const path = require("path");
3
- const util_1 = require("@e-mc/document/util");
4
- const types_1 = require("@e-mc/types");
3
+ const fs = require("fs");
5
4
  const Document = require("@e-mc/document");
5
+ const types_1 = require("@e-mc/types");
6
+ const util_1 = require("@e-mc/document/util");
6
7
  const REGEXP_SEMVER = /^((\s*,\s*)?[([\]]((\s*,\s*)?\d+\.\d+(\s*,\s*)?)+[)\][])+$/;
8
+ const REGEXP_DEPENDENCIES = /dependencies\s+\{((?:{[^{]*{|{[^}]*}|}[^}]*}|\\}*?|[^{}+])+)\}/;
9
+ const REGEXP_DEPENDENCY = /([ \t]*)(implementation|api|compileOnly(?:Api)?|runtimeOnly|(?:test|androidTest)(?:Implementation|RuntimeOnly|CompileOnly))(?:\s*\(?\s*["']([^"']+)["']\s*\)?|\s+((?:\s*(?:group|name|version)\s*:\s*(?:"[^"]+"|'[^']+')\s*,?){3}))?/gd;
10
+ const REGEXP_DEPENDENCY_KOTLIN = /([ \t]*)(implementation|api|compileOnly(?:Api)?|runtimeOnly|(?:test|androidTest)(?:Implementation|RuntimeOnly|CompileOnly))\((?:\s*(?:"([^"]+)"|((?:\s*(?:group|name|version)\s*=\s*"[^"]+"\s*,?){3}))\s*\))?/gd;
11
+ const REGEXP_VERSIONS = /([^\s]+)\s*=\s*(?:"([^":]+)"|'([^':]+)'|(\{(?:\s*(?:require|strictly|prefer|reject(?:All)?)\s*=\s*(?:"[^":]+"|'[^':]+')\s*,?)+\s*\}))/g;
12
+ const REGEXP_VERSIONS_LIB = /([^\s]+)\s*=\s*(?:\{\s*(group|name|module|version(?:\.ref)?)\s*=\s*(?:"([^"]+)"|'([^']+)'|(\{[^}]+\}))\s*,\s*(group|name|module|version(?:\.ref)?)\s*=\s*(?:"([^"]+)"|'([^']+)'|(\{[^}]+\}))(?:\s*,\s*(group|name|module|version(?:\.ref)?)\s*=\s*(?:"([^"]+)"|'([^']+)')|(\{[^}]+\}))?\s*\}|(?:"([^:]+:[^"]+)"|'([^:]+:[^']+)'))/gd;
7
13
  function isUpgrade(version, pending) {
8
- if (REGEXP_SEMVER.test(pending)) {
14
+ if (isSemVer(pending)) {
9
15
  return true;
10
16
  }
11
- if (!REGEXP_SEMVER.test(version)) {
17
+ if (!isSemVer(version)) {
12
18
  const previous = version.split(/[.-]/);
13
19
  const current = pending.split(/[.-]/);
14
20
  for (let i = 0; i < previous.length; ++i) {
@@ -27,15 +33,70 @@ function isUpgrade(version, pending) {
27
33
  }
28
34
  return false;
29
35
  }
30
- module.exports = function finalize(instance) {
31
- const { profileable, dependencies, dataBinding, versionName, versionCode, namespace, applicationId, mainParentDir } = instance.config;
32
- if (!profileable && !dependencies && !dataBinding && !versionName && !versionCode && !namespace && !applicationId) {
36
+ function writeMethod(kotlin, named, item, args = '', prefix = 'implementation') {
37
+ switch (parseInt(item[3])) {
38
+ case 0:
39
+ prefix = 'implementation';
40
+ break;
41
+ case 1:
42
+ prefix = 'api';
43
+ break;
44
+ case 2:
45
+ prefix = 'compileOnly';
46
+ break;
47
+ case 3:
48
+ prefix = 'compileOnlyApi';
49
+ break;
50
+ case 4:
51
+ prefix = 'runtimeOnly';
52
+ break;
53
+ case 5:
54
+ prefix = 'testImplementation';
55
+ break;
56
+ case 6:
57
+ prefix = 'testCompileOnly';
58
+ break;
59
+ case 7:
60
+ prefix = 'testRuntimeOnly';
61
+ break;
62
+ case 8:
63
+ prefix = 'androidTestImplementation';
64
+ break;
65
+ case 9:
66
+ prefix = 'androidTestCompileOnly';
67
+ break;
68
+ case 10:
69
+ prefix = 'androidTestRuntimeOnly';
70
+ break;
71
+ }
72
+ const [group, name, version] = item;
73
+ let dependency;
74
+ if (!name && !version) {
75
+ dependency = kotlin ? `(${group})` : ' ' + group;
76
+ }
77
+ else if (args || named) {
78
+ dependency = kotlin ? `(group = "${group}", name = "${name}"${version ? `, version = "${version}"` : ''})` : ` group: '${group}', name: '${name}'${version ? `, version: '${version}'` : ''})` + (args.endsWith(',') ? ',' : '');
79
+ }
80
+ else {
81
+ dependency = item.slice(0, 3).join(':');
82
+ if (dependency.endsWith(':')) {
83
+ dependency = dependency.substring(0, dependency.length - 1);
84
+ }
85
+ dependency = kotlin ? `("${dependency}")` : ` '${dependency}'`;
86
+ }
87
+ return prefix + dependency;
88
+ }
89
+ const isLatest = (value) => value === '' || value.startsWith('latest.');
90
+ const isSemVer = (value) => isLatest(value) || REGEXP_SEMVER.test(value);
91
+ const toCamelCase = (value) => value.replace(/-([a-z])/gi, (...capture) => capture[1].toUpperCase());
92
+ function finalize(instance) {
93
+ const { profileable, dependencies, dataBinding, jvmToolchain, versionName, versionCode, namespace, applicationId, mainParentDir } = instance.config;
94
+ if (!profileable && !dependencies && !dataBinding && !jvmToolchain && !versionName && !versionCode && !namespace && !applicationId) {
33
95
  return;
34
96
  }
35
- const options = { detect: this.incremental !== 'staging', languageOf: 'gradle' };
36
- let { localUri, source, existing, kotlin } = instance.findTemplate(path.join(this.baseDirectory, mainParentDir), "build.gradle", options);
97
+ let { localUri, source, existing, kotlin = false, language } = instance.findTemplate(path.join(this.baseDirectory, mainParentDir), "build.gradle", { detect: instance.detect(this), languageOf: 'gradle' });
37
98
  if (localUri && source && instance.canWrite(localUri, { ownPermissionOnly: true })) {
38
- const { javaVersion, dependencyScopes } = instance.config;
99
+ const javaVersion = instance.config.javaVersion;
39
100
  let jvmTarget, modified;
40
101
  const upgrade = javaVersion > 0;
41
102
  const setModified = (output) => {
@@ -45,10 +106,13 @@ module.exports = function finalize(instance) {
45
106
  }
46
107
  };
47
108
  if (dependencies) {
48
- let data;
109
+ const { dependencyScopes, versionCatalog } = instance.config;
110
+ let mavenData;
49
111
  const hasScope = (value) => (0, types_1.isArray)(dependencyScopes) && dependencyScopes.includes(value) || dependencyScopes === value;
50
112
  const snapshot = dependencyScopes === 1 || hasScope('snapshot');
51
- const getData = () => data ||= instance.findData('google-maven' + (snapshot ? '-snapshot' : '') + '.json', 'json');
113
+ const constraints = hasScope('constraints');
114
+ const checkVersion = (item, version, value) => !value && version.startsWith('{') && version.endsWith('}') ? false : snapshot || constraints && !item[2] || (version.length > 0 && !version.startsWith('$') || !kotlin && !!value?.includes("'")) && isUpgrade(version, item[2]);
115
+ const getData = () => mavenData ||= instance.findData('google-maven' + (snapshot ? '-snapshot' : '') + '.json', 'json');
52
116
  const items = dependencies.map(item => {
53
117
  let [groupId, artifactId, version, type] = item.split(':');
54
118
  if (!version || version === 'maven') {
@@ -61,13 +125,13 @@ module.exports = function finalize(instance) {
61
125
  version = '';
62
126
  }
63
127
  }
64
- return [groupId, artifactId, version || (snapshot ? 'latest.integration' : 'latest.release'), type];
128
+ return [groupId, artifactId, version || (snapshot ? 'latest.integration' : constraints ? '' : 'latest.release'), type];
65
129
  });
66
- if (dependencyScopes && (data = getData())) {
130
+ if (dependencyScopes && (mavenData = getData())) {
67
131
  const supplement = [];
68
132
  for (const item of items) {
69
133
  const [gId, id] = item;
70
- const target = data[gId]?.find(group => id === group.artifactId);
134
+ const target = mavenData[gId]?.find(group => id === group.artifactId);
71
135
  if (!target) {
72
136
  continue;
73
137
  }
@@ -95,8 +159,8 @@ module.exports = function finalize(instance) {
95
159
  if (current) {
96
160
  const t = parseInt(current[3]);
97
161
  if (t !== type) {
98
- const rangeVer = REGEXP_SEMVER.test(version);
99
- if (!REGEXP_SEMVER.test(current[2])) {
162
+ const rangeVer = isSemVer(version);
163
+ if (!isSemVer(current[2])) {
100
164
  if (rangeVer || type < t) {
101
165
  current[2] = version;
102
166
  found = true;
@@ -154,106 +218,201 @@ module.exports = function finalize(instance) {
154
218
  if (!kotlin && items.some(seg => seg[1].endsWith('-ktx'))) {
155
219
  setModified(Document.updateGradle(source, ['plugins'], "id 'kotlin-android'", { multiple: true }));
156
220
  }
157
- const match = /dependencies\s+\{((?:{[^{]*{|{[^}]*}|}[^}]*}|\\}*?|[^{}+])+)\}/.exec(source);
221
+ const match = REGEXP_DEPENDENCIES.exec(source);
158
222
  if (match) {
159
- const pattern = kotlin ? /([ \t]*)(implementation|api|compileOnly(?:Api)?|runtimeOnly|(?:test|androidTest)(?:Implementation|RuntimeOnly|CompileOnly))\((?:\s*(?:"([^"]+)"|((?:\s*(?:group|name|version)\s*=\s*"[^"]+"\s*,?){3}))\s*\))?/g : /([ \t]*)(implementation|api|compileOnly(?:Api)?|runtimeOnly|(?:test|androidTest)(?:Implementation|RuntimeOnly|CompileOnly))(?:\s*\(?\s*["']([^"']+)["']\s*\)?|\s+((?:\s*(?:group|name|version)\s*:\s*["'][^"']+["']\s*,?){3}))?/g;
160
- let content = match[1], named = false, indent, method;
161
- const writeMethod = (item, args, prefix = 'implementation') => {
162
- switch (parseInt(item[3])) {
163
- case 0:
164
- prefix = 'implementation';
165
- break;
166
- case 1:
167
- prefix = 'api';
168
- break;
169
- case 2:
170
- prefix = 'compileOnly';
171
- break;
172
- case 3:
173
- prefix = 'compileOnlyApi';
174
- break;
175
- case 4:
176
- prefix = 'runtimeOnly';
177
- break;
178
- case 5:
179
- prefix = 'testImplementation';
180
- break;
181
- case 6:
182
- prefix = 'testCompileOnly';
183
- break;
184
- case 7:
185
- prefix = 'testRuntimeOnly';
186
- break;
187
- case 8:
188
- prefix = 'androidTestImplementation';
189
- break;
190
- case 9:
191
- prefix = 'androidTestCompileOnly';
192
- break;
193
- case 10:
194
- prefix = 'androidTestRuntimeOnly';
195
- break;
196
- }
197
- let dependency;
198
- if (args || named) {
199
- const [group, name, version] = item;
200
- dependency = kotlin ? `(group = "${group}", name = "${name}", version = "${version}")` : ` group: '${group}', name: '${name}', version: '${version}'` + (args?.endsWith(',') ? ',' : '');
201
- }
202
- else {
203
- dependency = item.slice(0, 3).join(':');
204
- dependency = kotlin ? `("${dependency}")` : ` '${dependency}'`;
205
- }
206
- return prefix + dependency;
207
- };
208
- while (method = pattern.exec(match[1])) {
209
- let group, name, version;
210
- if (method[3]) {
211
- [group, name, version] = method[3].trim().split(/\s*:\s*/);
212
- }
213
- else if (method[4]) {
214
- const params = /(group|name|version)\s*[=:]\s*["']([^"']+)["']/g;
215
- let param;
216
- while (param = params.exec(method[4])) {
217
- const value = param[2].trim();
218
- switch (param[1]) {
219
- case 'group':
220
- group = value;
221
- break;
222
- case 'name':
223
- name = value;
224
- break;
225
- case 'version':
226
- version = value;
227
- break;
223
+ const newLine = source.includes('\r\n') ? '\r\n' : '\n';
224
+ const gradleDir = path.join(this.baseDirectory, 'gradle');
225
+ const template = instance.findTemplate(gradleDir, "libs.versions.toml", { detect: true, subDir: kotlin ? 'kotlin' : undefined, throwsDoesNotExist: false });
226
+ let content = match[1], named = false, versioning, indent;
227
+ if (template.localUri && template.source) {
228
+ versioning = kotlin && versionCatalog !== false || versionCatalog;
229
+ if (versioning || template.existing) {
230
+ const libraries = {};
231
+ const versions = {};
232
+ let config = template.source, catalog;
233
+ while (catalog = REGEXP_VERSIONS.exec(config)) {
234
+ versions[catalog[1]] = (catalog[2] || catalog[3] || catalog[4]).trim();
235
+ }
236
+ while (catalog = REGEXP_VERSIONS_LIB.exec(config)) {
237
+ const lib = {};
238
+ const inline = catalog[14] || catalog[15];
239
+ if (inline) {
240
+ [lib.group, lib.name] = inline.trim().split(':');
241
+ }
242
+ else {
243
+ let i = 0;
244
+ for (const attr of ['group', 'name', 'module', 'version.ref', 'version']) {
245
+ const index = catalog.findIndex(seg => seg === attr);
246
+ if (index !== -1) {
247
+ lib[attr] = (catalog[i = index + 1] || catalog[i = index + 2] || catalog[i = index + 3]).trim();
248
+ if (attr === 'version') {
249
+ lib.version_indices = catalog.indices[i];
250
+ }
251
+ }
252
+ }
253
+ }
254
+ let { group, name } = lib;
255
+ if (lib.module) {
256
+ [group, name] = lib.module.split(':');
257
+ }
258
+ if (group && name) {
259
+ const index = items.findIndex(seg => seg[0] === group && seg[1] === name);
260
+ if (index !== -1) {
261
+ const item = items[index];
262
+ items.splice(index, 1);
263
+ const ref = lib['version.ref'];
264
+ const version = ref ? versions[ref] : lib.version;
265
+ if (version && checkVersion(item, version)) {
266
+ if (ref) {
267
+ const target = new RegExp(`\\s${(0, types_1.escapePattern)(ref)}\\s*=\\s*(?:"([^":]+)"|'([^':]+)')`, 'd').exec(config);
268
+ if (target) {
269
+ const [start, end] = target.indices[1] || target.indices[2];
270
+ config = (0, util_1.spliceString)(config, start, end, versions[ref] = item[2], REGEXP_VERSIONS_LIB);
271
+ }
272
+ }
273
+ else if (lib.version_indices) {
274
+ const [start, end] = lib.version_indices;
275
+ config = (0, util_1.spliceString)(config, start, end, lib.version = item[2], REGEXP_VERSIONS_LIB);
276
+ }
277
+ }
278
+ }
279
+ libraries[catalog[1]] = lib;
228
280
  }
229
281
  }
230
- named = true;
231
- }
232
- if (group && name) {
233
- let found = 0, index = -1;
234
- if (version && (index = items.findIndex(seg => seg[0] === group && seg[1] === name)) !== -1) {
235
- found = (!version.startsWith('$') || !kotlin && method[0].includes("'")) && isUpgrade(version, items[index][2]) ? 2 : 1;
282
+ if (versioning && items.length > 0) {
283
+ let output = '[libraries]' + newLine, outputVer = '';
284
+ for (let i = 0, length = items.length; i < length; ++i) {
285
+ const item = items[i];
286
+ const [group, name, version] = item;
287
+ let key = group.replaceAll('.', '-');
288
+ if (libraries[key]) {
289
+ key += '-' + name.replaceAll('.', '-');
290
+ }
291
+ let versionRef;
292
+ found: {
293
+ for (const ref in versions) {
294
+ if (versions[ref] === version) {
295
+ for (const lib in libraries) {
296
+ if (libraries[lib]['version.ref'] === ref && (libraries[lib].group === group || libraries[lib].module?.startsWith(group + ':'))) {
297
+ versionRef = ref;
298
+ break found;
299
+ }
300
+ }
301
+ }
302
+ }
303
+ }
304
+ if (!versionRef) {
305
+ if (versions[versionRef = toCamelCase(name)]) {
306
+ const prefix = group.split('.').filter(seg => seg !== name).pop();
307
+ if (prefix) {
308
+ versionRef = toCamelCase(prefix + '-' + name);
309
+ }
310
+ else {
311
+ const baseRef = versionRef;
312
+ let j = 1;
313
+ do {
314
+ versionRef = baseRef + j++;
315
+ } while (versions[versionRef]);
316
+ }
317
+ }
318
+ versions[versionRef] = version;
319
+ outputVer += versionRef + ` = "${version}"` + newLine;
320
+ }
321
+ output += key + ` = { group = "${group}", name = "${name}", version.ref = "${versionRef}" }` + newLine;
322
+ item[0] = 'libs.' + key.replaceAll('-', '.');
323
+ item[1] = '';
324
+ item[2] = '';
325
+ libraries[key] = { group, name, "version.ref": versionRef };
326
+ }
327
+ let section = /\[libraries\]\s*/.exec(config);
328
+ const writeOutput = (value) => (0, util_1.spliceString)(config, section.index, section.index + section[0].length, value);
329
+ if (section) {
330
+ config = writeOutput(output);
331
+ }
332
+ else {
333
+ config += output;
334
+ }
335
+ if (outputVer) {
336
+ outputVer = '[versions]' + newLine + outputVer;
337
+ if (section = /\[versions\]\s*/.exec(config)) {
338
+ config = writeOutput(outputVer);
339
+ }
340
+ else {
341
+ config = outputVer + newLine + config;
342
+ }
343
+ }
344
+ REGEXP_VERSIONS.lastIndex = 0;
236
345
  }
237
- if (found) {
238
- if (found === 2) {
239
- content = content.replace(method[0].trim(), writeMethod(items[index], method[4], method[2]));
240
- modified = true;
346
+ if (instance.canWrite(template.localUri, { ownPermissionOnly: true }) && Document.createDir(gradleDir)) {
347
+ try {
348
+ if (instance.writeFile(template.localUri, config, { encoding: 'utf-8', ownPermissionOnly: true, throwsPermission: true })) {
349
+ this.add(template.localUri);
350
+ }
351
+ }
352
+ catch (err) {
353
+ this.writeFail(["Unable to write file", path.basename(template.localUri)], err, 8192);
241
354
  }
242
- items.splice(index, 1);
243
355
  }
244
- }
245
- if (method[1]) {
246
- indent = method[1];
356
+ REGEXP_VERSIONS_LIB.lastIndex = 0;
247
357
  }
248
358
  }
249
- if (items.length) {
250
- const newline = process.platform === 'win32' ? '\r\n' : '\n';
359
+ if (items.length > 0) {
360
+ if (!versioning) {
361
+ const pattern = kotlin ? REGEXP_DEPENDENCY_KOTLIN : REGEXP_DEPENDENCY;
362
+ pattern.lastIndex = 0;
363
+ let method;
364
+ while (method = pattern.exec(content)) {
365
+ let group, name, version;
366
+ if (method[1]) {
367
+ indent ||= method[1];
368
+ }
369
+ if (method[3]) {
370
+ [group, name, version] = method[3].trim().split(/\s*:\s*/);
371
+ }
372
+ else if (method[4]) {
373
+ const params = /(group|name|version)\s*[=:]\s*(?:"([^"]+)"|'([^']+)')/g;
374
+ let param;
375
+ while (param = params.exec(method[4])) {
376
+ const value = (param[2] || param[3]).trim();
377
+ switch (param[1]) {
378
+ case 'group':
379
+ group = value;
380
+ break;
381
+ case 'name':
382
+ name = value;
383
+ break;
384
+ case 'version':
385
+ version = value;
386
+ break;
387
+ }
388
+ }
389
+ named = true;
390
+ }
391
+ if (group && name) {
392
+ const index = items.findIndex(seg => seg[0] === group && seg[1] === name);
393
+ if (index !== -1) {
394
+ const item = items[index];
395
+ items.splice(index, 1);
396
+ if (!version) {
397
+ if (constraints) {
398
+ continue;
399
+ }
400
+ version = '';
401
+ }
402
+ if (checkVersion(item, version, method[0])) {
403
+ content = (0, util_1.spliceString)(content, method.index, method.index + method[0].length, method[1] + writeMethod(kotlin, named, item, method[4], method[2]) + newLine, pattern);
404
+ modified = true;
405
+ }
406
+ }
407
+ }
408
+ }
409
+ }
251
410
  indent ||= (0, util_1.getIndent)(source);
252
- content = items.reduce((a, b) => a + indent + writeMethod(b) + newline, content);
411
+ content = items.reduce((a, b) => a + indent + writeMethod(kotlin, named, b) + newLine, content);
253
412
  modified = true;
254
413
  }
255
414
  if (modified || !existing) {
256
- setModified(source.substring(0, match.index) + `dependencies {${content}}` + source.substring(match.index + match[0].length));
415
+ setModified((0, util_1.spliceString)(source, match.index, match.index + match[0].length, `dependencies {${content}}`));
257
416
  }
258
417
  }
259
418
  if (items.some(seg => seg[0] === 'androidx.compose.ui')) {
@@ -263,9 +422,12 @@ module.exports = function finalize(instance) {
263
422
  output = Document.updateGradle(output, ['android', 'buildFeatures'], 'compose = true');
264
423
  }
265
424
  else {
266
- output = Document.updateGradle(output, ['plugins'], "id 'org.jetbrains.kotlin.android'", { upgrade: true, multiple: true, addendum: `version '${instance.findVersion('org.jetbrains.kotlin:kotlin-stdlib', "1.9.24")}'` });
425
+ const stdLib = instance.findVersion('org.jetbrains.kotlin:kotlin-stdlib', "2.0.0");
426
+ output = Document.updateGradle(output, ['plugins'], "id 'org.jetbrains.kotlin.android'", { upgrade: true, multiple: true, addendum: `version '${stdLib}'` });
267
427
  output = Document.updateGradle(output, ['android', 'buildFeatures'], "compose true");
268
- output = Document.updateGradle(output, ['android', 'composeOptions'], `kotlinCompilerExtensionVersion '${instance.findVersion('kotlinCompilerExtensionVersion', "1.5.14")}'`, true);
428
+ if (stdLib.startsWith('1.')) {
429
+ output = Document.updateGradle(output, ['android', 'composeOptions'], `kotlinCompilerExtensionVersion '${instance.findVersion('kotlinCompilerExtensionVersion', "1.5.14")}'`, true);
430
+ }
269
431
  if (upgrade) {
270
432
  output = Document.updateGradle(output, ['android', 'kotlinOptions'], `jvmTarget = '${javaVersion}'`, true);
271
433
  }
@@ -291,6 +453,16 @@ module.exports = function finalize(instance) {
291
453
  }
292
454
  setModified(output);
293
455
  }
456
+ if (jvmToolchain) {
457
+ let output = source;
458
+ if (language === 'java') {
459
+ output = Document.updateGradle(output, ['java', 'toolchain'], kotlin ? `languageVersion.set(JavaLanguageVersion.of(${jvmToolchain}))` : `languageVersion = JavaLanguageVersion.of(${jvmToolchain})`, true);
460
+ }
461
+ else {
462
+ output = Document.updateGradle(output, ['kotlin'], kotlin ? `jvmToolchain(${jvmToolchain})` : 'jvmToolchain ' + jvmToolchain, true);
463
+ }
464
+ setModified(output);
465
+ }
294
466
  if (!existing) {
295
467
  const targetAPI = instance.targetAPI;
296
468
  let output = source;
@@ -372,16 +544,55 @@ module.exports = function finalize(instance) {
372
544
  }
373
545
  }
374
546
  if (!existing) {
375
- ({ localUri, source, existing, kotlin } = instance.findTemplate(this.baseDirectory, "build.gradle", { ...options, subDir: 'static' }));
376
- if (localUri && source && instance.canWrite(localUri, { ownPermissionOnly: true })) {
547
+ const template = instance.findTemplate(this.baseDirectory, "build.gradle", { detect: instance.detect(this), languageOf: 'gradle', subDir: 'static' });
548
+ if (template.localUri && template.source && instance.canWrite(template.localUri, { ownPermissionOnly: true })) {
377
549
  try {
378
- if (instance.writeFile(localUri, source, { encoding: 'utf-8', ownPermissionOnly: true, throwsPermission: true })) {
379
- this.add(localUri);
550
+ if (instance.writeFile(template.localUri, template.source, { encoding: 'utf-8', ownPermissionOnly: true, throwsPermission: true })) {
551
+ this.add(template.localUri);
380
552
  }
381
553
  }
382
554
  catch (err) {
383
- this.writeFail(["Unable to write file", path.basename(localUri)], err, 8192);
555
+ this.writeFail(["Unable to write file", path.basename(template.localUri)], err, 8192);
384
556
  }
385
557
  }
558
+ try {
559
+ const projectDir = instance.resolveDir('project');
560
+ if (projectDir) {
561
+ (function recurse(subDir, targetDir) {
562
+ fs.readdirSync(subDir, { withFileTypes: true }).forEach(item => {
563
+ const srcName = path.join(subDir, item.name);
564
+ if (item.isDirectory()) {
565
+ switch (/^\$\{([^}]+)\}$/.exec(item.name)?.[1]) {
566
+ case 'app':
567
+ if (instance.config.mainParentDir) {
568
+ recurse.call(this, srcName, path.join(targetDir, instance.config.mainParentDir));
569
+ }
570
+ break;
571
+ case 'src':
572
+ if (instance.config.mainSrcDir) {
573
+ recurse.call(this, srcName, path.join(targetDir, instance.config.mainSrcDir));
574
+ }
575
+ break;
576
+ default:
577
+ recurse.call(this, srcName, path.join(targetDir, item.name));
578
+ break;
579
+ }
580
+ }
581
+ else if (item.isFile()) {
582
+ const destDir = path.join(this.baseDirectory, targetDir);
583
+ const destName = path.join(destDir, item.name);
584
+ if (!Document.isPath(destName) && instance.canWrite(destName, { ownPermissionOnly: true }) && Document.createDir(destDir)) {
585
+ fs.copyFileSync(srcName, destName);
586
+ this.add(destName);
587
+ }
588
+ }
589
+ });
590
+ }).call(this, projectDir, './');
591
+ }
592
+ }
593
+ catch (err) {
594
+ this.writeFail("Path not found", err, 32);
595
+ }
386
596
  }
387
- };
597
+ }
598
+ module.exports = finalize;
@@ -2,12 +2,12 @@
2
2
  const path = require("path");
3
3
  const util_1 = require("@e-mc/document/util");
4
4
  const parse_1 = require("@e-mc/document/parse");
5
- module.exports = function finalize(instance) {
5
+ function finalize(instance) {
6
6
  const { dependencies, projectName, mainParentDir } = instance.config;
7
7
  if (!dependencies && !projectName) {
8
8
  return;
9
9
  }
10
- let { localUri, source, existing, kotlin } = instance.findTemplate(this.baseDirectory, "settings.gradle", { detect: this.incremental !== 'staging', languageOf: 'gradle' });
10
+ let { localUri, source, existing, kotlin } = instance.findTemplate(this.baseDirectory, "settings.gradle", { detect: instance.detect(this), languageOf: 'gradle' });
11
11
  if (localUri && source && instance.canWrite(localUri, { ownPermissionOnly: true })) {
12
12
  const targetName = projectName?.replace(/"/g, '\\"');
13
13
  let modified;
@@ -75,4 +75,5 @@ module.exports = function finalize(instance) {
75
75
  }
76
76
  }
77
77
  }
78
- };
78
+ }
79
+ module.exports = finalize;