react-native-integrate
Version:
Automate integration of additional code into React Native projects
300 lines (299 loc) • 14.8 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyContentModification = applyContentModification;
exports.updateBlockContent = updateBlockContent;
exports.getBlockName = getBlockName;
exports.applyContextReduction = applyContextReduction;
const picocolors_1 = __importDefault(require("picocolors"));
const processScript_1 = require("./processScript");
const prompter_1 = require("../prompter");
const variables_1 = require("../variables");
const escapeRegExp_1 = require("./escapeRegExp");
const findInsertionPoint_1 = require("./findInsertionPoint");
const findLineTools_1 = require("./findLineTools");
const getModContent_1 = require("./getModContent");
const setState_1 = require("./setState");
const stringSplice_1 = require("./stringSplice");
async function applyContentModification(args) {
let { content } = args;
const { configPath, packageName, action, findOrCreateBlock, indentation, additionalModification, buildComment, } = args;
let blockContent = {
start: 0,
end: content.length - 1,
match: content,
justCreated: false,
space: '',
};
if (action.block) {
action.block = (0, variables_1.getText)(action.block);
const foundBlock = findOrCreateBlock(content, action.block);
blockContent = foundBlock.blockContent;
content = foundBlock.content;
}
const getCodeToInsert = (text, kind) => {
const isBlockSameLine = !blockContent.match.includes('\n') ||
(!action.search && kind === 'replace');
let comment = '', blockIndentation = '', openingNewLine = '\n', closingNewLine = `\n${isBlockSameLine ? blockContent.space : ''}`;
const isAppend = 'append' in action || 'before' in action;
if (!isBlockSameLine) {
if (isAppend ||
(blockContent.start == 0 && blockContent.match[0] != '\n'))
openingNewLine = '';
else
closingNewLine = '';
}
if (action.block)
blockIndentation = ' '.repeat(indentation);
if (action.comment) {
const _buildCommand = buildComment || buildCommonComment;
const commentLines = _buildCommand((0, variables_1.getText)(action.comment));
commentLines.forEach(line => {
comment += `${blockContent.space}${blockIndentation}${line}\n`;
});
}
text = text.replace(/\n/g, `\n${blockContent.space}${blockIndentation}`);
return `${openingNewLine}${comment}${blockContent.space}${blockIndentation}${text}${closingNewLine}`;
};
const splittingMsgArr = applyContextReduction(action, blockContent, content);
const splittingMsg = splittingMsgArr.length
? ` (${splittingMsgArr.join(', ')})`
: '';
const runModifiers = async (spliceCallback) => {
const prependAction = async (prependRaw) => {
const prependText = await (0, getModContent_1.getModContent)(configPath, packageName, prependRaw);
const codeToInsert = action.exact
? prependText
: getCodeToInsert(prependText, 'prepend');
if (action.ifNotPresent &&
blockContent.match.includes((0, variables_1.getText)(action.ifNotPresent))) {
(0, prompter_1.logMessageGray)(`found existing ${(0, prompter_1.summarize)((0, variables_1.getText)(action.ifNotPresent))}, skipped inserting: ${(0, prompter_1.summarize)(prependText)}`);
(0, setState_1.setState)(action.name, {
state: 'skipped',
reason: 'prepend.ifNotPresent',
});
}
else if (!blockContent.match.includes(prependText)) {
const start = blockContent.start, rem = 0, insert = codeToInsert;
content = (0, stringSplice_1.stringSplice)(content, start, rem, insert);
if (spliceCallback)
spliceCallback(start, rem, insert);
updateBlockContent(blockContent, rem, insert, content);
(0, prompter_1.logMessage)(`prepended code in ${(0, prompter_1.summarize)(getBlockName(action))}${splittingMsg}: ${(0, prompter_1.summarize)(prependText)}`);
}
else {
(0, prompter_1.logMessageGray)(`code already exists, skipped prepending: ${(0, prompter_1.summarize)(prependText)}`);
(0, setState_1.setState)(action.name, {
state: 'skipped',
reason: 'prepend.exists',
});
}
};
const appendAction = async (appendRaw) => {
const appendText = await (0, getModContent_1.getModContent)(configPath, packageName, appendRaw);
const codeToInsert = action.exact
? appendText
: getCodeToInsert(appendText, 'append');
if (action.ifNotPresent &&
blockContent.match.includes((0, variables_1.getText)(action.ifNotPresent))) {
(0, prompter_1.logMessageGray)(`found existing ${(0, prompter_1.summarize)((0, variables_1.getText)(action.ifNotPresent))}, skipped inserting: ${(0, prompter_1.summarize)(appendText)}`);
(0, setState_1.setState)(action.name, {
state: 'skipped',
reason: 'append.ifNotPresent',
});
}
else if (!blockContent.match.includes(appendText)) {
const lineStart = action.exact
? blockContent.end
: (0, findLineTools_1.findLineStart)(content, blockContent.end, blockContent.start);
const start = lineStart, rem = 0, insert = codeToInsert;
content = (0, stringSplice_1.stringSplice)(content, start, rem, insert);
if (spliceCallback)
spliceCallback(start, rem, insert);
updateBlockContent(blockContent, rem, insert, content);
(0, prompter_1.logMessage)(`appended code in ${(0, prompter_1.summarize)(getBlockName(action))}${splittingMsg}: ${(0, prompter_1.summarize)(appendText)}`);
}
else {
(0, prompter_1.logMessageGray)(`code already exists, skipped appending: ${(0, prompter_1.summarize)(appendText)}`);
(0, setState_1.setState)(action.name, {
state: 'skipped',
reason: 'append.exists',
});
}
};
const replaceAction = async (replaceRaw) => {
const replaceText = await (0, getModContent_1.getModContent)(configPath, packageName, replaceRaw);
const codeToInsert = action.exact
? replaceText
: getCodeToInsert(replaceText, 'replace');
if (action.ifNotPresent &&
blockContent.match.includes((0, variables_1.getText)(action.ifNotPresent))) {
(0, prompter_1.logMessageGray)(`found existing ${(0, prompter_1.summarize)((0, variables_1.getText)(action.ifNotPresent))}, skipped inserting: ${(0, prompter_1.summarize)(replaceText)}`);
(0, setState_1.setState)(action.name, {
state: 'skipped',
reason: 'replace.ifNotPresent',
});
}
else {
const start = blockContent.start, rem = blockContent.end - blockContent.start, insert = codeToInsert;
content = (0, stringSplice_1.stringSplice)(content, start, rem, insert);
if (spliceCallback)
spliceCallback(start, rem, insert);
updateBlockContent(blockContent, rem, insert, content);
(0, prompter_1.logMessage)(`replaced code in ${(0, prompter_1.summarize)(getBlockName(action))}${splittingMsg}: ${(0, prompter_1.summarize)(replaceText)}`);
}
};
for (const key of Object.keys(action)) {
switch (key) {
case 'prepend':
if (action.prepend) {
await prependAction(action.prepend);
}
break;
case 'append':
if (action.append) {
await appendAction(action.append);
}
break;
case 'replace':
if (action.replace != null) {
await replaceAction(action.replace);
}
break;
case 'script':
if (action.script != null) {
if (action.ifNotPresent &&
blockContent.match.includes((0, variables_1.getText)(action.ifNotPresent))) {
(0, prompter_1.logMessageGray)(`found existing ${(0, prompter_1.summarize)((0, variables_1.getText)(action.ifNotPresent))}, skipped running script: ${(0, prompter_1.summarize)(action.script)}`);
(0, setState_1.setState)(action.name, {
state: 'skipped',
reason: 'script.ifNotPresent',
});
}
else {
await (0, processScript_1.processScript)(action.script, variables_1.variables, false, true, {
prepend: prependAction,
append: appendAction,
replace: replaceAction,
});
}
}
break;
}
}
};
if (action.search) {
const searchBlockContent = { ...blockContent };
let searchMatcher = typeof action.search == 'string'
? new RegExp((0, escapeRegExp_1.escapeRegExp)((0, variables_1.getText)(action.search)))
: new RegExp((0, variables_1.getText)(action.search.regex), action.search.flags);
const searchOnce = !searchMatcher.flags.includes('g');
if (searchOnce)
searchMatcher = new RegExp(searchMatcher.source, searchMatcher.flags + 'g');
let searching = true;
let isFirstSearch = true;
while (searching) {
const match = searchMatcher.exec(searchBlockContent.match);
if (!match) {
if (isFirstSearch)
(0, setState_1.setState)(action.name, {
state: 'skipped',
reason: 'search',
});
break;
}
isFirstSearch = false;
blockContent.start = searchBlockContent.start + match.index;
blockContent.end =
searchBlockContent.start + match.index + match[0].length;
blockContent.match = match[0];
if (!action.exact) {
//find context start
blockContent.start = (0, findLineTools_1.findLineStart)(content, blockContent.start, searchBlockContent.start, true);
//find context end
const lineEnd = (0, findLineTools_1.findLineEnd)(content, blockContent.end, searchBlockContent.end);
searchMatcher.lastIndex += lineEnd - blockContent.end;
blockContent.end = lineEnd;
blockContent.match = content.substring(blockContent.start, blockContent.end);
}
await runModifiers((_start, rem, insert) => {
searchMatcher.lastIndex += -rem + insert.length;
updateBlockContent(searchBlockContent, rem, insert, content);
});
if (searchOnce)
searching = false;
}
}
else
await runModifiers();
if (additionalModification) {
content = additionalModification({
content,
blockContent,
});
}
return content;
}
function buildCommonComment(comment) {
return comment.split('\n').map(x => `// ${x}`);
}
function updateBlockContent(blockContent, rem, insert, content) {
blockContent.end += -rem + insert.length;
blockContent.match = content.substring(blockContent.start, blockContent.end);
}
function resolveInsertionPoint(blockContent, _content, textOrRegex) {
if (blockContent.justCreated) {
return {
start: blockContent.start,
end: blockContent.end,
match: blockContent.match,
};
}
else {
const insertionPoint = (0, findInsertionPoint_1.findInsertionPoint)(blockContent.match, textOrRegex);
if (insertionPoint.start == -1)
return insertionPoint;
insertionPoint.start += blockContent.start;
insertionPoint.end += blockContent.start;
return insertionPoint;
}
}
function getBlockName(action) {
return action.block || 'file';
}
function applyContextReduction(action, blockContent, content) {
const splittingMsgArr = [];
if (action.after) {
const foundIndex = resolveInsertionPoint(blockContent, content, action.after);
if (foundIndex.start == -1) {
if (action.strict)
throw new Error('Could not find insertion point');
(0, prompter_1.logMessageGray)(`insertion point not found, ignoring ${picocolors_1.default.yellow('before')} criteria`);
}
else {
blockContent.start = action.exact
? foundIndex.end
: (0, findLineTools_1.findLineEnd)(content, foundIndex.end, blockContent.end);
blockContent.match = content.substring(blockContent.start, blockContent.end);
splittingMsgArr.push(`after ${(0, prompter_1.summarize)(foundIndex.match, 20)}`);
}
}
if (action.before) {
const foundIndex = resolveInsertionPoint(blockContent, content, action.before);
if (foundIndex.start == -1) {
if (action.strict)
throw new Error('Could not find insertion point');
(0, prompter_1.logMessageGray)(`insertion point not found, ignoring ${picocolors_1.default.yellow('before')} criteria`);
}
else {
blockContent.end = action.exact
? foundIndex.start
: (0, findLineTools_1.findLineStart)(content, foundIndex.start, blockContent.start);
blockContent.match = content.substring(blockContent.start, blockContent.end);
splittingMsgArr.push(`before ${(0, prompter_1.summarize)(foundIndex.match, 20)}`);
}
}
return splittingMsgArr;
}