UNPKG

@azure-tools/codegen

Version:
439 lines 14.8 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); exports.selectName = exports._setRegion = exports.setRegion = exports.getRegions = exports.nameof = exports.escapeString = exports.getPascalIdentifier = exports.camelCase = exports.pascalCase = exports.removeSequentialDuplicates = exports.isEqual = exports.removeProhibitedPrefix = exports.fixLeadingNumber = exports.convert = exports.isCapitalized = exports.deconstruct = exports.pall = exports.__selectMany = exports.ToMap = exports.map = exports.dotCombine = exports.docComment = exports.comment = exports.indent = exports.fixEOL = exports.toMap = exports.trimDots = exports.setIndentation = exports.sortByName = exports.joinComma = exports.join = exports.uncapitalize = exports.capitalize = exports.CommaChar = exports.EOL = exports.docCommentPrefix = exports.lineCommentPrefix = void 0; const file_generator_1 = require("./file-generator"); let indentation = " "; exports.lineCommentPrefix = "//"; exports.docCommentPrefix = "///"; exports.EOL = "\n"; exports.CommaChar = ", "; const acronyms = new Set([ "ip", "os", "ms", "vm", // 'ssl', 'https', 'http', '' ]); function capitalize(str) { if (acronyms.has(str)) { return str.toUpperCase(); } return str ? `${str.charAt(0).toUpperCase()}${str.slice(1)}` : str; } exports.capitalize = capitalize; function uncapitalize(str) { return str ? `${str.charAt(0).toLowerCase()}${str.slice(1)}` : str; } exports.uncapitalize = uncapitalize; function join(items, separator) { return items.filter((v) => (v ? true : false)).join(separator); } exports.join = join; function joinComma(items, mapFn) { return join(items.map(mapFn), exports.CommaChar); } exports.joinComma = joinComma; function sortByName(a, b) { return a.name < b.name ? -1 : a.name > b.name ? 1 : 0; } exports.sortByName = sortByName; function setIndentation(spaces) { indentation = " ".repeat(spaces); } exports.setIndentation = setIndentation; function trimDots(content) { return content.replace(/^[.\s]*(.*?)[.\s]*$/g, "$1"); } exports.trimDots = trimDots; function toMap(source, eachFn) { const result = new Map(); for (const each of source) { const key = eachFn(each); let values = result.get(key); if (!values) { values = new Array(); result.set(key, values); } values.push(each); } return result; } exports.toMap = toMap; function fixEOL(content) { return content.replace(/\r\n/g, exports.EOL); } exports.fixEOL = fixEOL; function indent(content, factor = 1) { const i = indentation.repeat(factor); content = i + fixEOL(content.trim()); return content.split(/\n/g).join(`${exports.EOL}${i}`); } exports.indent = indent; function comment(content, prefix = exports.lineCommentPrefix, factor = 0, maxLength = 120) { const result = new Array(); let line = ""; prefix = indent(prefix, factor); content = content.trim(); if (content) { for (const word of content.replace(/\n+/g, " » ").split(/\s+/g)) { if (word === "»") { result.push(line); line = prefix; continue; } if (maxLength < line.length) { result.push(line); line = ""; } if (!line) { line = prefix; } line += ` ${word}`; } if (line) { result.push(line); } return result.join(exports.EOL); } return ""; } exports.comment = comment; function docComment(content, prefix = exports.docCommentPrefix, factor = 0, maxLength = 120) { return comment(content, prefix, factor, maxLength); } exports.docComment = docComment; function dotCombine(prefix, content) { return trimDots([trimDots(prefix), trimDots(content)].join(".")); } exports.dotCombine = dotCombine; function map(dictionary, callbackfn, thisArg) { return Object.getOwnPropertyNames(dictionary).map((key) => callbackfn(key, dictionary[key])); } exports.map = map; function ToMap(dictionary) { const result = new Map(); Object.getOwnPropertyNames(dictionary).map((key) => result.set(key, dictionary[key])); return result; } exports.ToMap = ToMap; function __selectMany(multiArray) { const result = new Array(); multiArray.map((v) => result.push(...v)); return result; } exports.__selectMany = __selectMany; function pall(array, callbackfn, thisArg) { return Promise.all(array.map(callbackfn)); } exports.pall = pall; function deconstruct(identifier) { if (Array.isArray(identifier)) { return identifier.flatMap(deconstruct); } return `${identifier}` .replace(/([a-z]+)([A-Z])/g, "$1 $2") .replace(/(\d+)([a-z|A-Z]+)/g, "$1 $2") .replace(/\b([A-Z]+)([A-Z])([a-z])/, "$1 $2$3") .split(/[\W|_]+/) .map((each) => each.toLowerCase()); } exports.deconstruct = deconstruct; function isCapitalized(identifier) { return /^[A-Z]/.test(identifier); } exports.isCapitalized = isCapitalized; const ones = [ "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", ]; const teens = [ "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", ]; const tens = ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"]; const magnitude = [ "thousand", "million", "billion", "trillion", "quadrillion", "quintillion", "septillion", "octillion", ]; const magvalues = [10 ** 3, 10 ** 6, 10 ** 9, 10 ** 12, 10 ** 15, 10 ** 18, 10 ** 21, 10 ** 24, 10 ** 27]; function* convert(num) { if (!num) { yield "zero"; return; } if (num > 1e30) { yield "lots"; return; } if (num > 999) { for (let i = magvalues.length; i > -1; i--) { const c = magvalues[i]; if (num > c) { yield* convert(Math.floor(num / c)); yield magnitude[i]; num = num % c; } } } if (num > 99) { yield ones[Math.floor(num / 100)]; yield "hundred"; num %= 100; } if (num > 19) { yield tens[Math.floor(num / 10)]; num %= 10; } if (num) { yield ones[num]; } } exports.convert = convert; function fixLeadingNumber(identifier) { if (identifier.length > 0 && /^\d+/.exec(identifier[0])) { return [...convert(parseInt(identifier[0])), ...identifier.slice(1)]; } return identifier; } exports.fixLeadingNumber = fixLeadingNumber; function removeProhibitedPrefix(identifier, prohibitedPrefix, skipIdentifiers) { if (identifier.toLowerCase().startsWith(prohibitedPrefix.toLowerCase())) { const regex = new RegExp(`(^${prohibitedPrefix})(.*)`, "i"); let newIdentifier = identifier.replace(regex, "$2"); if (newIdentifier.length < 2) { // if it results in an empty string or a single letter string // then, it is not really a word. return identifier; } newIdentifier = isCapitalized(identifier) ? capitalize(newIdentifier) : uncapitalize(newIdentifier); return skipIdentifiers !== undefined ? skipIdentifiers.includes(newIdentifier) ? identifier : newIdentifier : newIdentifier; } return identifier; } exports.removeProhibitedPrefix = removeProhibitedPrefix; function isEqual(s1, s2) { // when s2 is undefined and s1 is the string 'undefined', it returns 0, making this true. // To prevent that, first we need to check if s2 is undefined. return s2 !== undefined && !!s1 && !s1.localeCompare(s2, undefined, { sensitivity: "base" }); } exports.isEqual = isEqual; function removeSequentialDuplicates(identifier) { const ids = [...identifier].filter((each) => !!each); for (let i = 0; i < ids.length; i++) { while (isEqual(ids[i], ids[i - 1])) { ids.splice(i, 1); } while (isEqual(ids[i], ids[i - 2]) && isEqual(ids[i + 1], ids[i - 1])) { ids.splice(i, 2); } } return ids; } exports.removeSequentialDuplicates = removeSequentialDuplicates; function pascalCase(identifier, removeDuplicates = true) { return identifier === undefined ? "" : typeof identifier === "string" ? pascalCase(fixLeadingNumber(deconstruct(identifier)), removeDuplicates) : (removeDuplicates ? [...removeSequentialDuplicates(identifier)] : identifier) .map((each) => capitalize(each)) .join(""); } exports.pascalCase = pascalCase; function camelCase(identifier) { if (typeof identifier === "string") { return camelCase(fixLeadingNumber(deconstruct(identifier))); } switch (identifier.length) { case 0: return ""; case 1: return uncapitalize(identifier[0]); } return `${uncapitalize(identifier[0])}${pascalCase(identifier.slice(1))}`; } exports.camelCase = camelCase; function getPascalIdentifier(name) { return pascalCase(fixLeadingNumber(deconstruct(name))); } exports.getPascalIdentifier = getPascalIdentifier; function escapeString(text) { if (text) { const q = JSON.stringify(text); return q.slice(1, -1); } return ""; } exports.escapeString = escapeString; /** emits c# to get the name of a property - uses nameof when it can, and uses a literal when it's an array value. */ function nameof(text) { if (text.indexOf("[") > -1) { return `$"${text.replace(/\[(.*)\]/, "[{$1}]")}"`; } return `nameof(${text})`; } exports.nameof = nameof; function* getRegions(source, prefix = "#", postfix = "") { source = source.replace(/\r?\n|\r/g, "«"); const rx = new RegExp(`(.*?)«?(\\s*${prefix}\\s*region\\s*(.*?)\\s*${postfix})\\s*«(.*?)«(\\s*${prefix}\\s*endregion\\s*${postfix})\\s*?«`, "g"); let match; let finalPosition = 0; /* eslint-disable */ while ((match = rx.exec(source))) { if (match[1]) { // we have text before this region. yield { name: "", start: "", content: match[1].replace(/«/g, "\n"), end: "", }; } // this region yield { name: match[3], start: match[2], content: match[4].replace(/«/g, "\n"), end: match[5], }; finalPosition = rx.lastIndex; } if (finalPosition < source.length) { // we have text after the last region. yield { name: "", start: "", content: source.substring(finalPosition).replace(/«/g, "\n"), end: "", }; } } exports.getRegions = getRegions; function setRegion(source, region, content, prepend = true, prefix = "#", postfix = "") { const result = new Array(); const ct = new file_generator_1.Text(content).text .replace(/\r?\n|\r/g, "«") .replace(/^«*/, "") .replace(/«*$/, ""); let found = false; for (const each of getRegions(source, prefix, postfix)) { if (each.name === region) { // found the region, replace it. // (this also makes sure that we only have one region by that name when replacing/deleting) if (!found && ct) { // well, only if it has content, otherwise, we're deleting it. result.push(each.start, ct, each.end, "«"); found = true; } } else { result.push(each.start, each.content, each.end, "«"); } } if (!found) { if (prepend) { result.splice(0, 0, `${prefix} region ${region} ${postfix}`, ct, `${prefix} endregion ${postfix}«`); } else { result.push(`${prefix} region ${region} ${postfix}`, ct, `${prefix} endregion ${postfix}«`); } } return result .join("«") .replace(/\r?\n|\r/g, "«") .replace(/^«*/, "") .replace(/«*$/, "") .replace(/«««*/g, "««") .replace(/«/g, "\n"); } exports.setRegion = setRegion; // Note: Where is this used? function _setRegion(source, region, content, prepend = true, prefix = "#", postfix = "") { const ct = new file_generator_1.Text(content).text .replace(/\r?\n|\r/g, "«") .replace(/^«*/, "") .replace(/«*$/, ""); source = source.replace(/\r?\n|\r/g, "«"); const rx = new RegExp(`«(\\s*${prefix}\\s*region\\s*${region}\\s*${postfix})\\s*«.*?(«\\s*${prefix}\\s*endregion\\s*${postfix}«?)`, "g"); if (rx.test(source)) { if (ct.length > 0) { source = source.replace(rx, `«$1«${ct}$2`); } else { source = source.replace(rx, ""); } } else { if (ct.length > 0) { const text = ${prefix} region ${region} ${postfix}«${ct}«${prefix} endregion ${postfix}«`; source = prepend ? text + source : source + text; } } source = source.replace(/«««*/g, "««").replace(/«/g, "\n"); return source; } exports._setRegion = _setRegion; function selectName(nameOptions, reservedNames) { // we're here because the original name is in conflict. // so we start with the alternatives (skip the 0th!) NOT for (const each of nameOptions) { if (!reservedNames.has(each)) { reservedNames.add(each); return each; } } // hmm, none of the names were suitable. // use the first one, and tack on a number until we have a free value let i = 1; do { const name = `${nameOptions[0]}${i}`; if (!reservedNames.has(name)) { reservedNames.add(name); return name; } i++; } while (i < 100); // after an unreasonalbe search, return something invalid return `InvalidPropertyName${nameOptions[0]}`; } exports.selectName = selectName; //# sourceMappingURL=text-manipulation.js.map