UNPKG

7.84 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.StringChecks = void 0;
4/**
5 * Helpers for validating various text string formats.
6 */
7var StringChecks = /** @class */ (function () {
8 function StringChecks() {
9 }
10 /**
11 * Tests whether the input string is a valid TSDoc tag name; if not, returns an error message.
12 * TSDoc tag names start with an at-sign ("@") followed by ASCII letters using
13 * "camelCase" capitalization.
14 */
15 StringChecks.explainIfInvalidTSDocTagName = function (tagName) {
16 if (tagName[0] !== '@') {
17 return 'A TSDoc tag name must start with an "@" symbol';
18 }
19 if (!StringChecks._tsdocTagNameRegExp.test(tagName)) {
20 return 'A TSDoc tag name must start with a letter and contain only letters and numbers';
21 }
22 return undefined;
23 };
24 /**
25 * Throws an exception if the input string is not a valid TSDoc tag name.
26 * TSDoc tag names start with an at-sign ("@") followed by ASCII letters using
27 * "camelCase" capitalization.
28 */
29 StringChecks.validateTSDocTagName = function (tagName) {
30 var explanation = StringChecks.explainIfInvalidTSDocTagName(tagName);
31 if (explanation) {
32 throw new Error(explanation);
33 }
34 };
35 /**
36 * Tests whether the input string is a URL form supported inside an "@link" tag; if not,
37 * returns an error message.
38 */
39 StringChecks.explainIfInvalidLinkUrl = function (url) {
40 if (url.length === 0) {
41 return 'The URL cannot be empty';
42 }
43 if (!StringChecks._urlSchemeRegExp.test(url)) {
44 return ('An @link URL must begin with a scheme comprised only of letters and numbers followed by "://".' +
45 ' (For general URLs, use an HTML "<a>" tag instead.)');
46 }
47 if (!StringChecks._urlSchemeAfterRegExp.test(url)) {
48 return 'An @link URL must have at least one character after "://"';
49 }
50 return undefined;
51 };
52 /**
53 * Tests whether the input string is a valid HTML element or attribute name.
54 */
55 StringChecks.explainIfInvalidHtmlName = function (htmlName) {
56 if (!StringChecks._htmlNameRegExp.test(htmlName)) {
57 return 'An HTML name must be an ASCII letter followed by zero or more letters, digits, or hyphens';
58 }
59 return undefined;
60 };
61 /**
62 * Throws an exception if the input string is a not valid HTML element or attribute name.
63 */
64 StringChecks.validateHtmlName = function (htmlName) {
65 var explanation = StringChecks.explainIfInvalidHtmlName(htmlName);
66 if (explanation) {
67 throw new Error(explanation);
68 }
69 };
70 /**
71 * Tests whether the input string is a valid NPM package name.
72 */
73 StringChecks.explainIfInvalidPackageName = function (packageName) {
74 if (packageName.length === 0) {
75 return 'The package name cannot be an empty string';
76 }
77 if (!StringChecks._validPackageNameRegExp.test(packageName)) {
78 return "The package name " + JSON.stringify(packageName) + " is not a valid package name";
79 }
80 return undefined;
81 };
82 /**
83 * Tests whether the input string is a valid declaration reference import path.
84 */
85 StringChecks.explainIfInvalidImportPath = function (importPath, prefixedByPackageName) {
86 if (importPath.length > 0) {
87 if (importPath.indexOf('//') >= 0) {
88 return 'An import path must not contain "//"';
89 }
90 if (importPath[importPath.length - 1] === '/') {
91 return 'An import path must not end with "/"';
92 }
93 if (!prefixedByPackageName) {
94 if (importPath[0] === '/') {
95 return 'An import path must not start with "/" unless prefixed by a package name';
96 }
97 }
98 }
99 return undefined;
100 };
101 /**
102 * Returns true if the input string is a TSDoc system selector.
103 */
104 StringChecks.isSystemSelector = function (selector) {
105 return StringChecks._systemSelectors.has(selector);
106 };
107 /**
108 * Tests whether the input string is a valid ECMAScript identifier.
109 * A precise check is extremely complicated and highly dependent on the standard version
110 * and how faithfully the interpreter implements it, so here we use a conservative heuristic.
111 */
112 StringChecks.explainIfInvalidUnquotedIdentifier = function (identifier) {
113 if (identifier.length === 0) {
114 return 'The identifier cannot be an empty string';
115 }
116 if (StringChecks._identifierBadCharRegExp.test(identifier)) {
117 return 'The identifier cannot non-word characters';
118 }
119 if (StringChecks._identifierNumberStartRegExp.test(identifier)) {
120 return 'The identifier must not start with a number';
121 }
122 return undefined;
123 };
124 /**
125 * Tests whether the input string can be used without quotes as a member identifier in a declaration reference.
126 * If not, it should be enclosed in quotes.
127 */
128 StringChecks.explainIfInvalidUnquotedMemberIdentifier = function (identifier) {
129 var explanation = StringChecks.explainIfInvalidUnquotedIdentifier(identifier);
130 if (explanation !== undefined) {
131 return explanation;
132 }
133 if (StringChecks.isSystemSelector(identifier)) {
134 // We do this to avoid confusion about the declaration reference syntax rules.
135 // For example if someone were to see "MyClass.(static:instance)" it would be unclear which
136 // side the colon is the selector.
137 return "The identifier \"" + identifier + "\" must be quoted because it is a TSDoc system selector name";
138 }
139 return undefined;
140 };
141 StringChecks._tsdocTagNameRegExp = /^@[a-z][a-z0-9]*$/i;
142 StringChecks._urlSchemeRegExp = /^[a-z][a-z0-9]*\:\/\//i;
143 StringChecks._urlSchemeAfterRegExp = /^[a-z][a-z0-9]*\:\/\/./i;
144 // HTML element definitions:
145 // https://spec.commonmark.org/0.29/#tag-name
146 // https://www.w3.org/TR/html5/syntax.html#tag-name
147 // https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
148 //
149 // We use the CommonMark spec:
150 // "A tag name consists of an ASCII letter followed by zero or more ASCII letters, digits, or hyphens (-)."
151 StringChecks._htmlNameRegExp = /^[a-z]+[a-z0-9\-]*$/i;
152 // Note: In addition to letters, numbers, underscores, and dollar signs, modern ECMAScript
153 // also allows Unicode categories such as letters, combining marks, digits, and connector punctuation.
154 // These are mostly supported in all environments except IE11, so if someone wants it, we would accept
155 // a PR to allow them (although the test surface might be somewhat large).
156 StringChecks._identifierBadCharRegExp = /[^a-z0-9_$]/i;
157 // Identifiers most not start with a number.
158 StringChecks._identifierNumberStartRegExp = /^[0-9]/;
159 // For detailed notes about NPM package name syntax, see:
160 // tslint:disable-next-line:max-line-length
161 // https://github.com/Microsoft/web-build-tools/blob/a417ca25c63aca31dba43a34d39cc9cd529b9c78/libraries/node-core-library/src/PackageName.ts
162 StringChecks._validPackageNameRegExp = /^(?:@[a-z0-9\-_\.]+\/)?[a-z0-9\-_\.]+$/i;
163 StringChecks._systemSelectors = new Set([
164 // For classes:
165 'instance',
166 'static',
167 'constructor',
168 // For merged declarations:
169 'class',
170 'enum',
171 'function',
172 'interface',
173 'namespace',
174 'type',
175 'variable'
176 ]);
177 return StringChecks;
178}());
179exports.StringChecks = StringChecks;
180//# sourceMappingURL=StringChecks.js.map
\No newline at end of file