react-native-legal 1.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +113 -0
- package/ReactNativeLegal.podspec +46 -0
- package/android/build.gradle +75 -0
- package/android/react-native-helpers.gradle +45 -0
- package/android/src/main/java/com/reactnativelegal/ReactNativeLegalActivity.kt +98 -0
- package/android/src/main/java/com/reactnativelegal/ReactNativeLegalModuleImpl.kt +19 -0
- package/android/src/main/java/com/reactnativelegal/ReactNativeLegalTurboPackage.kt +38 -0
- package/android/src/main/res/layout/activity_licenses.xml +28 -0
- package/android/src/main/res/values/styles.xml +7 -0
- package/android/src/main/res/values-v29/styles.xml +8 -0
- package/android/src/newarch/java/com/reactnativelegal/ReactNativeLegalModule.kt +17 -0
- package/android/src/oldarch/java/com/reactnativelegal/ReactNativeLegalModule.kt +23 -0
- package/app.plugin.js +1 -0
- package/bare-plugin/build/android/addListActivity.d.ts +4 -0
- package/bare-plugin/build/android/addListActivity.js +22 -0
- package/bare-plugin/build/android/androidCommand.d.ts +7 -0
- package/bare-plugin/build/android/androidCommand.js +25 -0
- package/bare-plugin/build/android/applyAndConfigureAboutLibrariesPlugin.d.ts +6 -0
- package/bare-plugin/build/android/applyAndConfigureAboutLibrariesPlugin.js +27 -0
- package/bare-plugin/build/android/declareAboutLibrariesPlugin.d.ts +6 -0
- package/bare-plugin/build/android/declareAboutLibrariesPlugin.js +27 -0
- package/bare-plugin/build/android/utils.d.ts +14 -0
- package/bare-plugin/build/android/utils.js +37 -0
- package/bare-plugin/build/index.d.ts +2 -0
- package/bare-plugin/build/index.js +9 -0
- package/bare-plugin/build/ios/addSettingsBundle.d.ts +4 -0
- package/bare-plugin/build/ios/addSettingsBundle.js +27 -0
- package/bare-plugin/build/ios/iosCommand.d.ts +7 -0
- package/bare-plugin/build/ios/iosCommand.js +23 -0
- package/bare-plugin/build/ios/registerLicensePlistBuildPhase.d.ts +7 -0
- package/bare-plugin/build/ios/registerLicensePlistBuildPhase.js +24 -0
- package/bare-plugin/build/ios/utils.d.ts +33 -0
- package/bare-plugin/build/ios/utils.js +98 -0
- package/bare-plugin/src/android/addListActivity.ts +22 -0
- package/bare-plugin/src/android/androidCommand.ts +23 -0
- package/bare-plugin/src/android/applyAndConfigureAboutLibrariesPlugin.ts +21 -0
- package/bare-plugin/src/android/declareAboutLibrariesPlugin.ts +21 -0
- package/bare-plugin/src/android/utils.ts +34 -0
- package/bare-plugin/src/index.ts +9 -0
- package/bare-plugin/src/ios/addSettingsBundle.ts +27 -0
- package/bare-plugin/src/ios/iosCommand.ts +21 -0
- package/bare-plugin/src/ios/registerLicensePlistBuildPhase.ts +22 -0
- package/bare-plugin/src/ios/utils.ts +120 -0
- package/bare-plugin/tsconfig.json +20 -0
- package/ios/ReactNativeLegal-Bridging-Header.h +1 -0
- package/ios/ReactNativeLegalDetailViewController.swift +156 -0
- package/ios/ReactNativeLegalLicenseMetadata.swift +4 -0
- package/ios/ReactNativeLegalModule.h +7 -0
- package/ios/ReactNativeLegalModule.mm +29 -0
- package/ios/ReactNativeLegalModuleImpl.swift +78 -0
- package/ios/ReactNativeLegalTableViewController.swift +72 -0
- package/lib/commonjs/NativeReactNativeLegal.js +10 -0
- package/lib/commonjs/NativeReactNativeLegal.js.map +1 -0
- package/lib/commonjs/ReactNativeLegal.android.js +18 -0
- package/lib/commonjs/ReactNativeLegal.android.js.map +1 -0
- package/lib/commonjs/ReactNativeLegal.ios.js +18 -0
- package/lib/commonjs/ReactNativeLegal.ios.js.map +1 -0
- package/lib/commonjs/ReactNativeLegal.js +13 -0
- package/lib/commonjs/ReactNativeLegal.js.map +1 -0
- package/lib/commonjs/index.js +13 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/NativeReactNativeLegal.js +3 -0
- package/lib/module/NativeReactNativeLegal.js.map +1 -0
- package/lib/module/ReactNativeLegal.android.js +10 -0
- package/lib/module/ReactNativeLegal.android.js.map +1 -0
- package/lib/module/ReactNativeLegal.ios.js +10 -0
- package/lib/module/ReactNativeLegal.ios.js.map +1 -0
- package/lib/module/ReactNativeLegal.js +6 -0
- package/lib/module/ReactNativeLegal.js.map +1 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/NativeReactNativeLegal.d.ts +7 -0
- package/lib/typescript/NativeReactNativeLegal.d.ts.map +1 -0
- package/lib/typescript/ReactNativeLegal.android.d.ts +4 -0
- package/lib/typescript/ReactNativeLegal.android.d.ts.map +1 -0
- package/lib/typescript/ReactNativeLegal.d.ts +4 -0
- package/lib/typescript/ReactNativeLegal.d.ts.map +1 -0
- package/lib/typescript/ReactNativeLegal.ios.d.ts +4 -0
- package/lib/typescript/ReactNativeLegal.ios.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/package.json +97 -0
- package/plugin/build/android/addListActivity.d.ts +5 -0
- package/plugin/build/android/addListActivity.js +17 -0
- package/plugin/build/android/applyAndConfigureAboutLibrariesPlugin.d.ts +7 -0
- package/plugin/build/android/applyAndConfigureAboutLibrariesPlugin.js +22 -0
- package/plugin/build/android/declareAboutLibrariesPlugin.d.ts +7 -0
- package/plugin/build/android/declareAboutLibrariesPlugin.js +22 -0
- package/plugin/build/android/withAndroidLegal.d.ts +8 -0
- package/plugin/build/android/withAndroidLegal.js +30 -0
- package/plugin/build/index.d.ts +3 -0
- package/plugin/build/index.js +11 -0
- package/plugin/build/ios/addSettingsBundle.d.ts +5 -0
- package/plugin/build/ios/addSettingsBundle.js +28 -0
- package/plugin/build/ios/registerLicensePlistBuildPhase.d.ts +8 -0
- package/plugin/build/ios/registerLicensePlistBuildPhase.js +23 -0
- package/plugin/build/ios/withIosLegal.d.ts +8 -0
- package/plugin/build/ios/withIosLegal.js +28 -0
- package/plugin/jest.config.js +1 -0
- package/plugin/src/android/addListActivity.ts +19 -0
- package/plugin/src/android/applyAndConfigureAboutLibrariesPlugin.ts +23 -0
- package/plugin/src/android/declareAboutLibrariesPlugin.ts +21 -0
- package/plugin/src/android/withAndroidLegal.ts +28 -0
- package/plugin/src/index.ts +14 -0
- package/plugin/src/ios/addSettingsBundle.ts +29 -0
- package/plugin/src/ios/registerLicensePlistBuildPhase.ts +24 -0
- package/plugin/src/ios/withIosLegal.ts +26 -0
- package/plugin/tsconfig.json +9 -0
- package/plugin-utils/build/android.d.ts +12 -0
- package/plugin-utils/build/android.js +91 -0
- package/plugin-utils/build/common.d.ts +45 -0
- package/plugin-utils/build/common.js +312 -0
- package/plugin-utils/build/ios.d.ts +11 -0
- package/plugin-utils/build/ios.js +86 -0
- package/plugin-utils/src/android.ts +99 -0
- package/plugin-utils/src/common.ts +398 -0
- package/plugin-utils/src/ios.ts +102 -0
- package/plugin-utils/tsconfig.json +20 -0
- package/react-native.config.js +13 -0
- package/src/NativeReactNativeLegal.ts +8 -0
- package/src/ReactNativeLegal.android.ts +10 -0
- package/src/ReactNativeLegal.ios.ts +10 -0
- package/src/ReactNativeLegal.ts +5 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.declareAboutLibrariesPlugin = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const android_1 = require("../../../plugin-utils/build/android");
|
|
10
|
+
const utils_1 = require("./utils");
|
|
11
|
+
/**
|
|
12
|
+
* Modifies root build.gradle with a declaration for AboutLibraries Gradle plugin
|
|
13
|
+
*
|
|
14
|
+
* NOTE: As of now, it doesn't support build.gradle.kts (Gradle Kotlin Script)
|
|
15
|
+
*/
|
|
16
|
+
function declareAboutLibrariesPlugin(androidProjectPath) {
|
|
17
|
+
if (fs_1.default.existsSync(path_1.default.join(androidProjectPath, 'build.gradle.kts'))) {
|
|
18
|
+
console.warn('Gradle Kotlin scripts are not supported yet');
|
|
19
|
+
}
|
|
20
|
+
else if (fs_1.default.existsSync(path_1.default.join(androidProjectPath, 'build.gradle'))) {
|
|
21
|
+
(0, utils_1.modifyFileContent)(path_1.default.join(androidProjectPath, 'build.gradle'), android_1.declareAboutLibrariesPluginUtil);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
console.warn('Cannot find build.gradle file');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.declareAboutLibrariesPlugin = declareAboutLibrariesPlugin;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Used to modify a file at a specified file path
|
|
3
|
+
*
|
|
4
|
+
* It provides the file content as a utf-8 string inside a callback parameter.
|
|
5
|
+
* The modified result should be returned from a callback parameter as a utf-8 string
|
|
6
|
+
*/
|
|
7
|
+
export declare function modifyFileContent(filepath: string, transformFile: (fileContent: string) => string): void;
|
|
8
|
+
/**
|
|
9
|
+
* Used to modify a XML file at a specified file path
|
|
10
|
+
*
|
|
11
|
+
* It provides XML content parsed to a JS object inside a callback parameter
|
|
12
|
+
* The modified result should be a JS object returned from a callback parameter
|
|
13
|
+
*/
|
|
14
|
+
export declare function modifyXMLFileContent(filepath: string, transformXMLFile: (xmlObj: any) => any): Promise<void>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.modifyXMLFileContent = exports.modifyFileContent = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const xml2js_1 = __importDefault(require("xml2js"));
|
|
9
|
+
/**
|
|
10
|
+
* Used to modify a file at a specified file path
|
|
11
|
+
*
|
|
12
|
+
* It provides the file content as a utf-8 string inside a callback parameter.
|
|
13
|
+
* The modified result should be returned from a callback parameter as a utf-8 string
|
|
14
|
+
*/
|
|
15
|
+
function modifyFileContent(filepath, transformFile) {
|
|
16
|
+
const content = fs_1.default.readFileSync(filepath, { encoding: 'utf-8' });
|
|
17
|
+
const modifiedContent = transformFile(content);
|
|
18
|
+
fs_1.default.writeFileSync(filepath, modifiedContent);
|
|
19
|
+
}
|
|
20
|
+
exports.modifyFileContent = modifyFileContent;
|
|
21
|
+
/**
|
|
22
|
+
* Used to modify a XML file at a specified file path
|
|
23
|
+
*
|
|
24
|
+
* It provides XML content parsed to a JS object inside a callback parameter
|
|
25
|
+
* The modified result should be a JS object returned from a callback parameter
|
|
26
|
+
*/
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
async function modifyXMLFileContent(filepath, transformXMLFile) {
|
|
29
|
+
const content = fs_1.default.readFileSync(filepath, { encoding: 'utf-8' });
|
|
30
|
+
const parser = new xml2js_1.default.Parser();
|
|
31
|
+
const obj = await parser.parseStringPromise(content);
|
|
32
|
+
const modifiedObj = transformXMLFile(obj);
|
|
33
|
+
const builder = new xml2js_1.default.Builder({ headless: true });
|
|
34
|
+
const modifiedContent = builder.buildObject(modifiedObj);
|
|
35
|
+
fs_1.default.writeFileSync(filepath, modifiedContent);
|
|
36
|
+
}
|
|
37
|
+
exports.modifyXMLFileContent = modifyXMLFileContent;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const androidCommand_1 = require("./android/androidCommand");
|
|
4
|
+
const iosCommand_1 = require("./ios/iosCommand");
|
|
5
|
+
function generateLegal(androidProjectPath, iosProjectPath) {
|
|
6
|
+
(0, androidCommand_1.androidCommand)(androidProjectPath);
|
|
7
|
+
(0, iosCommand_1.iosCommand)(iosProjectPath);
|
|
8
|
+
}
|
|
9
|
+
exports.default = generateLegal;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.addSettingsBundle = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const ios_1 = require("../../../plugin-utils/build/ios");
|
|
9
|
+
const utils_1 = require("./utils");
|
|
10
|
+
/**
|
|
11
|
+
* Creates a Settings.bundle and links it to all application native targets
|
|
12
|
+
*/
|
|
13
|
+
function addSettingsBundle(iosProjectPath) {
|
|
14
|
+
(0, ios_1.addSettingsBundleUtil)(iosProjectPath, ({ settingsBundleFilename }) => {
|
|
15
|
+
const projectName = (0, utils_1.getIOSProjectName)(iosProjectPath);
|
|
16
|
+
const { pbxproj, pbxprojPath } = (0, utils_1.getIOSPbxProj)(iosProjectPath);
|
|
17
|
+
const settingsBundleFile = pbxproj.addFile(settingsBundleFilename, pbxproj.findPBXGroupKey({ name: projectName }));
|
|
18
|
+
if (!settingsBundleFile) {
|
|
19
|
+
throw new Error('Could not add Settings.bundle file reference to xcode project');
|
|
20
|
+
}
|
|
21
|
+
settingsBundleFile.uuid = pbxproj.generateUuid();
|
|
22
|
+
pbxproj.addToPbxBuildFileSection(settingsBundleFile);
|
|
23
|
+
(0, utils_1.addToAllPbxResourcesBuildPhases)(pbxproj, settingsBundleFile);
|
|
24
|
+
fs_1.default.writeFileSync(pbxprojPath, pbxproj.writeSync());
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
exports.addSettingsBundle = addSettingsBundle;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Implementation of bare plugin's iOS/tvOS setup
|
|
3
|
+
*
|
|
4
|
+
* It scans the NPM dependencies, generates LicensePlist-compatible metadata for them,
|
|
5
|
+
* configures Settings.bundle and registers a shell script generating LicensePlist metadata for iOS dependencies
|
|
6
|
+
*/
|
|
7
|
+
export declare function iosCommand(iosProjectPath: string): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.iosCommand = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const common_1 = require("../../../plugin-utils/build/common");
|
|
9
|
+
const addSettingsBundle_1 = require("./addSettingsBundle");
|
|
10
|
+
const registerLicensePlistBuildPhase_1 = require("./registerLicensePlistBuildPhase");
|
|
11
|
+
/**
|
|
12
|
+
* Implementation of bare plugin's iOS/tvOS setup
|
|
13
|
+
*
|
|
14
|
+
* It scans the NPM dependencies, generates LicensePlist-compatible metadata for them,
|
|
15
|
+
* configures Settings.bundle and registers a shell script generating LicensePlist metadata for iOS dependencies
|
|
16
|
+
*/
|
|
17
|
+
function iosCommand(iosProjectPath) {
|
|
18
|
+
const licenses = (0, common_1.scanDependencies)(path_1.default.join(path_1.default.resolve(iosProjectPath, '..'), 'package.json'));
|
|
19
|
+
(0, common_1.generateLicensePlistNPMOutput)(licenses, iosProjectPath);
|
|
20
|
+
(0, addSettingsBundle_1.addSettingsBundle)(iosProjectPath);
|
|
21
|
+
(0, registerLicensePlistBuildPhase_1.registerLicensePlistBuildPhase)(iosProjectPath);
|
|
22
|
+
}
|
|
23
|
+
exports.iosCommand = iosCommand;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registers a shell script that invokes generation of license metadata with LicensePlist
|
|
3
|
+
*
|
|
4
|
+
* It scans available application native targets and for each of them
|
|
5
|
+
* creates and links a shell script build phase responsible for iOS native deps license metadata
|
|
6
|
+
*/
|
|
7
|
+
export declare function registerLicensePlistBuildPhase(iosProjectPath: string): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerLicensePlistBuildPhase = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const ios_1 = require("../../../plugin-utils/build/ios");
|
|
9
|
+
const utils_1 = require("./utils");
|
|
10
|
+
/**
|
|
11
|
+
* Registers a shell script that invokes generation of license metadata with LicensePlist
|
|
12
|
+
*
|
|
13
|
+
* It scans available application native targets and for each of them
|
|
14
|
+
* creates and links a shell script build phase responsible for iOS native deps license metadata
|
|
15
|
+
*/
|
|
16
|
+
function registerLicensePlistBuildPhase(iosProjectPath) {
|
|
17
|
+
const { pbxproj, pbxprojPath } = (0, utils_1.getIOSPbxProj)(iosProjectPath);
|
|
18
|
+
const nativeTargets = (0, utils_1.getAllApplicationNativeTargets)(pbxproj);
|
|
19
|
+
nativeTargets.map((nativeTarget) => {
|
|
20
|
+
(0, ios_1.registerLicensePlistBuildPhaseUtil)(nativeTarget.uuid, pbxproj);
|
|
21
|
+
});
|
|
22
|
+
fs_1.default.writeFileSync(pbxprojPath, pbxproj.writeSync());
|
|
23
|
+
}
|
|
24
|
+
exports.registerLicensePlistBuildPhase = registerLicensePlistBuildPhase;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { XcodeProject } from 'xcode';
|
|
2
|
+
import xcode from 'xcode';
|
|
3
|
+
/**
|
|
4
|
+
* Used to obtain first target of type "com.apple.product-type.application"
|
|
5
|
+
*/
|
|
6
|
+
export declare function getFirstApplicationNativeTarget(pbxproj: XcodeProject): {
|
|
7
|
+
uuid: string;
|
|
8
|
+
target: xcode.PBXNativeTarget;
|
|
9
|
+
} | null;
|
|
10
|
+
/**
|
|
11
|
+
* Used to get all targets of type "com.apple.product-type.application"
|
|
12
|
+
*/
|
|
13
|
+
export declare function getAllApplicationNativeTargets(pbxproj: XcodeProject): {
|
|
14
|
+
uuid: string;
|
|
15
|
+
target: xcode.PBXNativeTarget;
|
|
16
|
+
}[];
|
|
17
|
+
/**
|
|
18
|
+
* Used to add the file to all "Resources" build phases
|
|
19
|
+
*
|
|
20
|
+
* It's very handy especially when we have multiple application targets and each of them has separate "Resources" build phase
|
|
21
|
+
*/
|
|
22
|
+
export declare function addToAllPbxResourcesBuildPhases(pbxproj: XcodeProject, pbxFile: pbxFile): void;
|
|
23
|
+
/**
|
|
24
|
+
* Returns the name of the main group in the project (the main folder where `AppDelegate` usually lives)
|
|
25
|
+
*/
|
|
26
|
+
export declare function getIOSProjectName(iosProjectPath: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Used to grab the XcodeProject instance
|
|
29
|
+
*/
|
|
30
|
+
export declare function getIOSPbxProj(iosProjectPath: string): {
|
|
31
|
+
pbxproj: XcodeProject;
|
|
32
|
+
pbxprojPath: string;
|
|
33
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getIOSPbxProj = exports.getIOSProjectName = exports.addToAllPbxResourcesBuildPhases = exports.getAllApplicationNativeTargets = exports.getFirstApplicationNativeTarget = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const xcode_1 = __importDefault(require("xcode"));
|
|
9
|
+
const glob = require('glob');
|
|
10
|
+
const ignoredPaths = ['**/@(Carthage|Pods|vendor|node_modules)/**'];
|
|
11
|
+
/**
|
|
12
|
+
* Used to obtain first target of type "com.apple.product-type.application"
|
|
13
|
+
*/
|
|
14
|
+
function getFirstApplicationNativeTarget(pbxproj) {
|
|
15
|
+
return pbxproj.getTarget('com.apple.product-type.application');
|
|
16
|
+
}
|
|
17
|
+
exports.getFirstApplicationNativeTarget = getFirstApplicationNativeTarget;
|
|
18
|
+
/**
|
|
19
|
+
* Used to get all targets of type "com.apple.product-type.application"
|
|
20
|
+
*/
|
|
21
|
+
function getAllApplicationNativeTargets(pbxproj) {
|
|
22
|
+
const targets = pbxproj.getFirstProject().firstProject.targets;
|
|
23
|
+
const nativeTargets = pbxproj.pbxNativeTargetSection();
|
|
24
|
+
return targets.reduce((acc, target) => {
|
|
25
|
+
const targetUuid = target.value;
|
|
26
|
+
if (nativeTargets[targetUuid].productType === '"com.apple.product-type.application"') {
|
|
27
|
+
return [...acc, { uuid: targetUuid, target: nativeTargets[targetUuid] }];
|
|
28
|
+
}
|
|
29
|
+
return acc;
|
|
30
|
+
}, []);
|
|
31
|
+
}
|
|
32
|
+
exports.getAllApplicationNativeTargets = getAllApplicationNativeTargets;
|
|
33
|
+
/**
|
|
34
|
+
* Used to add the file to all "Resources" build phases
|
|
35
|
+
*
|
|
36
|
+
* It's very handy especially when we have multiple application targets and each of them has separate "Resources" build phase
|
|
37
|
+
*/
|
|
38
|
+
function addToAllPbxResourcesBuildPhases(pbxproj, pbxFile) {
|
|
39
|
+
getAllApplicationNativeTargets(pbxproj).map((nativeTarget) => {
|
|
40
|
+
nativeTarget.target.buildPhases.map((buildPhase) => {
|
|
41
|
+
if (buildPhase.comment !== RESOURCES_BUILD_PHASE_IDENTIFIER) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const section = pbxproj.hash.project.objects['PBXResourcesBuildPhase'];
|
|
45
|
+
const buildPhaseKey = buildPhase.value + '_comment';
|
|
46
|
+
for (const key in section) {
|
|
47
|
+
if (!COMMENT_KEY.test(key) || (buildPhaseKey && buildPhaseKey !== key)) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (typeof section[key] === 'string' && section[key] === RESOURCES_BUILD_PHASE_IDENTIFIER) {
|
|
51
|
+
const sectionKey = key.split(COMMENT_KEY)[0];
|
|
52
|
+
const sources = section[sectionKey];
|
|
53
|
+
if (typeof sources === 'object') {
|
|
54
|
+
sources.files.push({
|
|
55
|
+
value: pbxFile.uuid,
|
|
56
|
+
comment: `${pbxFile.basename} in ${pbxFile.group}`,
|
|
57
|
+
});
|
|
58
|
+
pbxproj.hash.project.objects['PBXResourcesBuildPhase'][sectionKey] = sources;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
exports.addToAllPbxResourcesBuildPhases = addToAllPbxResourcesBuildPhases;
|
|
66
|
+
/**
|
|
67
|
+
* Returns the name of the main group in the project (the main folder where `AppDelegate` usually lives)
|
|
68
|
+
*/
|
|
69
|
+
function getIOSProjectName(iosProjectPath) {
|
|
70
|
+
const [appDelegatePath] = glob.sync('*/AppDelegate.@(m|mm|swift)', {
|
|
71
|
+
cwd: iosProjectPath,
|
|
72
|
+
absolute: true,
|
|
73
|
+
nocase: true,
|
|
74
|
+
nodir: true,
|
|
75
|
+
ignore: ignoredPaths,
|
|
76
|
+
});
|
|
77
|
+
return path_1.default.basename(path_1.default.dirname(appDelegatePath));
|
|
78
|
+
}
|
|
79
|
+
exports.getIOSProjectName = getIOSProjectName;
|
|
80
|
+
/**
|
|
81
|
+
* Used to grab the XcodeProject instance
|
|
82
|
+
*/
|
|
83
|
+
function getIOSPbxProj(iosProjectPath) {
|
|
84
|
+
const [xcodeprojPath] = glob.sync('*.xcodeproj', {
|
|
85
|
+
cwd: iosProjectPath,
|
|
86
|
+
absolute: true,
|
|
87
|
+
nocase: true,
|
|
88
|
+
nodir: false,
|
|
89
|
+
ignore: ignoredPaths,
|
|
90
|
+
});
|
|
91
|
+
const pbxprojPath = path_1.default.join(xcodeprojPath, 'project.pbxproj');
|
|
92
|
+
const pbxproj = xcode_1.default.project(pbxprojPath);
|
|
93
|
+
pbxproj.parseSync();
|
|
94
|
+
return { pbxproj, pbxprojPath };
|
|
95
|
+
}
|
|
96
|
+
exports.getIOSPbxProj = getIOSPbxProj;
|
|
97
|
+
const RESOURCES_BUILD_PHASE_IDENTIFIER = 'Resources';
|
|
98
|
+
const COMMENT_KEY = /_comment$/;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import { addListActivityUtil } from '../../../plugin-utils/build/android';
|
|
4
|
+
|
|
5
|
+
import { modifyXMLFileContent } from './utils';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Adds an Android Activity with list of dependencies and their licenses to project's AndroidManifest.xml
|
|
9
|
+
*/
|
|
10
|
+
export async function addListActivity(androidProjectPath: string) {
|
|
11
|
+
const androidManifestPath = path.join(androidProjectPath, 'app', 'src', 'main', 'AndroidManifest.xml');
|
|
12
|
+
|
|
13
|
+
await modifyXMLFileContent(androidManifestPath, (manifestObj) => {
|
|
14
|
+
if (manifestObj.manifest.application?.[0].activity) {
|
|
15
|
+
manifestObj.manifest.application[0].activity = addListActivityUtil(
|
|
16
|
+
manifestObj.manifest.application?.[0].activity,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return manifestObj;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import { generateAboutLibrariesNPMOutput, scanDependencies } from '../../../plugin-utils/build/common';
|
|
4
|
+
|
|
5
|
+
import { addListActivity } from './addListActivity';
|
|
6
|
+
import { applyAndConfigureAboutLibrariesPlugin } from './applyAndConfigureAboutLibrariesPlugin';
|
|
7
|
+
import { declareAboutLibrariesPlugin } from './declareAboutLibrariesPlugin';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Implementation of bare plugin's Android/Android TV setup
|
|
11
|
+
*
|
|
12
|
+
* It scans the NPM dependencies, generates AboutLibraries-compatible metadata for them,
|
|
13
|
+
* installs & configures AboutLibraries Gradle plugin and adds Android Activity with a list of dependencies and their licenses
|
|
14
|
+
*/
|
|
15
|
+
export function androidCommand(androidProjectPath: string) {
|
|
16
|
+
const licenses = scanDependencies(path.join(path.resolve(androidProjectPath, '..'), 'package.json'));
|
|
17
|
+
|
|
18
|
+
generateAboutLibrariesNPMOutput(licenses, androidProjectPath);
|
|
19
|
+
|
|
20
|
+
declareAboutLibrariesPlugin(androidProjectPath);
|
|
21
|
+
applyAndConfigureAboutLibrariesPlugin(androidProjectPath);
|
|
22
|
+
addListActivity(androidProjectPath);
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
import { applyAndConfigureAboutLibrariesPluginUtil } from '../../../plugin-utils/build/android';
|
|
5
|
+
|
|
6
|
+
import { modifyFileContent } from './utils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Modifies application's build.gradle with AboutLibraries plugin
|
|
10
|
+
*
|
|
11
|
+
* NOTE: As of now, it doesn't support build.gradle.kts (Gradle Kotlin Script)
|
|
12
|
+
*/
|
|
13
|
+
export function applyAndConfigureAboutLibrariesPlugin(androidProjectPath: string) {
|
|
14
|
+
if (fs.existsSync(path.join(androidProjectPath, 'app', 'build.gradle.kts'))) {
|
|
15
|
+
console.warn('Gradle Kotlin scripts are not supported yet');
|
|
16
|
+
} else if (fs.existsSync(path.join(androidProjectPath, 'app', 'build.gradle'))) {
|
|
17
|
+
modifyFileContent(path.join(androidProjectPath, 'app', 'build.gradle'), applyAndConfigureAboutLibrariesPluginUtil);
|
|
18
|
+
} else {
|
|
19
|
+
console.warn('Cannot find app/build.gradle file');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
import { declareAboutLibrariesPluginUtil } from '../../../plugin-utils/build/android';
|
|
5
|
+
|
|
6
|
+
import { modifyFileContent } from './utils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Modifies root build.gradle with a declaration for AboutLibraries Gradle plugin
|
|
10
|
+
*
|
|
11
|
+
* NOTE: As of now, it doesn't support build.gradle.kts (Gradle Kotlin Script)
|
|
12
|
+
*/
|
|
13
|
+
export function declareAboutLibrariesPlugin(androidProjectPath: string) {
|
|
14
|
+
if (fs.existsSync(path.join(androidProjectPath, 'build.gradle.kts'))) {
|
|
15
|
+
console.warn('Gradle Kotlin scripts are not supported yet');
|
|
16
|
+
} else if (fs.existsSync(path.join(androidProjectPath, 'build.gradle'))) {
|
|
17
|
+
modifyFileContent(path.join(androidProjectPath, 'build.gradle'), declareAboutLibrariesPluginUtil);
|
|
18
|
+
} else {
|
|
19
|
+
console.warn('Cannot find build.gradle file');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
|
|
3
|
+
import xml2js from 'xml2js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Used to modify a file at a specified file path
|
|
7
|
+
*
|
|
8
|
+
* It provides the file content as a utf-8 string inside a callback parameter.
|
|
9
|
+
* The modified result should be returned from a callback parameter as a utf-8 string
|
|
10
|
+
*/
|
|
11
|
+
export function modifyFileContent(filepath: string, transformFile: (fileContent: string) => string) {
|
|
12
|
+
const content = fs.readFileSync(filepath, { encoding: 'utf-8' });
|
|
13
|
+
const modifiedContent = transformFile(content);
|
|
14
|
+
|
|
15
|
+
fs.writeFileSync(filepath, modifiedContent);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Used to modify a XML file at a specified file path
|
|
20
|
+
*
|
|
21
|
+
* It provides XML content parsed to a JS object inside a callback parameter
|
|
22
|
+
* The modified result should be a JS object returned from a callback parameter
|
|
23
|
+
*/
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
|
+
export async function modifyXMLFileContent(filepath: string, transformXMLFile: (xmlObj: any) => any) {
|
|
26
|
+
const content = fs.readFileSync(filepath, { encoding: 'utf-8' });
|
|
27
|
+
const parser = new xml2js.Parser();
|
|
28
|
+
const obj = await parser.parseStringPromise(content);
|
|
29
|
+
const modifiedObj = transformXMLFile(obj);
|
|
30
|
+
const builder = new xml2js.Builder({ headless: true });
|
|
31
|
+
const modifiedContent = builder.buildObject(modifiedObj);
|
|
32
|
+
|
|
33
|
+
fs.writeFileSync(filepath, modifiedContent);
|
|
34
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { androidCommand } from './android/androidCommand';
|
|
2
|
+
import { iosCommand } from './ios/iosCommand';
|
|
3
|
+
|
|
4
|
+
function generateLegal(androidProjectPath: string, iosProjectPath: string) {
|
|
5
|
+
androidCommand(androidProjectPath);
|
|
6
|
+
iosCommand(iosProjectPath);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default generateLegal;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
|
|
3
|
+
import { addSettingsBundleUtil } from '../../../plugin-utils/build/ios';
|
|
4
|
+
|
|
5
|
+
import { addToAllPbxResourcesBuildPhases, getIOSPbxProj, getIOSProjectName } from './utils';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Creates a Settings.bundle and links it to all application native targets
|
|
9
|
+
*/
|
|
10
|
+
export function addSettingsBundle(iosProjectPath: string) {
|
|
11
|
+
addSettingsBundleUtil(iosProjectPath, ({ settingsBundleFilename }) => {
|
|
12
|
+
const projectName = getIOSProjectName(iosProjectPath);
|
|
13
|
+
const { pbxproj, pbxprojPath } = getIOSPbxProj(iosProjectPath);
|
|
14
|
+
const settingsBundleFile = pbxproj.addFile(settingsBundleFilename, pbxproj.findPBXGroupKey({ name: projectName }));
|
|
15
|
+
|
|
16
|
+
if (!settingsBundleFile) {
|
|
17
|
+
throw new Error('Could not add Settings.bundle file reference to xcode project');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
settingsBundleFile.uuid = pbxproj.generateUuid();
|
|
21
|
+
|
|
22
|
+
pbxproj.addToPbxBuildFileSection(settingsBundleFile);
|
|
23
|
+
addToAllPbxResourcesBuildPhases(pbxproj, settingsBundleFile);
|
|
24
|
+
|
|
25
|
+
fs.writeFileSync(pbxprojPath, pbxproj.writeSync());
|
|
26
|
+
});
|
|
27
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import { generateLicensePlistNPMOutput, scanDependencies } from '../../../plugin-utils/build/common';
|
|
4
|
+
|
|
5
|
+
import { addSettingsBundle } from './addSettingsBundle';
|
|
6
|
+
import { registerLicensePlistBuildPhase } from './registerLicensePlistBuildPhase';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Implementation of bare plugin's iOS/tvOS setup
|
|
10
|
+
*
|
|
11
|
+
* It scans the NPM dependencies, generates LicensePlist-compatible metadata for them,
|
|
12
|
+
* configures Settings.bundle and registers a shell script generating LicensePlist metadata for iOS dependencies
|
|
13
|
+
*/
|
|
14
|
+
export function iosCommand(iosProjectPath: string) {
|
|
15
|
+
const licenses = scanDependencies(path.join(path.resolve(iosProjectPath, '..'), 'package.json'));
|
|
16
|
+
|
|
17
|
+
generateLicensePlistNPMOutput(licenses, iosProjectPath);
|
|
18
|
+
|
|
19
|
+
addSettingsBundle(iosProjectPath);
|
|
20
|
+
registerLicensePlistBuildPhase(iosProjectPath);
|
|
21
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
|
|
3
|
+
import { registerLicensePlistBuildPhaseUtil } from '../../../plugin-utils/build/ios';
|
|
4
|
+
|
|
5
|
+
import { getAllApplicationNativeTargets, getIOSPbxProj } from './utils';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Registers a shell script that invokes generation of license metadata with LicensePlist
|
|
9
|
+
*
|
|
10
|
+
* It scans available application native targets and for each of them
|
|
11
|
+
* creates and links a shell script build phase responsible for iOS native deps license metadata
|
|
12
|
+
*/
|
|
13
|
+
export function registerLicensePlistBuildPhase(iosProjectPath: string) {
|
|
14
|
+
const { pbxproj, pbxprojPath } = getIOSPbxProj(iosProjectPath);
|
|
15
|
+
const nativeTargets = getAllApplicationNativeTargets(pbxproj);
|
|
16
|
+
|
|
17
|
+
nativeTargets.map((nativeTarget) => {
|
|
18
|
+
registerLicensePlistBuildPhaseUtil(nativeTarget.uuid, pbxproj);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
fs.writeFileSync(pbxprojPath, pbxproj.writeSync());
|
|
22
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
|
|
3
|
+
import type { XcodeProject } from 'xcode';
|
|
4
|
+
import xcode from 'xcode';
|
|
5
|
+
|
|
6
|
+
const glob = require('glob');
|
|
7
|
+
|
|
8
|
+
const ignoredPaths = ['**/@(Carthage|Pods|vendor|node_modules)/**'];
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Used to obtain first target of type "com.apple.product-type.application"
|
|
12
|
+
*/
|
|
13
|
+
export function getFirstApplicationNativeTarget(pbxproj: XcodeProject) {
|
|
14
|
+
return pbxproj.getTarget('com.apple.product-type.application');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Used to get all targets of type "com.apple.product-type.application"
|
|
19
|
+
*/
|
|
20
|
+
export function getAllApplicationNativeTargets(pbxproj: XcodeProject) {
|
|
21
|
+
const targets = pbxproj.getFirstProject().firstProject.targets;
|
|
22
|
+
const nativeTargets = pbxproj.pbxNativeTargetSection();
|
|
23
|
+
|
|
24
|
+
return targets.reduce(
|
|
25
|
+
(acc, target) => {
|
|
26
|
+
const targetUuid = target.value;
|
|
27
|
+
|
|
28
|
+
if (nativeTargets[targetUuid].productType === '"com.apple.product-type.application"') {
|
|
29
|
+
return [...acc, { uuid: targetUuid, target: nativeTargets[targetUuid] }];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return acc;
|
|
33
|
+
},
|
|
34
|
+
[] as {
|
|
35
|
+
uuid: string;
|
|
36
|
+
target: xcode.PBXNativeTarget;
|
|
37
|
+
}[],
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Used to add the file to all "Resources" build phases
|
|
43
|
+
*
|
|
44
|
+
* It's very handy especially when we have multiple application targets and each of them has separate "Resources" build phase
|
|
45
|
+
*/
|
|
46
|
+
export function addToAllPbxResourcesBuildPhases(pbxproj: XcodeProject, pbxFile: pbxFile) {
|
|
47
|
+
getAllApplicationNativeTargets(pbxproj).map((nativeTarget) => {
|
|
48
|
+
nativeTarget.target.buildPhases.map((buildPhase) => {
|
|
49
|
+
if (buildPhase.comment !== RESOURCES_BUILD_PHASE_IDENTIFIER) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const section: Record<
|
|
54
|
+
string,
|
|
55
|
+
| {
|
|
56
|
+
[key: string]: any;
|
|
57
|
+
isa: 'PBXResourcesBuildPhase';
|
|
58
|
+
name: string;
|
|
59
|
+
}
|
|
60
|
+
| string
|
|
61
|
+
> = pbxproj.hash.project.objects['PBXResourcesBuildPhase'];
|
|
62
|
+
const buildPhaseKey = buildPhase.value + '_comment';
|
|
63
|
+
|
|
64
|
+
for (const key in section) {
|
|
65
|
+
if (!COMMENT_KEY.test(key) || (buildPhaseKey && buildPhaseKey !== key)) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (typeof section[key] === 'string' && section[key] === RESOURCES_BUILD_PHASE_IDENTIFIER) {
|
|
70
|
+
const sectionKey = key.split(COMMENT_KEY)[0];
|
|
71
|
+
const sources = section[sectionKey];
|
|
72
|
+
|
|
73
|
+
if (typeof sources === 'object') {
|
|
74
|
+
sources.files.push({
|
|
75
|
+
value: pbxFile.uuid,
|
|
76
|
+
comment: `${pbxFile.basename} in ${pbxFile.group}`,
|
|
77
|
+
});
|
|
78
|
+
pbxproj.hash.project.objects['PBXResourcesBuildPhase'][sectionKey] = sources;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Returns the name of the main group in the project (the main folder where `AppDelegate` usually lives)
|
|
88
|
+
*/
|
|
89
|
+
export function getIOSProjectName(iosProjectPath: string) {
|
|
90
|
+
const [appDelegatePath] = glob.sync('*/AppDelegate.@(m|mm|swift)', {
|
|
91
|
+
cwd: iosProjectPath,
|
|
92
|
+
absolute: true,
|
|
93
|
+
nocase: true,
|
|
94
|
+
nodir: true,
|
|
95
|
+
ignore: ignoredPaths,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return path.basename(path.dirname(appDelegatePath));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Used to grab the XcodeProject instance
|
|
103
|
+
*/
|
|
104
|
+
export function getIOSPbxProj(iosProjectPath: string) {
|
|
105
|
+
const [xcodeprojPath] = glob.sync('*.xcodeproj', {
|
|
106
|
+
cwd: iosProjectPath,
|
|
107
|
+
absolute: true,
|
|
108
|
+
nocase: true,
|
|
109
|
+
nodir: false,
|
|
110
|
+
ignore: ignoredPaths,
|
|
111
|
+
});
|
|
112
|
+
const pbxprojPath = path.join(xcodeprojPath, 'project.pbxproj');
|
|
113
|
+
const pbxproj = xcode.project(pbxprojPath);
|
|
114
|
+
|
|
115
|
+
pbxproj.parseSync();
|
|
116
|
+
return { pbxproj, pbxprojPath };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const RESOURCES_BUILD_PHASE_IDENTIFIER = 'Resources';
|
|
120
|
+
const COMMENT_KEY = /_comment$/;
|