Update app and tooling

This commit is contained in:
Lawrence Chen 2026-01-29 17:36:26 -08:00
parent 3046531bdd
commit e620ec7349
4950 changed files with 2975120 additions and 10 deletions

429
node_modules/code-block-writer/CHANGELOG.md generated vendored Normal file
View file

@ -0,0 +1,429 @@
# Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="10.1.1"></a>
## [10.1.1](https://github.com/dsherret/code-block-writer/compare/v10.1.0...v10.1.1) (2020-11-12)
<a name="10.1.0"></a>
# [10.1.0](https://github.com/dsherret/code-block-writer/compare/v10.0.0...v10.1.0) (2019-11-23)
### Features
- Add `iterateLastCharCodes` which is slightly more efficient than `iterateLastChars`. ([5e27b85](https://github.com/dsherret/code-block-writer/commit/5e27b85))
### Performance Improvements
- Use `charCodeAt` instead of indexing into the string (to avoid an allocation). ([48b4e3e](https://github.com/dsherret/code-block-writer/commit/48b4e3e))
<a name="10.0.0"></a>
# [10.0.0](https://github.com/dsherret/code-block-writer/compare/v9.4.1...v10.0.0) (2019-09-02)
### Bug Fixes
- [#32](https://github.com/dsherret/code-block-writer/issues/32) - Doing a non-escaped newline within a string literal would not properly update the writer state. ([a155e47](https://github.com/dsherret/code-block-writer/commit/a155e47))
### Code Refactoring
- Rename `indentBlock` to `indent`. ([34fd843](https://github.com/dsherret/code-block-writer/commit/34fd843))
- Rename `withHangingIndentation` to `hangingIndent`. ([f87cb91](https://github.com/dsherret/code-block-writer/commit/f87cb91))
### BREAKING CHANGES
- `indentBlock` is now merged with `indent`.
- `withHangingIndentation` is now `hangingIndent`.
<a name="9.4.1"></a>
## [9.4.1](https://github.com/dsherret/code-block-writer/compare/v9.4.0...v9.4.1) (2019-07-16)
### Bug Fixes
- Remove accidentally added chai dependency. ([582b4b6](https://github.com/dsherret/code-block-writer/commit/582b4b6))
<a name="9.4.0"></a>
# [9.4.0](https://github.com/dsherret/code-block-writer/compare/v9.3.0...v9.4.0) (2019-06-18)
### Features
- Add `unsafeInsert`. ([88cce9a](https://github.com/dsherret/code-block-writer/commit/88cce9a))
<a name="9.3.0"></a>
# [9.3.0](https://github.com/dsherret/code-block-writer/compare/v9.2.1...v9.3.0) (2019-06-09)
### Features
- Add `#endsWith(text: string)` ([460e007](https://github.com/dsherret/code-block-writer/commit/460e007))
<a name="9.2.1"></a>
## [9.2.1](https://github.com/dsherret/code-block-writer/compare/v9.2.0...v9.2.1) (2019-05-31)
### Bug Fixes
- Make private function not show up in declaration file. ([3263724](https://github.com/dsherret/code-block-writer/commit/3263724))
<a name="9.2.0"></a>
# [9.2.0](https://github.com/dsherret/code-block-writer/compare/v9.1.3...v9.2.0) (2019-05-31)
### Features
- [#27](https://github.com/dsherret/code-block-writer/issues/27) - Add `iterateLastChars`. ([5ce22c2](https://github.com/dsherret/code-block-writer/commit/5ce22c2))
- Add `withHangingIndentationUnlessBlock(action)` ([c04bef2](https://github.com/dsherret/code-block-writer/commit/c04bef2))
<a name="9.1.3"></a>
## [9.1.3](https://github.com/dsherret/code-block-writer/compare/v9.1.1...v9.1.3) (2019-05-20)
### Bug Fixes
- Fix incorrect jsdoc in `withIndentationLevel` ([8e26c5f](https://github.com/dsherret/code-block-writer/commit/8e26c5f))
### Performance Improvements
- No longer pushes empty strings onto internal array. ([4d46a72](https://github.com/dsherret/code-block-writer/commit/4d46a72))
<a name="8.3.0"></a>
# [8.3.0](https://github.com/dsherret/code-block-writer/compare/v8.2.0...v8.3.0) (2019-05-05)
### Features
- Add `#withHangingIndentation` ([2c77357](https://github.com/dsherret/code-block-writer/commit/2c77357))
<a name="8.2.0"></a>
# [8.2.0](https://github.com/dsherret/code-block-writer/compare/v8.1.2...v8.2.0) (2019-05-05)
### Features
- Add `#withQueuedIndentationLevel` and `#withIndentationLevel`. ([1bcf7c8](https://github.com/dsherret/code-block-writer/commit/1bcf7c8))
<a name="8.1.2"></a>
## [8.1.2](https://github.com/dsherret/code-block-writer/compare/v8.1.1...v8.1.2) (2019-05-02)
### Bug Fixes
- Hide remaining private methods/properties from declaration file. ([5e7aaef](https://github.com/dsherret/code-block-writer/commit/5e7aaef))
<a name="8.1.1"></a>
## [8.1.1](https://github.com/dsherret/code-block-writer/compare/v8.1.0...v8.1.1) (2019-05-02)
### Bug Fixes
- Restrict `newLine` to "\n" | "\r\n". ([699a41f](https://github.com/dsherret/code-block-writer/commit/699a41f))
### Performance Improvements
- Calling `#getLength()` does not internally call `#toString()`. ([b19c7ab](https://github.com/dsherret/code-block-writer/commit/b19c7ab))
- Calling `#isLastBlankLine()` does not internally call `#toString()`. ([d225b67](https://github.com/dsherret/code-block-writer/commit/d225b67))
<a name="8.1.0"></a>
# [8.1.0](https://github.com/dsherret/code-block-writer/compare/v8.0.0...v8.1.0) (2019-05-02)
### Features
- [#24](https://github.com/dsherret/code-block-writer/issues/24) - Add `indent(times)`. ([0108dab](https://github.com/dsherret/code-block-writer/commit/0108dab))
<a name="8.0.0"></a>
# [8.0.0](https://github.com/dsherret/code-block-writer/compare/v7.3.1...v8.0.0) (2019-04-28)
### Performance Improvements
- [#25](https://github.com/dsherret/code-block-writer/issues/25) Improve performance. ([6061b25](https://github.com/dsherret/code-block-writer/commit/6061b25))
### BREAKING CHANGES
- Library now targets ES2015 instead of ES5.
<a name="7.3.1"></a>
## [7.3.1](https://github.com/dsherret/code-block-writer/compare/v7.3.0...v7.3.1) (2019-04-14)
### Bug Fixes
- `isInString()` was not handling escaped string characters. ([a357278](https://github.com/dsherret/code-block-writer/commit/a357278))
<a name="7.3.0"></a>
# [7.3.0](https://github.com/dsherret/code-block-writer/compare/v7.2.2...v7.3.0) (2019-03-16)
### Bug Fixes
- Should not write space on block if last was a newline. ([37706b9](https://github.com/dsherret/code-block-writer/commit/37706b9))
### Features
- [#23](https://github.com/dsherret/code-block-writer/issues/23) - Add closeComment(). ([cf9f722](https://github.com/dsherret/code-block-writer/commit/cf9f722))
<a name="7.2.2"></a>
## [7.2.2](https://github.com/dsherret/code-block-writer/compare/v7.2.1...v7.2.2) (2018-09-27)
### Performance Improvements
- [#21](https://github.com/dsherret/code-block-writer/issues/21) - Make regex static. ([c27e208](https://github.com/dsherret/code-block-writer/commit/c27e208))
<a name="7.2.1"></a>
## [7.2.1](https://github.com/dsherret/code-block-writer/compare/v7.2.0...v7.2.1) (2018-07-14)
### Bug Fixes
- Queued indentation would not by applied when not writing anything and doing a .newline(). ([2d33d46](https://github.com/dsherret/code-block-writer/commit/2d33d46))
<a name="7.2.0"></a>
# [7.2.0](https://github.com/dsherret/code-block-writer/compare/v7.1.0...v7.2.0) (2018-05-28)
### Features
- Allow passing in a decimal indentation level. ([c77fa14](https://github.com/dsherret/code-block-writer/commit/c77fa14))
<a name="7.1.0"></a>
# [7.1.0](https://github.com/dsherret/code-block-writer/compare/v7.0.0...v7.1.0) (2018-05-08)
### Features
- Add .tab(), .tabIfLastNot(), .isLastTab() ([0e6f6e9](https://github.com/dsherret/code-block-writer/commit/0e6f6e9))
<a name="7.0.0"></a>
# [7.0.0](https://github.com/dsherret/code-block-writer/compare/v6.13.0...v7.0.0) (2018-04-29)
### Code Refactoring
- Remove deprecated methods. ([e7fca86](https://github.com/dsherret/code-block-writer/commit/e7fca86))
### Features
- allow passing a function into conditional write methods ([d299c84](https://github.com/dsherret/code-block-writer/commit/d299c84))
### BREAKING CHANGES
- `newLineIfLastNotNewLine`, `blankLineIfLastNotBlankLine`, `spaceIfLastNotSpace` are removed. Use the shorter method names like `spaceIfLastNot`.
<a name="6.14.0"></a>
# [6.14.0](https://github.com/dsherret/code-block-writer/compare/v6.13.0...v6.14.0) (2018-04-10)
### Features
- allow passing a function into conditional write methods ([d299c84](https://github.com/dsherret/code-block-writer/commit/d299c84))
Thanks a lot to [@lazarljubenovic](https://github.com/lazarljubenovic) for implementing this feature!
<a name="6.13.0"></a>
# [6.13.0](https://github.com/dsherret/code-block-writer/compare/v6.12.0...v6.13.0) (2018-04-08)
### Features
- Add getOptions(). ([a58dc31](https://github.com/dsherret/code-block-writer/commit/a58dc31))
<a name="6.12.0"></a>
# [6.12.0](https://github.com/dsherret/code-block-writer/compare/v6.11.0...v6.12.0) (2018-04-07)
### Bug Fixes
- Remove warning for now. ([ee36fac](https://github.com/dsherret/code-block-writer/commit/ee36fac))
### Features
- Add .isAtStartOfFirstLineOfBlock() ([d5eda32](https://github.com/dsherret/code-block-writer/commit/d5eda32))
<a name="6.11.0"></a>
# [6.11.0](https://github.com/dsherret/code-block-writer/compare/v6.10.0...v6.11.0) (2018-04-07)
### Features
- Add .isOnFirstLineOfBlock() ([b2a10c6](https://github.com/dsherret/code-block-writer/commit/b2a10c6))
<a name="6.10.1"></a>
# [6.10.1](https://github.com/dsherret/code-block-writer/compare/v6.9.0...v6.10.1) (2018-04-04)
### Bug Fixes
- Remove warning for now. ([ee36fac](https://github.com/dsherret/code-block-writer/commit/ee36fac))
<a name="6.10.0"></a>
# [6.10.0](https://github.com/dsherret/code-block-writer/compare/v6.9.0...v6.10.0) (2018-04-03)
### Features
- Deprecate all XIfLastNotX methods to XIfLastNot. ([d6c31f1](https://github.com/dsherret/code-block-writer/commit/d6c31f1))
<a name="6.9.0"></a>
# [6.9.0](https://github.com/dsherret/code-block-writer/compare/v6.8.0...v6.9.0) (2018-04-03)
### Features
- Add .blankLineIfLastNotBlankLine() ([9119043](https://github.com/dsherret/code-block-writer/commit/9119043))
- Add isLastBlankLine(). ([1dec5aa](https://github.com/dsherret/code-block-writer/commit/1dec5aa))
<a name="6.8.0"></a>
# [6.8.0](https://github.com/dsherret/code-block-writer/compare/v6.7.2...v6.8.0) (2018-04-03)
### Features
- Add conditionalBlankLine. ([7801d42](https://github.com/dsherret/code-block-writer/commit/7801d42))
<a name="6.7.2"></a>
## [6.7.2](https://github.com/dsherret/code-block-writer/compare/v6.7.1...v6.7.2) (2018-03-31)
### Bug Fixes
- Should not be in a string when using a string char in a regular expression literal. ([70e88a5](https://github.com/dsherret/code-block-writer/commit/70e88a5))
<a name="6.7.1"></a>
## [6.7.1](https://github.com/dsherret/code-block-writer/compare/v6.7.0...v6.7.1) (2018-03-27)
### Bug Fixes
- Writing within quote should escape string chars. ([bd9ddaa](https://github.com/dsherret/code-block-writer/commit/bd9ddaa))
<a name="6.7.0"></a>
# [6.7.0](https://github.com/dsherret/code-block-writer/compare/v6.6.0...v6.7.0) (2018-03-25)
### Features
- Add .space() method. ([d3a7134](https://github.com/dsherret/code-block-writer/commit/d3a7134))
<a name="6.6.0"></a>
# [6.6.0](https://github.com/dsherret/code-block-writer/compare/v6.5.3...v6.6.0) (2018-02-28)
### Features
- Add .getIndentationLevel() ([949acb0](https://github.com/dsherret/code-block-writer/commit/949acb0))
<a name="6.5.3"></a>
## [6.5.3](https://github.com/dsherret/code-block-writer/compare/v6.5.2...v6.5.3) (2018-02-28)
### Bug Fixes
- Fix incorrect double newline after indentBlock ([8ff5766](https://github.com/dsherret/code-block-writer/commit/8ff5766))
<a name="6.5.2"></a>
## [6.5.2](https://github.com/dsherret/code-block-writer/compare/v6.5.1...v6.5.2) (2018-02-27)
### Bug Fixes
- isLastNewLine() should return true when it's \n and newline kind is \r\n. ([347f783](https://github.com/dsherret/code-block-writer/commit/347f783))
<a name="6.5.1"></a>
## [6.5.1](https://github.com/dsherret/code-block-writer/compare/v6.5.0...v6.5.1) (2018-02-27)
### Bug Fixes
- Should do a conditional newline when starting an indent block. ([109c71f](https://github.com/dsherret/code-block-writer/commit/109c71f))
<a name="6.5.0"></a>
# [6.5.0](https://github.com/dsherret/code-block-writer/compare/v6.4.1...v6.5.0) (2018-02-27)
### Features
- Add indentBlock to indent a block of code. ([e69205c](https://github.com/dsherret/code-block-writer/commit/e69205c))
<a name="6.4.1"></a>
## [6.4.1](https://github.com/dsherret/code-block-writer/compare/v6.4.0...v6.4.1) (2018-02-27)
### Bug Fixes
- Passing an empty string at the start of a line should write the current indentation. ([f3b3ed8](https://github.com/dsherret/code-block-writer/commit/f3b3ed8))
<a name="6.4.0"></a>
# [6.4.0](https://github.com/dsherret/code-block-writer/compare/v6.3.1...v6.4.0) (2018-02-27)
### Features
- isLastNewLine, isLastSpace, getLastChar ([d4d850e](https://github.com/dsherret/code-block-writer/commit/d4d850e))
<a name="6.3.1"></a>
## [6.3.1](https://github.com/dsherret/code-block-writer/compare/v6.3.0...v6.3.1) (2018-02-27)
### Bug Fixes
- Include js docs. ([c01c697](https://github.com/dsherret/code-block-writer/commit/c01c697))
<a name="6.3.0"></a>
# [6.3.0](https://github.com/dsherret/code-block-writer/compare/v6.2.0...v6.3.0) (2018-02-27)
### Features
- Add queueIndentationLevel(...). ([6719913](https://github.com/dsherret/code-block-writer/commit/6719913))
<a name="6.2.0"></a>
# [6.2.0](https://github.com/dsherret/code-block-writer/compare/v6.1.1...v6.2.0) (2017-12-05)
### Features
- [#14](https://github.com/dsherret/code-block-writer/issues/14) - Add .quote() and .quote(text: string) ([efe2280](https://github.com/dsherret/code-block-writer/commit/efe2280))
<a name="6.1.1"></a>
## [6.1.1](https://github.com/dsherret/code-block-writer/compare/v6.1.0...v6.1.1) (2017-12-02)
### Bug Fixes
- Fixed out of date definition file. ([f9d6a07](https://github.com/dsherret/code-block-writer/commit/f9d6a07))
<a name="6.1.0"></a>
# [6.1.0](https://github.com/dsherret/code-block-writer/compare/v6.0.0...v6.1.0) (2017-12-02)
### Features
- Ability to provide undefined for conditions and blocks. ([9c48b3a](https://github.com/dsherret/code-block-writer/commit/9c48b3a))
<a name="6.0.0"></a>
# [6.0.0](https://github.com/dsherret/code-block-writer/compare/v5.0.1...v6.0.0) (2017-12-02)
### Bug Fixes
- Add documentation comments. ([d3b5031](https://github.com/dsherret/code-block-writer/commit/d3b5031))
- Should be allowed to have two newlines at the end of a file. ([3855742](https://github.com/dsherret/code-block-writer/commit/3855742))
### Features
- [#13](https://github.com/dsherret/code-block-writer/issues/13) - Set indentation level. ([10484c7](https://github.com/dsherret/code-block-writer/commit/10484c7))
- isInComment and isInString ([8fa02a2](https://github.com/dsherret/code-block-writer/commit/8fa02a2))
### BREAKING CHANGES
- #12 - Library is now JS/TS specific and will not indent text on newlines while in a string.
<a name="5.0.1"></a>
## [5.0.1](https://github.com/dsherret/code-block-writer/compare/5.0.0...5.0.1) (2017-12-02)

22
node_modules/code-block-writer/LICENSE generated vendored Normal file
View file

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 David Sherret
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.

1
node_modules/code-block-writer/dist/CommentChar.d.ts generated vendored Normal file
View file

@ -0,0 +1 @@
export {};

9
node_modules/code-block-writer/dist/CommentChar.js generated vendored Normal file
View file

@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommentChar = void 0;
/** @internal */
var CommentChar;
(function (CommentChar) {
CommentChar[CommentChar["Line"] = 0] = "Line";
CommentChar[CommentChar["Star"] = 1] = "Star";
})(CommentChar = exports.CommentChar || (exports.CommentChar = {}));

View file

@ -0,0 +1,275 @@
/**
* Options for the writer.
*/
export interface Options {
/**
* Newline character.
* @remarks Defaults to \n.
*/
newLine: "\n" | "\r\n";
/**
* Number of spaces to indent when `useTabs` is false.
* @remarks Defaults to 4.
*/
indentNumberOfSpaces: number;
/**
* Whether to use tabs (true) or spaces (false).
* @remarks Defaults to false.
*/
useTabs: boolean;
/**
* Whether to use a single quote (true) or double quote (false).
* @remarks Defaults to false.
*/
useSingleQuote: boolean;
}
/**
* Code writer that assists with formatting and visualizing blocks of JavaScript or TypeScript code.
*/
export default class CodeBlockWriter {
/**
* Constructor.
* @param opts - Options for the writer.
*/
constructor(opts?: Partial<Options>);
/**
* Gets the options.
*/
getOptions(): Options;
/**
* Queues the indentation level for the next lines written.
* @param indentationLevel - Indentation level to queue.
*/
queueIndentationLevel(indentationLevel: number): this;
/**
* Queues the indentation level for the next lines written using the provided indentation text.
* @param whitespaceText - Gets the indentation level from the indentation text.
*/
queueIndentationLevel(whitespaceText: string): this;
/**
* Writes the text within the provided action with hanging indentation.
* @param action - Action to perform with hanging indentation.
*/
hangingIndent(action: () => void): this;
/**
* Writes the text within the provided action with hanging indentation unless writing a block.
* @param action - Action to perform with hanging indentation unless a block is written.
*/
hangingIndentUnlessBlock(action: () => void): this;
/**
* Sets the current indentation level.
* @param indentationLevel - Indentation level to be at.
*/
setIndentationLevel(indentationLevel: number): this;
/**
* Sets the current indentation using the provided indentation text.
* @param whitespaceText - Gets the indentation level from the indentation text.
*/
setIndentationLevel(whitespaceText: string): this;
/**
* Sets the indentation level within the provided action and restores the writer's indentation
* state afterwards.
* @remarks Restores the writer's state after the action.
* @param indentationLevel - Indentation level to set.
* @param action - Action to perform with the indentation.
*/
withIndentationLevel(indentationLevel: number, action: () => void): this;
/**
* Sets the indentation level with the provided indentation text within the provided action
* and restores the writer's indentation state afterwards.
* @param whitespaceText - Gets the indentation level from the indentation text.
* @param action - Action to perform with the indentation.
*/
withIndentationLevel(whitespaceText: string, action: () => void): this;
/**
* Gets the current indentation level.
*/
getIndentationLevel(): number;
/**
* Writes a block using braces.
* @param block - Write using the writer within this block.
*/
block(block?: () => void): this;
/**
* Writes an inline block with braces.
* @param block - Write using the writer within this block.
*/
inlineBlock(block?: () => void): this;
/**
* Indents the code one level for the current line.
*/
indent(times?: number): this;
/**
* Indents a block of code.
* @param block - Block to indent.
*/
indent(block: () => void): this;
/**
* Conditionally writes a line of text.
* @param condition - Condition to evaluate.
* @param textFunc - A function that returns a string to write if the condition is true.
*/
conditionalWriteLine(condition: boolean | undefined, textFunc: () => string): this;
/**
* Conditionally writes a line of text.
* @param condition - Condition to evaluate.
* @param text - Text to write if the condition is true.
*/
conditionalWriteLine(condition: boolean | undefined, text: string): this;
/**
* Writes a line of text.
* @param text - String to write.
*/
writeLine(text: string): this;
/**
* Writes a newline if the last line was not a newline.
*/
newLineIfLastNot(): this;
/**
* Writes a blank line if the last written text was not a blank line.
*/
blankLineIfLastNot(): this;
/**
* Writes a blank line if the condition is true.
* @param condition - Condition to evaluate.
*/
conditionalBlankLine(condition: boolean | undefined): this;
/**
* Writes a blank line.
*/
blankLine(): this;
/**
* Writes a newline if the condition is true.
* @param condition - Condition to evaluate.
*/
conditionalNewLine(condition: boolean | undefined): this;
/**
* Writes a newline.
*/
newLine(): this;
/**
* Writes a quote character.
*/
quote(): this;
/**
* Writes text surrounded in quotes.
* @param text - Text to write.
*/
quote(text: string): this;
/**
* Writes a space if the last character was not a space.
*/
spaceIfLastNot(): this;
/**
* Writes a space.
* @param times - Number of times to write a space.
*/
space(times?: number): this;
/**
* Writes a tab if the last character was not a tab.
*/
tabIfLastNot(): this;
/**
* Writes a tab.
* @param times - Number of times to write a tab.
*/
tab(times?: number): this;
/**
* Conditionally writes text.
* @param condition - Condition to evaluate.
* @param textFunc - A function that returns a string to write if the condition is true.
*/
conditionalWrite(condition: boolean | undefined, textFunc: () => string): this;
/**
* Conditionally writes text.
* @param condition - Condition to evaluate.
* @param text - Text to write if the condition is true.
*/
conditionalWrite(condition: boolean | undefined, text: string): this;
/**
* Writes the provided text.
* @param text - Text to write.
*/
write(text: string): this;
/**
* Writes text to exit a comment if in a comment.
*/
closeComment(): this;
/**
* Inserts text at the provided position.
*
* This method is "unsafe" because it won't update the state of the writer unless
* inserting at the end position. It is biased towards being fast at inserting closer
* to the start or end, but slower to insert in the middle. Only use this if
* absolutely necessary.
* @param pos - Position to insert at.
* @param text - Text to insert.
*/
unsafeInsert(pos: number, text: string): this;
/**
* Gets the length of the string in the writer.
*/
getLength(): number;
/**
* Gets if the writer is currently in a comment.
*/
isInComment(): boolean;
/**
* Gets if the writer is currently at the start of the first line of the text, block, or indentation block.
*/
isAtStartOfFirstLineOfBlock(): boolean;
/**
* Gets if the writer is currently on the first line of the text, block, or indentation block.
*/
isOnFirstLineOfBlock(): boolean;
/**
* Gets if the writer is currently in a string.
*/
isInString(): boolean;
/**
* Gets if the last chars written were for a newline.
*/
isLastNewLine(): boolean;
/**
* Gets if the last chars written were for a blank line.
*/
isLastBlankLine(): boolean;
/**
* Gets if the last char written was a space.
*/
isLastSpace(): boolean;
/**
* Gets if the last char written was a tab.
*/
isLastTab(): boolean;
/**
* Gets the last char written.
*/
getLastChar(): string | undefined;
/**
* Gets if the writer ends with the provided text.
* @param text - Text to check if the writer ends with the provided text.
*/
endsWith(text: string): boolean;
/**
* Iterates over the writer characters in reverse order. The iteration stops when a non-null or
* undefined value is returned from the action. The returned value is then returned by the method.
*
* @remarks It is much more efficient to use this method rather than `#toString()` since `#toString()`
* will combine the internal array into a string.
*/
iterateLastChars<T>(action: (char: string, index: number) => T | undefined): T | undefined;
/**
* Iterates over the writer character char codes in reverse order. The iteration stops when a non-null or
* undefined value is returned from the action. The returned value is then returned by the method.
*
* @remarks It is much more efficient to use this method rather than `#toString()` since `#toString()`
* will combine the internal array into a string. Additionally, this is slightly more efficient that
* `iterateLastChars` as this won't allocate a string per character.
*/
iterateLastCharCodes<T>(action: (charCode: number, index: number) => T | undefined): T | undefined;
/**
* Gets the writer's text.
*/
toString(): string;
}

View file

@ -0,0 +1,724 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const stringUtils_1 = require("./utils/stringUtils");
const CommentChar_1 = require("./CommentChar");
// Using the char codes is a performance improvement (about 5.5% faster when writing because it eliminates additional string allocations).
const CHARS = {
BACK_SLASH: "\\".charCodeAt(0),
FORWARD_SLASH: "/".charCodeAt(0),
NEW_LINE: "\n".charCodeAt(0),
CARRIAGE_RETURN: "\r".charCodeAt(0),
ASTERISK: "*".charCodeAt(0),
DOUBLE_QUOTE: "\"".charCodeAt(0),
SINGLE_QUOTE: "'".charCodeAt(0),
BACK_TICK: "`".charCodeAt(0),
OPEN_BRACE: "{".charCodeAt(0),
CLOSE_BRACE: "}".charCodeAt(0),
DOLLAR_SIGN: "$".charCodeAt(0),
};
const isCharToHandle = new Set([
CHARS.BACK_SLASH,
CHARS.FORWARD_SLASH,
CHARS.NEW_LINE,
CHARS.CARRIAGE_RETURN,
CHARS.ASTERISK,
CHARS.DOUBLE_QUOTE,
CHARS.SINGLE_QUOTE,
CHARS.BACK_TICK,
CHARS.OPEN_BRACE,
CHARS.CLOSE_BRACE,
]);
/**
* Code writer that assists with formatting and visualizing blocks of JavaScript or TypeScript code.
*/
class CodeBlockWriter {
/**
* Constructor.
* @param opts - Options for the writer.
*/
constructor(opts = {}) {
/** @internal */
this._currentIndentation = 0;
/** @internal */
this._length = 0;
/** @internal */
this._newLineOnNextWrite = false;
/** @internal */
this._currentCommentChar = undefined;
/** @internal */
this._stringCharStack = [];
/** @internal */
this._isInRegEx = false;
/** @internal */
this._isOnFirstLineOfBlock = true;
// An array of strings is used rather than a single string because it was
// found to be ~11x faster when printing a 10K line file (~11s to ~1s).
/** @internal */
this._texts = [];
this._newLine = opts.newLine || "\n";
this._useTabs = opts.useTabs || false;
this._indentNumberOfSpaces = opts.indentNumberOfSpaces || 4;
this._indentationText = getIndentationText(this._useTabs, this._indentNumberOfSpaces);
this._quoteChar = opts.useSingleQuote ? "'" : `"`;
}
/**
* Gets the options.
*/
getOptions() {
return {
indentNumberOfSpaces: this._indentNumberOfSpaces,
newLine: this._newLine,
useTabs: this._useTabs,
useSingleQuote: this._quoteChar === "'",
};
}
queueIndentationLevel(countOrText) {
this._queuedIndentation = this._getIndentationLevelFromArg(countOrText);
this._queuedOnlyIfNotBlock = undefined;
return this;
}
/**
* Writes the text within the provided action with hanging indentation.
* @param action - Action to perform with hanging indentation.
*/
hangingIndent(action) {
return this._withResetIndentation(() => this.queueIndentationLevel(this.getIndentationLevel() + 1), action);
}
/**
* Writes the text within the provided action with hanging indentation unless writing a block.
* @param action - Action to perform with hanging indentation unless a block is written.
*/
hangingIndentUnlessBlock(action) {
return this._withResetIndentation(() => {
this.queueIndentationLevel(this.getIndentationLevel() + 1);
this._queuedOnlyIfNotBlock = true;
}, action);
}
setIndentationLevel(countOrText) {
this._currentIndentation = this._getIndentationLevelFromArg(countOrText);
return this;
}
withIndentationLevel(countOrText, action) {
return this._withResetIndentation(() => this.setIndentationLevel(countOrText), action);
}
/** @internal */
_withResetIndentation(setStateAction, writeAction) {
const previousState = this._getIndentationState();
setStateAction();
try {
writeAction();
}
finally {
this._setIndentationState(previousState);
}
return this;
}
/**
* Gets the current indentation level.
*/
getIndentationLevel() {
return this._currentIndentation;
}
/**
* Writes a block using braces.
* @param block - Write using the writer within this block.
*/
block(block) {
this._newLineIfNewLineOnNextWrite();
if (this.getLength() > 0 && !this.isLastNewLine())
this.spaceIfLastNot();
this.inlineBlock(block);
this._newLineOnNextWrite = true;
return this;
}
/**
* Writes an inline block with braces.
* @param block - Write using the writer within this block.
*/
inlineBlock(block) {
this._newLineIfNewLineOnNextWrite();
this.write("{");
this._indentBlockInternal(block);
this.newLineIfLastNot().write("}");
return this;
}
indent(timesOrBlock = 1) {
if (typeof timesOrBlock === "number") {
this._newLineIfNewLineOnNextWrite();
return this.write(this._indentationText.repeat(timesOrBlock));
}
else {
this._indentBlockInternal(timesOrBlock);
if (!this.isLastNewLine())
this._newLineOnNextWrite = true;
return this;
}
}
/** @internal */
_indentBlockInternal(block) {
if (this.getLastChar() != null)
this.newLineIfLastNot();
this._currentIndentation++;
this._isOnFirstLineOfBlock = true;
if (block != null)
block();
this._isOnFirstLineOfBlock = false;
this._currentIndentation = Math.max(0, this._currentIndentation - 1);
}
conditionalWriteLine(condition, strOrFunc) {
if (condition)
this.writeLine(stringUtils_1.getStringFromStrOrFunc(strOrFunc));
return this;
}
/**
* Writes a line of text.
* @param text - String to write.
*/
writeLine(text) {
this._newLineIfNewLineOnNextWrite();
if (this.getLastChar() != null)
this.newLineIfLastNot();
this._writeIndentingNewLines(text);
this.newLine();
return this;
}
/**
* Writes a newline if the last line was not a newline.
*/
newLineIfLastNot() {
this._newLineIfNewLineOnNextWrite();
if (!this.isLastNewLine())
this.newLine();
return this;
}
/**
* Writes a blank line if the last written text was not a blank line.
*/
blankLineIfLastNot() {
if (!this.isLastBlankLine())
this.blankLine();
return this;
}
/**
* Writes a blank line if the condition is true.
* @param condition - Condition to evaluate.
*/
conditionalBlankLine(condition) {
if (condition)
this.blankLine();
return this;
}
/**
* Writes a blank line.
*/
blankLine() {
return this.newLineIfLastNot().newLine();
}
/**
* Writes a newline if the condition is true.
* @param condition - Condition to evaluate.
*/
conditionalNewLine(condition) {
if (condition)
this.newLine();
return this;
}
/**
* Writes a newline.
*/
newLine() {
this._newLineOnNextWrite = false;
this._baseWriteNewline();
return this;
}
quote(text) {
this._newLineIfNewLineOnNextWrite();
this._writeIndentingNewLines(text == null ? this._quoteChar : this._quoteChar + stringUtils_1.escapeForWithinString(text, this._quoteChar) + this._quoteChar);
return this;
}
/**
* Writes a space if the last character was not a space.
*/
spaceIfLastNot() {
this._newLineIfNewLineOnNextWrite();
if (!this.isLastSpace())
this._writeIndentingNewLines(" ");
return this;
}
/**
* Writes a space.
* @param times - Number of times to write a space.
*/
space(times = 1) {
this._newLineIfNewLineOnNextWrite();
this._writeIndentingNewLines(" ".repeat(times));
return this;
}
/**
* Writes a tab if the last character was not a tab.
*/
tabIfLastNot() {
this._newLineIfNewLineOnNextWrite();
if (!this.isLastTab())
this._writeIndentingNewLines("\t");
return this;
}
/**
* Writes a tab.
* @param times - Number of times to write a tab.
*/
tab(times = 1) {
this._newLineIfNewLineOnNextWrite();
this._writeIndentingNewLines("\t".repeat(times));
return this;
}
conditionalWrite(condition, textOrFunc) {
if (condition)
this.write(stringUtils_1.getStringFromStrOrFunc(textOrFunc));
return this;
}
/**
* Writes the provided text.
* @param text - Text to write.
*/
write(text) {
this._newLineIfNewLineOnNextWrite();
this._writeIndentingNewLines(text);
return this;
}
/**
* Writes text to exit a comment if in a comment.
*/
closeComment() {
const commentChar = this._currentCommentChar;
switch (commentChar) {
case CommentChar_1.CommentChar.Line:
this.newLine();
break;
case CommentChar_1.CommentChar.Star:
if (!this.isLastNewLine())
this.spaceIfLastNot();
this.write("*/");
break;
default:
const assertUndefined = commentChar;
break;
}
return this;
}
/**
* Inserts text at the provided position.
*
* This method is "unsafe" because it won't update the state of the writer unless
* inserting at the end position. It is biased towards being fast at inserting closer
* to the start or end, but slower to insert in the middle. Only use this if
* absolutely necessary.
* @param pos - Position to insert at.
* @param text - Text to insert.
*/
unsafeInsert(pos, text) {
const textLength = this._length;
const texts = this._texts;
verifyInput();
if (pos === textLength)
return this.write(text);
updateInternalArray();
this._length += text.length;
return this;
function verifyInput() {
if (pos < 0)
throw new Error(`Provided position of '${pos}' was less than zero.`);
if (pos > textLength)
throw new Error(`Provided position of '${pos}' was greater than the text length of '${textLength}'.`);
}
function updateInternalArray() {
const { index, localIndex } = getArrayIndexAndLocalIndex();
if (localIndex === 0)
texts.splice(index, 0, text);
else if (localIndex === texts[index].length)
texts.splice(index + 1, 0, text);
else {
const textItem = texts[index];
const startText = textItem.substring(0, localIndex);
const endText = textItem.substring(localIndex);
texts.splice(index, 1, startText, text, endText);
}
}
function getArrayIndexAndLocalIndex() {
if (pos < textLength / 2) {
// start searching from the front
let endPos = 0;
for (let i = 0; i < texts.length; i++) {
const textItem = texts[i];
const startPos = endPos;
endPos += textItem.length;
if (endPos >= pos)
return { index: i, localIndex: pos - startPos };
}
}
else {
// start searching from the back
let startPos = textLength;
for (let i = texts.length - 1; i >= 0; i--) {
const textItem = texts[i];
startPos -= textItem.length;
if (startPos <= pos)
return { index: i, localIndex: pos - startPos };
}
}
throw new Error("Unhandled situation inserting. This should never happen.");
}
}
/**
* Gets the length of the string in the writer.
*/
getLength() {
return this._length;
}
/**
* Gets if the writer is currently in a comment.
*/
isInComment() {
return this._currentCommentChar !== undefined;
}
/**
* Gets if the writer is currently at the start of the first line of the text, block, or indentation block.
*/
isAtStartOfFirstLineOfBlock() {
return this.isOnFirstLineOfBlock() && (this.isLastNewLine() || this.getLastChar() == null);
}
/**
* Gets if the writer is currently on the first line of the text, block, or indentation block.
*/
isOnFirstLineOfBlock() {
return this._isOnFirstLineOfBlock;
}
/**
* Gets if the writer is currently in a string.
*/
isInString() {
return this._stringCharStack.length > 0 && this._stringCharStack[this._stringCharStack.length - 1] !== CHARS.OPEN_BRACE;
}
/**
* Gets if the last chars written were for a newline.
*/
isLastNewLine() {
const lastChar = this.getLastChar();
return lastChar === "\n" || lastChar === "\r";
}
/**
* Gets if the last chars written were for a blank line.
*/
isLastBlankLine() {
let foundCount = 0;
// todo: consider extracting out iterating over past characters, but don't use
// an iterator because it will be slow.
for (let i = this._texts.length - 1; i >= 0; i--) {
const currentText = this._texts[i];
for (let j = currentText.length - 1; j >= 0; j--) {
const currentChar = currentText.charCodeAt(j);
if (currentChar === CHARS.NEW_LINE) {
foundCount++;
if (foundCount === 2)
return true;
}
else if (currentChar !== CHARS.CARRIAGE_RETURN) {
return false;
}
}
}
return false;
}
/**
* Gets if the last char written was a space.
*/
isLastSpace() {
return this.getLastChar() === " ";
}
/**
* Gets if the last char written was a tab.
*/
isLastTab() {
return this.getLastChar() === "\t";
}
/**
* Gets the last char written.
*/
getLastChar() {
const charCode = this._getLastCharCodeWithOffset(0);
return charCode == null ? undefined : String.fromCharCode(charCode);
}
/**
* Gets if the writer ends with the provided text.
* @param text - Text to check if the writer ends with the provided text.
*/
endsWith(text) {
const length = this._length;
return this.iterateLastCharCodes((charCode, index) => {
const offset = length - index;
const textIndex = text.length - offset;
if (text.charCodeAt(textIndex) !== charCode)
return false;
return textIndex === 0 ? true : undefined;
}) || false;
}
/**
* Iterates over the writer characters in reverse order. The iteration stops when a non-null or
* undefined value is returned from the action. The returned value is then returned by the method.
*
* @remarks It is much more efficient to use this method rather than `#toString()` since `#toString()`
* will combine the internal array into a string.
*/
iterateLastChars(action) {
return this.iterateLastCharCodes((charCode, index) => action(String.fromCharCode(charCode), index));
}
/**
* Iterates over the writer character char codes in reverse order. The iteration stops when a non-null or
* undefined value is returned from the action. The returned value is then returned by the method.
*
* @remarks It is much more efficient to use this method rather than `#toString()` since `#toString()`
* will combine the internal array into a string. Additionally, this is slightly more efficient that
* `iterateLastChars` as this won't allocate a string per character.
*/
iterateLastCharCodes(action) {
let index = this._length;
for (let i = this._texts.length - 1; i >= 0; i--) {
const currentText = this._texts[i];
for (let j = currentText.length - 1; j >= 0; j--) {
index--;
const result = action(currentText.charCodeAt(j), index);
if (result != null)
return result;
}
}
return undefined;
}
/**
* Gets the writer's text.
*/
toString() {
if (this._texts.length > 1) {
const text = this._texts.join("");
this._texts.length = 0;
this._texts.push(text);
}
return this._texts[0] || "";
}
/** @internal */
_writeIndentingNewLines(text) {
text = text || "";
if (text.length === 0) {
writeIndividual(this, "");
return;
}
const items = text.split(CodeBlockWriter._newLineRegEx);
items.forEach((s, i) => {
if (i > 0)
this._baseWriteNewline();
if (s.length === 0)
return;
writeIndividual(this, s);
});
function writeIndividual(writer, s) {
if (!writer.isInString()) {
const isAtStartOfLine = writer.isLastNewLine() || writer.getLastChar() == null;
if (isAtStartOfLine)
writer._writeIndentation();
}
writer._updateInternalState(s);
writer._internalWrite(s);
}
}
/** @internal */
_baseWriteNewline() {
if (this._currentCommentChar === CommentChar_1.CommentChar.Line)
this._currentCommentChar = undefined;
const lastStringCharOnStack = this._stringCharStack[this._stringCharStack.length - 1];
if ((lastStringCharOnStack === CHARS.DOUBLE_QUOTE || lastStringCharOnStack === CHARS.SINGLE_QUOTE) && this._getLastCharCodeWithOffset(0) !== CHARS.BACK_SLASH)
this._stringCharStack.pop();
this._internalWrite(this._newLine);
this._isOnFirstLineOfBlock = false;
this._dequeueQueuedIndentation();
}
/** @internal */
_dequeueQueuedIndentation() {
if (this._queuedIndentation == null)
return;
if (this._queuedOnlyIfNotBlock && wasLastBlock(this)) {
this._queuedIndentation = undefined;
this._queuedOnlyIfNotBlock = undefined;
}
else {
this._currentIndentation = this._queuedIndentation;
this._queuedIndentation = undefined;
}
function wasLastBlock(writer) {
let foundNewLine = false;
return writer.iterateLastCharCodes(charCode => {
switch (charCode) {
case CHARS.NEW_LINE:
if (foundNewLine)
return false;
else
foundNewLine = true;
break;
case CHARS.CARRIAGE_RETURN:
return undefined;
case CHARS.OPEN_BRACE:
return true;
default:
return false;
}
});
}
}
/** @internal */
_updateInternalState(str) {
for (let i = 0; i < str.length; i++) {
const currentChar = str.charCodeAt(i);
// This is a performance optimization to short circuit all the checks below. If the current char
// is not in this set then it won't change any internal state so no need to continue and do
// so many other checks (this made it 3x faster in one scenario I tested).
if (!isCharToHandle.has(currentChar))
continue;
const pastChar = i === 0 ? this._getLastCharCodeWithOffset(0) : str.charCodeAt(i - 1);
const pastPastChar = i === 0 ? this._getLastCharCodeWithOffset(1) : i === 1 ? this._getLastCharCodeWithOffset(0) : str.charCodeAt(i - 2);
// handle regex
if (this._isInRegEx) {
if (pastChar === CHARS.FORWARD_SLASH && pastPastChar !== CHARS.BACK_SLASH || pastChar === CHARS.NEW_LINE)
this._isInRegEx = false;
else
continue;
}
else if (!this.isInString() && !this.isInComment() && isRegExStart(currentChar, pastChar, pastPastChar)) {
this._isInRegEx = true;
continue;
}
// handle comments
if (this._currentCommentChar == null && pastChar === CHARS.FORWARD_SLASH && currentChar === CHARS.FORWARD_SLASH)
this._currentCommentChar = CommentChar_1.CommentChar.Line;
else if (this._currentCommentChar == null && pastChar === CHARS.FORWARD_SLASH && currentChar === CHARS.ASTERISK)
this._currentCommentChar = CommentChar_1.CommentChar.Star;
else if (this._currentCommentChar === CommentChar_1.CommentChar.Star && pastChar === CHARS.ASTERISK && currentChar === CHARS.FORWARD_SLASH)
this._currentCommentChar = undefined;
if (this.isInComment())
continue;
// handle strings
const lastStringCharOnStack = this._stringCharStack.length === 0 ? undefined : this._stringCharStack[this._stringCharStack.length - 1];
if (pastChar !== CHARS.BACK_SLASH && (currentChar === CHARS.DOUBLE_QUOTE || currentChar === CHARS.SINGLE_QUOTE || currentChar === CHARS.BACK_TICK)) {
if (lastStringCharOnStack === currentChar)
this._stringCharStack.pop();
else if (lastStringCharOnStack === CHARS.OPEN_BRACE || lastStringCharOnStack === undefined)
this._stringCharStack.push(currentChar);
}
else if (pastPastChar !== CHARS.BACK_SLASH && pastChar === CHARS.DOLLAR_SIGN && currentChar === CHARS.OPEN_BRACE && lastStringCharOnStack === CHARS.BACK_TICK)
this._stringCharStack.push(currentChar);
else if (currentChar === CHARS.CLOSE_BRACE && lastStringCharOnStack === CHARS.OPEN_BRACE)
this._stringCharStack.pop();
}
}
/** @internal - This is private, but exposed for testing. */
_getLastCharCodeWithOffset(offset) {
if (offset >= this._length || offset < 0)
return undefined;
for (let i = this._texts.length - 1; i >= 0; i--) {
const currentText = this._texts[i];
if (offset >= currentText.length)
offset -= currentText.length;
else
return currentText.charCodeAt(currentText.length - 1 - offset);
}
return undefined;
}
/** @internal */
_writeIndentation() {
const flooredIndentation = Math.floor(this._currentIndentation);
this._internalWrite(this._indentationText.repeat(flooredIndentation));
const overflow = this._currentIndentation - flooredIndentation;
if (this._useTabs) {
if (overflow > 0.5)
this._internalWrite(this._indentationText);
}
else {
const portion = Math.round(this._indentationText.length * overflow);
// build up the string first, then append it for performance reasons
let text = "";
for (let i = 0; i < portion; i++)
text += this._indentationText[i];
this._internalWrite(text);
}
}
/** @internal */
_newLineIfNewLineOnNextWrite() {
if (!this._newLineOnNextWrite)
return;
this._newLineOnNextWrite = false;
this.newLine();
}
/** @internal */
_internalWrite(text) {
if (text.length === 0)
return;
this._texts.push(text);
this._length += text.length;
}
/** @internal */
_getIndentationLevelFromArg(countOrText) {
if (typeof countOrText === "number") {
if (countOrText < 0)
throw new Error("Passed in indentation level should be greater than or equal to 0.");
return countOrText;
}
else if (typeof countOrText === "string") {
if (!CodeBlockWriter._spacesOrTabsRegEx.test(countOrText))
throw new Error("Provided string must be empty or only contain spaces or tabs.");
const { spacesCount, tabsCount } = getSpacesAndTabsCount(countOrText);
return tabsCount + spacesCount / this._indentNumberOfSpaces;
}
else {
throw new Error("Argument provided must be a string or number.");
}
}
/** @internal */
_setIndentationState(state) {
this._currentIndentation = state.current;
this._queuedIndentation = state.queued;
this._queuedOnlyIfNotBlock = state.queuedOnlyIfNotBlock;
}
/** @internal */
_getIndentationState() {
return {
current: this._currentIndentation,
queued: this._queuedIndentation,
queuedOnlyIfNotBlock: this._queuedOnlyIfNotBlock,
};
}
}
exports.default = CodeBlockWriter;
/** @internal */
CodeBlockWriter._newLineRegEx = /\r?\n/;
/** @internal */
CodeBlockWriter._spacesOrTabsRegEx = /^[ \t]*$/;
function isRegExStart(currentChar, pastChar, pastPastChar) {
return pastChar === CHARS.FORWARD_SLASH
&& currentChar !== CHARS.FORWARD_SLASH
&& currentChar !== CHARS.ASTERISK
&& pastPastChar !== CHARS.ASTERISK
&& pastPastChar !== CHARS.FORWARD_SLASH;
}
function getIndentationText(useTabs, numberSpaces) {
if (useTabs)
return "\t";
return Array(numberSpaces + 1).join(" ");
}
function getSpacesAndTabsCount(str) {
let spacesCount = 0;
let tabsCount = 0;
for (const char of str) {
if (char === " ")
spacesCount++;
else if (char === "\t")
tabsCount++;
}
return { spacesCount, tabsCount };
}

View file

@ -0,0 +1,27 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStringFromStrOrFunc = exports.escapeChar = exports.escapeForWithinString = void 0;
const newlineRegex = /(\r?\n)/g;
/** @internal */
function escapeForWithinString(str, quoteKind) {
return escapeChar(str, quoteKind).replace(newlineRegex, "\\$1");
}
exports.escapeForWithinString = escapeForWithinString;
/** @internal */
function escapeChar(str, char) {
if (char.length !== 1)
throw new Error(`Specified char must be one character long.`);
let result = "";
for (let i = 0; i < str.length; i++) {
if (str[i] === char)
result += "\\";
result += str[i];
}
return result;
}
exports.escapeChar = escapeChar;
/** @internal */
function getStringFromStrOrFunc(strOrFunc) {
return strOrFunc instanceof Function ? strOrFunc() : strOrFunc;
}
exports.getStringFromStrOrFunc = getStringFromStrOrFunc;

56
node_modules/code-block-writer/package.json generated vendored Normal file
View file

@ -0,0 +1,56 @@
{
"name": "code-block-writer",
"version": "10.1.1",
"description": "A simple code writer that assists with formatting and visualizing blocks of code.",
"main": "dist/code-block-writer.js",
"typings": "dist/code-block-writer.d.ts",
"scripts": {
"test": "nyc --reporter=lcov mocha",
"test:debug": "cross-env TS_NODE_TRANSPILE_ONLY=\"true\" mocha --inspect-brk",
"build": "rimraf dist && tsc",
"format": "dprint",
"dopublish": "npm run build && echo \"Run: npm publish --otp\""
},
"repository": {
"type": "git",
"url": "git+https://github.com/dsherret/code-block-writer.git"
},
"keywords": [
"typescript",
"writer",
"printer"
],
"author": "David Sherret",
"license": "MIT",
"bugs": {
"url": "https://github.com/dsherret/code-block-writer/issues"
},
"homepage": "https://github.com/dsherret/code-block-writer#readme",
"nyc": {
"extension": [
".ts",
".tsx"
],
"include": [
"src/**/*.ts",
"!src/tests/**/*.ts"
],
"reporter": [
"html"
],
"all": true
},
"dependencies": {},
"devDependencies": {
"@types/chai": "^4.2.12",
"@types/mocha": "^8.0.3",
"@types/node": "^14.6.0",
"chai": "^4.2.0",
"coveralls": "^3.1.0",
"cross-env": "^7.0.2",
"mocha": "^8.1.1",
"nyc": "^15.1.0",
"ts-node": "^8.10.2",
"typescript": "^4.0.2"
}
}

109
node_modules/code-block-writer/readme.md generated vendored Normal file
View file

@ -0,0 +1,109 @@
# code-block-writer
[![npm version](https://badge.fury.io/js/code-block-writer.svg)](https://badge.fury.io/js/code-block-writer)
[![Build Status](https://travis-ci.org/dsherret/code-block-writer.svg)](https://travis-ci.org/dsherret/code-block-writer)
[![Coverage Status](https://coveralls.io/repos/dsherret/code-block-writer/badge.svg?branch=master&service=github)](https://coveralls.io/github/dsherret/code-block-writer?branch=master)
[![stable](http://badges.github.io/stability-badges/dist/stable.svg)](http://github.com/badges/stability-badges)
Code writer that assists with formatting and visualizing blocks of JavaScript or TypeScript code.
```
npm install --save code-block-writer
```
## Example
<!-- dprint-ignore -->
```typescript
import CodeBlockWriter from "code-block-writer";
const writer = new CodeBlockWriter({
// optional options
newLine: "\r\n", // default: "\n"
indentNumberOfSpaces: 2, // default: 4
useTabs: false, // default: false
useSingleQuote: true // default: false
});
const className = "MyClass";
writer.write(`class ${className} extends OtherClass`).block(() => {
writer.writeLine(`@MyDecorator(1, 2)`);
writer.write(`myMethod(myParam: any)`).block(() => {
writer.write("return this.post(").quote("myArgument").write(");");
});
});
console.log(writer.toString());
```
Outputs (using "\r\n" for newlines):
```text
class MyClass extends OtherClass {
@MyDecorator(1, 2)
myMethod(myParam: any) {
return this.post('myArgument');
}
}
```
## Methods
- `block(block?: () => void)` - Indents all the code written within and surrounds it in braces.
- `inlineBlock(block?: () => void)` - Same as block, but doesn't add a space before the first brace and doesn't add a newline at the end.
- `getLength()` - Get the current number of characters.
- `writeLine(text: string)` - Writes some text and adds a newline.
- `newLine()` - Writes a newline.
- `newLineIfLastNot()` - Writes a newline if what was written last wasn't a newline.
- `blankLine()` - Writes a blank line. Does not allow consecutive blank lines.
- `blankLineIfLastNot()` - Writes a blank line if what was written last wasn't a blank line.
- `quote()` - Writes a quote character.
- `quote(text: string)` - Writes text surrounded in quotes.
- `indent(times?: number)` - Indents the current line. Optionally indents multiple times when providing a number.
- `indent(block?: () => void)` - Indents a block of code.
- `space(times?: number)` - Writes a space. Optionally writes multiple spaces when providing a number.
- `spaceIfLastNot()` - Writes a space if the last was not a space.
- `tab(times?: number)` - Writes a tab. Optionally writes multiple tabs when providing a number.
- `tabIfLastNot()` - Writes a tab if the last was not a tab.
- `write(text: string)` - Writes some text.
- `conditionalNewLine(condition: boolean)` - Writes a newline if the condition is matched.
- `conditionalBlankLine(condition: boolean)` - Writes a blank line if the condition is matched.
- `conditionalWrite(condition: boolean, text: string)` - Writes if the condition is matched.
- `conditionalWrite(condition: boolean, textFunc: () => string)` - Writes if the condition is matched.
- `conditionalWriteLine(condition: boolean, text: string)` - Writes some text and adds a newline if the condition is matched.
- `conditionalWriteLine(condition: boolean, textFunc: () => string)` - Writes some text and adds a newline if the condition is matched.
- `setIndentationLevel(indentationLevel: number)` - Sets the current indentation level.
- `setIndentationLevel(whitespaceText: string)` - Sets the current indentation level based on the provided whitespace text.
- `withIndentationLevel(indentationLevel: number, action: () => void)` - Sets the indentation level within the provided action.
- `withIndentationLevel(whitespaceText: string, action: () => void)` - Sets the indentation level based on the provided whitespace text within the action.
- `getIndentationLevel()` - Gets the current indentation level.
- `queueIndentationLevel(indentationLevel: number)` - Queues an indentation level to be used once a new line is written.
- `queueIndentationLevel(whitespaceText: string)` - Queues an indentation level to be used once a new line is written based on the provided whitespace text.
- `hangingIndent(action: () => void)` - Writes the code within the action with hanging indentation.
- `hangingIndentUnlessBlock(action: () => void)` - Writes the code within the action with hanging indentation unless a block is written going from the first line to the second.
- `closeComment()` - Writes text to exit a comment if in a comment.
- `unsafeInsert(pos: number, text: string)` - Inserts text into the writer. This will not update the writer's state. Read more in its jsdoc.
- `isInComment()` - Gets if the writer is currently in a comment.
- `isAtStartOfFirstLineOfBlock()` - Gets if the writer is currently at the start of the first line of the text, block, or indentation block.
- `isOnFirstLineOfBlock()` - Gets if the writer is currently on the first line of the text, block, or indentation block.
- `isInString()` - Gets if the writer is currently in a string.
- `isLastNewLine()` - Gets if the writer last wrote a newline.
- `isLastBlankLine()` - Gets if the writer last wrote a blank line.
- `isLastSpace()` - Gets if the writer last wrote a space.
- `isLastTab()` - Gets if the writer last wrote a tab.
- `getLastChar()` - Gets the last character written.
- `endsWith(text: string)` - Gets if the writer ends with the provided text.
- `iterateLastChars<T>(action: (char: string, index: number) => T | undefined): T | undefined` - Iterates over the writer's characters in reverse order, stopping once a non-null or undefined value is returned and returns that value.
- `iterateLastCharCodes<T>(action: (charCode: number, index: number) => T | undefined): T | undefined` - A slightly faster version of `iterateLastChars` that doesn't allocate a string per character.
- `getOptions()` - Gets the writer options.
- `toString()` - Gets the string.
## Other Features
- Does not indent within strings.
- Escapes newlines within double and single quotes created with `.quote(text)`.
## C# Version
See [CodeBlockWriterSharp](https://github.com/dsherret/CodeBlockWriterSharp).