Add comprehensive development roadmap via GitHub Issues

Created 10 detailed GitHub issues covering:
- Project activation and management UI (#1-2)
- Worker node coordination and visualization (#3-4)
- Automated GitHub repository scanning (#5)
- Intelligent model-to-issue matching (#6)
- Multi-model task execution system (#7)
- N8N workflow integration (#8)
- Hive-Bzzz P2P bridge (#9)
- Peer assistance protocol (#10)

Each issue includes detailed specifications, acceptance criteria,
technical implementation notes, and dependency mapping.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-07-12 19:41:01 +10:00
parent 9a6a06da89
commit e89f2f4b7b
4980 changed files with 1501266 additions and 57 deletions

55
frontend/node_modules/ts-dedent/HISTORY.md generated vendored Normal file
View File

@@ -0,0 +1,55 @@
# History
## vNext
TBA
## v2.2.0
Add indentation to values with multiline strings & added ESM module
- Updated all dependencies to their latest version
- Updated CI settings (added node 16, multiple os platforms)
- Moved from Travis CI to Github Actions
## v2.1.1
Security update with dependency changes
- Updated all dependencies to their latest version
- Updated CI settings (added node 15)
## v2.1.0
- Correctly handle escape sequences when used as a tag
- Add test build to CI
- Only run coverage once per change
## v2.0.0
Fixes #4
- ! Might break/change existing behavior
- If a line does not start with whitespace don't remove the indentation
## v1.2.0
Security update with dependency changes
- Updated all dependencies to their latest version
- Updated CI settings
- Replaced tslint with typescript-eslint
- Removed unused @types/node
- Added lint to run with the test suite
## v1.1.0
Security update with dependency changes
- Updated all dependencies to their latest version
## v1.0.0
First release includes following functions
- `function dedent(TemplateStringsArray | string, ...any[]): string

21
frontend/node_modules/ts-dedent/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Tamino Martinius
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.

107
frontend/node_modules/ts-dedent/README.md generated vendored Normal file
View File

@@ -0,0 +1,107 @@
# TypeScript Dedent
[![codecov](https://codecov.io/gh/tamino-martinius/node-ts-dedent/branch/master/graph/badge.svg)](https://codecov.io/gh/tamino-martinius/node-ts-dedent)
TypeScript package which smartly trims and strips indentation from multi-line strings.
## Usage Examples
```js
import dedent from 'dedent';
console.log(dedent`A string that gets so long you need to break it over
multiple lines. Luckily dedent is here to keep it
readable without lots of spaces ending up in the string
itself.`);
console.log(dedent`
A string that gets so long you need to break it over
multiple lines. Luckily dedent is here to keep it
readable without lots of spaces ending up in the string
itself.
`);
```
```txt
A string that gets so long you need to break it over
multiple lines. Luckily dedent is here to keep it
readable without lots of spaces ending up in the string
itself.
```
---
```js
console.log(dedent`
Leading and trailing lines will be trimmed, so you can write something like
this and have it work as you expect:
* how convenient it is
* that I can use an indented list
- and still have it do the right thing
That's all.
`);
```
```txt
Leading and trailing lines will be trimmed, so you can write something like
this and have it work as you expect:
* how convenient it is
* that I can use an indented list
- and still have it do the right thing
That's all.
```
---
```js
console.log(dedent`
Also works fine
${1}. With any kind of
${2}. Placeholders
`);
```
```txt
Also works fine
1. With any kind of
2. Placeholders
```
---
```js
console.log(dedent(`
Wait! I lied. Dedent can also be used as a function.
`);
```
```txt
Wait! I lied. Dedent can also be used as a function.
```
## License
MIT
## Based on
- [dedent](https://www.npmjs.com/package/dedent) by ~dmnd
- [dedent-js](https://www.npmjs.com/package/dedent-js) by ~martin-kolarik
## Changelog
See [history](HISTORY.md) for more details.
- `2.2.0` **2021-08-01** Add indentation to values with multiline strings & added ESM module
- `2.1.1` **2021-03-31** Update dependencies
- `2.1.0` **2021-03-24** Bugfixes
- `2.0.0` **2020-09-28** Bugfixes
- `1.2.0` **2020-09-28** Update dependencies and a couple of minor improvments
- `1.1.0` **2019-07-26** Update dependencies and fixed links in readme
- `1.0.0` **2018-06-14** Initial release

2
frontend/node_modules/ts-dedent/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export declare function dedent(templ: TemplateStringsArray | string, ...values: unknown[]): string;
export default dedent;

42
frontend/node_modules/ts-dedent/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.dedent = void 0;
function dedent(templ) {
var values = [];
for (var _i = 1; _i < arguments.length; _i++) {
values[_i - 1] = arguments[_i];
}
var strings = Array.from(typeof templ === 'string' ? [templ] : templ);
strings[strings.length - 1] = strings[strings.length - 1].replace(/\r?\n([\t ]*)$/, '');
var indentLengths = strings.reduce(function (arr, str) {
var matches = str.match(/\n([\t ]+|(?!\s).)/g);
if (matches) {
return arr.concat(matches.map(function (match) { var _a, _b; return (_b = (_a = match.match(/[\t ]/g)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; }));
}
return arr;
}, []);
if (indentLengths.length) {
var pattern_1 = new RegExp("\n[\t ]{" + Math.min.apply(Math, indentLengths) + "}", 'g');
strings = strings.map(function (str) { return str.replace(pattern_1, '\n'); });
}
strings[0] = strings[0].replace(/^\r?\n/, '');
var string = strings[0];
values.forEach(function (value, i) {
var endentations = string.match(/(?:^|\n)( *)$/);
var endentation = endentations ? endentations[1] : '';
var indentedValue = value;
if (typeof value === 'string' && value.includes('\n')) {
indentedValue = String(value)
.split('\n')
.map(function (str, i) {
return i === 0 ? str : "" + endentation + str;
})
.join('\n');
}
string += indentedValue + strings[i + 1];
});
return string;
}
exports.dedent = dedent;
exports.default = dedent;
//# sourceMappingURL=index.js.map

1
frontend/node_modules/ts-dedent/dist/index.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,SAAgB,MAAM,CACpB,KAAoC;IACpC,gBAAoB;SAApB,UAAoB,EAApB,qBAAoB,EAApB,IAAoB;QAApB,+BAAoB;;IAEpB,IAAI,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAGtE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,OAAO,CAC/D,gBAAgB,EAChB,EAAE,CACH,CAAC;IAGF,IAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,UAAC,GAAG,EAAE,GAAG;QAC5C,IAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACjD,IAAI,OAAO,EAAE;YACX,OAAO,GAAG,CAAC,MAAM,CACf,OAAO,CAAC,GAAG,CAAC,UAAC,KAAK,gBAAK,OAAA,MAAA,MAAA,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,0CAAE,MAAM,mCAAI,CAAC,CAAA,EAAA,CAAC,CAC3D,CAAC;SACH;QACD,OAAO,GAAG,CAAC;IACb,CAAC,EAAY,EAAE,CAAC,CAAC;IAGjB,IAAI,aAAa,CAAC,MAAM,EAAE;QACxB,IAAM,SAAO,GAAG,IAAI,MAAM,CAAC,aAAW,IAAI,CAAC,GAAG,OAAR,IAAI,EAAQ,aAAa,OAAI,EAAE,GAAG,CAAC,CAAC;QAE1E,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,UAAC,GAAG,IAAK,OAAA,GAAG,CAAC,OAAO,CAAC,SAAO,EAAE,IAAI,CAAC,EAA1B,CAA0B,CAAC,CAAC;KAC5D;IAGD,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAG9C,IAAI,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAExB,MAAM,CAAC,OAAO,CAAC,UAAC,KAAK,EAAE,CAAC;QAEtB,IAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;QAClD,IAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QACvD,IAAI,aAAa,GAAG,KAAK,CAAA;QAEzB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YACrD,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC;iBAC1B,KAAK,CAAC,IAAI,CAAC;iBACX,GAAG,CAAC,UAAC,GAAG,EAAE,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAG,WAAW,GAAG,GAAK,CAAA;YAC/C,CAAC,CAAC;iBACD,IAAI,CAAC,IAAI,CAAC,CAAC;SACf;QAED,MAAM,IAAI,aAAa,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAvDD,wBAuDC;AAED,kBAAe,MAAM,CAAC"}

2
frontend/node_modules/ts-dedent/esm/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export declare function dedent(templ: TemplateStringsArray | string, ...values: unknown[]): string;
export default dedent;

38
frontend/node_modules/ts-dedent/esm/index.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
export function dedent(templ) {
var values = [];
for (var _i = 1; _i < arguments.length; _i++) {
values[_i - 1] = arguments[_i];
}
var strings = Array.from(typeof templ === 'string' ? [templ] : templ);
strings[strings.length - 1] = strings[strings.length - 1].replace(/\r?\n([\t ]*)$/, '');
var indentLengths = strings.reduce(function (arr, str) {
var matches = str.match(/\n([\t ]+|(?!\s).)/g);
if (matches) {
return arr.concat(matches.map(function (match) { var _a, _b; return (_b = (_a = match.match(/[\t ]/g)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0; }));
}
return arr;
}, []);
if (indentLengths.length) {
var pattern_1 = new RegExp("\n[\t ]{" + Math.min.apply(Math, indentLengths) + "}", 'g');
strings = strings.map(function (str) { return str.replace(pattern_1, '\n'); });
}
strings[0] = strings[0].replace(/^\r?\n/, '');
var string = strings[0];
values.forEach(function (value, i) {
var endentations = string.match(/(?:^|\n)( *)$/);
var endentation = endentations ? endentations[1] : '';
var indentedValue = value;
if (typeof value === 'string' && value.includes('\n')) {
indentedValue = String(value)
.split('\n')
.map(function (str, i) {
return i === 0 ? str : "" + endentation + str;
})
.join('\n');
}
string += indentedValue + strings[i + 1];
});
return string;
}
export default dedent;
//# sourceMappingURL=index.js.map

1
frontend/node_modules/ts-dedent/esm/index.js.map generated vendored Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,MAAM,CACpB,KAAoC;IACpC,gBAAoB;SAApB,UAAoB,EAApB,qBAAoB,EAApB,IAAoB;QAApB,+BAAoB;;IAEpB,IAAI,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAGtE,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,OAAO,CAC/D,gBAAgB,EAChB,EAAE,CACH,CAAC;IAGF,IAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,UAAC,GAAG,EAAE,GAAG;QAC5C,IAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACjD,IAAI,OAAO,EAAE;YACX,OAAO,GAAG,CAAC,MAAM,CACf,OAAO,CAAC,GAAG,CAAC,UAAC,KAAK,gBAAK,OAAA,MAAA,MAAA,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,0CAAE,MAAM,mCAAI,CAAC,CAAA,EAAA,CAAC,CAC3D,CAAC;SACH;QACD,OAAO,GAAG,CAAC;IACb,CAAC,EAAY,EAAE,CAAC,CAAC;IAGjB,IAAI,aAAa,CAAC,MAAM,EAAE;QACxB,IAAM,SAAO,GAAG,IAAI,MAAM,CAAC,aAAW,IAAI,CAAC,GAAG,OAAR,IAAI,EAAQ,aAAa,OAAI,EAAE,GAAG,CAAC,CAAC;QAE1E,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,UAAC,GAAG,IAAK,OAAA,GAAG,CAAC,OAAO,CAAC,SAAO,EAAE,IAAI,CAAC,EAA1B,CAA0B,CAAC,CAAC;KAC5D;IAGD,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAG9C,IAAI,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAExB,MAAM,CAAC,OAAO,CAAC,UAAC,KAAK,EAAE,CAAC;QAEtB,IAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;QAClD,IAAM,WAAW,GAAG,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QACvD,IAAI,aAAa,GAAG,KAAK,CAAA;QAEzB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YACrD,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC;iBAC1B,KAAK,CAAC,IAAI,CAAC;iBACX,GAAG,CAAC,UAAC,GAAG,EAAE,CAAC;gBACV,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAG,WAAW,GAAG,GAAK,CAAA;YAC/C,CAAC,CAAC;iBACD,IAAI,CAAC,IAAI,CAAC,CAAC;SACf;QAED,MAAM,IAAI,aAAa,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,eAAe,MAAM,CAAC"}

68
frontend/node_modules/ts-dedent/package.json generated vendored Normal file
View File

@@ -0,0 +1,68 @@
{
"name": "ts-dedent",
"version": "2.2.0",
"description": "TypeScript package which smartly trims and strips indentation from multi-line strings",
"author": "Tamino Martinius <dev@zaku.eu>",
"main": "./dist/index.js",
"module": "./esm/index.js",
"jsnext:main": "./dist/index.js",
"typings": "./dist/index.d.ts",
"license": "MIT",
"files": [
"dist",
"esm",
"src"
],
"repository": {
"type": "git",
"url": "https://github.com/tamino-martinius/node-ts-dedent.git"
},
"keywords": [
"dedent",
"deindent",
"indentation",
"multi-line string",
"multiline strings",
"template literals",
"template strings",
"ts",
"typescript",
"es6",
"harmony"
],
"engines": {
"node": ">=6.10"
},
"scripts": {
"coverage": "rm -rf coverage* && jest --coverage",
"pretest": "npm run lint",
"test": "jest",
"lint": "eslint .",
"watch": "tsc -w",
"ci": "npm run coverage && codecov",
"compile": "rm -rf dist/* && rm -rf esm/* && tsc --module commonjs --outdir dist && tsc --module es6 --outdir esm",
"preversion": "npm run compile && git add ."
},
"devDependencies": {
"@types/jest": "^26.0.24",
"@typescript-eslint/eslint-plugin": "^4.28.5",
"@typescript-eslint/parser": "^4.28.5",
"codecov": "^3.8.3",
"eslint": "^7.32.0",
"jest": "^27.0.6",
"ts-jest": "^27.0.4",
"typescript": "~4.3.5"
},
"jest": {
"transform": {
".ts": "ts-jest"
},
"testRegex": "\\.(test|spec)\\.ts$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"json"
]
}
}

View File

@@ -0,0 +1,554 @@
import { dedent } from '..';
function tag(strings: TemplateStringsArray, ...values: number[]) {
let string = strings[0];
values.forEach((value, i) => {
string += 2 * value + strings[i + 1];
});
return string;
}
describe('dedent tag', () => {
it('should work with empty string', () => {
expect(dedent``).toEqual('');
});
it('should work with tabs', () => {
expect(dedent`Line #1
Line #2
Line #3`).toEqual('Line #1\nLine #2\nLine #3');
expect(dedent`Line #${1}
Line #${2}
Line #${3}`).toEqual('Line #1\nLine #2\nLine #3');
expect(dedent`${1}. line #${1}
${2}. line #${2}
${3}. line`).toEqual('1. line #1\n2. line #2\n3. line');
});
it('should work with spaces', () => {
expect(dedent`Line #1
Line #2
Line #3`).toEqual('Line #1\nLine #2\nLine #3');
expect(dedent`Line #${1}
Line #${2}
Line #${3}`).toEqual('Line #1\nLine #2\nLine #3');
expect(dedent`${1}. line #${1}
${2}. line #${2}
${3}. line`).toEqual('1. line #1\n2. line #2\n3. line');
});
it('should remove leading/trailing line break', () => {
expect(
dedent`
Line #1
Line #2
Line #3
`,
).toEqual('Line #1\nLine #2\nLine #3');
expect(
dedent`
Line #1
Line #2
Line #3
`,
).toEqual('Line #1\n\tLine #2\n\tLine #3');
expect(
dedent`
Line #${1}
Line #${2}
Line #${3}
`,
).toEqual('Line #1\nLine #2\nLine #3');
expect(
dedent`
Line #${1}
Line #${2}
Line #${3}
`,
).toEqual('Line #1\n\tLine #2\n\tLine #3');
expect(
dedent`
${1}. line #${1}
${2}. line #${2}
${3}. line
`,
).toEqual('1. line #1\n2. line #2\n3. line');
});
it('should not remove more than one leading/trailing line break', () => {
expect(
dedent`
Line #1
Line #2
Line #3
`,
).toEqual('\nLine #1\nLine #2\nLine #3\n');
expect(
dedent`
Line #${1}
Line #${2}
Line #${3}
`,
).toEqual('\nLine #1\nLine #2\nLine #3\n');
expect(
dedent`
${1}. line #${1}
${2}. line #${2}
${3}. line
`,
).toEqual('\n1. line #1\n2. line #2\n3. line\n');
});
it('should remove the same number of tabs/spaces from each line', () => {
expect(
dedent`
Line #1
Line #2
Line #3
`,
).toEqual('Line #1\n\tLine #2\n\t\tLine #3');
expect(
dedent`
Line #${1}
Line #${2}
Line #${3}
`,
).toEqual('Line #1\n\tLine #2\n\t\tLine #3');
expect(
dedent`
${1}. line #${1}
${2}. line #${2}
${3}. line
`,
).toEqual('1. line #1\n\t2. line #2\n\t\t3. line');
});
it("should ignore the last line if it doesn't contain anything else than whitespace", () => {
expect(
(() => {
return dedent`
Line #1
Line #2
Line #3
`;
})(),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
(() => {
return dedent`
Line #${1}
Line #${2}
Line #${3}
`;
})(),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
(() => {
return dedent`
${1}. line #${1}
${2}. line #${2}
${3}. line
`;
})(),
).toEqual('1. line #1\n2. line #2\n3. line');
});
it("should process escape sequences", () => {
expect(
(() => {
return dedent`
\${not interpolated}
\`
`;
})(),
).toEqual('${not interpolated}\n`');
});
});
describe('dedent() function', () => {
it('should work with tabs', () => {
expect(
dedent(`Line #1
Line #2
Line #3`),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
dedent(`Line #${1}
Line #${2}
Line #${3}`),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
dedent(`${1}. line #${1}
${2}. line #${2}
${3}. line`),
).toEqual('1. line #1\n2. line #2\n3. line');
});
it('should work with spaces', () => {
expect(
dedent(`Line #1
Line #2
Line #3`),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
dedent(`Line #${1}
Line #${2}
Line #${3}`),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
dedent(`${1}. line #${1}
${2}. line #${2}
${3}. line`),
).toEqual('1. line #1\n2. line #2\n3. line');
});
it('should remove leading/trailing line break', () => {
expect(
dedent(`
Line #1
Line #2
Line #3
`),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
dedent(`
Line #1
Line #2
Line #3
`),
).toEqual('Line #1\n\tLine #2\n\tLine #3');
expect(
dedent(`
Line #${1}
Line #${2}
Line #${3}
`),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
dedent(`
Line #${1}
Line #${2}
Line #${3}
`),
).toEqual('Line #1\n\tLine #2\n\tLine #3');
expect(
dedent(`
${1}. line #${1}
${2}. line #${2}
${3}. line
`),
).toEqual('1. line #1\n2. line #2\n3. line');
});
it('should not remove more than one leading/trailing line break', () => {
expect(
dedent(`
Line #1
Line #2
Line #3
`),
).toEqual('\nLine #1\nLine #2\nLine #3\n');
expect(
dedent(`
Line #${1}
Line #${2}
Line #${3}
`),
).toEqual('\nLine #1\nLine #2\nLine #3\n');
expect(
dedent(`
${1}. line #${1}
${2}. line #${2}
${3}. line
`),
).toEqual('\n1. line #1\n2. line #2\n3. line\n');
});
it('should remove the same number of tabs/spaces from each line', () => {
expect(
dedent(`
Line #1
Line #2
Line #3
`),
).toEqual('Line #1\n\tLine #2\n\t\tLine #3');
expect(
dedent(`
Line #${1}
Line #${2}
Line #${3}
`),
).toEqual('Line #1\n\tLine #2\n\t\tLine #3');
expect(
dedent(`
${1}. line #${1}
${2}. line #${2}
${3}. line
`),
).toEqual('1. line #1\n\t2. line #2\n\t\t3. line');
});
it("should ignore the last line if it doesn't contain anything else than whitespace", () => {
expect(
(() => {
return dedent(`
Line #1
Line #2
Line #3
`);
})(),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
(() => {
return dedent(`
Line #${1}
Line #${2}
Line #${3}
`);
})(),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
(() => {
return dedent(`
${1}. line #${1}
${2}. line #${2}
${3}. line
`);
})(),
).toEqual('1. line #1\n2. line #2\n3. line');
});
it("should process escape sequences", () => {
expect(
dedent(`
\${not interpolated}
\`
`),
).toEqual('${not interpolated}\n`');
});
});
describe('dedent() function with custom tag', () => {
it('should work with tabs', () => {
expect(
dedent(tag`Line #1
Line #2
Line #3`),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
dedent(tag`Line #${1}
Line #${2}
Line #${3}`),
).toEqual('Line #2\nLine #4\nLine #6');
expect(
dedent(tag`${1}. line #${1}
${2}. line #${2}
${3}. line`),
).toEqual('2. line #2\n4. line #4\n6. line');
});
it('should work with spaces', () => {
expect(
dedent(tag`Line #1
Line #2
Line #3`),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
dedent(tag`Line #${1}
Line #${2}
Line #${3}`),
).toEqual('Line #2\nLine #4\nLine #6');
expect(
dedent(tag`${1}. line #${1}
${2}. line #${2}
${3}. line`),
).toEqual('2. line #2\n4. line #4\n6. line');
});
it('should remove leading/trailing line break', () => {
expect(
dedent(tag`
Line #1
Line #2
Line #3
`),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
dedent(tag`
Line #1
Line #2
Line #3
`),
).toEqual('Line #1\n\tLine #2\n\tLine #3');
expect(
dedent(tag`
Line #${1}
Line #${2}
Line #${3}
`),
).toEqual('Line #2\nLine #4\nLine #6');
expect(
dedent(tag`
Line #${1}
Line #${2}
Line #${3}
`),
).toEqual('Line #2\n\tLine #4\n\tLine #6');
expect(
dedent(tag`
${1}. line #${1}
${2}. line #${2}
${3}. line
`),
).toEqual('2. line #2\n4. line #4\n6. line');
});
it('should not remove more than one leading/trailing line break', () => {
expect(
dedent(tag`
Line #1
Line #2
Line #3
`),
).toEqual('\nLine #1\nLine #2\nLine #3\n');
expect(
dedent(tag`
Line #${1}
Line #${2}
Line #${3}
`),
).toEqual('\nLine #2\nLine #4\nLine #6\n');
expect(
dedent(tag`
${1}. line #${1}
${2}. line #${2}
${3}. line
`),
).toEqual('\n2. line #2\n4. line #4\n6. line\n');
});
it('should remove the same number of tabs/spaces from each line', () => {
expect(
dedent(tag`
Line #1
Line #2
Line #3
`),
).toEqual('Line #1\n\tLine #2\n\t\tLine #3');
expect(
dedent(tag`
Line #${1}
Line #${2}
Line #${3}
`),
).toEqual('Line #2\n\tLine #4\n\t\tLine #6');
expect(
dedent(tag`
${1}. line #${1}
${2}. line #${2}
${3}. line
`),
).toEqual('2. line #2\n\t4. line #4\n\t\t6. line');
});
it("should ignore the last line if it doesn't contain anything else than whitespace", () => {
expect(
(() => {
return dedent(tag`
Line #1
Line #2
Line #3
`);
})(),
).toEqual('Line #1\nLine #2\nLine #3');
expect(
(() => {
return dedent(tag`
Line #${1}
Line #${2}
Line #${3}
`);
})(),
).toEqual('Line #2\nLine #4\nLine #6');
expect(
(() => {
return dedent(tag`
${1}. line #${1}
${2}. line #${2}
${3}. line
`);
})(),
).toEqual('2. line #2\n4. line #4\n6. line');
});
it("should process escape sequences", () => {
expect(
dedent(tag`
\${not interpolated}
\`
`),
).toEqual('${not interpolated}\n`');
});
});

View File

@@ -0,0 +1,88 @@
import { dedent } from '..';
describe('Issue 21', () => {
it('should dedent nested dedents correctly', () => {
const fieldDocs = dedent`
* a
* b
* c
`
const a = dedent`
/**
${fieldIntro()}
*
${fieldDocs}
*
${fieldExample()}
*/
`
function fieldIntro() {
return dedent`
* 0
`
}
function fieldExample() {
return dedent`
* d
`
}
const expected = `/**
* 0
*
* a
* b
* c
*
* d
*/`
expect(a).toEqual(expected);
});
/**
* Could not find a way to handle this but is an edge case we'd like to solve eventually
*/
it.skip('should handle function calls of nested dedents correctly', () => {
const fieldDocs = dedent(`
* a
* b
* c
`)
const a = dedent(`
/**
${fieldIntro()}
*
${fieldDocs}
*
${fieldExample()}
*/
`)
function fieldIntro() {
return dedent(`
* 0
`)
}
function fieldExample() {
return dedent(`
* d
`)
}
const expected = `/**
* 0
*
* a
* b
* c
*
* d
*/`
expect(a).toEqual(expected);
});
});

58
frontend/node_modules/ts-dedent/src/index.ts generated vendored Normal file
View File

@@ -0,0 +1,58 @@
export function dedent(
templ: TemplateStringsArray | string,
...values: unknown[]
): string {
let strings = Array.from(typeof templ === 'string' ? [templ] : templ);
// 1. Remove trailing whitespace.
strings[strings.length - 1] = strings[strings.length - 1].replace(
/\r?\n([\t ]*)$/,
'',
);
// 2. Find all line breaks to determine the highest common indentation level.
const indentLengths = strings.reduce((arr, str) => {
const matches = str.match(/\n([\t ]+|(?!\s).)/g);
if (matches) {
return arr.concat(
matches.map((match) => match.match(/[\t ]/g)?.length ?? 0),
);
}
return arr;
}, <number[]>[]);
// 3. Remove the common indentation from all strings.
if (indentLengths.length) {
const pattern = new RegExp(`\n[\t ]{${Math.min(...indentLengths)}}`, 'g');
strings = strings.map((str) => str.replace(pattern, '\n'));
}
// 4. Remove leading whitespace.
strings[0] = strings[0].replace(/^\r?\n/, '');
// 5. Perform interpolation.
let string = strings[0];
values.forEach((value, i) => {
// 5.1 Read current indentation level
const endentations = string.match(/(?:^|\n)( *)$/)
const endentation = endentations ? endentations[1] : ''
let indentedValue = value
// 5.2 Add indentation to values with multiline strings
if (typeof value === 'string' && value.includes('\n')) {
indentedValue = String(value)
.split('\n')
.map((str, i) => {
return i === 0 ? str : `${endentation}${str}`
})
.join('\n');
}
string += indentedValue + strings[i + 1];
});
return string;
}
export default dedent;