- expand custom placeholders to the global template

- introuce capability of accessing and referencing custom placeholders of PRs in the global template
```
${{CUSTOM_PLACEHOLDER[0]}}
${{CUSTOM_PLACEHOLDER[*]}}
```
- introduce new testcase checking the custom placeholder functionality
This commit is contained in:
Mike Penz
2022-07-29 16:11:14 +00:00
committed by GitHub
parent 7b1021454a
commit fba9cdb51d
5 changed files with 171 additions and 67 deletions
+45 -5
View File
@@ -1,7 +1,7 @@
import {buildChangelog} from '../src/transform' import {buildChangelog} from '../src/transform'
import {PullRequestInfo} from '../src/pullRequests' import {PullRequestInfo} from '../src/pullRequests'
import moment from 'moment' import moment from 'moment'
import { DefaultConfiguration } from '../src/configuration'; import { Configuration, DefaultConfiguration } from '../src/configuration';
import { DefaultDiffInfo } from '../src/commits'; import { DefaultDiffInfo } from '../src/commits';
jest.setTimeout(180000) jest.setTimeout(180000)
@@ -41,7 +41,7 @@ mergedPullRequests.push(
repoName: 'test-repo', repoName: 'test-repo',
labels: new Set<string>(), labels: new Set<string>(),
milestone: '', milestone: '',
body: 'no magic body for this matter', body: 'no magic body1 for this matter',
assignees: [], assignees: [],
requestedReviewers: [], requestedReviewers: [],
approvedReviewers: [], approvedReviewers: [],
@@ -59,7 +59,7 @@ mergedPullRequests.push(
repoName: 'test-repo', repoName: 'test-repo',
labels: new Set<string>(), labels: new Set<string>(),
milestone: '', milestone: '',
body: 'no magic body for this matter', body: 'no magic body2 for this matter',
assignees: [], assignees: [],
requestedReviewers: [], requestedReviewers: [],
approvedReviewers: [], approvedReviewers: [],
@@ -77,7 +77,7 @@ mergedPullRequests.push(
repoName: 'test-repo', repoName: 'test-repo',
labels: new Set<string>(), labels: new Set<string>(),
milestone: '', milestone: '',
body: 'no magic body for this matter', body: 'no magic body3 for this matter',
assignees: [], assignees: [],
requestedReviewers: [], requestedReviewers: [],
approvedReviewers: [], approvedReviewers: [],
@@ -95,7 +95,7 @@ mergedPullRequests.push(
repoName: 'test-repo', repoName: 'test-repo',
labels: new Set<string>(), labels: new Set<string>(),
milestone: '', milestone: '',
body: 'no magic body for this matter', body: 'no magic body4 for this matter',
assignees: [], assignees: [],
requestedReviewers: [], requestedReviewers: [],
approvedReviewers: [], approvedReviewers: [],
@@ -583,3 +583,43 @@ it('Use exclude labels to not include a PR within a category.', async () => {
`## 🚀 Features and 🐛 Issues\n\n- [ABC-1234] - this is a PR 3 title message\n - PR: #3\n\n## 🚀 Features and/or 🐛 Issues But No 🐛 Fixes\n\n- [ABC-1234] - this is a PR 1 title message\n - PR: #1\n\n` `## 🚀 Features and 🐛 Issues\n\n- [ABC-1234] - this is a PR 3 title message\n - PR: #3\n\n## 🚀 Features and/or 🐛 Issues But No 🐛 Fixes\n\n- [ABC-1234] - this is a PR 1 title message\n - PR: #1\n\n`
) )
}) })
it('Extract custom placeholder from PR body and replace in global template', async () => {
const customConfig = Object.assign({}, configuration)
customConfig.custom_placeholders = [
{
name: "C_PLACEHOLDER_1",
source: "BODY",
transformer: {
pattern: '.+ (b....).+',
target: '- $1'
}
},
{
name: "C_PLACEHOLER_2",
source: "BODY",
transformer: {
pattern: '.+ b(....).+',
target: '\n- $1'
}
}
]
customConfig.template = "${{CHANGELOG}}\n\n${{C_PLACEHOLER_2[2]}}\n\n${{C_PLACEHOLER_2[*]}}"
customConfig.pr_template = "${{BODY}} ----> ${{C_PLACEHOLDER_1}}"
const resultChangelog = buildChangelog(DefaultDiffInfo, mergedPullRequests, {
owner: 'mikepenz',
repo: 'test-repo',
fromTag: { name: '1.0.0' },
toTag: { name: '2.0.0' },
includeOpen: false,
failOnError: false,
fetchReviewers: false,
fetchReleaseInformation: false,
commitMode: false,
configuration: customConfig
})
expect(resultChangelog).toStrictEqual(`## 🚀 Features\n\nno magic body1 for this matter ----> - body1\nno magic body3 for this matter ----> - body3\n\n## 🐛 Fixes\n\nno magic body2 for this matter ----> - body2\nno magic body3 for this matter ----> - body3\n\n## 🧪 Others\n\nno magic body4 for this matter ----> - body4\n\n\n\n\n- ody3\n\n\n- ody1\n- ody2\n- ody3\n- ody4`)
})
Generated Vendored
+57 -29
View File
@@ -1449,6 +1449,7 @@ exports.validateTransformer = exports.replaceEmptyTemplate = exports.buildChange
const core = __importStar(__nccwpck_require__(2186)); const core = __importStar(__nccwpck_require__(2186));
const configuration_1 = __nccwpck_require__(5527); const configuration_1 = __nccwpck_require__(5527);
const pullRequests_1 = __nccwpck_require__(4217); const pullRequests_1 = __nccwpck_require__(4217);
const utils_1 = __nccwpck_require__(918);
function buildChangelog(diffInfo, prs, options) { function buildChangelog(diffInfo, prs, options) {
// sort to target order // sort to target order
const config = options.configuration; const config = options.configuration;
@@ -1494,15 +1495,17 @@ function buildChangelog(diffInfo, prs, options) {
} }
} }
} }
// keep reference for the placeholder values
const placeholders = new Map(); const placeholders = new Map();
for (const ph of config.custom_placeholders || []) { for (const ph of config.custom_placeholders || []) {
placeholders.set(ph.source, ph); (0, utils_1.createOrSet)(placeholders, ph.source, ph);
} }
const placeholderPrMap = new Map();
const validatedTransformers = validateTransformers(config.transformers); const validatedTransformers = validateTransformers(config.transformers);
const transformedMap = new Map(); const transformedMap = new Map();
// convert PRs to their text representation // convert PRs to their text representation
for (const pr of prs) { for (const pr of prs) {
transformedMap.set(pr, transform(fillTemplate(pr, config.pr_template || configuration_1.DefaultConfiguration.pr_template, placeholders), validatedTransformers)); transformedMap.set(pr, transform(fillPrTemplate(pr, config.pr_template || configuration_1.DefaultConfiguration.pr_template, placeholders, placeholderPrMap), validatedTransformers));
} }
core.info(`️ Used ${validatedTransformers.length} transformers to adjust message`); core.info(`️ Used ${validatedTransformers.length} transformers to adjust message`);
core.info(`✒️ Wrote messages for ${prs.length} pull requests`); core.info(`✒️ Wrote messages for ${prs.length} pull requests`);
@@ -1519,7 +1522,7 @@ function buildChangelog(diffInfo, prs, options) {
const uncategorizedPrs = []; const uncategorizedPrs = [];
// bring elements in order // bring elements in order
for (const [pr, body] of transformedMap) { for (const [pr, body] of transformedMap) {
if (haveCommonElements(ignoredLabels.map(lbl => lbl.toLocaleLowerCase('en')), pr.labels)) { if ((0, utils_1.haveCommonElements)(ignoredLabels.map(lbl => lbl.toLocaleLowerCase('en')), pr.labels)) {
ignoredPrs.push(body); ignoredPrs.push(body);
continue; continue;
} }
@@ -1530,7 +1533,7 @@ function buildChangelog(diffInfo, prs, options) {
for (const [category, pullRequests] of categorized) { for (const [category, pullRequests] of categorized) {
// check if any exclude label matches // check if any exclude label matches
if (category.exclude_labels !== undefined) { if (category.exclude_labels !== undefined) {
if (haveCommonElements(category.exclude_labels.map(lbl => lbl.toLocaleLowerCase('en')), pr.labels)) { if ((0, utils_1.haveCommonElements)(category.exclude_labels.map(lbl => lbl.toLocaleLowerCase('en')), pr.labels)) {
if (core.isDebug()) { if (core.isDebug()) {
const prNum = pr.number; const prNum = pr.number;
const prLabels = pr.labels; const prLabels = pr.labels;
@@ -1541,13 +1544,13 @@ function buildChangelog(diffInfo, prs, options) {
} }
} }
if (category.exhaustive === true) { if (category.exhaustive === true) {
if (haveEveryElements(category.labels.map(lbl => lbl.toLocaleLowerCase('en')), pr.labels)) { if ((0, utils_1.haveEveryElements)(category.labels.map(lbl => lbl.toLocaleLowerCase('en')), pr.labels)) {
pullRequests.push(body); pullRequests.push(body);
matched = true; matched = true;
} }
} }
else { else {
if (haveCommonElements(category.labels.map(lbl => lbl.toLocaleLowerCase('en')), pr.labels)) { if ((0, utils_1.haveCommonElements)(category.labels.map(lbl => lbl.toLocaleLowerCase('en')), pr.labels)) {
pullRequests.push(body); pullRequests.push(body);
matched = true; matched = true;
} }
@@ -1643,7 +1646,8 @@ function buildChangelog(diffInfo, prs, options) {
placeholderMap.set('COMMITS', diffInfo.commits.toString()); placeholderMap.set('COMMITS', diffInfo.commits.toString());
fillAdditionalPlaceholders(options, placeholderMap); fillAdditionalPlaceholders(options, placeholderMap);
let transformedChangelog = config.template || configuration_1.DefaultConfiguration.template; let transformedChangelog = config.template || configuration_1.DefaultConfiguration.template;
transformedChangelog = replacePlaceHolders(transformedChangelog, placeholderMap, placeholders); transformedChangelog = replacePlaceholders(transformedChangelog, placeholderMap, placeholders, placeholderPrMap);
transformedChangelog = replacePrPlaceholders(transformedChangelog, placeholderPrMap);
core.info(`️ Filled template`); core.info(`️ Filled template`);
return transformedChangelog; return transformedChangelog;
} }
@@ -1651,16 +1655,15 @@ exports.buildChangelog = buildChangelog;
function replaceEmptyTemplate(template, options) { function replaceEmptyTemplate(template, options) {
const placeholders = new Map(); const placeholders = new Map();
for (const ph of options.configuration.custom_placeholders || []) { for (const ph of options.configuration.custom_placeholders || []) {
placeholders.set(ph.source, ph); (0, utils_1.createOrSet)(placeholders, ph.source, ph);
} }
const placeholderMap = new Map(); const placeholderMap = new Map();
fillAdditionalPlaceholders(options, placeholderMap); fillAdditionalPlaceholders(options, placeholderMap);
return replacePlaceHolders(template, placeholderMap, placeholders); return replacePlaceholders(template, placeholderMap, placeholders);
} }
exports.replaceEmptyTemplate = replaceEmptyTemplate; exports.replaceEmptyTemplate = replaceEmptyTemplate;
function fillAdditionalPlaceholders(options, placeholderMap) { function fillAdditionalPlaceholders(options, placeholderMap /* placeholderKey and original value */) {
var _a, _b; var _a, _b;
// repository placeholders
placeholderMap.set('OWNER', options.owner); placeholderMap.set('OWNER', options.owner);
placeholderMap.set('REPO', options.repo); placeholderMap.set('REPO', options.repo);
placeholderMap.set('FROM_TAG', options.fromTag.name); placeholderMap.set('FROM_TAG', options.fromTag.name);
@@ -1677,7 +1680,7 @@ function fillAdditionalPlaceholders(options, placeholderMap) {
} }
placeholderMap.set('RELEASE_DIFF', `https://github.com/${options.owner}/${options.repo}/compare/${options.fromTag.name}...${options.toTag.name}`); placeholderMap.set('RELEASE_DIFF', `https://github.com/${options.owner}/${options.repo}/compare/${options.fromTag.name}...${options.toTag.name}`);
} }
function fillTemplate(pr, template, placeholders) { function fillPrTemplate(pr, template, placeholders /* placeholders to apply */, placeholderPrMap /* map to keep replaced placeholder values with their key */) {
var _a, _b, _c, _d, _e, _f; var _a, _b, _c, _d, _e, _f;
const placeholderMap = new Map(); const placeholderMap = new Map();
placeholderMap.set('NUMBER', pr.number.toString()); placeholderMap.set('NUMBER', pr.number.toString());
@@ -1696,26 +1699,39 @@ function fillTemplate(pr, template, placeholders) {
placeholderMap.set('APPROVERS', ((_f = pr.approvedReviewers) === null || _f === void 0 ? void 0 : _f.join(', ')) || ''); placeholderMap.set('APPROVERS', ((_f = pr.approvedReviewers) === null || _f === void 0 ? void 0 : _f.join(', ')) || '');
placeholderMap.set('BRANCH', pr.branch || ''); placeholderMap.set('BRANCH', pr.branch || '');
placeholderMap.set('BASE_BRANCH', pr.baseBranch); placeholderMap.set('BASE_BRANCH', pr.baseBranch);
return replacePlaceHolders(template, placeholderMap, placeholders); return replacePlaceholders(template, placeholderMap, placeholders, placeholderPrMap);
} }
function replacePlaceHolders(template, placeholderMap, placeholders) { function replacePlaceholders(template, placeholderMap /* placeholderKey and original value */, placeholders /* placeholders to apply */, placeholderPrMap /* map to keep replaced placeholder values with their key */) {
let transformed = template; let transformed = template;
for (const [key, value] of placeholderMap) { for (const [key, value] of placeholderMap) {
transformed = transformed.replaceAll(`\${{${key}}}`, value); transformed = transformed.replaceAll(`\${{${key}}}`, value);
// replace custom placeholders // replace custom placeholders
transformed = applyCustomPlaceholder(transformed, value, placeholders.get(key)); const phs = placeholders.get(key);
} if (phs) {
return transformed; for (const placeholder of phs) {
}
function applyCustomPlaceholder(template, value, placeholder) {
if (placeholder) {
const transformer = validateTransformer(placeholder.transformer); const transformer = validateTransformer(placeholder.transformer);
if (transformer === null || transformer === void 0 ? void 0 : transformer.pattern) { if (transformer === null || transformer === void 0 ? void 0 : transformer.pattern) {
const extractedValue = value.replace(transformer.pattern, transformer.target); const extractedValue = value.replace(transformer.pattern, transformer.target);
return template.replaceAll(`\${{${placeholder.name}}}`, extractedValue); // note: `.replace` will return the full string again if there was no match
if (extractedValue && placeholderPrMap && extractedValue !== value) {
(0, utils_1.createOrSet)(placeholderPrMap, placeholder.name, extractedValue);
}
transformed = transformed.replaceAll(`\${{${placeholder.name}}}`, extractedValue);
} }
} }
return template; }
}
return transformed;
}
function replacePrPlaceholders(template, placeholderPrMap /* map with all pr related custom placeholder values */) {
let transformed = template;
for (const [key, values] of placeholderPrMap) {
for (let i = 0; i < values.length; i++) {
transformed = transformed.replaceAll(`\${{${key}[${i}]}}`, values[i]);
}
transformed = transformed.replaceAll(`\${{${key}[*]}}`, values.join(''));
}
return transformed;
} }
function transform(filled, transformers) { function transform(filled, transformers) {
if (transformers.length === 0) { if (transformers.length === 0) {
@@ -1821,12 +1837,6 @@ function extractValuesFromString(value, extractor) {
} }
return null; return null;
} }
function haveCommonElements(arr1, arr2) {
return arr1.some(item => arr2.has(item));
}
function haveEveryElements(arr1, arr2) {
return arr1.every(item => arr2.has(item));
}
/***/ }), /***/ }),
@@ -1860,7 +1870,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result; return result;
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.writeOutput = exports.directoryExistsSync = exports.parseConfiguration = exports.resolveConfiguration = exports.failOrError = exports.retrieveRepositoryPath = void 0; exports.haveEveryElements = exports.haveCommonElements = exports.createOrSet = exports.writeOutput = exports.directoryExistsSync = exports.parseConfiguration = exports.resolveConfiguration = exports.failOrError = exports.retrieveRepositoryPath = void 0;
const core = __importStar(__nccwpck_require__(2186)); const core = __importStar(__nccwpck_require__(2186));
const fs = __importStar(__nccwpck_require__(7147)); const fs = __importStar(__nccwpck_require__(7147));
const path = __importStar(__nccwpck_require__(1017)); const path = __importStar(__nccwpck_require__(1017));
@@ -1994,6 +2004,24 @@ function writeOutput(githubWorkspacePath, outputFile, changelog) {
} }
} }
exports.writeOutput = writeOutput; exports.writeOutput = writeOutput;
function createOrSet(map, key, value) {
const entry = map.get(key);
if (!entry) {
map.set(key, [value]);
}
else {
entry.push(value);
}
}
exports.createOrSet = createOrSet;
function haveCommonElements(arr1, arr2) {
return arr1.some(item => arr2.has(item));
}
exports.haveCommonElements = haveCommonElements;
function haveEveryElements(arr1, arr2) {
return arr1.every(item => arr2.has(item));
}
exports.haveEveryElements = haveEveryElements;
/***/ }), /***/ }),
Generated Vendored
+1 -1
View File
File diff suppressed because one or more lines are too long
+50 -31
View File
@@ -3,6 +3,7 @@ import {Category, DefaultConfiguration, Extractor, Placeholder, Transformer} fro
import {PullRequestInfo, sortPullRequests} from './pullRequests' import {PullRequestInfo, sortPullRequests} from './pullRequests'
import {ReleaseNotesOptions} from './releaseNotes' import {ReleaseNotesOptions} from './releaseNotes'
import {DiffInfo} from './commits' import {DiffInfo} from './commits'
import {createOrSet, haveCommonElements, haveEveryElements} from './utils'
export interface RegexTransformer { export interface RegexTransformer {
pattern: RegExp | null pattern: RegExp | null
@@ -59,10 +60,12 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
} }
} }
const placeholders = new Map<string, Placeholder>() // keep reference for the placeholder values
const placeholders = new Map<string, Placeholder[]>()
for (const ph of config.custom_placeholders || []) { for (const ph of config.custom_placeholders || []) {
placeholders.set(ph.source, ph) createOrSet(placeholders, ph.source, ph)
} }
const placeholderPrMap = new Map<string, string[]>()
const validatedTransformers = validateTransformers(config.transformers) const validatedTransformers = validateTransformers(config.transformers)
const transformedMap = new Map<PullRequestInfo, string>() const transformedMap = new Map<PullRequestInfo, string>()
@@ -71,7 +74,7 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
transformedMap.set( transformedMap.set(
pr, pr,
transform( transform(
fillTemplate(pr, config.pr_template || DefaultConfiguration.pr_template, placeholders), fillPrTemplate(pr, config.pr_template || DefaultConfiguration.pr_template, placeholders, placeholderPrMap),
validatedTransformers validatedTransformers
) )
) )
@@ -250,24 +253,26 @@ export function buildChangelog(diffInfo: DiffInfo, prs: PullRequestInfo[], optio
fillAdditionalPlaceholders(options, placeholderMap) fillAdditionalPlaceholders(options, placeholderMap)
let transformedChangelog = config.template || DefaultConfiguration.template let transformedChangelog = config.template || DefaultConfiguration.template
transformedChangelog = replacePlaceHolders(transformedChangelog, placeholderMap, placeholders) transformedChangelog = replacePlaceholders(transformedChangelog, placeholderMap, placeholders, placeholderPrMap)
transformedChangelog = replacePrPlaceholders(transformedChangelog, placeholderPrMap)
core.info(`️ Filled template`) core.info(`️ Filled template`)
return transformedChangelog return transformedChangelog
} }
export function replaceEmptyTemplate(template: string, options: ReleaseNotesOptions): string { export function replaceEmptyTemplate(template: string, options: ReleaseNotesOptions): string {
const placeholders = new Map<string, Placeholder>() const placeholders = new Map<string, Placeholder[]>()
for (const ph of options.configuration.custom_placeholders || []) { for (const ph of options.configuration.custom_placeholders || []) {
placeholders.set(ph.source, ph) createOrSet(placeholders, ph.source, ph)
} }
const placeholderMap = new Map<string, string>() const placeholderMap = new Map<string, string>()
fillAdditionalPlaceholders(options, placeholderMap) fillAdditionalPlaceholders(options, placeholderMap)
return replacePlaceHolders(template, placeholderMap, placeholders) return replacePlaceholders(template, placeholderMap, placeholders)
} }
function fillAdditionalPlaceholders(options: ReleaseNotesOptions, placeholderMap: Map<string, string>): void { function fillAdditionalPlaceholders(
// repository placeholders options: ReleaseNotesOptions,
placeholderMap: Map<string, string> /* placeholderKey and original value */
): void {
placeholderMap.set('OWNER', options.owner) placeholderMap.set('OWNER', options.owner)
placeholderMap.set('REPO', options.repo) placeholderMap.set('REPO', options.repo)
placeholderMap.set('FROM_TAG', options.fromTag.name) placeholderMap.set('FROM_TAG', options.fromTag.name)
@@ -287,7 +292,12 @@ function fillAdditionalPlaceholders(options: ReleaseNotesOptions, placeholderMap
) )
} }
function fillTemplate(pr: PullRequestInfo, template: string, placeholders: Map<string, Placeholder>): string { function fillPrTemplate(
pr: PullRequestInfo,
template: string,
placeholders: Map<string, Placeholder[]> /* placeholders to apply */,
placeholderPrMap: Map<string, string[]> /* map to keep replaced placeholder values with their key */
): string {
const placeholderMap = new Map<string, string>() const placeholderMap = new Map<string, string>()
placeholderMap.set('NUMBER', pr.number.toString()) placeholderMap.set('NUMBER', pr.number.toString())
placeholderMap.set('TITLE', pr.title) placeholderMap.set('TITLE', pr.title)
@@ -305,33 +315,50 @@ function fillTemplate(pr: PullRequestInfo, template: string, placeholders: Map<s
placeholderMap.set('APPROVERS', pr.approvedReviewers?.join(', ') || '') placeholderMap.set('APPROVERS', pr.approvedReviewers?.join(', ') || '')
placeholderMap.set('BRANCH', pr.branch || '') placeholderMap.set('BRANCH', pr.branch || '')
placeholderMap.set('BASE_BRANCH', pr.baseBranch) placeholderMap.set('BASE_BRANCH', pr.baseBranch)
return replacePlaceHolders(template, placeholderMap, placeholders) return replacePlaceholders(template, placeholderMap, placeholders, placeholderPrMap)
} }
function replacePlaceHolders( function replacePlaceholders(
template: string, template: string,
placeholderMap: Map<string, string>, placeholderMap: Map<string, string> /* placeholderKey and original value */,
placeholders: Map<string, Placeholder> placeholders: Map<string, Placeholder[]> /* placeholders to apply */,
placeholderPrMap?: Map<string, string[]> /* map to keep replaced placeholder values with their key */
): string { ): string {
let transformed = template let transformed = template
for (const [key, value] of placeholderMap) { for (const [key, value] of placeholderMap) {
transformed = transformed.replaceAll(`\${{${key}}}`, value) transformed = transformed.replaceAll(`\${{${key}}}`, value)
// replace custom placeholders // replace custom placeholders
transformed = applyCustomPlaceholder(transformed, value, placeholders.get(key)) const phs = placeholders.get(key)
if (phs) {
for (const placeholder of phs) {
const transformer = validateTransformer(placeholder.transformer)
if (transformer?.pattern) {
const extractedValue = value.replace(transformer.pattern, transformer.target)
// note: `.replace` will return the full string again if there was no match
if (extractedValue && placeholderPrMap && extractedValue !== value) {
createOrSet(placeholderPrMap, placeholder.name, extractedValue)
}
transformed = transformed.replaceAll(`\${{${placeholder.name}}}`, extractedValue)
}
}
}
} }
return transformed return transformed
} }
function applyCustomPlaceholder(template: string, value: string, placeholder: Placeholder | undefined): string { function replacePrPlaceholders(
if (placeholder) { template: string,
const transformer = validateTransformer(placeholder.transformer) placeholderPrMap: Map<string, string[]> /* map with all pr related custom placeholder values */
if (transformer?.pattern) { ): string {
const extractedValue = value.replace(transformer.pattern, transformer.target) let transformed = template
return template.replaceAll(`\${{${placeholder.name}}}`, extractedValue) for (const [key, values] of placeholderPrMap) {
for (let i = 0; i < values.length; i++) {
transformed = transformed.replaceAll(`\${{${key}[${i}]}}`, values[i])
} }
transformed = transformed.replaceAll(`\${{${key}[*]}}`, values.join(''))
} }
return template return transformed
} }
function transform(filled: string, transformers: RegexTransformer[]): string { function transform(filled: string, transformers: RegexTransformer[]): string {
@@ -442,11 +469,3 @@ function extractValuesFromString(value: string, extractor: RegexTransformer): st
} }
return null return null
} }
function haveCommonElements(arr1: string[], arr2: Set<string>): Boolean {
return arr1.some(item => arr2.has(item))
}
function haveEveryElements(arr1: string[], arr2: Set<string>): Boolean {
return arr1.every(item => arr2.has(item))
}
+17
View File
@@ -132,3 +132,20 @@ export function writeOutput(githubWorkspacePath: string, outputFile: string, cha
} }
export type Unpacked<T> = T extends (infer U)[] ? U : T export type Unpacked<T> = T extends (infer U)[] ? U : T
export function createOrSet<T>(map: Map<String, T[]>, key: string, value: T): void {
const entry = map.get(key)
if (!entry) {
map.set(key, [value])
} else {
entry.push(value)
}
}
export function haveCommonElements(arr1: string[], arr2: Set<string>): Boolean {
return arr1.some(item => arr2.has(item))
}
export function haveEveryElements(arr1: string[], arr2: Set<string>): Boolean {
return arr1.every(item => arr2.has(item))
}