summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--LICENSE21
-rw-r--r--README.md7
-rw-r--r--jsr.json6
-rw-r--r--mod.ts122
5 files changed, 158 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fafff2e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.DS_Store
+Thumbs.db
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a66a1e3
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 netop://ウィビ
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ce09f4b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# dedent
+
+The [original dedent repo](https://github.com/dmnd/dedent) has too many files and I already use this all-in-one file across my projects.
+
+Might as well make it a module.
+
+Find it on [JSR](https://jsr.io/@netopwibby/dedent)!
diff --git a/jsr.json b/jsr.json
new file mode 100644
index 0000000..bf2540d
--- /dev/null
+++ b/jsr.json
@@ -0,0 +1,6 @@
+{
+ "exports": "./mod.ts",
+ "license": "MIT",
+ "name": "@netopwibby/dedent",
+ "version": "0.1.0"
+}
diff --git a/mod.ts b/mod.ts
new file mode 100644
index 0000000..2600198
--- /dev/null
+++ b/mod.ts
@@ -0,0 +1,122 @@
+/*
+ * SPDX-License-Identifier: MIT
+ * Copyright © 2015-2025 Desmond Brand
+ * Copyright © 2026 Paul Anthony Webb (modifications)
+ *
+ * Dap is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE.
+ */
+
+/*** UTILITY ------------------------------------------ ***/
+
+const dedent: Dedent = createDedent({});
+
+interface Dedent {
+ (literals: string): string;
+ (strings: TemplateStringsArray, ...values: unknown[]): string;
+ withOptions: CreateDedent;
+}
+
+interface DedentOptions {
+ alignValues?: boolean;
+ escapeSpecialCharacters?: boolean;
+ trimWhitespace?: boolean;
+}
+
+type CreateDedent = (options: DedentOptions) => Dedent;
+
+/*** EXPORT ------------------------------------------- ***/
+
+export default dedent;
+
+/*** PROGRAM ------------------------------------------ ***/
+
+function createDedent(options: DedentOptions): Dedent {
+ function dedent(literals: string): string;
+ function dedent(strings: TemplateStringsArray, ...values: unknown[]): string;
+
+ function dedent(strings: TemplateStringsArray | string, ...values: unknown[]) {
+ const raw = typeof strings === "string" ?
+ [strings] :
+ strings.raw;
+
+ const {
+ alignValues = false,
+ escapeSpecialCharacters = Array.isArray(strings),
+ trimWhitespace = true
+ } = options;
+
+ let result = "";
+
+ for (let i = 0; i < raw.length; i++) {
+ let next = raw[i];
+
+ if (escapeSpecialCharacters) {
+ next = next
+ .replace(/\\\n[ \t]*/g, "")
+ .replace(/\\`/g, "`")
+ .replace(/\\\$/g, "$")
+ .replace(/\\\{/g, "{");
+ }
+
+ result += next;
+
+ if (i < values.length) {
+ result += alignValues ?
+ alignValue(values[i], result) :
+ values[i];
+ }
+ }
+
+ const lines = result.split("\n");
+ let minIndent: number | null = null;
+
+ for (const line of lines) {
+ const match = line.match(/^(\s+)\S+/);
+
+ if (match) {
+ const indent = match[1].length;
+
+ minIndent = minIndent === null ?
+ indent :
+ Math.min(minIndent, indent);
+ }
+ }
+
+ if (minIndent !== null) {
+ result = lines
+ .map((line) => (line[0] === " " || line[0] === "\t" ? line.slice(minIndent) : line))
+ .join("\n");
+ }
+
+ if (trimWhitespace)
+ result = result.trim();
+
+ if (escapeSpecialCharacters)
+ result = result.replace(/\\n/g, "\n");
+
+ return result;
+ }
+
+ dedent.withOptions = (newOptions: DedentOptions): Dedent => createDedent({ ...options, ...newOptions });
+
+ return dedent;
+}
+
+/*** HELPER ------------------------------------------- ***/
+
+function alignValue(value: unknown, precedingText: string) {
+ if (typeof value !== "string" || !value.includes("\n"))
+ return value;
+
+ const currentLine = precedingText.slice(precedingText.lastIndexOf("\n") + 1);
+ const indentMatch = currentLine.match(/^(\s+)/);
+
+ if (indentMatch)
+ return value.replace(/\n/g, `\n${indentMatch[1]}`);
+
+ return value;
+}
+
+/*** adapted from https://github.com/dmnd/dedent ***/