diff --git a/types/common-tags/common-tags-tests.ts b/types/common-tags/common-tags-tests.ts
index e504624943..37a1fba789 100644
--- a/types/common-tags/common-tags-tests.ts
+++ b/types/common-tags/common-tags-tests.ts
@@ -1,167 +1,242 @@
-import * as commonTags from 'common-tags';
+import {
+ html,
+ safeHtml,
+ oneLine,
+ oneLineTrim,
+ stripIndent,
+ stripIndents,
+ inlineLists,
+ oneLineInlineLists,
+ commaLists,
+ commaListsOr,
+ commaListsAnd,
+ oneLineCommaLists,
+ oneLineCommaListsOr,
+ oneLineCommaListsAnd,
+ id,
+ TemplateTag,
+ trimResultTransformer,
+ stripIndentTransformer,
+ replaceResultTransformer,
+ replaceSubstitutionTransformer,
+ inlineArrayTransformer,
+ splitStringTransformer,
+ createTag,
+ TemplateTransformer,
+ replaceStringTransformer,
+} from 'common-tags';
-/* Test Built-in Tags */
-
-commonTags.commaLists `
- I like ${['apples', 'bananas', 'watermelons']}
- They're good!
+const userMessages = ['hi', 'what are you up to?', ''];
+html`
+
+
+ ${userMessages.map(message => safeHtml`- ${message}
`)}
+
+
`;
-commonTags.commaListsAnd`
- I like ${['apples', 'bananas', 'watermelons']}
- They're good!
-`;
-
-commonTags.commaListsOr`
- I like ${['apples', 'bananas', 'watermelons']}
- They're good!
-`;
-
-let fruits = ['apple', 'orange', 'watermelon'];
-
-commonTags.html`
-
-
- ${fruits.map(fruit => `- ${fruit}
`)}
- ${'- kiwi
\n- guava
'}
-
-
-`;
-
-commonTags.codeBlock`
-
-
- ${fruits.map(fruit => `- ${fruit}
`)}
- ${'- kiwi
\n- guava
'}
-
-
-`;
-
-commonTags.source`
-
-
- ${fruits.map(fruit => `- ${fruit}
`)}
- ${'- kiwi
\n- guava
'}
-
-
-`;
-
-let userMessages = ['hi', 'what are you up to?', '']
-commonTags.html`
-
-
- ${userMessages.map(message => commonTags.safeHtml`- ${message}
`)}
-
-
-`
-
-commonTags.oneLine`
+oneLine`
foo
bar
baz
`;
-commonTags.oneLineTrim`
+oneLineTrim`
https://news.com/article
?utm_source=designernews.co
`;
-commonTags.oneLineCommaLists`
- I like ${['apples', 'bananas', 'watermelons']}
- They're good!
-`;
-
-commonTags.oneLineCommaListsOr`
- I like ${['apples', 'bananas', 'watermelons']}
- They're good!
-`;
-
-commonTags.oneLineCommaListsAnd`
- I like ${['apples', 'bananas', 'watermelons']}
- They're good!
-`;
-
-commonTags.inlineLists`
- I like ${['apples', 'bananas', 'watermelons']}
- They're good!
-`;
-
-commonTags.oneLineInlineLists`
- I like ${['apples', 'bananas', 'watermelons']}
- They're good!
-`;
-
-let verb = 'notice';
-
-commonTags.stripIndent`
+const verb = 'notice';
+stripIndent`
This is a multi-line string.
You'll ${verb} that it is indented.
We don't want to output this indentation.
But we do want to keep this line indented.
`;
-commonTags.stripIndents`
+stripIndents`
This is a multi-line string.
You'll ${verb} that it is indented.
We don't want to output this indentation.
We don't want to keep this line indented either.
`;
-/* Test Tag Constructor */
+inlineLists`
+ I like ${['apples', 'bananas', 'watermelons']}
+ They're good!
+`;
-new commonTags.TemplateTag();
+oneLineInlineLists`
+ I like ${['apples', 'bananas', 'watermelons']}
+ They're good!
+`;
-const substitutionReplacer = (oldValue : string, newValue : string) => ({
- onSubstitution(substitution : string, resultSoFar : string) {
+commaLists`
+ I like ${['apples', 'bananas', 'watermelons']}
+ They're good!
+`;
+
+commaListsOr`
+ I like ${['apples', 'bananas', 'watermelons']}
+ They're good!
+`;
+
+commaListsAnd`
+ I like ${['apples', 'bananas', 'watermelons']}
+ They're good!
+`;
+
+oneLineCommaLists`
+ I like ${['apples', 'bananas', 'watermelons']}
+ They're good!
+`;
+
+oneLineCommaListsOr`
+ I like ${['apples', 'bananas', 'watermelons']}
+ They're good!
+`;
+
+oneLineCommaListsAnd`
+ I like ${['apples', 'bananas', 'watermelons']}
+ They're good!
+`;
+
+id`hello ${'world'}`;
+
+oneLine(String.raw)`
+ foo
+ bar\nbaz
+`;
+
+stripIndent(' foo\n bar');
+
+const doNothing = createTag();
+doNothing`foo bar`;
+
+const substitutionReplacer = (oldValue: string, newValue: string): TemplateTransformer => ({
+ onSubstitution(substitution, resultSoFar) {
if (substitution === oldValue) {
return newValue;
}
return substitution;
- }
+ },
});
-new commonTags.TemplateTag(substitutionReplacer('fizz', 'buzz'));
+const replaceFizzWithBuzz = createTag(substitutionReplacer('fizz', 'buzz'));
+replaceFizzWithBuzz`foo bar ${'fizz'}`;
-new commonTags.TemplateTag(
- substitutionReplacer('fizz', 'buzz'),
- substitutionReplacer('foo', 'bar')
+createTag();
+createTag(substitutionReplacer('fizz', 'buzz'));
+createTag(substitutionReplacer('fizz', 'buzz'), substitutionReplacer('foo', 'bar'));
+createTag([substitutionReplacer('fizz', 'buzz'), substitutionReplacer('foo', 'bar')]);
+new TemplateTag();
+new TemplateTag(substitutionReplacer('fizz', 'buzz'));
+new TemplateTag(substitutionReplacer('fizz', 'buzz'), substitutionReplacer('foo', 'bar'));
+new TemplateTag([substitutionReplacer('fizz', 'buzz'), substitutionReplacer('foo', 'bar')]);
+
+const tt: TemplateTransformer<{ foo: string }> = {
+ getInitialContext() {
+ return { foo: 'bar' };
+ },
+ onString(str, context) {
+ // $ExpectType string
+ str;
+ // $ExpectType { foo: string; }
+ context;
+ return '';
+ },
+ onSubstitution(substitution, resultSoFar, context) {
+ // $ExpectType string
+ substitution;
+ // $ExpectType string
+ resultSoFar;
+ // $ExpectType { foo: string; }
+ context;
+ return '';
+ },
+ onEndResult(endResult, context) {
+ // $ExpectType string
+ endResult;
+ // $ExpectType { foo: string; }
+ context;
+ return '';
+ },
+};
+
+createTag({});
+createTag(tt);
+createTag({
+ onString: str => `${str}!`,
+});
+createTag({
+ onSubstitution: substitution => `${substitution}!`,
+});
+createTag({
+ onEndResult: endResult => `${endResult}!`,
+});
+new TemplateTag({});
+new TemplateTag(tt);
+new TemplateTag({
+ onString: str => `${str}!`,
+});
+new TemplateTag({
+ onSubstitution: substitution => `${substitution}!`,
+});
+new TemplateTag({
+ onEndResult: endResult => `${endResult}!`,
+});
+
+createTag(trimResultTransformer());
+createTag(trimResultTransformer(''));
+createTag(trimResultTransformer('start'));
+createTag(trimResultTransformer('end'));
+createTag(trimResultTransformer('left'));
+createTag(trimResultTransformer('right'));
+
+createTag(stripIndentTransformer());
+createTag(stripIndentTransformer('initial'));
+createTag(stripIndentTransformer('all'));
+
+createTag(replaceResultTransformer('foo', 'bar'));
+createTag(replaceResultTransformer(/baz/g, 'bar'));
+createTag(
+ replaceResultTransformer(/baz/g, (substring, ...matches) => {
+ // $ExpectType string
+ substring;
+ // $ExpectType any[]
+ matches;
+ return '';
+ })
);
-new commonTags.TemplateTag([
- substitutionReplacer('fizz', 'buzz'),
- substitutionReplacer('foo', 'bar')
-]);
+createTag(replaceSubstitutionTransformer('foo', 'bar'));
+createTag(replaceSubstitutionTransformer(/baz/g, 'bar'));
+createTag(
+ replaceSubstitutionTransformer(/baz/g, (substring, ...matches) => {
+ // $ExpectType string
+ substring;
+ // $ExpectType any[]
+ matches;
+ return '';
+ })
+);
-new commonTags.TemplateTag({});
+createTag(replaceStringTransformer('foo', 'bar'));
+createTag(replaceStringTransformer(/baz/g, 'bar'));
+createTag(
+ replaceStringTransformer(/baz/g, (substring, ...matches) => {
+ // $ExpectType string
+ substring;
+ // $ExpectType any[]
+ matches;
+ return '';
+ })
+);
-new commonTags.TemplateTag({
- onEndResult: endResult => `${endResult}!`
-});
+createTag(inlineArrayTransformer());
+createTag(inlineArrayTransformer({}));
+createTag(inlineArrayTransformer({ separator: 'foo' }));
+createTag(inlineArrayTransformer({ conjunction: 'bar' }));
+createTag(inlineArrayTransformer({ serial: true }));
-new commonTags.TemplateTag({
- onSubstitution: substitution => `${substitution}!`,
- onEndResult: endResult => `${endResult}!`
-});
-
-/* Tests Built-in Transformers */
-
-new commonTags.TemplateTag(commonTags.trimResultTransformer());
-new commonTags.TemplateTag(commonTags.trimResultTransformer('left'));
-new commonTags.TemplateTag(commonTags.trimResultTransformer('right'));
-
-new commonTags.TemplateTag(commonTags.stripIndentTransformer());
-new commonTags.TemplateTag(commonTags.stripIndentTransformer('initial'));
-new commonTags.TemplateTag(commonTags.stripIndentTransformer('all'));
-
-new commonTags.TemplateTag(commonTags.replaceResultTransformer('foo', 'bar'));
-new commonTags.TemplateTag(commonTags.replaceSubstitutionTransformer(/baz/g, 'bar'));
-
-new commonTags.TemplateTag(commonTags.replaceSubstitutionTransformer('foo', 'bar'));
-new commonTags.TemplateTag(commonTags.replaceSubstitutionTransformer(/baz/g, 'bar'));
-
-new commonTags.TemplateTag(commonTags.inlineArrayTransformer());
-new commonTags.TemplateTag(commonTags.inlineArrayTransformer({}));
-new commonTags.TemplateTag(commonTags.inlineArrayTransformer({separator: 'foo'}));
-new commonTags.TemplateTag(commonTags.inlineArrayTransformer({conjunction: 'bar'}));
-
-new commonTags.TemplateTag(commonTags.splitStringTransformer('foo'));
+createTag(splitStringTransformer('foo'));
diff --git a/types/common-tags/index.d.ts b/types/common-tags/index.d.ts
index 65f0b61673..3a12c91109 100644
--- a/types/common-tags/index.d.ts
+++ b/types/common-tags/index.d.ts
@@ -1,67 +1,220 @@
-// Type definitions for common-tags v1.4.0
+// Type definitions for common-tags 1.8
// Project: https://github.com/declandewet/common-tags
// Definitions by: Viktor Zozuliak
// Paul Wang
+// BendingBender
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+// TypeScript Version: 2.3
-declare module 'common-tags' {
- type TemplateTag = (literals: TemplateStringsArray, ...placeholders: any[]) => string;
+export as namespace commonTags;
- type TemplateTransformer = {
- onSubstitution?: (substitution: string, resultSoFar: string) => string;
- onEndResult?: (endResult : string) => string;
- }
+export type JSTag = (literals: TemplateStringsArray, ...placeholders: any[]) => string;
- /* Built-in Tags */
- export var commaLists: TemplateTag;
-
- export var commaListsAnd: TemplateTag;
-
- export var commaListsOr: TemplateTag;
-
- export var html: TemplateTag;
-
- export var codeBlock: TemplateTag;
-
- export var source: TemplateTag;
-
- export var safeHtml: TemplateTag;
-
- export var oneLine: TemplateTag;
-
- export var oneLineTrim: TemplateTag;
-
- export var oneLineCommaLists: TemplateTag;
-
- export var oneLineCommaListsOr: TemplateTag;
-
- export var oneLineCommaListsAnd: TemplateTag;
-
- export var inlineLists: TemplateTag;
-
- export var oneLineInlineLists: TemplateTag;
-
- export var stripIndent: TemplateTag;
-
- export var stripIndents: TemplateTag;
-
- /* New Tag Constructor */
- export var TemplateTag: {
- new(): TemplateTag;
- new(...transformers: TemplateTransformer[]): TemplateTag;
- new(transformers: TemplateTransformer[]): TemplateTag;
- };
-
- /* Built-in Transformers */
- export var trimResultTransformer: (side?: 'left'|'right') => TemplateTransformer;
-
- export var stripIndentTransformer: (type?: 'initial'|'all') => TemplateTransformer;
-
- export var replaceResultTransformer: (replaceWhat: string|RegExp, replaceWith: string) => TemplateTransformer;
-
- export var replaceSubstitutionTransformer: (replaceWhat: string|RegExp, replaceWith: string) => TemplateTransformer;
-
- export var inlineArrayTransformer: (opts?: {separator?: string, conjunction?: string}) => TemplateTransformer;
-
- export var splitStringTransformer: (splitBy: string) => TemplateTransformer;
+export interface TemplateTag {
+ (str: string): string;
+ (tag: JSTag): TemplateTag;
+ (literals: TemplateStringsArray, ...placeholders: any[]): string;
}
+
+/**
+ * You'll often find that you might want to include an array in a template.
+ * Typically, doing something like `${array.join(', ')}` would work - but what if you're printing a list of items
+ * in an HTML template and want to maintain the indentation? You'd have to count the spaces manually and include
+ * them in the `.join()` call - which is a bit ugly for my taste.
+ * This tag properly indents arrays, as well as newline characters in string substitutions,
+ * by converting them to an array split by newline and re-using the same array inclusion logic.
+ */
+export const html: TemplateTag;
+
+/**
+ * alias for `html`
+ */
+export const codeBlock: TemplateTag;
+
+/**
+ * alias for `html`
+ */
+export const source: TemplateTag;
+
+/**
+ * A tag very similar to `html` but it does safe HTML escaping for strings coming from substitutions.
+ * When combined with regular `html` tag, you can do basic HTML templating that is safe from
+ * XSS (Cross-Site Scripting) attacks.
+ */
+export const safeHtml: TemplateTag;
+
+/**
+ * Allows you to keep your single-line strings under 80 characters without resorting to crazy string concatenation.
+ */
+export const oneLine: TemplateTag;
+
+/**
+ * Allows you to keep your single-line strings under 80 characters while trimming the new lines.
+ */
+export const oneLineTrim: TemplateTag;
+
+/**
+ * If you want to strip the initial indentation from the beginning of each line in a multiline string.
+ * Important note: this tag will not indent multiline strings coming from the substitutions.
+ * If you want that behavior, use the `html` tag (aliases: `source`, `codeBlock`).
+ */
+export const stripIndent: TemplateTag;
+
+/**
+ * If you want to strip *all* of the indentation from the beginning of each line in a multiline string.
+ */
+export const stripIndents: TemplateTag;
+
+/**
+ * Allows you to inline an array substitution as a list.
+ */
+export const inlineLists: TemplateTag;
+
+/**
+ * Allows you to inline an array substitution as a list, rendered out on a single line.
+ */
+export const oneLineInlineLists: TemplateTag;
+
+/**
+ * Allows you to inline an array substitution as a comma-separated list.
+ */
+export const commaLists: TemplateTag;
+
+/**
+ * Allows you to inline an array substitution as a comma-separated list, the last of which is preceded by the word "or".
+ */
+export const commaListsOr: TemplateTag;
+
+/**
+ * Allows you to inline an array substitution as a comma-separated list, the last of which is preceded by the word "and".
+ */
+export const commaListsAnd: TemplateTag;
+
+/**
+ * Allows you to inline an array substitution as a comma-separated list, and is rendered out on to a single line.
+ */
+export const oneLineCommaLists: TemplateTag;
+
+/**
+ * Allows you to inline an array substitution as a comma-separated list, the last of which is preceded by the word "or", and is rendered out on to a single line.
+ */
+export const oneLineCommaListsOr: TemplateTag;
+
+/**
+ * Allows you to inline an array substitution as a comma-separated list, the last of which is preceded by the word "and", and is rendered out on to a single line.
+ */
+export const oneLineCommaListsAnd: TemplateTag;
+
+/**
+ * A no-op tag that might come in useful in some scenarios, e.g. mocking.
+ */
+export const id: TemplateTag;
+
+export interface TemplateTransformer {
+ /**
+ * Called before everything else.
+ * The result of this hook will be passed to other hooks as `context`.
+ * If omitted, `context` will be an empty object.
+ */
+ getInitialContext?: () => TCtx;
+ /**
+ * Called when the tag encounters a string.
+ * (a string is whatever's not inside "${}" in your template literal)
+ * `str` is the value of the current string
+ */
+ onString?: (str: string, context: TCtx) => string;
+ /**
+ * Called when the tag encounters a substitution.
+ * (a substitution is whatever's inside "${}" in your template literal)
+ * `substitution` is the value of the current substitution
+ * `resultSoFar` is the end result up to the point of this substitution
+ */
+ onSubstitution?: (substitution: string, resultSoFar: string, context: TCtx) => string;
+ /**
+ * Called when all substitutions have been parsed
+ * `endResult` is the final value.
+ */
+ onEndResult?: (endResult: string, context: TCtx) => string;
+}
+
+export type PluginFunction = (oldValue: string, newValue: string) => TemplateTransformer;
+
+/**
+ * New Tag factory
+ */
+export function createTag(transformers?: Array>): TemplateTag;
+export function createTag(...transformers: Array>): TemplateTag;
+export function createTag(...pluginFunctions: PluginFunction[]): TemplateTag;
+
+export const TemplateTag: {
+ /**
+ * New Tag Constructor
+ * @deprecated
+ */
+ new (transformers?: Array>): TemplateTag;
+ new (...transformers: Array>): TemplateTag;
+ new (...pluginFunctions: PluginFunction[]): TemplateTag;
+};
+
+/**
+ * TemplateTag transformer that trims whitespace on the end result of a tagged template
+ * @param [side=''] The side of the string to trim. Can be 'start' or 'end' (alternatively 'left' or 'right')
+ * @return a TemplateTag transformer
+ */
+export function trimResultTransformer(
+ side?: 'start' | 'end' | 'left' | 'right' | ''
+): TemplateTransformer;
+
+/**
+ * strips indentation from a template literal
+ * @param [type='initial'] whether to remove all indentation or just leading indentation. can be 'all' or 'initial'
+ * @return a TemplateTag transformer
+ */
+export function stripIndentTransformer(type?: 'initial' | 'all'): TemplateTransformer;
+
+/**
+ * Replaces a value or pattern in the end result with a new value.
+ * @param replaceWhat the value or pattern that should be replaced
+ * @param replaceWith the replacement value
+ * @return a TemplateTag transformer
+ */
+export function replaceResultTransformer(
+ replaceWhat: string | RegExp,
+ replaceWith: string | ((substring: string, ...args: any[]) => string)
+): TemplateTransformer;
+
+/**
+ * Replaces the result of all substitutions (results of calling ${ ... }) with a new value.
+ * Same as for `replaceResultTransformer`, replaceWhat can be a string or regular expression and replaceWith is the new value.
+ */
+export function replaceSubstitutionTransformer(
+ replaceWhat: string | RegExp,
+ replaceWith: string | ((substring: string, ...args: any[]) => string)
+): TemplateTransformer;
+
+/**
+ * Replaces the result of all strings (what's not in ${ ... }) with a new value.
+ * Same as for `replaceResultTransformer`, replaceWhat can be a string or regular expression and replaceWith is the new value.
+ */
+export function replaceStringTransformer(
+ replaceWhat: string | RegExp,
+ replaceWith: string | ((substring: string, ...args: any[]) => string)
+): TemplateTransformer;
+
+/**
+ * Converts an array substitution to a string containing a list
+ * @param [opts.separator=''] what to separate each item with (always followed by a space)
+ * @param [opts.conjunction=''] replace the last separator with this value
+ * @param [opts.serial=false] should the separator be included before the conjunction? As in the case of serial/oxford commas
+ * @return a TemplateTag transformer
+ */
+export function inlineArrayTransformer(opts?: {
+ separator?: string;
+ conjunction?: string;
+ serial?: boolean;
+}): TemplateTransformer;
+
+/**
+ * Splits a string substitution into an array by the provided splitBy substring, only if the string contains the splitBy substring.
+ */
+export function splitStringTransformer(splitBy: string): TemplateTransformer;
diff --git a/types/common-tags/tslint.json b/types/common-tags/tslint.json
index a41bf5d19a..f93cf8562a 100644
--- a/types/common-tags/tslint.json
+++ b/types/common-tags/tslint.json
@@ -1,79 +1,3 @@
{
- "extends": "dtslint/dt.json",
- "rules": {
- "adjacent-overload-signatures": false,
- "array-type": false,
- "arrow-return-shorthand": false,
- "ban-types": false,
- "callable-types": false,
- "comment-format": false,
- "dt-header": false,
- "eofline": false,
- "export-just-namespace": false,
- "import-spacing": false,
- "interface-name": false,
- "interface-over-type-literal": false,
- "jsdoc-format": false,
- "max-line-length": false,
- "member-access": false,
- "new-parens": false,
- "no-any-union": false,
- "no-boolean-literal-compare": false,
- "no-conditional-assignment": false,
- "no-consecutive-blank-lines": false,
- "no-construct": false,
- "no-declare-current-package": false,
- "no-duplicate-imports": false,
- "no-duplicate-variable": false,
- "no-empty-interface": false,
- "no-for-in-array": false,
- "no-inferrable-types": false,
- "no-internal-module": false,
- "no-irregular-whitespace": false,
- "no-mergeable-namespace": false,
- "no-misused-new": false,
- "no-namespace": false,
- "no-object-literal-type-assertion": false,
- "no-padding": false,
- "no-redundant-jsdoc": false,
- "no-redundant-jsdoc-2": false,
- "no-redundant-undefined": false,
- "no-reference-import": false,
- "no-relative-import-in-test": false,
- "no-self-import": false,
- "no-single-declare-module": false,
- "no-string-throw": false,
- "no-unnecessary-callback-wrapper": false,
- "no-unnecessary-class": false,
- "no-unnecessary-generics": false,
- "no-unnecessary-qualifier": false,
- "no-unnecessary-type-assertion": false,
- "no-useless-files": false,
- "no-var-keyword": false,
- "no-var-requires": false,
- "no-void-expression": false,
- "no-trailing-whitespace": false,
- "object-literal-key-quotes": false,
- "object-literal-shorthand": false,
- "one-line": false,
- "one-variable-per-declaration": false,
- "only-arrow-functions": false,
- "prefer-conditional-expression": false,
- "prefer-const": false,
- "prefer-declare-function": false,
- "prefer-for-of": false,
- "prefer-method-signature": false,
- "prefer-template": false,
- "radix": false,
- "semicolon": false,
- "space-before-function-paren": false,
- "space-within-parens": false,
- "strict-export-declare-modifiers": false,
- "trim-file": false,
- "triple-equals": false,
- "typedef-whitespace": false,
- "unified-signatures": false,
- "void-return": false,
- "whitespace": false
- }
+ "extends": "dtslint/dt.json"
}