@pi-r/android 0.2.2 → 0.3.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.
@@ -21,14 +21,14 @@ function finalize(instance) {
21
21
  const profileable = config.profileable;
22
22
  let modified;
23
23
  if (!existing) {
24
- source = (0, util_1.replaceAll)(source.replace(manifestPackage ? '{{package}}' : ' package="{{package}}"', manifestPackage || ''), (name) => {
24
+ source = (0, util_1.replaceAll)(source, (name) => {
25
25
  switch (name) {
26
26
  case 'supportsRtl':
27
27
  return supportsRtl === false ? 'false' : 'true';
28
28
  case 'label':
29
29
  return '@string/' + (label || 'app_name');
30
30
  case 'theme':
31
- return theme ? '@style/' + theme : '';
31
+ return '@style/' + (theme || 'Theme.Android2');
32
32
  case 'activityName':
33
33
  return activityName || '';
34
34
  case 'profileable':
@@ -46,7 +46,7 @@ function finalize(instance) {
46
46
  }
47
47
  let target = null;
48
48
  if (manifestPackage && (target = domutils.findOne(elem => elem.tagName === 'manifest', dom, true))) {
49
- target.attribs['package'] = manifestPackage;
49
+ target.attribs.package = manifestPackage;
50
50
  modified = true;
51
51
  }
52
52
  if (target = domutils.findOne(elem => elem.tagName === 'application', dom, true)) {
@@ -142,26 +142,27 @@ function finalize(instance) {
142
142
  return;
143
143
  }
144
144
  const app = domutils.findOne(elem => elem.tagName === 'application', dom, true);
145
- if (app) {
146
- for (const { name, resource, value } of metaData) {
147
- if (name && (resource || value)) {
148
- let item = domutils.findOne(elem => elem.tagName === 'meta-data' && elem.attribs['android:name'] === name, app.childNodes);
149
- if (!item) {
150
- domutils.appendChild(app, item = new domhandler.Element('meta-data', { 'android:name': name }));
151
- domutils.append(item, new domhandler.Text('\n'));
152
- }
153
- else if (item.attribs['android:resource'] === resource || item.attribs['android:value'] === value) {
154
- continue;
155
- }
156
- if (resource) {
157
- item.attribs['android:resource'] = resource;
158
- }
159
- if (value) {
160
- item.attribs['android:value'] = value;
161
- }
162
- source = domserializer.default(dom, { xmlMode: true });
163
- modified = true;
145
+ if (!app) {
146
+ return;
147
+ }
148
+ for (const { name, resource, value } of metaData) {
149
+ if (name && (resource || value)) {
150
+ let item = domutils.findOne(elem => elem.tagName === 'meta-data' && elem.attribs['android:name'] === name, app.childNodes);
151
+ if (!item) {
152
+ domutils.appendChild(app, item = new domhandler.Element('meta-data', { 'android:name': name }));
153
+ domutils.append(item, new domhandler.Text('\n'));
164
154
  }
155
+ else if (item.attribs['android:resource'] === resource || item.attribs['android:value'] === value) {
156
+ continue;
157
+ }
158
+ if (resource) {
159
+ item.attribs['android:resource'] = resource;
160
+ }
161
+ if (value) {
162
+ item.attribs['android:value'] = value;
163
+ }
164
+ source = domserializer.default(dom, { xmlMode: true });
165
+ modified = true;
165
166
  }
166
167
  }
167
168
  }), { xmlMode: true, decodeEntities: false }).end(source);
@@ -10,7 +10,8 @@ function finalize(instance) {
10
10
  if (!profileable && !dependencies && !dataBinding && !versionName && !versionCode && !config.namespace) {
11
11
  return;
12
12
  }
13
- let { localUri, source, existing, kotlin } = instance.findTemplate(path.join(this.baseDirectory, config.mainParentDir), 'build.gradle', { detect: this.incremental !== 'staging', languageOf: 'gradle' });
13
+ const detect = this.incremental !== 'staging';
14
+ let { localUri, source, existing, kotlin } = instance.findTemplate(path.join(this.baseDirectory, config.mainParentDir), "build.gradle" /* GRADLE.FILENAME */, { detect, languageOf: 'gradle' });
14
15
  if (localUri && source && instance.canWrite(localUri, { ownPermissionOnly: true })) {
15
16
  let { namespace, javaVersion } = config, jvmTarget, modified;
16
17
  const upgrade = javaVersion > 0;
@@ -25,7 +26,7 @@ function finalize(instance) {
25
26
  if (!kotlin && items.some(value => value[1].endsWith('-ktx'))) {
26
27
  setModified(Document.updateGradle(source, ['plugins'], "id 'kotlin-android'", { multiple: true }));
27
28
  }
28
- const match = /dependencies\s+\{([^}]+)\}/.exec(source);
29
+ const match = /dependencies\s+\{((?:{[^}]*}|(?![{}])[\S\s])+)\}/.exec(source);
29
30
  if (match) {
30
31
  const writeImpl = (item) => 'implementation' + (kotlin ? `("${item.join(':')}")` : ` '${item.join(':')}'`);
31
32
  const pattern = kotlin ? /([ \t]*)implementation\((?:\s*"([^"]+)"\s*\))?/g : /([ \t]*)implementation(?:\s*\(?\s*["']([^"']+)["']\s*\)?|\s+((?:\s*(?:group|name|version)\s*:\s*["'][^"']+["']\s*,?){3}))?/g;
@@ -55,18 +56,28 @@ function finalize(instance) {
55
56
  }
56
57
  if (group && name) {
57
58
  let found = 0, index = -1;
58
- if (version) {
59
- index = items.findIndex(seg => seg[0] === group && seg[1] === name);
60
- if (index !== -1) {
61
- found = 1;
62
- if (version[0] !== '$' || !kotlin && impl[0].indexOf("'") !== -1) {
63
- const current = items[index][2].split('.').map(seg => +seg);
64
- const parts = version.split('.');
65
- for (let i = 0, value; i < parts.length; ++i) {
66
- if (isNaN(value = +parts[i]) || +current[i] > value) {
59
+ if (version && (index = items.findIndex(seg => seg[0] === group && seg[1] === name)) !== -1) {
60
+ found = 1;
61
+ if (version[0] !== '$' || !kotlin && impl[0].indexOf("'") !== -1) {
62
+ const semver = /^((\s*,\s*)?[([\]]((\s*,\s*)?\d+\.\d+(\s*,\s*)?)+[)\][])+$/;
63
+ const pending = items[index][2];
64
+ if (semver.test(pending)) {
65
+ found = 2;
66
+ }
67
+ else if (!semver.test(version)) {
68
+ const getArray = (value) => value.split(/[.-]/).map(seg => +seg);
69
+ const current = getArray(pending);
70
+ const previous = getArray(version);
71
+ for (let i = 0; i < previous.length; ++i) {
72
+ const a = previous[i];
73
+ const b = current[i];
74
+ if (isNaN(a) || b > a) {
67
75
  found = 2;
68
76
  break;
69
77
  }
78
+ if (isNaN(b) || b < a) {
79
+ break;
80
+ }
70
81
  }
71
82
  }
72
83
  }
@@ -99,9 +110,9 @@ function finalize(instance) {
99
110
  output = Document.updateGradle(output, ['android', 'buildFeatures'], 'compose = true');
100
111
  }
101
112
  else {
102
- output = Document.updateGradle(output, ['plugins'], "id 'org.jetbrains.kotlin.android'", { upgrade: true, multiple: true, addendum: `version '${instance.findVersion('org.jetbrains.kotlin:kotlin-stdlib', "1.8.21" /* VERSIONS.KOTLIN_STDLIB */)}'` });
113
+ 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.10" /* VERSIONS.KOTLIN_STDLIB */)}'` });
103
114
  output = Document.updateGradle(output, ['android', 'buildFeatures'], "compose true");
104
- output = Document.updateGradle(output, ['android', 'composeOptions'], `kotlinCompilerExtensionVersion '${instance.findVersion('kotlinCompilerExtensionVersion', "1.4.6" /* VERSIONS.KOTLIN_COMPILER */)}'`, true);
115
+ output = Document.updateGradle(output, ['android', 'composeOptions'], `kotlinCompilerExtensionVersion '${instance.findVersion('kotlinCompilerExtensionVersion', "1.5.5" /* VERSIONS.KOTLIN_COMPILER */)}'`, true);
105
116
  if (upgrade) {
106
117
  output = Document.updateGradle(output, ['android', 'kotlinOptions'], `jvmTarget = '${javaVersion}'`, true);
107
118
  }
@@ -203,6 +214,19 @@ function finalize(instance) {
203
214
  }
204
215
  }
205
216
  }
217
+ if (!existing) {
218
+ ({ localUri, source, existing, kotlin } = instance.findTemplate(this.baseDirectory, "build.gradle" /* GRADLE.FILENAME */, { detect, languageOf: 'gradle', subDir: 'static' }));
219
+ if (localUri && source && instance.canWrite(localUri, { ownPermissionOnly: true })) {
220
+ try {
221
+ if (instance.writeFile(localUri, source, { encoding: 'utf-8', ownPermissionOnly: true, throwsPermission: true })) {
222
+ this.add(localUri);
223
+ }
224
+ }
225
+ catch (err) {
226
+ this.writeFail(["Unable to write file" /* ERR_MESSAGE.WRITE_FILE */, path.basename(localUri)], err, 8192 /* LOG_TYPE.PERMISSION */);
227
+ }
228
+ }
229
+ }
206
230
  }
207
231
 
208
232
  module.exports = finalize;
@@ -4,14 +4,13 @@ const path = require("path");
4
4
  const util_1 = require("@e-mc/document/util");
5
5
  const parse_1 = require("@e-mc/document/parse");
6
6
  function finalize(instance) {
7
- const { dependencies, projectName, mainParentDir } = instance.config;
7
+ const { dependencies, projectName, manifest, mainParentDir } = instance.config;
8
8
  if (!dependencies && !projectName) {
9
9
  return;
10
10
  }
11
11
  let { localUri, source, existing, kotlin } = instance.findTemplate(this.baseDirectory, 'settings.gradle', { detect: this.incremental !== 'staging', languageOf: 'gradle' });
12
12
  if (localUri && source && instance.canWrite(localUri, { ownPermissionOnly: true })) {
13
- const targetName = projectName ? projectName.replace(/"/g, '\\"') : '';
14
- let modified;
13
+ let targetName = projectName?.replace(/"/g, '\\"'), modified;
15
14
  if (existing) {
16
15
  let match;
17
16
  if (dependencies) {
@@ -51,10 +50,14 @@ function finalize(instance) {
51
50
  }
52
51
  }
53
52
  else {
53
+ if (!targetName && (targetName = manifest?.package)) {
54
+ const index = targetName.lastIndexOf('.');
55
+ targetName = index !== -1 ? targetName.substring(index + 1) : '';
56
+ }
54
57
  source = (0, util_1.replaceAll)(source, (name) => {
55
58
  switch (name) {
56
59
  case 'projectName':
57
- return targetName;
60
+ return targetName || '';
58
61
  case 'name':
59
62
  return ':' + mainParentDir;
60
63
  default:
@@ -5,6 +5,7 @@ const fs = require("fs");
5
5
  const child_process = require("child_process");
6
6
  const types_1 = require("@e-mc/types");
7
7
  const Document = require("@e-mc/document");
8
+ const checkWin32 = (value) => value === "gradlew" /* STRINGS.GRADLEW */ && process.platform === 'win32' ? value + '.bat' : value;
8
9
  async function finalize(instance) {
9
10
  const commands = instance.config.commands;
10
11
  if (!commands || this.incremental === 'staging') {
@@ -25,7 +26,9 @@ async function finalize(instance) {
25
26
  else {
26
27
  return;
27
28
  }
28
- let { broadcastId, baseDirectory } = this, command = instance.settings.extensions?.task?.command, title, name, foundCwd;
29
+ const settings = instance.settings.extensions?.task || {};
30
+ const exec = settings.exec;
31
+ let { broadcastId, baseDirectory } = this, command = settings.command, uid, gid, title, filename, foundCwd;
29
32
  if (command) {
30
33
  if (command.indexOf('mvn') !== -1) {
31
34
  title = 'maven';
@@ -34,20 +37,20 @@ async function finalize(instance) {
34
37
  title = /([^\\/]+?)(?:\.[a-z]+)?$/i.exec(command)?.[1] || 'SPAWN';
35
38
  }
36
39
  command = path.normalize(command);
37
- if (!command.includes(path.sep)) {
38
- name = command;
40
+ if (!/[\\/]/.test(command = path.normalize(command))) {
41
+ filename = checkWin32(command);
39
42
  }
40
43
  command = Document.sanitizeCmd(command);
41
44
  }
42
45
  else {
43
- name = 'gradlew';
44
- command = '.' + path.sep + name;
46
+ filename = checkWin32("gradlew" /* STRINGS.GRADLEW */);
47
+ command = '.' + path.sep + filename;
45
48
  title = 'gradle';
46
49
  }
47
- if (name) {
50
+ if (filename) {
48
51
  try {
49
52
  let appDir = baseDirectory;
50
- while (!(foundCwd = fs.existsSync(path.join(appDir, name)))) {
53
+ while (!(foundCwd = fs.existsSync(path.join(appDir, filename)))) {
51
54
  const parent = path.dirname(appDir);
52
55
  if (parent === appDir) {
53
56
  break;
@@ -61,6 +64,15 @@ async function finalize(instance) {
61
64
  catch {
62
65
  }
63
66
  }
67
+ if ((0, types_1.isPlainObject)(exec)) {
68
+ let { uid: u, gid: g } = exec;
69
+ if ((u = parseInt(u)) >= 0) {
70
+ uid = u;
71
+ }
72
+ if ((g = parseInt(g)) >= 0) {
73
+ gid = g;
74
+ }
75
+ }
64
76
  for (const args of taskArgs) {
65
77
  if (instance.aborted) {
66
78
  return Promise.reject((0, types_1.createAbortError)());
@@ -70,7 +82,7 @@ async function finalize(instance) {
70
82
  await new Promise((resolve, reject) => {
71
83
  this.formatMessage(4 /* LOG_TYPE.PROCESS */, title, ['Executing task...', task], baseDirectory);
72
84
  let out = '', message = '';
73
- const { stdout, stderr } = child_process.spawn(command, Document.sanitizeArgs(args), { cwd: baseDirectory, shell: true, stdio: Document.hasLogType(32768 /* LOG_TYPE.STDOUT */) && !broadcastId ? 'inherit' : undefined, signal: instance.signal })
85
+ const { stdout, stderr } = child_process.spawn(command, Document.sanitizeArgs(args), { cwd: baseDirectory, shell: true, stdio: Document.hasLogType(32768 /* LOG_TYPE.STDOUT */) && !broadcastId ? 'inherit' : undefined, signal: instance.signal, uid, gid })
74
86
  .on('exit', code => {
75
87
  if (!code) {
76
88
  instance.addLog(types_1.STATUS_TYPE.INFO, out);
package/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import type { IFileManager } from '@e-mc/types/types/lib';
2
-
3
- import type { AndroidDocumentConstructor, DocumentAsset } from './types';
4
-
5
- declare const Android: AndroidDocumentConstructor<IFileManager<DocumentAsset>>;
6
-
1
+ import type { IFileManager } from '@e-mc/types/types/lib';
2
+
3
+ import type { AndroidDocumentConstructor, DocumentAsset } from './types';
4
+
5
+ declare const Android: AndroidDocumentConstructor<IFileManager<DocumentAsset>>;
6
+
7
7
  export = Android;
package/index.js CHANGED
@@ -163,9 +163,9 @@ class AndroidDocument extends Document {
163
163
  }
164
164
  }
165
165
  findTemplate(baseDir, filename, options) {
166
- let detect, languageOf;
166
+ let detect, languageOf, subDir;
167
167
  if (options) {
168
- ({ detect, languageOf } = options);
168
+ ({ detect, languageOf, subDir } = options);
169
169
  }
170
170
  let kotlin, language;
171
171
  if (languageOf) {
@@ -179,7 +179,14 @@ class AndroidDocument extends Document {
179
179
  const localUri = path.join(baseDir, filename);
180
180
  try {
181
181
  const existing = detect && fs.existsSync(localUri);
182
- const paths = language ? [language, filename] : [filename];
182
+ const paths = [];
183
+ if (language) {
184
+ paths.push(language);
185
+ }
186
+ if (subDir) {
187
+ paths.push(...Array.isArray(subDir) ? subDir : [subDir]);
188
+ }
189
+ paths.push(filename);
183
190
  let uri;
184
191
  if (!existing && !(uri = this.resolveDir('template', ...paths)) && !fs.existsSync(uri = path.join(__dirname, 'template', ...paths))) {
185
192
  throw (0, types_1.errorValue)("File not found" /* ERR_MESSAGE.NOTFOUND_FILE */, uri);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-r/android",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "description": "Android document constructor for E-mc.",
5
5
  "main": "index.js",
6
6
  "publishConfig": {
@@ -20,8 +20,8 @@
20
20
  "license": "MIT",
21
21
  "homepage": "https://github.com/anpham6/pi-r#readme",
22
22
  "dependencies": {
23
- "@e-mc/document": "^0.5.3",
24
- "@e-mc/types": "^0.5.3",
23
+ "@e-mc/document": "^0.6.0",
24
+ "@e-mc/types": "^0.6.0",
25
25
  "htmlparser2": "^9.0.0"
26
26
  }
27
27
  }
@@ -1,9 +1,11 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="{{package}}">
2
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
3
 
4
4
  <application
5
+ android:allowBackup="true"
5
6
  android:icon="@mipmap/ic_launcher"
6
7
  android:label="{{label}}"
8
+ android:roundIcon="@mipmap/ic_launcher_round"
7
9
  android:supportsRtl="{{supportsRtl}}"
8
10
  android:theme="{{theme}}">
9
11
  <activity
@@ -4,12 +4,12 @@ plugins {
4
4
 
5
5
  android {
6
6
  namespace ''
7
- compileSdk 33
7
+ compileSdk 34
8
8
 
9
9
  defaultConfig {
10
10
  applicationId ''
11
- minSdk 19
12
- targetSdk 33
11
+ minSdk 21
12
+ targetSdk 34
13
13
  versionCode 1
14
14
  versionName '1.0'
15
15
 
@@ -1,8 +1,8 @@
1
1
  pluginManagement {
2
2
  repositories {
3
- gradlePluginPortal()
4
3
  google()
5
4
  mavenCentral()
5
+ gradlePluginPortal()
6
6
  }
7
7
  }
8
8
 
@@ -0,0 +1,4 @@
1
+ plugins {
2
+ id 'com.android.application' version '8.2.0' apply false
3
+ id 'com.android.library' version '8.2.0' apply false
4
+ }
@@ -5,12 +5,12 @@ plugins {
5
5
 
6
6
  android {
7
7
  namespace ''
8
- compileSdk 33
8
+ compileSdk 34
9
9
 
10
10
  defaultConfig {
11
11
  applicationId ''
12
- minSdk 19
13
- targetSdk 33
12
+ minSdk 21
13
+ targetSdk 34
14
14
  versionCode 1
15
15
  versionName '1.0'
16
16
 
@@ -37,7 +37,7 @@ android {
37
37
  }
38
38
 
39
39
  dependencies {
40
- implementation 'androidx.core:core-ktx:1.10.0'
40
+ implementation 'androidx.core:core-ktx:1.12.0'
41
41
  testImplementation 'junit:junit:4.13.2'
42
42
  androidTestImplementation 'androidx.test.ext:junit:1.1.5'
43
43
  androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
@@ -1,8 +1,8 @@
1
1
  pluginManagement {
2
2
  repositories {
3
- gradlePluginPortal()
4
3
  google()
5
4
  mavenCentral()
5
+ gradlePluginPortal()
6
6
  }
7
7
  }
8
8
 
@@ -0,0 +1,5 @@
1
+ plugins {
2
+ id 'com.android.application' version '8.2.0' apply false
3
+ id 'com.android.library' version '8.2.0' apply false
4
+ id 'org.jetbrains.kotlin.android' version '1.9.10' apply false
5
+ }
@@ -1,23 +1,23 @@
1
1
  plugins {
2
2
  id("com.android.application")
3
- kotlin("android")
3
+ id("org.jetbrains.kotlin.android")
4
4
  }
5
5
 
6
6
  android {
7
7
  namespace = ""
8
- compileSdk(33)
8
+ compileSdk = 34
9
9
 
10
10
  defaultConfig {
11
11
  applicationId = ""
12
- minSdk(19)
13
- targetSdk(33)
12
+ minSdk = 21
13
+ targetSdk = 34
14
14
  versionCode = 1
15
15
  versionName = "1.0"
16
16
 
17
17
  testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
18
18
  }
19
19
  buildTypes {
20
- getByName("release") {
20
+ release {
21
21
  isDebuggable = false
22
22
  isMinifyEnabled = true
23
23
  isShrinkResources = false
@@ -38,8 +38,8 @@ java {
38
38
  }
39
39
 
40
40
  dependencies {
41
- implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.21")
42
- implementation("androidx.core:core-ktx:1.10.0")
41
+ implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.10")
42
+ implementation("androidx.core:core-ktx:1.12.0")
43
43
  testImplementation("junit:junit:4.13.2")
44
44
  androidTestImplementation("androidx.test.ext:junit:1.1.5")
45
45
  androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
@@ -1,18 +1,18 @@
1
- pluginManagement {
2
- repositories {
3
- gradlePluginPortal()
4
- google()
5
- mavenCentral()
6
- }
7
- }
8
-
9
- dependencyResolutionManagement {
10
- repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
11
- repositories {
12
- google()
13
- mavenCentral()
14
- }
15
- }
16
-
17
- rootProject.name = "${{projectName}}"
1
+ pluginManagement {
2
+ repositories {
3
+ google()
4
+ mavenCentral()
5
+ gradlePluginPortal()
6
+ }
7
+ }
8
+
9
+ dependencyResolutionManagement {
10
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
11
+ repositories {
12
+ google()
13
+ mavenCentral()
14
+ }
15
+ }
16
+
17
+ rootProject.name = "{{projectName}}"
18
18
  include("{{name}}")
@@ -0,0 +1,5 @@
1
+ plugins {
2
+ id("com.android.application") version "8.2.0" apply false
3
+ id("com.android.library") version "8.2.0" apply false
4
+ id("org.jetbrains.kotlin.android") version "1.9.10" apply false
5
+ }
package/types/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { FinalizedElement } from '@e-mc/types/lib/squared';
2
2
 
3
3
  import type { DocumentConstructor, IDocument, IFileManager } from '@e-mc/types/lib';
4
4
  import type { ExternalAsset } from '@e-mc/types/lib/asset';
5
- import type { DocumentDirectory as IDocumentDirectory, DocumentModule as IDocumentModule } from '@e-mc/types/lib/settings';
5
+ import type { DocumentDirectory as IDocumentDirectory, DocumentModule as IDocumentModule, ExecAction } from '@e-mc/types/lib/settings';
6
6
 
7
7
  import type { DocumentOutput } from './squared';
8
8
 
@@ -13,6 +13,7 @@ interface DocumentDirectory extends IDocumentDirectory {
13
13
  interface AndroidDocumentSettings extends PlainObject {
14
14
  extensions?: {
15
15
  task?: {
16
+ exec?: ExecAction;
16
17
  command?: string;
17
18
  };
18
19
  };
@@ -48,6 +49,7 @@ export interface TemplateData {
48
49
  export interface FindTemplateOptions {
49
50
  detect?: boolean;
50
51
  languageOf?: LanguageType;
52
+ subDir?: ArrayOf<string>;
51
53
  }
52
54
 
53
55
  export interface IAndroidDocument<T extends IFileManager<U>, U extends DocumentAsset = DocumentAsset> extends IDocument<T, U>, Pick<DocumentOutput, DocumentProperties> {