UNPKG

react-native-integrate

Version:

Automate integration of additional code into React Native projects

204 lines (203 loc) 9.07 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.summary = void 0; exports.androidManifestTask = androidManifestTask; exports.runTask = runTask; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const constants_1 = require("../constants"); const prompter_1 = require("../prompter"); const applyContentModification_1 = require("../utils/applyContentModification"); const checkCondition_1 = require("../utils/checkCondition"); const escapeRegExp_1 = require("../utils/escapeRegExp"); const findClosingTagIndex_1 = require("../utils/findClosingTagIndex"); const getErrMessage_1 = require("../utils/getErrMessage"); const getProjectPath_1 = require("../utils/getProjectPath"); const setState_1 = require("../utils/setState"); const stringSplice_1 = require("../utils/stringSplice"); const variables_1 = require("../variables"); async function androidManifestTask(args) { let { content } = args; const { task, configPath, packageName } = args; for (const action of task.actions) { variables_1.variables.set('CONTENT', content); if (action.when && !(0, checkCondition_1.checkCondition)(action.when)) { (0, setState_1.setState)(action.name, { state: 'skipped', reason: 'when', }); continue; } (0, setState_1.setState)(action.name, { state: 'progress', }); try { const additionalModification = (args) => applyAttributeModification({ ...args, action }); content = await (0, applyContentModification_1.applyContentModification)({ action, findOrCreateBlock, configPath, packageName, content, indentation: 0, additionalModification, buildComment: buildXmlComment, }); (0, setState_1.setState)(action.name, { state: 'done', }); } catch (e) { (0, setState_1.setState)(action.name, { state: 'error', reason: (0, getErrMessage_1.getErrMessage)(e), }); throw e; } } return content; } function buildXmlComment(comment) { return comment.split('\n').map(x => `<!-- ${x} -->`); } function applyAttributeModification(args) { const { action, blockContent } = args; let { content } = args; if (action.attributes) { if (!action.block) throw new Error('you must set block to update attributes'); const blockDefinition = blockDefinitions[action.block]; const { regex, indentation } = blockDefinition; const getCodeToInsert = (text, isReplacing) => { let openingNewLine = '\n', closingNewLine = '', blockIndentation = ' '.repeat(indentation); if (isReplacing) { openingNewLine = ''; closingNewLine = '\n'; } if (isReplacing) { closingNewLine = ''; blockIndentation = ''; } return `${openingNewLine}${isReplacing ? '' : blockIndentation}${text}${closingNewLine}`; }; Object.entries(action.attributes).forEach(([name, value]) => { value = (0, variables_1.transformTextInObject)(value); const blockStart = regex.exec(content); checkBlockStartValue(blockStart); if (blockStart) { // noinspection RegExpSimplifiable const existingMatcher = new RegExp(`\\b${(0, escapeRegExp_1.escapeRegExp)(name)}="(?:\\\\.|[^\\\\"])*"([\\s]+)?`); const existingMatch = existingMatcher.exec(blockStart[0]); // delete if (typeof value == 'object' && value.$delete) { if (existingMatch) { const start = existingMatch.index + blockStart.index, rem = existingMatch[0].length, insert = ''; content = (0, stringSplice_1.stringSplice)(content, start, rem, insert); (0, applyContentModification_1.updateBlockContent)(blockContent, rem, insert, content); (0, prompter_1.logMessage)(`deleted attribute ${(0, prompter_1.summarize)(name)} in ${(0, prompter_1.summarize)((0, applyContentModification_1.getBlockName)(action))}`); } else { (0, prompter_1.logMessageGray)(`attribute ${(0, prompter_1.summarize)(name)} does not exist in ${(0, prompter_1.summarize)((0, applyContentModification_1.getBlockName)(action))} - skipping delete operation`); } } else { // set or replace const codeToInsert = getCodeToInsert(`${name}="${value}"`, !!existingMatch); if (existingMatch) { // replace const start = existingMatch.index + blockStart.index, rem = existingMatch[0].length, insert = codeToInsert; content = (0, stringSplice_1.stringSplice)(content, start, rem, insert); (0, applyContentModification_1.updateBlockContent)(blockContent, rem, insert, content); (0, prompter_1.logMessage)(`set existing attribute in ${(0, prompter_1.summarize)((0, applyContentModification_1.getBlockName)(action))} - ${(0, prompter_1.summarize)(name)}: ${(0, prompter_1.summarize)(value)}`); } else { // set const endOfOpeningTagIndex = blockStart.index + blockStart[0].length - 1; // noinspection UnnecessaryLocalVariableJS const start = endOfOpeningTagIndex, rem = 0, insert = codeToInsert; content = (0, stringSplice_1.stringSplice)(content, start, rem, insert); (0, applyContentModification_1.updateBlockContent)(blockContent, rem, insert, content); (0, prompter_1.logMessage)(`set new attribute in ${(0, prompter_1.summarize)((0, applyContentModification_1.getBlockName)(action))} - ${(0, prompter_1.summarize)(name)}: ${(0, prompter_1.summarize)(value)}`); } } } }); } return content; } function checkBlockStartValue(value) { if (!value) { throw new Error('block could not be found, something wrong?'); } } function findOrCreateBlock(content, block) { let blockContent = { start: 0, end: content.length, match: content, space: '', justCreated: false, }; const blockDefinition = blockDefinitions[block]; if (!blockDefinition) throw new Error(`Invalid block: ${block}`); const { regex } = blockDefinition; const blockStart = regex.exec(content); checkBlockStartValue(blockStart); if (blockStart) { const blockEndIndex = (0, findClosingTagIndex_1.findClosingTagIndex)(content, blockStart.index + blockStart[0].length, findClosingTagIndex_1.TagDefinitions.XML); const blockBody = content.substring(blockStart.index + blockStart[0].length, blockEndIndex); blockContent = { start: blockStart.index + blockStart[0].length, end: blockEndIndex, match: blockBody, justCreated: false, space: ' '.repeat(blockDefinition.indentation), }; } return { blockContent, content, }; } const blockDefinitions = { manifest: { regex: /<manifest.*?>/s, indentation: 4, }, application: { regex: /<application.*?>/s, indentation: 6, }, activity: { regex: /<activity.*?>/s, indentation: 8, }, }; function getAndroidManifestPath() { const projectPath = (0, getProjectPath_1.getProjectPath)(); const buildGradlePath = path_1.default.join(projectPath, constants_1.Constants.ANDROID_MAIN_FILE_PATH, constants_1.Constants.ANDROID_MANIFEST_FILE_NAME); if (!fs_1.default.existsSync(buildGradlePath)) throw new Error(`AndroidManifest.xml file not found at ${buildGradlePath}`); return buildGradlePath; } function readAndroidManifestContent() { const manifestPath = getAndroidManifestPath(); return fs_1.default.readFileSync(manifestPath, 'utf-8'); } function writeAndroidManifestContent(content) { const manifestPath = getAndroidManifestPath(); return fs_1.default.writeFileSync(manifestPath, content, 'utf-8'); } async function runTask(args) { let content = readAndroidManifestContent(); content = await androidManifestTask({ ...args, content, }); writeAndroidManifestContent(content); } exports.summary = 'AndroidManifest.xml modification';