Skip to content

Commit

Permalink
build: convert dedent.ts and tests to TypeScript (#51)
Browse files Browse the repository at this point in the history
Fixes #50.

Integrates with a few tools:

* TypeScript itself for type checking (`yarn tsc`)
* [Babel's TypeScript
preset](https://babeljs.io/docs/babel-preset-typescript) to stick with
the existing output process (`yarn build:legacy`, `yarn build:modern`)
* [tsup](https://tsup.egoist.dev) to generate a single `.d.ts` from
`dedent.ts` (`yarn build:types`)

Types are moved from `index.d.ts` to `dist/dedent.d.ts` to match the
other `dist/*` files. I confirmed with [the `attw`
cli](https://github.com/arethetypeswrong/arethetypeswrong.github.io/tree/e33adb4d894b041a51b8366bf0611ff5ecaf38cb/packages/cli)
that these support various Node resolution strategies.

`macro.js` and `macro.d.ts` are untouched, per #50 -> #52.
  • Loading branch information
JoshuaKGoldberg authored Jul 17, 2023
1 parent 642d99f commit 7d735a5
Show file tree
Hide file tree
Showing 15 changed files with 923 additions and 588 deletions.
6 changes: 4 additions & 2 deletions .babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"legacy": {
"plugins": [["add-module-exports", { "addDefaultProperty": true }]],
"presets": [
"@babel/preset-typescript",
[
"@babel/preset-env",
{
Expand All @@ -16,6 +17,7 @@
},
"modern": {
"presets": [
"@babel/preset-typescript",
[
"@babel/preset-env",
{
Expand All @@ -30,6 +32,7 @@
}
},
"presets": [
"@babel/preset-typescript",
[
"@babel/preset-env",
{
Expand All @@ -39,6 +42,5 @@
}
}
]
],
"plugins": ["@babel/plugin-transform-flow-comments"]
]
}
4 changes: 4 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dist/

# https://github.com/dmnd/dedent/issues/52
macro.js
17 changes: 0 additions & 17 deletions .eslintrc

This file was deleted.

13 changes: 13 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* eslint-env node */
module.exports = {
parser: "@typescript-eslint/parser",
parserOptions: {
project: true,
tsconfigRootDir: __dirname,
},
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/strict-type-checked",
"plugin:@typescript-eslint/stylistic-type-checked",
],
};
File renamed without changes.
17 changes: 7 additions & 10 deletions __tests__/dedent-tests.js → __tests__/dedent-tests.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
// @flow

import dd from '../dedent';
import dd from "../dedent";

describe("dedent", () => {
it("works without interpolation", () => {
Expand Down Expand Up @@ -69,15 +67,16 @@ describe("dedent", () => {

it("works with single line and inline closing backtick", () => {
expect(dd`
A single line of input.`
).toMatchSnapshot();
A single line of input.`).toMatchSnapshot();
});
});

it("can be used as a function", () => {
expect(dd(`
expect(
dd(`
A test argument.
`)).toMatchSnapshot();
`)
).toMatchSnapshot();
});

it("escapes backticks", () => {
Expand Down Expand Up @@ -110,9 +109,7 @@ describe("dedent", () => {
});

it("works with escaped tabs for indentation", () => {
expect(
dd("\t\tfirst\n\t\t\tsecond\n\t\t\t\tthird")
).toMatchSnapshot();
expect(dd("\t\tfirst\n\t\t\tsecond\n\t\t\t\tthird")).toMatchSnapshot();
});
/* eslint-enable indent */
});
50 changes: 0 additions & 50 deletions dedent.js

This file was deleted.

59 changes: 59 additions & 0 deletions dedent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
export default function dedent(literals: string): string;
export default function dedent(
strings: TemplateStringsArray,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...values: any[]
): string;
export default function dedent(
strings: string | TemplateStringsArray,
...values: string[]
) {
const raw = typeof strings === "string" ? [strings] : strings.raw;

// first, perform interpolation
let result = "";
for (let i = 0; i < raw.length; i++) {
result += raw[i]
// join lines when there is a suppressed newline
.replace(/\\\n[ \t]*/g, "")
// handle escaped backticks
.replace(/\\`/g, "`");

if (i < values.length) {
result += values[i];
}
}

// now strip indentation
const lines = result.split("\n");
let mindent: number | null = null;
for (const l of lines) {
const m = l.match(/^(\s+)\S+/);
if (m) {
const indent = m[1].length;
if (!mindent) {
// this is the first indented line
mindent = indent;
} else {
mindent = Math.min(mindent, indent);
}
}
}

if (mindent !== null) {
const m = mindent; // appease TypeScript
result = lines
// https://github.com/typescript-eslint/typescript-eslint/issues/7140
// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with
.map((l) => (l[0] === " " || l[0] === "\t" ? l.slice(m) : l))
.join("\n");
}

return (
result
// dedent eats leading and trailing whitespace too
.trim()
// handle escaped newlines at the end to ensure they don't get stripped too
.replace(/\\n/g, "\n")
);
}
Loading

0 comments on commit 7d735a5

Please sign in to comment.