From af9b485b770b764812377fa6597357db292afabb Mon Sep 17 00:00:00 2001 From: Heekang Park Date: Wed, 8 Feb 2023 18:14:46 +0900 Subject: [PATCH] v0.1.0 --- .editorconfig | 10 - .eslintignore | 3 - .eslintrc | 23 - .gitignore | 17 - .npmrc | 1 - LICENSE | 21 + README.md | 364 +- README_ko.md | 318 ++ dist/main.js | 674 +++ dist/manifest.json | 11 + dist/styles.css | 140 + dist/versions.json | 3 + esbuild.config.mjs | 11 +- imgs/copybtn.png | Bin 0 -> 6021 bytes imgs/highlight1.png | Bin 0 -> 7981 bytes imgs/highlight2.png | Bin 0 -> 8885 bytes imgs/language1.png | Bin 0 -> 5925 bytes imgs/language2.png | Bin 0 -> 6016 bytes imgs/linenos1.png | Bin 0 -> 6121 bytes imgs/linenos2.png | Bin 0 -> 6385 bytes imgs/linenos3.png | Bin 0 -> 6385 bytes imgs/prompt1.png | Bin 0 -> 5197 bytes imgs/prompt2.png | Bin 0 -> 5131 bytes imgs/prompt3.png | Bin 0 -> 6433 bytes imgs/result1.png | Bin 0 -> 7605 bytes imgs/result2.png | Bin 0 -> 9310 bytes imgs/result3.png | Bin 0 -> 10939 bytes imgs/title.png | Bin 0 -> 7345 bytes main.ts | 137 - manifest.json | 11 - package-lock.json | 4582 +++++++++++++++++++++ package.json | 18 +- src/HKCodeBlockProcessor.ts | 343 ++ src/HKCodeBlockSettingTab.ts | 267 ++ src/HKCodeBlockSettings.ts | 49 + src/main.ts | 48 + src/prism-plugins/prism-command-line.js | 243 ++ src/prism-plugins/prism-line-highlight.js | 346 ++ src/prism-plugins/prism-line-numbers.js | 252 ++ src/styles.scss | 190 + styles.css | 8 - tsconfig.json | 13 +- version-bump.mjs | 11 +- versions.json | 3 - 44 files changed, 7816 insertions(+), 301 deletions(-) delete mode 100644 .editorconfig delete mode 100644 .eslintignore delete mode 100644 .eslintrc delete mode 100644 .npmrc create mode 100644 LICENSE create mode 100644 README_ko.md create mode 100644 dist/main.js create mode 100644 dist/manifest.json create mode 100644 dist/styles.css create mode 100644 dist/versions.json create mode 100644 imgs/copybtn.png create mode 100644 imgs/highlight1.png create mode 100644 imgs/highlight2.png create mode 100644 imgs/language1.png create mode 100644 imgs/language2.png create mode 100644 imgs/linenos1.png create mode 100644 imgs/linenos2.png create mode 100644 imgs/linenos3.png create mode 100644 imgs/prompt1.png create mode 100644 imgs/prompt2.png create mode 100644 imgs/prompt3.png create mode 100644 imgs/result1.png create mode 100644 imgs/result2.png create mode 100644 imgs/result3.png create mode 100644 imgs/title.png delete mode 100644 main.ts delete mode 100644 manifest.json create mode 100644 package-lock.json create mode 100755 src/HKCodeBlockProcessor.ts create mode 100755 src/HKCodeBlockSettingTab.ts create mode 100755 src/HKCodeBlockSettings.ts create mode 100755 src/main.ts create mode 100755 src/prism-plugins/prism-command-line.js create mode 100755 src/prism-plugins/prism-line-highlight.js create mode 100755 src/prism-plugins/prism-line-numbers.js create mode 100644 src/styles.scss delete mode 100644 styles.css delete mode 100644 versions.json diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 84b8a66..0000000 --- a/.editorconfig +++ /dev/null @@ -1,10 +0,0 @@ -# top-most EditorConfig file -root = true - -[*] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -indent_style = tab -indent_size = 4 -tab_width = 4 diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index e019f3c..0000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -node_modules/ - -main.js diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 0807290..0000000 --- a/.eslintrc +++ /dev/null @@ -1,23 +0,0 @@ -{ - "root": true, - "parser": "@typescript-eslint/parser", - "env": { "node": true }, - "plugins": [ - "@typescript-eslint" - ], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended" - ], - "parserOptions": { - "sourceType": "module" - }, - "rules": { - "no-unused-vars": "off", - "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }], - "@typescript-eslint/ban-ts-comment": "off", - "no-prototype-builtins": "off", - "@typescript-eslint/no-empty-function": "off" - } - } \ No newline at end of file diff --git a/.gitignore b/.gitignore index e09a007..8233e48 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,5 @@ # vscode .vscode -# Intellij -*.iml -.idea - -# npm node_modules -# Don't include the compiled main.js file in the repo. -# They should be uploaded to GitHub releases instead. -main.js - -# Exclude sourcemaps -*.map - -# obsidian -data.json - -# Exclude macOS Finder (System Explorer) View States -.DS_Store diff --git a/.npmrc b/.npmrc deleted file mode 100644 index b973752..0000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -tag-version-prefix="" \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6362352 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2021 + +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. \ No newline at end of file diff --git a/README.md b/README.md index 31e5155..8840aad 100644 --- a/README.md +++ b/README.md @@ -1,96 +1,318 @@ -# Obsidian Sample Plugin +# HK CodeBlock -This is a sample plugin for Obsidian (https://obsidian.md). +[Obsidian](https://obsidian.md) plugin developed by Heekang Park -This project uses Typescript to provide type checking and documentation. -The repo depends on the latest plugin API (obsidian.d.ts) in Typescript Definition format, which contains TSDoc comments describing what it does. +[ English | [한국어](https://github.com/HeekangPark/obsidian-hk-code-block/blob/master/README_ko.md) ] -**Note:** The Obsidian API is still in early alpha and is subject to change at any time! +With HK CodeBlock, you can add various features to code blocks. -This sample plugin demonstrates some of the basic functionality the plugin API can do. -- Changes the default font color to red using `styles.css`. -- Adds a ribbon icon, which shows a Notice when clicked. -- Adds a command "Open Sample Modal" which opens a Modal. -- Adds a plugin setting tab to the settings page. -- Registers a global click event and output 'click' to the console. -- Registers a global interval which logs 'setInterval' to the console. +Inspired from [Prism.js](https://prismjs.com/)'s plugin, [Better Code Block](https://github.com/stargrey/obsidian-better-codeblock), [Code Block Enhancer](https://github.com/nyable/obsidian-code-block-enhancer). -## First time developing plugins? +## Features -Quick starting guide for new plugin devs: +### Title -- Check if [someone already developed a plugin for what you want](https://obsidian.md/plugins)! There might be an existing plugin similar enough that you can partner up with. -- Make a copy of this repo as a template with the "Use this template" button (login to GitHub if you don't see it). -- Clone your repo to a local development folder. For convenience, you can place this folder in your `.obsidian/plugins/your-plugin-name` folder. -- Install NodeJS, then run `npm i` in the command line under your repo folder. -- Run `npm run dev` to compile your plugin from `main.ts` to `main.js`. -- Make changes to `main.ts` (or create new `.ts` files). Those changes should be automatically compiled into `main.js`. -- Reload Obsidian to load the new version of your plugin. -- Enable plugin in settings window. -- For updates to the Obsidian API run `npm update` in the command line under your repo folder. +You can add title to the code block like this. -## Releasing new releases + ```python title:"Title of the code block" + print("Hello world") + ``` -- Update your `manifest.json` with your new version number, such as `1.0.1`, and the minimum Obsidian version required for your latest release. -- Update your `versions.json` file with `"new-plugin-version": "minimum-obsidian-version"` so older versions of Obsidian can download an older version of your plugin that's compatible. -- Create new GitHub release using your new version number as the "Tag version". Use the exact version number, don't include a prefix `v`. See here for an example: https://github.com/obsidianmd/obsidian-sample-plugin/releases -- Upload the files `manifest.json`, `main.js`, `styles.css` as binary attachments. Note: The manifest.json file must be in two places, first the root path of your repository and also in the release. -- Publish the release. +![title](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/title.png) -> You can simplify the version bump process by running `npm version patch`, `npm version minor` or `npm version major` after updating `minAppVersion` manually in `manifest.json`. -> The command will bump version in `manifest.json` and `package.json`, and add the entry for the new version to `versions.json` +You must put the title in quotes. You can use both single and double quotes. -## Adding your plugin to the community plugin list +### Line Numbers -- Check https://github.com/obsidianmd/obsidian-releases/blob/master/plugin-review.md -- Publish an initial version. -- Make sure you have a `README.md` file in the root of your repo. -- Make a pull request at https://github.com/obsidianmd/obsidian-releases to add your plugin. +You can add line numbers to the code block like this. -## How to use + ```python linenos + print("Hello world") + ``` -- Clone this repo. -- `npm i` or `yarn` to install dependencies -- `npm run dev` to start compilation in watch mode. +Or like this. -## Manually installing the plugin + ```python linenos:true + print("Hello world") + ``` -- Copy over `main.js`, `styles.css`, `manifest.json` to your vault `VaultFolder/.obsidian/plugins/your-plugin-id/`. +![linenos1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/linenos1.png) -## Improve code quality with eslint (optional) -- [ESLint](https://eslint.org/) is a tool that analyzes your code to quickly find problems. You can run ESLint against your plugin to find common bugs and ways to improve your code. -- To use eslint with this project, make sure to install eslint from terminal: - - `npm install -g eslint` -- To use eslint to analyze this project use this command: - - `eslint main.ts` - - eslint will then create a report with suggestions for code improvement by file and line number. -- If your source code is in a folder, such as `src`, you can use eslint with this command to analyze all files in that folder: - - `eslint .\src\` +If you don't specify any options, the line numbers will start from the value set in the settings (default: 1). If you want the line numbers to start from a specific value, you can do it like this. -## Funding URL + ```python linenos:10 + print("Hello world") + ``` -You can include funding URLs where people who use your plugin can financially support it. +![linenos2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/linenos2.png) -The simple way is to set the `fundingUrl` field to your link in your `manifest.json` file: +You can also use negative values. -```json -{ - "fundingUrl": "https://buymeacoffee.com" -} -``` + ```python linenos:-10 + print("Hello world") + ``` -If you have multiple URLs, you can also do: +![linenos3](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/linenos3.png) -```json -{ - "fundingUrl": { - "Buy Me a Coffee": "https://buymeacoffee.com", - "GitHub Sponsor": "https://github.com/sponsors", - "Patreon": "https://www.patreon.com/" - } -} -``` +If you want to explicitly hide the line numbers, you can do it like this. -## API Documentation + ```python linenos:false + print("Hello world") + ``` -See https://github.com/obsidianmd/obsidian-api +### Line Highlight + +You can highlight specific lines in the code block with commas like this. + + ```python highlight:"2,3" + print("Hello world") + print("I love you") + print("Wow") + ``` + +![highlight1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/highlight1.png) + +You must put the line numbers in quotes. You can use both single and double quotes. + +If you use the line numbers feature and set the line numbers don't start from 1, you must enter the line numbers to be highlighted according to that. + + ```python linenos:10 highlight:"10,11" + print("Hello world") + print("I love you") + print("Wow") + ``` + +![highlight2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/highlight2.png) + +### Language Indicator + +You can add the language indicator to the code block like this. + + ```python language + print("Hello world") + ``` + +Or like this. + + ```python language:true + print("Hello world") + ``` + +![language1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/language1.png) + +The displayed language is following the language of the code block by default, but if you want, you can specify it explicitly. In this case, you can change the language displayed while keeping the syntax highlighting done by the language of the code block. + + ```python language:"javascript" + print("Hello world") + ``` + +![language2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/language2.png) + +You must put the language in quotes. You can use both single and double quotes. + +If neither the language of the code block nor the language specified by the language option is specified, the language displayed is the value set in the settings (default: "plain text"). + +If you want to explicitly hide the language indicator, you can do it like this. + + ```python language:false + print("Hello world") + ``` + +### Copy Button + +You can add a copy button to the code block like this. + + ```python copybtn + print("Hello world") + ``` + +Or like this. + + ```python copybtn:true + print("Hello world") + ``` + +![copybtn](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/copybtn.png) + +If you want to explicitly hide the copy button, you can do it like this. + + ```python copybtn:false + print("Hello world") + ``` + +### Prompt + +You can add a prompt to the code block like this. + + ```bash prompt + mkdir test + ``` + +Or like this. + + ```bash prompt:true + mkdir test + ``` + +![prompt1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/prompt1.png) + +If you don't specify any options, the prompt will be the value set in the settings (default: "$"). If you want to use another prompt, you can do it like this. + + ```bash prompt:"#" + mkdir test + ``` + +![prompt2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/prompt2.png) + +You must put the prompt in quotes. You can use both single and double quotes. + +If there is a "\" character at the end of the line, the prompt will not be displayed on the next line. + + ```bash prompt + docker run -it \ + ubuntu:latest + ``` + +![prompt3](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/prompt3.png) + +If you want to explicitly hide the prompt, you can do it like this. + + ```bash prompt:false + mkdir test + ``` + +### Result + +You can add a result to the code block like this. + + ```python + print("Hello world!") + ``` + + ```result + Hello world! + ``` + +![result1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/result1.png) + +Note that the Result Code Block must be placed immediately after the Code Block to which the result belongs. You must not put any other components between them. + +Also note that the result code block is not dynamically generated. Result code blocks are just simple plain-text code blocks. You must enter the result manually. + +You can use line numbers, line highlight features only in the result code block. Other features will be ignored even if you specify them. + + ```python + print("Hello world!") + ``` + + ```result linenos + Hello world! + ``` + + ```result highlight:"1" + Hello world! + ``` + +![result2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/result2.png) + +The prompt of the result code block is the value set in the settings by default (default: "Result"). If you want to use another prompt, you can do it like this. + + ```python + import random + print(random.randint(1, 100)) + ``` + + ```result prompt:"Result (may be different depending on your environment)" + 42 + ``` + +![result3](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/result3.png) + +## Settings + +You can change the default settings of each feature of HK Code Block in the settings. + +### Title + +- Use Title + - default off, but on when specified : the title will only be shown if the title statement is specified + - always off : the title will never be shown + +### Line numbers + +- Use Line Numbers + - always on : line numbers will always be shown + - default on, but off when specified : line numbers will always be shown, but will not be shown if linenos statement is specified as false + - default off, but on when specified : line numbers will only be shown if the linenos statement is specified as true + - always off : line numbers will never be shown +- Default Line Number Start : the default line number start of the code block (default: 1) +- Show Line Number Splitter : whether to show the line number splitter (default: true) + +### Line Highlight + +- Use Line Highlight + - default off, but on when specified : line highlight will only be shown if the line highlight statement is specified + - always off : line highlight will never be shown +- Line Highlight Color : The background color of the highlighted line. Note that the given color will be applied with 0.2 opacity. (default: #ff0000) + +### Language Indicator + +- Use Language Indicator + - always on : language indicator will always be shown + - default on, but off when specified : language indicator will always be shown, but will not be shown if the language indicator statement is specified as false + - default off, but on when specified : language indicator will only be shown if the language indicator statement is specified as true + - always off : language indicator will never be shown +- Default Language : the default language name of the code block if the language is not specified. (default: "plain text") + +### Copy Button + +- Use Copy Button + - always on : copy button will always be shown + - default on, but off when specified : copy button will always be shown, but will not be shown if the copy button statement is specified as false + - default off, but on when specified : copy button will only be shown if the copy button statement is specified as true + - always off : copy button will never be shown + +### Prompt + +- Use Prompt + - always on : prompt will always be shown for languages specified in the "Prompting Languages" option + - default on, but off when specified : prompt will always be shown for languages specified in the "Prompting Languages" option, but will not be shown if the prompt statement is specified as false + - default off, but on when specified : prompt will only be shown if the prompt statement is specified as true + - always off : prompt will never be shown +- Prompting Languages : The languages that will be prompted by default. You can specify multiple languages by separating them with enters. (default: "bash") +- Default Prompt : The default prompt of the code block. (default: "$") + +### Result + +- Use Result + - enable : use the result feature + - disable : do not use the result feature +- Default Result Prompt : The default prompt of the result code block. (default: "Result") + +### Developers + +- Debug Mode + - true : enable debug mode. Log messages will be displayed in the console. + - false : disable debug mode. + +## License + +MIT License + +## Known Issues + +- Some features may not work properly depending on the theme you are using. Currently on 2023-02, I checked that the following themes are working properly. + - Default Theme + - [Minimal Theme](https://github.com/kepano/obsidian-minimal) + - [Obsidian Nord](https://github.com/insanum/obsidian_nord) + - [Obsidianite](https://github.com/bennyxguo/Obsidian-Obsidianite) + - [Sanctum](https://github.com/jdanielmourao/obsidian-sanctum) + - [Shimmering Focus](https://github.com/chrisgrieser/shimmering-focus) + - [Wasp](https://github.com/santiyounger/Wasp-Obsidian-Theme) + - [Typewriter](https://github.com/crashmoney/obsidian-typewriter) + +## Changelog + +### 0.1.0 + +- Initial release \ No newline at end of file diff --git a/README_ko.md b/README_ko.md new file mode 100644 index 0000000..0002bf0 --- /dev/null +++ b/README_ko.md @@ -0,0 +1,318 @@ +# HK CodeBlock + +[Obsidian](https://obsidian.md) plugin developed by Heekang Park + +[ 한국어 | [English](https://github.com/HeekangPark/obsidian-hk-code-block/blob/master/README.md) ] + +HK CodeBlock을 이용하면 Code Block에 다양한 기능들을 추가할 수 있습니다. + +[Prism.js](https://prismjs.com/)의 플러그인, [Better Code Block](https://github.com/stargrey/obsidian-better-codeblock), [Code Block Enhancer](https://github.com/nyable/obsidian-code-block-enhancer) 등에서 영감을 받아 만들었습니다. + +## 기능 + +### 제목 + +다음과 같이 하면 Code Block에 제목을 설정할 수 있습니다. + + ```python title:"Title of the code block" + print("Hello world") + ``` + +![title](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/title.png) + +반드시 따옴표 안에 제목을 넣어야 합니다. 큰따옴표와 작은 따옴표 모두 사용 가능합니다. + +### 줄 번호 + +다음과 같이 하면 Code Block에 줄 번호를 추가할 수 있습니다. + + ```python linenos + print("Hello world") + ``` + +또는 다음과 같이 할 수도 있습니다. + + ```python linenos:true + print("Hello world") + ``` + +![linenos1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/linenos1.png) + +아무런 옵션을 주지 않으면 줄 번호는 설정에서 설정한 값(기본값: 1)부터 시작합니다. 줄 번호가 특정 값으로 시작하도록 하려면 다음과 같이 하면 됩니다. + + ```python linenos:10 + print("Hello world") + ``` + +![linenos2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/linenos2.png) + +음수 값도 가능합니다. + + ```python linenos:-10 + print("Hello world") + ``` + +![linenos3](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/linenos3.png) + +다음과 같이 하면 명시적으로 줄 번호를 숨길 수 있습니다. + + ```python linenos:false + print("Hello world") + ``` + +### 줄 강조 + +다음과 같이 강조하고 싶은 줄의 번호를 콤마로 구분하여 입력하면 해당 줄에 강조 효과를 줄 수 있습니다. + + ```python highlight:"2,3" + print("Hello world") + print("I love you") + print("Wow") + ``` + +![highlight1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/highlight1.png) + +반드시 따옴표 안에 줄 번호를 넣어야 합니다. 큰따옴표와 작은 따옴표 모두 사용 가능합니다. + +만약 줄 번호 기능을 사용해 줄 번호가 1부터 시작하지 않도록 했다면, 강조할 줄 번호를 입력할 때도 이에 맞춰서 입력해야 합니다. + + ```python linenos:10 highlight:"10,11" + print("Hello world") + print("I love you") + print("Wow") + ``` + +![highlight2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/highlight2.png) + +### 언어 표시 + +다음과 같이 하면 Code Block에 Code Block의 언어를 표시할 수 있습니다. + + ```python language + print("Hello world") + ``` + +또는 다음과 같이 할 수도 있습니다. + + ```python language:true + print("Hello world") + ``` + +![language1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/language1.png) + +표시되는 언어는 기본적으로 Code Block의 언어를 따라가지만, 만약 원한다면 직접 명시할 수 있습니다. 이렇게 하면 구문 강조(syntax highlighting)는 Code Block의 언어를 따라가게 하면서 표시되는 언어만 바꿀 수 있습니다. + + ```python language:"javascript" + print("Hello world") + ``` + +![language2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/language2.png) + +언어를 직접 명시할 때는 반드시 따옴표 안에 언어를 넣어야 합니다. 큰따옴표와 작은 따옴표 모두 사용 가능합니다. + +만약 Code Block의 언어도, language 옵션으로 명시한 언어도 없다면, 언어 표시는 설정에서 설정된 값(기본값: "plain text")이 적용됩니다. + +다음과 같이 하면 명시적으로 언어를 숨길 수 있습니다. + + ```python language:false + print("Hello world") + ``` + +### 복사 버튼 + +다음과 같이 하면 Code Block에 복사 버튼을 추가할 수 있습니다. + + ```python copybtn + print("Hello world") + ``` + +또는 다음과 같이 할 수도 있습니다. + + ```python copybtn:true + print("Hello world") + ``` + +![copybtn](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/copybtn.png) + +다음과 같이 하면 명시적으로 복사 버튼을 숨길 수 있습니다. + + ```python copybtn:false + print("Hello world") + ``` + +### 프롬프트 + +다음과 같이 하면 Code Block에 프롬프트를 추가할 수 있습니다. + + ```bash prompt + mkdir test + ``` + +또는 다음과 같이 할 수도 있습니다. + + ```bash prompt:true + mkdir test + ``` + +![prompt1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/prompt1.png) + +아무런 옵션을 주지 않으면 프롬프트는 설정에서 설정한 값(기본값: "$")이 사용됩니다. 다른 프롬프트를 사용하고 싶다면 다음과 같이 하면 됩니다. + + ```bash prompt:"#" + mkdir test + ``` + +![prompt2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/prompt2.png) + +프롬프트를 직접 명시할 때는 반드시 따옴표 안에 프롬프트를 넣어야 합니다. 큰따옴표와 작은 따옴표 모두 사용 가능합니다. + +줄 끝에 "\" 문자가 있는 경우 다음 줄에는 프롬프트가 표시되지 않습니다. + + ```bash prompt + docker run -it \ + ubuntu:latest + ``` + +![prompt3](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/prompt3.png) + +다음과 같이 하면 명시적으로 프롬프트를 숨길 수 있습니다. + + ```bash prompt:false + mkdir test + ``` + +### 실행 결과 표시 + +다음과 같이 하면 Code Block의 실행 결과를 표시할 수 있습니다. + + ```python + print("Hello world!") + ``` + + ```result + Hello world! + ``` + +![result1](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/result1.png) + +Result Code Block은 반드시 실행 결과를 표시할 Code Block 바로 다음에 위치해야 합니다. 두 Code Block 사이에 어떠한 요소도 있으면 안됩니다. + +또 Result Code Block은 Code Block을 실행해 동적으로 생성되는 그런 것이 아닙니다. Result Code Block은 단순한 텍스트 Code Block(plain-text code block)일 뿐입니다. 사용자가 직접 실행 결과를 입력해야 합니다. + +Result Code Block에서는 줄 번호, 줄 강조 기능만 사용 가능합니다. 나머지 기능들은 명시해도 무시됩니다. + + ```python + print("Hello world!") + ``` + + ```result linenos + Hello world! + ``` + + ```result highlight:"1" + Hello world! + ``` + +![result2](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/result2.png) + +Result Code Block의 프롬프트는 설정에서 설정한 값(기본값: "Result")이 사용됩니다. 다른 프롬프트를 사용하고 싶다면 다음과 같이 하면 됩니다. + + ```python + import random + print(random.randint(1, 100)) + ``` + + ```result prompt:"Result (may be different depending on your environment)" + 42 + ``` + +![result3](https://github.com/HeekangPark/obsidian-hk-code-block/raw/master/imgs/result3.png) + +## 설정 + +설정에서는 HK Code Block의 각 기능별 기본 설정을 변경할 수 있습니다. + +### Title + +- Use Title + - default off, but on when specified : 기본적으로 제목 기능을 사용하지 않습니다. 하지만 title 옵션을 명시하면 제목 기능을 사용합니다. + - always off : 제목 기능을 항상 사용하지 않습니다. + +### Line numbers + +- Use Line Numbers + - always on : 줄 번호 기능을 항상 사용합니다. + - default on, but off when specified : 기본적으로 줄 번호 기능을 사용합니다. 하지만 줄 번호 기능을 사용하지 않는다고 명시하면 줄 번호 기능을 사용하지 않습니다. + - default off, but on when specified : 기본적으로 줄 번호 기능을 사용하지 않습니다. 하지만 줄 번호 기능을 사용한다고 명시하면 줄 번호 기능을 사용합니다. + - always off : 줄 번호 기능을 항상 사용하지 않습니다. +- Default Line Number Start : 줄의 시작 번호를 설정합니다. 기본값은 1입니다. +- Show Line Number Splitter : 줄 번호와 코드 사이에 구분선을 표시합니다. 기본값은 true입니다. + +### Line Highlight + +- Use Line Highlight + - default off, but on when specified : 기본적으로 줄 강조 기능을 사용하지 않습니다. 하지만 줄 강조 기능을 사용한다고 명시하면 줄 강조 기능을 사용합니다. + - always off : 줄 강조 기능을 항상 사용하지 않습니다. +- Line Highlight Color : 강조색을 설정합니다. 기본값은 #ff0000입니다. 실제 줄 강조에는 여기 명시된 색에 opacity 0.2가 적용된다는 점에 유의하세요. + +### Language Indicator + +- Use Language Indicator + - always on : 언어 표시 기능을 항상 사용합니다. + - default on, but off when specified : 기본적으로 언어 표시 기능을 사용합니다. 하지만 언어 표시 기능을 사용하지 않는다고 명시하면 언어 표시 기능을 사용하지 않습니다. + - default off, but on when specified : 기본적으로 언어 표시 기능을 사용하지 않습니다. 하지만 언어 표시 기능을 사용한다고 명시하면 언어 표시 기능을 사용합니다. + - always off : 언어 표시 기능을 항상 사용하지 않습니다. +- Default Language : 언어 표시 기능을 사용할 때 아무런 언어가 명시되지 않았다면 기본으로 사용할 언어를 설정합니다. 기본값은 "plain text"입니다. + +### Copy Button + +- Use Copy Button + - always on : 복사 버튼 기능을 항상 사용합니다. + - default on, but off when specified : 기본적으로 복사 버튼 기능을 사용합니다. 하지만 복사 버튼 기능을 사용하지 않는다고 명시하면 복사 버튼 기능을 사용하지 않습니다. + - default off, but on when specified : 기본적으로 복사 버튼 기능을 사용하지 않습니다. 하지만 복사 버튼 기능을 사용한다고 명시하면 복사 버튼 기능을 사용합니다. + - always off : 복사 버튼 기능을 항상 사용하지 않습니다. + +### Prompt + +- Use Prompt + - always on : Prompting Languages에 명시된 언어들에 대해, 프롬프트 기능을 항상 사용합니다. + - default on, but off when specified : Prompting Languages에 명시된 언어들에 대해, 기본적으로 프롬프트 기능을 사용합니다. 하지만 프롬프트 기능을 사용하지 않는다고 명시하면 프롬프트 기능을 사용하지 않습니다. + - default off, but on when specified : 기본적으로 프롬프트 기능을 사용하지 않습니다. 하지만 프롬프트 기능을 사용한다고 명시하면 프롬프트 기능을 사용합니다. + - always off : 프롬프트 기능을 항상 사용하지 않습니다. +- Prompting Languages : 프롬프트 기능을 기본적으로 사용할 언어를 설정합니다. 엔터 키로 구분해 여러 개의 언어를 설정할 수 있습니다. 기본값은 "bash"입니다. +- Default Prompt : 프롬프트 기능을 사용할 때 아무런 프롬프트가 명시되지 않았다면 기본으로 사용할 프롬프트를 설정합니다. 기본값은 "$"입니다. + +### Result + +- Use Result + - enable : 실행 결과 표시 기능을 사용합니다. + - disable : 실행 결과 표시 기능을 사용하지 않습니다. +- Default Result Prompt : 실행 결과 표시 Code Block의 프롬프트를 설정합니다. 기본값은 "Result"입니다. + +### Developers + +- Debug Mode + - true : 디버그 모드를 활성화해 log를 console에 출력합니다. + - false : 디버그 모드를 비활성화합니다. + +## 라이센스 + +MIT License + +## 알려진 문제점 + +- 테마별 설정에 따라 몇몇 기능들이 제대로 동작하지 않을 수 있습니다. 2023년 02월 현재, 정상 동작을 시험해본 테마는 다음과 같습니다. + - Default Theme + - [Minimal Theme](https://github.com/kepano/obsidian-minimal) + - [Obsidian Nord](https://github.com/insanum/obsidian_nord) + - [Obsidianite](https://github.com/bennyxguo/Obsidian-Obsidianite) + - [Sanctum](https://github.com/jdanielmourao/obsidian-sanctum) + - [Shimmering Focus](https://github.com/chrisgrieser/shimmering-focus) + - [Wasp](https://github.com/santiyounger/Wasp-Obsidian-Theme) + - [Typewriter](https://github.com/crashmoney/obsidian-typewriter) + +## Changelog + +### 0.1.0 + +- 최초 배포 \ No newline at end of file diff --git a/dist/main.js b/dist/main.js new file mode 100644 index 0000000..073a20b --- /dev/null +++ b/dist/main.js @@ -0,0 +1,674 @@ +/* +THIS IS A GENERATED/BUNDLED FILE BY ESBUILD +if you want to view the source, please visit the github repository of this plugin +*/ + +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// src/main.ts +var main_exports = {}; +__export(main_exports, { + default: () => HKCodeBlockPlugin +}); +module.exports = __toCommonJS(main_exports); +var import_obsidian3 = require("obsidian"); + +// src/HKCodeBlockSettings.ts +var DEFAULT_SETTINGS = { + useTitleGlobal: "default off, but on when specified", + useLinenosGlobal: "default off, but on when specified", + defaultLinenosStart: 1, + showLinenosSplitter: true, + useHighlightGlobal: "default off, but on when specified", + highlightColor: "#ff0000", + useLanguageGlobal: "default on, but off when specified", + defaultLanguage: "plain text", + useCopyBtnGlobal: "default on, but off when specified", + usePromptGlobal: "default on, but off when specified", + promptingLanguages: ["bash"], + defaultPrompt: "$", + useResultGlobal: "enable", + defaultResultPrompt: "Result", + debugMode: false +}; + +// src/HKCodeBlockSettingTab.ts +var import_obsidian = require("obsidian"); +var fragWithHTML = (text) => { + return createFragment((frag) => { + frag.createDiv().innerHTML = text.split("\n").map((line) => line.trim()).join("
"); + }); +}; +var HKCodeBlockSettingTab = class extends import_obsidian.PluginSettingTab { + constructor(app2, plugin) { + super(app2, plugin); + this.plugin = plugin; + } + display() { + const { containerEl } = this; + containerEl.empty(); + containerEl.createEl("h2", { text: "Title" }); + new import_obsidian.Setting(containerEl).setName("Use Title").setDesc(fragWithHTML(`- default off, but on when specified : the title will only be shown if the title statement is specified + - always off : the title will never be shown`)).addDropdown( + (tc) => tc.addOptions({ + "default off, but on when specified": "default off, but on when specified", + "always off": "always off" + }).setValue(this.plugin.settings.useTitleGlobal).onChange(async (value) => { + this.plugin.settings.useTitleGlobal = value; + await this.plugin.saveSettings(); + }) + ); + containerEl.createEl("h2", { text: "Line Numbers" }); + new import_obsidian.Setting(containerEl).setName("Use Line Numbers").setDesc(fragWithHTML(`- always on : line numbers will always be shown + - default on, but off when specified : line numbers will always be shown, but will not be shown if linenos statement is specified as false + - default off, but on when specified : line numbers will only be shown if the linenos statement is specified as true + - always off : line numbers will never be shown`)).addDropdown( + (tc) => tc.addOptions({ + "always on": "always on", + "default on, but off when specified": "default on, but off when specified", + "default off, but on when specified": "default off, but on when specified", + "always off": "always off" + }).setValue(this.plugin.settings.useLinenosGlobal).onChange(async (value) => { + this.plugin.settings.useLinenosGlobal = value; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian.Setting(containerEl).setName("Default Line Number Start").setDesc("The default line number start of the code block.").addText( + (tc) => tc.setValue(this.plugin.settings.defaultLinenosStart.toString()).onChange(async (value) => { + const num = parseInt(value); + if (isNaN(num)) + return; + this.plugin.settings.defaultLinenosStart = num; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian.Setting(containerEl).setName("Show Line Number Splitter").addToggle( + (tc) => tc.setValue(this.plugin.settings.showLinenosSplitter).onChange(async (value) => { + this.plugin.settings.showLinenosSplitter = value; + await this.plugin.saveSettings(); + }) + ); + containerEl.createEl("h2", { text: "Line Highlight" }); + new import_obsidian.Setting(containerEl).setName("Use Line Highlight").setDesc(fragWithHTML(`- default off, but on when specified : line highlight will only be shown if the line highlight statement is specified + - always off : line highlight will never be shown`)).addDropdown( + (tc) => tc.addOptions({ + "default off, but on when specified": "default off, but on when specified", + "always off": "always off" + }).setValue(this.plugin.settings.useHighlightGlobal).onChange(async (value) => { + this.plugin.settings.useHighlightGlobal = value; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian.Setting(containerEl).setName("Line Highlight Color").setDesc("The background color of the highlighted line. Note that the given color will be applied with 0.2 opacity.").addText( + (tc) => tc.setValue(this.plugin.settings.highlightColor).onChange(async (value) => { + this.plugin.settings.highlightColor = value; + await this.plugin.saveSettings(); + }) + ); + containerEl.createEl("h2", { text: "Language Indicator" }); + new import_obsidian.Setting(containerEl).setName("Use Language Indicator").setDesc(fragWithHTML(`- always on : language indicator will always be shown + - default on, but off when specified : language indicator will always be shown, but will not be shown if the language indicator statement is specified as false + - default off, but on when specified : language indicator will only be shown if the language indicator statement is specified as true + - always off : language indicator will never be shown`)).addDropdown( + (tc) => tc.addOptions({ + "always on": "always on", + "default on, but off when specified": "default on, but off when specified", + "default off, but on when specified": "default off, but on when specified", + "always off": "always off" + }).setValue(this.plugin.settings.useLanguageGlobal).onChange(async (value) => { + this.plugin.settings.useLanguageGlobal = value; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian.Setting(containerEl).setName("Default Language").setDesc("The default language name of the code block if the language is not specified.").addText( + (tc) => tc.setValue(this.plugin.settings.defaultLanguage).onChange(async (value) => { + this.plugin.settings.defaultLanguage = value; + await this.plugin.saveSettings(); + }) + ); + containerEl.createEl("h2", { text: "Copy Button" }); + new import_obsidian.Setting(containerEl).setName("Use Copy Button").setDesc(fragWithHTML(`- always on : copy button will always be shown + - default on, but off when specified : copy button will always be shown, but will not be shown if the copy button statement is specified as false + - default off, but on when specified : copy button will only be shown if the copy button statement is specified as true + - always off : copy button will never be shown`)).addDropdown( + (tc) => tc.addOptions({ + "always on": "always on", + "default on, but off when specified": "default on, but off when specified", + "default off, but on when specified": "default off, but on when specified", + "always off": "always off" + }).setValue(this.plugin.settings.useCopyBtnGlobal).onChange(async (value) => { + this.plugin.settings.useCopyBtnGlobal = value; + await this.plugin.saveSettings(); + }) + ); + containerEl.createEl("h2", { text: "Prompt" }); + new import_obsidian.Setting(containerEl).setName("Use Prompt").setDesc(fragWithHTML(`- always on : prompt will always be shown + - default on, but off when specified : prompt will always be shown, but will not be shown if the prompt statement is specified as false + - default off, but on when specified : prompt will only be shown if the prompt statement is specified as true + - always off : prompt will never be shown + You can also specify the prompt by the statement like \`prompt:"My Prompt"\`. (default: "$")`)).addDropdown( + (tc) => tc.addOptions({ + "always on": "always on", + "default on, but off when specified": "default on, but off when specified", + "default off, but on when specified": "default off, but on when specified", + "always off": "always off" + }).setValue(this.plugin.settings.usePromptGlobal).onChange(async (value) => { + this.plugin.settings.usePromptGlobal = value; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian.Setting(containerEl).setName("Prompting Languages").setDesc("The languages that will be prompted by default. You can specify multiple languages by separating them with enters.").addTextArea( + (tc) => tc.setValue(this.plugin.settings.promptingLanguages.join("\n")).onChange(async (value) => { + const lines = value.split("\n").filter((line) => line.trim() !== ""); + this.plugin.settings.promptingLanguages = lines; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian.Setting(containerEl).setName("Default Prompt").setDesc("The default prompt of the bash code block.").addText( + (tc) => tc.setValue(this.plugin.settings.defaultPrompt).onChange(async (value) => { + this.plugin.settings.defaultPrompt = value; + await this.plugin.saveSettings(); + }) + ); + containerEl.createEl("h2", { text: "Result" }); + new import_obsidian.Setting(containerEl).setName("Use Result").setDesc(fragWithHTML(`- enable : treat the code block starts like \`\`\`\`result\` as the result of the adjacent previous code block + - disable : treat the code block with \`result\` as its language name as a normal code block`)).addDropdown( + (tc) => tc.addOptions({ + "enable": "enable", + "disable": "disable" + }).setValue(this.plugin.settings.useResultGlobal).onChange(async (value) => { + this.plugin.settings.useResultGlobal = value; + await this.plugin.saveSettings(); + }) + ); + new import_obsidian.Setting(containerEl).setName("Default Result Prompt").setDesc("The default prompt of the result code block.").addText( + (tc) => tc.setValue(this.plugin.settings.defaultResultPrompt).onChange(async (value) => { + this.plugin.settings.defaultResultPrompt = value; + await this.plugin.saveSettings(); + }) + ); + containerEl.createEl("h2", { text: "Developers" }); + new import_obsidian.Setting(containerEl).setName("Debug Mode").setDesc("Show logs in the console.").addToggle( + (tc) => tc.setValue(this.plugin.settings.debugMode).onChange(async (value) => { + this.plugin.settings.debugMode = value; + await this.plugin.saveSettings(); + }) + ); + } +}; + +// src/HKCodeBlockProcessor.ts +var import_obsidian2 = require("obsidian"); +var REGEX = { + TITLE: /\stitle:(?:'(.*?)'|"(.*?)")\s/, + LINENOS_SIMPLE: /\slinenos\s/, + LINENOS_COMPLICATE: /\slinenos:(true|false|(-{0,1}\d+))\s/, + HIGHLIGHT: /\shighlight:(?:'(.*?)'|"(.*?)")\s/, + LANGUAGE_FROM_CLASS: /^language-(\w+)$/, + LANGUAGE_SIMPLE: /\slanguage\s/, + LANGUAGE_COMPLICATE: /\slanguage:(true|false|'(.*?)'|"(.*?)")\s/, + COPYBTN_SIMPLE: /\scopybtn\s/, + COPYBTN_COMPLICATE: /\scopybtn:(true|false)\s/, + RESULT: /^```result\s/, + PROMPT_SIMPLE: /\sprompt\s/, + PROMPT_COMPLICATE: /\sprompt:(true|false|'(.*?)'|"(.*?)")\s/ +}; +function getMeta(view, elem_code, section_code, settings) { + const firstline = view.editor.getLine(section_code.lineStart) + " "; + let showTitle = void 0; + let title = ""; + const regexResult_title = REGEX.TITLE.exec(firstline); + if (regexResult_title) { + showTitle = true; + title = regexResult_title[1] || regexResult_title[2]; + } + let showLinenos = void 0; + let linenosStart = settings.defaultLinenosStart; + const linenosNum = section_code.lineEnd - section_code.lineStart - 1; + const regexResult_linenosSimple = REGEX.LINENOS_SIMPLE.exec(firstline); + const regexResult_linenosComplicate = REGEX.LINENOS_COMPLICATE.exec(firstline); + if (regexResult_linenosSimple) { + showLinenos = true; + } else if (regexResult_linenosComplicate) { + if (regexResult_linenosComplicate[1] === "true") { + showLinenos = true; + } else if (regexResult_linenosComplicate[1] === "false") { + showLinenos = false; + } else { + showLinenos = true; + linenosStart = parseInt(regexResult_linenosComplicate[2]) || 1; + } + } + let showHighlight = void 0; + let highlightLines = []; + const regexResult_highlight = REGEX.HIGHLIGHT.exec(firstline); + if (regexResult_highlight) { + showHighlight = true; + const highlightLines_str = regexResult_highlight[1] || regexResult_highlight[2]; + highlightLines = highlightLines_str.split(",").map((line) => parseInt(line)); + if (highlightLines.some((line) => isNaN(line))) { + showHighlight = void 0; + highlightLines = []; + } else { + highlightLines = highlightLines.filter((line) => line >= linenosStart && line < linenosStart + linenosNum); + } + } + let showLanguage = void 0; + let language = (() => { + let language2 = settings.defaultLanguage; + elem_code.classList.forEach((className) => { + const regexResult_languageFromClass = REGEX.LANGUAGE_FROM_CLASS.exec(className.trim()); + if (regexResult_languageFromClass) + language2 = regexResult_languageFromClass[1]; + }); + return language2; + })(); + const regexResult_languageSimple = REGEX.LANGUAGE_SIMPLE.exec(firstline); + const regexResult_languageComplicate = REGEX.LANGUAGE_COMPLICATE.exec(firstline); + if (regexResult_languageSimple) { + showLanguage = true; + } else if (regexResult_languageComplicate) { + if (regexResult_languageComplicate[1] === "true") { + showLanguage = true; + } else if (regexResult_languageComplicate[1] === "false") { + showLanguage = false; + } else { + showLanguage = true; + language = regexResult_languageComplicate[2] || regexResult_languageComplicate[3]; + } + } + let showCopyBtn = void 0; + const regexResult_copyBtnSimple = REGEX.COPYBTN_SIMPLE.exec(firstline); + const regexResult_copyBtnComplicate = REGEX.COPYBTN_COMPLICATE.exec(firstline); + if (regexResult_copyBtnSimple) { + showCopyBtn = true; + } else if (regexResult_copyBtnComplicate) { + if (regexResult_copyBtnComplicate[1] === "true") { + showCopyBtn = true; + } else if (regexResult_copyBtnComplicate[1] === "false") { + showCopyBtn = false; + } + } + let showPrompt = void 0; + let prompt = settings.defaultPrompt; + const regexResult_promptSimple = REGEX.PROMPT_SIMPLE.exec(firstline); + const regexResult_promptComplicate = REGEX.PROMPT_COMPLICATE.exec(firstline); + if (regexResult_promptSimple) { + showPrompt = true; + } else if (regexResult_promptComplicate) { + if (regexResult_promptComplicate[1] === "true") { + showPrompt = true; + } else if (regexResult_promptComplicate[1] === "false") { + showPrompt = false; + } else { + showPrompt = true; + prompt = regexResult_promptComplicate[2] || regexResult_promptComplicate[3]; + } + } + let isResult = false; + let resultPrompt = settings.defaultResultPrompt; + const regexResult_result = REGEX.RESULT.exec(firstline); + const regexResultPrompt_result = REGEX.PROMPT_COMPLICATE.exec(firstline); + if (regexResult_result) { + isResult = true; + showTitle = false; + showLanguage = false; + showCopyBtn = false; + showPrompt = false; + if (regexResultPrompt_result) { + resultPrompt = regexResultPrompt_result[2] || regexResultPrompt_result[3]; + } + } + return { + showTitle, + title, + showLinenos, + linenosStart, + linenosNum, + showHighlight, + highlightLines, + showLanguage, + language, + showCopyBtn, + isResult, + resultPrompt, + showPrompt, + prompt + }; +} +async function HKCodeBlockProcessor(el, context, plugin) { + const settings = plugin.settings; + const view = app.workspace.getActiveViewOfType(import_obsidian2.MarkdownView); + if (!view) + return; + const elem_code = el.querySelector("pre:not(.frontmatter) > code"); + if (!elem_code) + return; + const elem_pre = elem_code.parentElement; + if (!elem_pre) + return; + const elem_div = elem_pre.parentElement; + if (!elem_div) + return; + const elem_copyBtn = elem_div.querySelector(".copy-code-button"); + if (!elem_copyBtn) + return; + const section_code = context.getSectionInfo(elem_code); + if (!section_code) + return; + const { + showTitle, + title, + showLinenos, + linenosStart, + linenosNum, + showHighlight, + highlightLines, + showLanguage, + language, + showCopyBtn, + isResult, + resultPrompt, + showPrompt, + prompt + } = getMeta(view, elem_code, section_code, settings); + if (settings.debugMode) { + console.log({ + showTitle, + title, + showLinenos, + linenosStart, + linenosNum, + showHighlight, + highlightLines, + showLanguage, + language, + showCopyBtn, + isResult, + resultPrompt, + showPrompt, + prompt + }); + } + elem_div.classList.add("hk-codeblock"); + elem_code.classList.add("hk-codeblock-code"); + elem_copyBtn.remove(); + if (settings.useTitleGlobal === "default off, but on when specified" && showTitle === true) { + elem_div.classList.add("hk-codeblock-show-title"); + const elem_title = document.createElement("div"); + elem_title.classList.add("hk-codeblock-title"); + elem_title.innerHTML = title; + elem_div.insertBefore(elem_title, elem_pre); + } + if (settings.useLinenosGlobal === "always on" || settings.useLinenosGlobal === "default on, but off when specified" && (showLinenos === void 0 || showLinenos === true) || settings.useLinenosGlobal === "default off, but on when specified" && showLinenos === true) { + elem_div.classList.add("hk-codeblock-show-linenos"); + const elem_linenos = document.createElement("code"); + elem_linenos.classList.add("hk-codeblock-linenos"); + elem_linenos.innerText = Array(linenosNum).fill(0).map((_, idx) => idx + linenosStart).join("\n"); + elem_pre.insertBefore(elem_linenos, elem_code); + if (settings.showLinenosSplitter) { + elem_linenos.classList.add("show-splitter"); + } + } + if (settings.useHighlightGlobal === "default off, but on when specified" && showHighlight === true) { + elem_div.classList.add("hk-codeblock-show-highlight"); + elem_div.style.setProperty("--hk-codeblock-highlight-background-color", settings.highlightColor); + const elem_highlight = document.createElement("code"); + elem_highlight.classList.add("hk-codeblock-highlight"); + elem_highlight.innerHTML = Array(linenosNum).fill(0).map((_, idx) => { + const classNames = []; + if (highlightLines.includes(idx + linenosStart)) + classNames.push("highlight"); + return ` `; + }).join("\n"); + elem_pre.insertBefore(elem_highlight, elem_code); + } + if (settings.useLanguageGlobal === "always on" || settings.useLanguageGlobal === "default on, but off when specified" && (showLanguage === void 0 || showLanguage === true) || settings.useLanguageGlobal === "default off, but on when specified" && showLanguage === true) { + elem_div.classList.add("hk-codeblock-show-language"); + const elem_language = document.createElement("div"); + elem_language.classList.add("hk-codeblock-language"); + elem_language.innerText = language; + elem_pre.prepend(elem_language); + } + if (settings.useCopyBtnGlobal === "always on" || settings.useCopyBtnGlobal === "default on, but off when specified" && (showCopyBtn === void 0 || showCopyBtn === true) || settings.useCopyBtnGlobal === "default off, but on when specified" && showCopyBtn === true) { + elem_div.classList.add("hk-codeblock-show-copybtn"); + elem_pre.appendChild(elem_copyBtn); + } + if (settings.usePromptGlobal === "always on" && settings.promptingLanguages.includes(language) || settings.usePromptGlobal === "default on, but off when specified" && settings.promptingLanguages.includes(language) && (showPrompt === void 0 || showPrompt === true) || settings.usePromptGlobal === "default off, but on when specified" && showPrompt === true) { + elem_div.classList.add("hk-codeblock-show-prompt"); + let code_lines = elem_code.innerText.split("\n"); + if (code_lines[code_lines.length - 1].trim().length == 0) + code_lines.pop(); + const no_prompt_line_idxs = code_lines.map((line, idx) => { + if (line.trim().length == 0) + return idx + 1; + if (line.startsWith("#")) + return idx + 1; + return -1; + }).filter((idx) => idx != -1); + elem_pre.classList.add("command-line"); + elem_pre.setAttribute("data-prompt", prompt); + elem_pre.setAttribute("data-continuation-str", "\\"); + elem_pre.setAttribute("data-continuation-prompt", " ".repeat(prompt.length)); + elem_pre.setAttribute("data-output", no_prompt_line_idxs.join(", ")); + } + if (settings.useResultGlobal === "enable" && isResult === true) { + elem_div.classList.add("hk-codeblock-result"); + elem_code.classList.add("hk-codeblock-result-code"); + elem_div.setAttribute("data-result-prompt", resultPrompt); + } +} + +// src/prism-plugins/prism-command-line.js +function PrismPlugin_CommandLine(Prism) { + if (typeof Prism === "undefined" || typeof document === "undefined") { + return; + } + var CLASS_PATTERN = /(?:^|\s)command-line(?:\s|$)/; + var PROMPT_CLASS = "command-line-prompt"; + var startsWith = "".startsWith ? function(s, p) { + return s.startsWith(p); + } : function(s, p) { + return s.indexOf(p) === 0; + }; + var endsWith = "".endsWith ? function(str, suffix) { + return str.endsWith(suffix); + } : function(str, suffix) { + var len = str.length; + return str.substring(len - suffix.length, len) === suffix; + }; + function hasCommandLineInfo(env) { + var vars = env.vars = env.vars || {}; + return "command-line" in vars; + } + function getCommandLineInfo(env) { + var vars = env.vars = env.vars || {}; + return vars["command-line"] = vars["command-line"] || {}; + } + Prism.hooks.add("before-highlight", function(env) { + var commandLine = getCommandLineInfo(env); + if (commandLine.complete || !env.code) { + commandLine.complete = true; + return; + } + var pre = env.element.parentElement; + if (!pre || !/pre/i.test(pre.nodeName) || // Abort only if neither the
 nor the  have the class
+    !CLASS_PATTERN.test(pre.className) && !CLASS_PATTERN.test(env.element.className)) {
+      commandLine.complete = true;
+      return;
+    }
+    var existingPrompt = env.element.querySelector("." + PROMPT_CLASS);
+    if (existingPrompt) {
+      existingPrompt.remove();
+    }
+    var codeLines = env.code.split("\n");
+    if (codeLines[codeLines.length - 1].trim().length === 0) {
+      commandLine.numberOfLines = codeLines.length - 1;
+    } else {
+      commandLine.numberOfLines = codeLines.length;
+    }
+    var outputLines = commandLine.outputLines = [];
+    var outputSections = pre.getAttribute("data-output");
+    var outputFilter = pre.getAttribute("data-filter-output");
+    if (outputSections !== null) {
+      outputSections.split(",").forEach(function(section) {
+        var range = section.split("-");
+        var outputStart = parseInt(range[0], 10);
+        var outputEnd = range.length === 2 ? parseInt(range[1], 10) : outputStart;
+        if (!isNaN(outputStart) && !isNaN(outputEnd)) {
+          if (outputStart < 1) {
+            outputStart = 1;
+          }
+          if (outputEnd > codeLines.length) {
+            outputEnd = codeLines.length;
+          }
+          outputStart--;
+          outputEnd--;
+          for (var j2 = outputStart; j2 <= outputEnd; j2++) {
+            outputLines[j2] = codeLines[j2];
+            codeLines[j2] = "";
+          }
+        }
+      });
+    } else if (outputFilter) {
+      for (var i = 0; i < codeLines.length; i++) {
+        if (startsWith(codeLines[i], outputFilter)) {
+          outputLines[i] = codeLines[i].slice(outputFilter.length);
+          codeLines[i] = "";
+        }
+      }
+    }
+    var continuationLineIndicies = commandLine.continuationLineIndicies = /* @__PURE__ */ new Set();
+    var lineContinuationStr = pre.getAttribute("data-continuation-str");
+    var continuationFilter = pre.getAttribute("data-filter-continuation");
+    for (var j = 0; j < codeLines.length; j++) {
+      var line = codeLines[j];
+      if (!line) {
+        continue;
+      }
+      if (lineContinuationStr && endsWith(line, lineContinuationStr)) {
+        continuationLineIndicies.add(j + 1);
+      }
+      if (j > 0 && continuationFilter && startsWith(line, continuationFilter)) {
+        codeLines[j] = line.slice(continuationFilter.length);
+        continuationLineIndicies.add(j);
+      }
+    }
+    env.code = codeLines.join("\n");
+  });
+  Prism.hooks.add("before-insert", function(env) {
+    var commandLine = getCommandLineInfo(env);
+    if (commandLine.complete) {
+      return;
+    }
+    var codeLines = env.highlightedCode.split("\n");
+    var outputLines = commandLine.outputLines || [];
+    for (var i = 0, l = codeLines.length; i < l; i++) {
+      if (outputLines.hasOwnProperty(i)) {
+        codeLines[i] = '' + Prism.util.encode(outputLines[i]) + "";
+      } else {
+        codeLines[i] = '' + codeLines[i] + "";
+      }
+    }
+    env.highlightedCode = codeLines.join("\n");
+  });
+  Prism.hooks.add("complete", function(env) {
+    if (!hasCommandLineInfo(env)) {
+      return;
+    }
+    var commandLine = getCommandLineInfo(env);
+    if (commandLine.complete) {
+      return;
+    }
+    var pre = env.element.parentElement;
+    if (CLASS_PATTERN.test(env.element.className)) {
+      env.element.className = env.element.className.replace(CLASS_PATTERN, " ");
+    }
+    if (!CLASS_PATTERN.test(pre.className)) {
+      pre.className += " command-line";
+    }
+    function getAttribute(key, defaultValue) {
+      return (pre.getAttribute(key) || defaultValue).replace(/"/g, """);
+    }
+    var promptLines = "";
+    var rowCount = commandLine.numberOfLines || 0;
+    var promptText = getAttribute("data-prompt", "");
+    var promptLine;
+    if (promptText !== "") {
+      promptLine = '';
+    } else {
+      var user = getAttribute("data-user", "user");
+      var host = getAttribute("data-host", "localhost");
+      promptLine = '';
+    }
+    var continuationLineIndicies = commandLine.continuationLineIndicies || /* @__PURE__ */ new Set();
+    var continuationPromptText = getAttribute("data-continuation-prompt", ">");
+    var continuationPromptLine = '';
+    for (var j = 0; j < rowCount; j++) {
+      if (continuationLineIndicies.has(j)) {
+        promptLines += continuationPromptLine;
+      } else {
+        promptLines += promptLine;
+      }
+    }
+    var prompt = document.createElement("span");
+    prompt.className = PROMPT_CLASS;
+    prompt.innerHTML = promptLines;
+    var outputLines = commandLine.outputLines || [];
+    for (var i = 0, l = outputLines.length; i < l; i++) {
+      if (outputLines.hasOwnProperty(i)) {
+        var node = prompt.children[i];
+        node.removeAttribute("data-user");
+        node.removeAttribute("data-host");
+        node.removeAttribute("data-prompt");
+      }
+    }
+    env.element.insertBefore(prompt, env.element.firstChild);
+    commandLine.complete = true;
+  });
+}
+
+// src/main.ts
+var HKCodeBlockPlugin = class extends import_obsidian3.Plugin {
+  async onload() {
+    await this.loadSettings();
+    if (this.settings.debugMode) {
+      console.log("loading HKCodeBlock plugin");
+    }
+    const Prism = await (0, import_obsidian3.loadPrism)();
+    PrismPlugin_CommandLine(Prism);
+    this.addSettingTab(new HKCodeBlockSettingTab(this.app, this));
+    const processor = this.registerMarkdownPostProcessor((el, ctx) => {
+      HKCodeBlockProcessor(el, ctx, this);
+    });
+    processor.sortOrder = 100;
+  }
+  onunload() {
+    if (this.settings.debugMode) {
+      console.log("unloading HKCodeBlock plugin");
+    }
+  }
+  async loadSettings() {
+    this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
+  }
+  async saveSettings() {
+    await this.saveData(this.settings);
+  }
+};
+//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL21haW4udHMiLCAiLi4vc3JjL0hLQ29kZUJsb2NrU2V0dGluZ3MudHMiLCAiLi4vc3JjL0hLQ29kZUJsb2NrU2V0dGluZ1RhYi50cyIsICIuLi9zcmMvSEtDb2RlQmxvY2tQcm9jZXNzb3IudHMiLCAiLi4vc3JjL3ByaXNtLXBsdWdpbnMvcHJpc20tY29tbWFuZC1saW5lLmpzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyBQbHVnaW4sIGxvYWRQcmlzbSB9IGZyb20gJ29ic2lkaWFuJztcblxuaW1wb3J0IHR5cGUgeyBIS0NvZGVCbG9ja1NldHRpbmdzIH0gZnJvbSAnLi9IS0NvZGVCbG9ja1NldHRpbmdzJztcbmltcG9ydCB7IERFRkFVTFRfU0VUVElOR1MgfSBmcm9tICcuL0hLQ29kZUJsb2NrU2V0dGluZ3MnO1xuaW1wb3J0IHsgSEtDb2RlQmxvY2tTZXR0aW5nVGFiIH0gZnJvbSAnLi9IS0NvZGVCbG9ja1NldHRpbmdUYWInO1xuaW1wb3J0IHsgSEtDb2RlQmxvY2tQcm9jZXNzb3IgfSBmcm9tICcuL0hLQ29kZUJsb2NrUHJvY2Vzc29yJztcblxuaW1wb3J0IHsgUHJpc21QbHVnaW5fQ29tbWFuZExpbmUgfSBmcm9tICcuL3ByaXNtLXBsdWdpbnMvcHJpc20tY29tbWFuZC1saW5lJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSEtDb2RlQmxvY2tQbHVnaW4gZXh0ZW5kcyBQbHVnaW4ge1xuXHRzZXR0aW5nczogSEtDb2RlQmxvY2tTZXR0aW5ncztcblxuXHRhc3luYyBvbmxvYWQoKSB7XG5cdFx0YXdhaXQgdGhpcy5sb2FkU2V0dGluZ3MoKTtcblx0XHRpZiAodGhpcy5zZXR0aW5ncy5kZWJ1Z01vZGUpIHtcblx0XHRcdGNvbnNvbGUubG9nKFwibG9hZGluZyBIS0NvZGVCbG9jayBwbHVnaW5cIik7XG5cdFx0fVxuXG5cdFx0Y29uc3QgUHJpc20gPSBhd2FpdCBsb2FkUHJpc20oKTtcblxuXHRcdC8vIGFjdGl2YXRlIFByaXNtLmpzIHBsdWdpbnNcblx0XHRQcmlzbVBsdWdpbl9Db21tYW5kTGluZShQcmlzbSk7XG5cblx0XHQvLyByZWdpc3RlciBzZXR0aW5ncyB0YWJcblx0XHR0aGlzLmFkZFNldHRpbmdUYWIobmV3IEhLQ29kZUJsb2NrU2V0dGluZ1RhYih0aGlzLmFwcCwgdGhpcykpO1xuXG5cdFx0Ly8gcmVnaXN0ZXIgbWFya2Rvd24gcG9zdCBwcm9jZXNzb3Jcblx0XHRjb25zdCBwcm9jZXNzb3IgPSB0aGlzLnJlZ2lzdGVyTWFya2Rvd25Qb3N0UHJvY2Vzc29yKChlbCwgY3R4KSA9PiB7XG5cdFx0XHRIS0NvZGVCbG9ja1Byb2Nlc3NvcihlbCwgY3R4LCB0aGlzKTtcblx0XHR9KTtcblxuXHRcdHByb2Nlc3Nvci5zb3J0T3JkZXIgPSAxMDA7IC8vIHJ1biBhZnRlciB0aGUgZGVmYXVsdCBjb2RlIGJsb2NrIHByb2Nlc3NvclxuXHR9XG5cblx0b251bmxvYWQoKSB7XG5cdFx0aWYgKHRoaXMuc2V0dGluZ3MuZGVidWdNb2RlKSB7XG5cdFx0XHRjb25zb2xlLmxvZyhcInVubG9hZGluZyBIS0NvZGVCbG9jayBwbHVnaW5cIik7XG5cdFx0fVxuXHR9XG5cblx0YXN5bmMgbG9hZFNldHRpbmdzKCkge1xuXHRcdHRoaXMuc2V0dGluZ3MgPSBPYmplY3QuYXNzaWduKHt9LCBERUZBVUxUX1NFVFRJTkdTLCBhd2FpdCB0aGlzLmxvYWREYXRhKCkpO1xuXHR9XG5cblx0YXN5bmMgc2F2ZVNldHRpbmdzKCkge1xuXHRcdGF3YWl0IHRoaXMuc2F2ZURhdGEodGhpcy5zZXR0aW5ncyk7XG5cdH1cbn0iLCAiZXhwb3J0IGludGVyZmFjZSBIS0NvZGVCbG9ja1NldHRpbmdzIHtcblx0dXNlVGl0bGVHbG9iYWw6IChcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIiB8IFwiYWx3YXlzIG9mZlwiKTtcblxuXHR1c2VMaW5lbm9zR2xvYmFsOiAoXCJhbHdheXMgb25cIiB8IFwiZGVmYXVsdCBvbiwgYnV0IG9mZiB3aGVuIHNwZWNpZmllZFwiIHwgXCJkZWZhdWx0IG9mZiwgYnV0IG9uIHdoZW4gc3BlY2lmaWVkXCIgfCBcImFsd2F5cyBvZmZcIik7XG5cdGRlZmF1bHRMaW5lbm9zU3RhcnQ6IG51bWJlcjtcblx0c2hvd0xpbmVub3NTcGxpdHRlcjogYm9vbGVhbjtcblxuXHR1c2VIaWdobGlnaHRHbG9iYWw6IChcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIiB8IFwiYWx3YXlzIG9mZlwiKTtcblx0aGlnaGxpZ2h0Q29sb3I6IHN0cmluZztcblxuXHR1c2VMYW5ndWFnZUdsb2JhbDogKFwiYWx3YXlzIG9uXCIgfCBcImRlZmF1bHQgb24sIGJ1dCBvZmYgd2hlbiBzcGVjaWZpZWRcIiB8IFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiIHwgXCJhbHdheXMgb2ZmXCIpO1xuXHRkZWZhdWx0TGFuZ3VhZ2U6IHN0cmluZztcblx0XG5cdHVzZUNvcHlCdG5HbG9iYWw6IChcImFsd2F5cyBvblwiIHwgXCJkZWZhdWx0IG9uLCBidXQgb2ZmIHdoZW4gc3BlY2lmaWVkXCIgfCBcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIiB8IFwiYWx3YXlzIG9mZlwiKTtcblx0XG5cdHVzZVByb21wdEdsb2JhbDogKFwiYWx3YXlzIG9uXCIgfCBcImRlZmF1bHQgb24sIGJ1dCBvZmYgd2hlbiBzcGVjaWZpZWRcIiB8IFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiIHwgXCJhbHdheXMgb2ZmXCIpO1xuXHRkZWZhdWx0UHJvbXB0OiBzdHJpbmc7XG5cdFxuXHR1c2VSZXN1bHRHbG9iYWw6IChcImVuYWJsZVwiIHwgXCJkaXNhYmxlXCIpO1xuXHRwcm9tcHRpbmdMYW5ndWFnZXM6IHN0cmluZ1tdO1xuXHRkZWZhdWx0UmVzdWx0UHJvbXB0OiBzdHJpbmc7XG5cblx0ZGVidWdNb2RlOiBib29sZWFuO1xufVxuXG5leHBvcnQgY29uc3QgREVGQVVMVF9TRVRUSU5HUzogSEtDb2RlQmxvY2tTZXR0aW5ncyA9IHtcblx0dXNlVGl0bGVHbG9iYWw6IFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiLFxuXG5cdHVzZUxpbmVub3NHbG9iYWw6IFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiLFxuXHRkZWZhdWx0TGluZW5vc1N0YXJ0OiAxLFxuXHRzaG93TGluZW5vc1NwbGl0dGVyOiB0cnVlLFxuXG5cdHVzZUhpZ2hsaWdodEdsb2JhbDogXCJkZWZhdWx0IG9mZiwgYnV0IG9uIHdoZW4gc3BlY2lmaWVkXCIsXG5cdGhpZ2hsaWdodENvbG9yOiBcIiNmZjAwMDBcIixcblxuXHR1c2VMYW5ndWFnZUdsb2JhbDogXCJkZWZhdWx0IG9uLCBidXQgb2ZmIHdoZW4gc3BlY2lmaWVkXCIsXG5cdGRlZmF1bHRMYW5ndWFnZTogXCJwbGFpbiB0ZXh0XCIsXG5cblx0dXNlQ29weUJ0bkdsb2JhbDogXCJkZWZhdWx0IG9uLCBidXQgb2ZmIHdoZW4gc3BlY2lmaWVkXCIsXG5cblx0dXNlUHJvbXB0R2xvYmFsOiBcImRlZmF1bHQgb24sIGJ1dCBvZmYgd2hlbiBzcGVjaWZpZWRcIixcblx0cHJvbXB0aW5nTGFuZ3VhZ2VzOiBbXCJiYXNoXCJdLFxuXHRkZWZhdWx0UHJvbXB0OiBcIiRcIixcblxuXHR1c2VSZXN1bHRHbG9iYWw6IFwiZW5hYmxlXCIsXG5cdGRlZmF1bHRSZXN1bHRQcm9tcHQ6IFwiUmVzdWx0XCIsXG5cblx0ZGVidWdNb2RlOiBmYWxzZSxcbn0iLCAiaW1wb3J0IHsgQXBwLCBQbHVnaW5TZXR0aW5nVGFiLCBTZXR0aW5nIH0gZnJvbSAnb2JzaWRpYW4nO1xuXG5pbXBvcnQgSEtDb2RlQmxvY2tQbHVnaW4gZnJvbSAnLi9tYWluJztcblxuZXhwb3J0IGNvbnN0IGZyYWdXaXRoSFRNTCA9ICh0ZXh0OiBzdHJpbmcpID0+IHtcblx0cmV0dXJuIGNyZWF0ZUZyYWdtZW50KChmcmFnKSA9PiB7XG5cdFx0ZnJhZy5jcmVhdGVEaXYoKS5pbm5lckhUTUwgPSB0ZXh0LnNwbGl0KFwiXFxuXCIpLm1hcCgobGluZSkgPT4gbGluZS50cmltKCkpLmpvaW4oXCI8YnI+XCIpO1xuXHR9KTtcbn1cblxuZXhwb3J0IGNsYXNzIEhLQ29kZUJsb2NrU2V0dGluZ1RhYiBleHRlbmRzIFBsdWdpblNldHRpbmdUYWIge1xuXHRwbHVnaW46IEhLQ29kZUJsb2NrUGx1Z2luO1xuXG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBwbHVnaW46IEhLQ29kZUJsb2NrUGx1Z2luKSB7XG5cdFx0c3VwZXIoYXBwLCBwbHVnaW4pO1xuXHRcdHRoaXMucGx1Z2luID0gcGx1Z2luO1xuXHR9XG5cblx0ZGlzcGxheSgpOiB2b2lkIHtcblx0XHRjb25zdCB7IGNvbnRhaW5lckVsIH0gPSB0aGlzO1xuXHRcdGNvbnRhaW5lckVsLmVtcHR5KCk7XG5cblx0XHQvLyB0aXRsZVxuXHRcdGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMicsIHsgdGV4dDogJ1RpdGxlJyB9KTtcblxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdFx0LnNldE5hbWUoJ1VzZSBUaXRsZScpXG5cdFx0XHQuc2V0RGVzYyhmcmFnV2l0aEhUTUwoYC0gPGI+ZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZDwvYj4gOiB0aGUgdGl0bGUgd2lsbCBvbmx5IGJlIHNob3duIGlmIHRoZSB0aXRsZSBzdGF0ZW1lbnQgaXMgc3BlY2lmaWVkXG5cdFx0XHRcdC0gPGI+YWx3YXlzIG9mZjwvYj4gOiB0aGUgdGl0bGUgd2lsbCBuZXZlciBiZSBzaG93bmApKVxuXHRcdFx0LmFkZERyb3Bkb3duKHRjID0+XG5cdFx0XHRcdHRjLmFkZE9wdGlvbnMoe1xuXHRcdFx0XHRcdFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiOiBcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIixcblx0XHRcdFx0XHRcImFsd2F5cyBvZmZcIjogXCJhbHdheXMgb2ZmXCIsXG5cdFx0XHRcdH0pXG5cdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnVzZVRpdGxlR2xvYmFsKVxuXHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWU6IHN0cmluZykgPT4ge1xuXHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MudXNlVGl0bGVHbG9iYWwgPSB2YWx1ZSBhcyAoXCJkZWZhdWx0IG9mZiwgYnV0IG9uIHdoZW4gc3BlY2lmaWVkXCIgfCBcImFsd2F5cyBvZmZcIik7XG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHR9KVxuXHRcdFx0KTtcblxuXHRcdC8vIGxpbmUgbnVtYmVyc1xuXHRcdGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMicsIHsgdGV4dDogJ0xpbmUgTnVtYmVycycgfSk7XG5cblx0XHRuZXcgU2V0dGluZyhjb250YWluZXJFbClcblx0XHRcdC5zZXROYW1lKCdVc2UgTGluZSBOdW1iZXJzJylcblx0XHRcdC5zZXREZXNjKGZyYWdXaXRoSFRNTChgLSA8Yj5hbHdheXMgb248L2I+IDogbGluZSBudW1iZXJzIHdpbGwgYWx3YXlzIGJlIHNob3duXG5cdFx0XHRcdC0gPGI+ZGVmYXVsdCBvbiwgYnV0IG9mZiB3aGVuIHNwZWNpZmllZDwvYj4gOiBsaW5lIG51bWJlcnMgd2lsbCBhbHdheXMgYmUgc2hvd24sIGJ1dCB3aWxsIG5vdCBiZSBzaG93biBpZiBsaW5lbm9zIHN0YXRlbWVudCBpcyBzcGVjaWZpZWQgYXMgZmFsc2Vcblx0XHRcdFx0LSA8Yj5kZWZhdWx0IG9mZiwgYnV0IG9uIHdoZW4gc3BlY2lmaWVkPC9iPiA6IGxpbmUgbnVtYmVycyB3aWxsIG9ubHkgYmUgc2hvd24gaWYgdGhlIGxpbmVub3Mgc3RhdGVtZW50IGlzIHNwZWNpZmllZCBhcyB0cnVlXG5cdFx0XHRcdC0gPGI+YWx3YXlzIG9mZjwvYj4gOiBsaW5lIG51bWJlcnMgd2lsbCBuZXZlciBiZSBzaG93bmApKVxuXHRcdFx0LmFkZERyb3Bkb3duKHRjID0+XG5cdFx0XHRcdHRjLmFkZE9wdGlvbnMoe1xuXHRcdFx0XHRcdFwiYWx3YXlzIG9uXCI6IFwiYWx3YXlzIG9uXCIsXG5cdFx0XHRcdFx0XCJkZWZhdWx0IG9uLCBidXQgb2ZmIHdoZW4gc3BlY2lmaWVkXCI6IFwiZGVmYXVsdCBvbiwgYnV0IG9mZiB3aGVuIHNwZWNpZmllZFwiLFxuXHRcdFx0XHRcdFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiOiBcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIixcblx0XHRcdFx0XHRcImFsd2F5cyBvZmZcIjogXCJhbHdheXMgb2ZmXCIsXG5cdFx0XHRcdH0pXG5cdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnVzZUxpbmVub3NHbG9iYWwpXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy51c2VMaW5lbm9zR2xvYmFsID0gdmFsdWUgYXMgKFwiYWx3YXlzIG9uXCIgfCBcImRlZmF1bHQgb24sIGJ1dCBvZmYgd2hlbiBzcGVjaWZpZWRcIiB8IFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiIHwgXCJhbHdheXMgb2ZmXCIpO1xuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0fSlcblx0XHRcdCk7XG5cblx0XHRuZXcgU2V0dGluZyhjb250YWluZXJFbClcblx0XHRcdC5zZXROYW1lKCdEZWZhdWx0IExpbmUgTnVtYmVyIFN0YXJ0Jylcblx0XHRcdC5zZXREZXNjKCdUaGUgZGVmYXVsdCBsaW5lIG51bWJlciBzdGFydCBvZiB0aGUgY29kZSBibG9jay4nKVxuXHRcdFx0LmFkZFRleHQodGMgPT5cblx0XHRcdFx0dGMuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZGVmYXVsdExpbmVub3NTdGFydC50b1N0cmluZygpKVxuXHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWU6IHN0cmluZykgPT4ge1xuXHRcdFx0XHRcdFx0Y29uc3QgbnVtID0gcGFyc2VJbnQodmFsdWUpO1xuXHRcdFx0XHRcdFx0aWYgKGlzTmFOKG51bSkpIHJldHVybjtcblxuXHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuZGVmYXVsdExpbmVub3NTdGFydCA9IG51bTtcblx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdH0pXG5cdFx0XHQpO1xuXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG5cdFx0XHQuc2V0TmFtZSgnU2hvdyBMaW5lIE51bWJlciBTcGxpdHRlcicpXG5cdFx0XHQuYWRkVG9nZ2xlKHRjID0+XG5cdFx0XHRcdHRjLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnNob3dMaW5lbm9zU3BsaXR0ZXIpXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogYm9vbGVhbikgPT4ge1xuXHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3Muc2hvd0xpbmVub3NTcGxpdHRlciA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0fSlcblx0XHRcdCk7XG5cblx0XHQvLyBsaW5lIGhpZ2hsaWdodFxuXHRcdGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMicsIHsgdGV4dDogJ0xpbmUgSGlnaGxpZ2h0JyB9KTtcblxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdFx0LnNldE5hbWUoJ1VzZSBMaW5lIEhpZ2hsaWdodCcpXG5cdFx0XHQuc2V0RGVzYyhmcmFnV2l0aEhUTUwoYC0gPGI+ZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZDwvYj4gOiBsaW5lIGhpZ2hsaWdodCB3aWxsIG9ubHkgYmUgc2hvd24gaWYgdGhlIGxpbmUgaGlnaGxpZ2h0IHN0YXRlbWVudCBpcyBzcGVjaWZpZWRcblx0XHRcdFx0LSA8Yj5hbHdheXMgb2ZmPC9iPiA6IGxpbmUgaGlnaGxpZ2h0IHdpbGwgbmV2ZXIgYmUgc2hvd25gKSlcblx0XHRcdC5hZGREcm9wZG93bih0YyA9PlxuXHRcdFx0XHR0Yy5hZGRPcHRpb25zKHtcblx0XHRcdFx0XHRcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIjogXCJkZWZhdWx0IG9mZiwgYnV0IG9uIHdoZW4gc3BlY2lmaWVkXCIsXG5cdFx0XHRcdFx0XCJhbHdheXMgb2ZmXCI6IFwiYWx3YXlzIG9mZlwiLFxuXHRcdFx0XHR9KVxuXHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy51c2VIaWdobGlnaHRHbG9iYWwpXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy51c2VIaWdobGlnaHRHbG9iYWwgPSB2YWx1ZSBhcyAoXCJkZWZhdWx0IG9mZiwgYnV0IG9uIHdoZW4gc3BlY2lmaWVkXCIgfCBcImFsd2F5cyBvZmZcIik7XG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHR9KVxuXHRcdFx0KTtcblxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdFx0LnNldE5hbWUoJ0xpbmUgSGlnaGxpZ2h0IENvbG9yJylcblx0XHRcdC5zZXREZXNjKCdUaGUgYmFja2dyb3VuZCBjb2xvciBvZiB0aGUgaGlnaGxpZ2h0ZWQgbGluZS4gTm90ZSB0aGF0IHRoZSBnaXZlbiBjb2xvciB3aWxsIGJlIGFwcGxpZWQgd2l0aCAwLjIgb3BhY2l0eS4nKVxuXHRcdFx0LmFkZFRleHQodGMgPT5cblx0XHRcdFx0dGMuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuaGlnaGxpZ2h0Q29sb3IpXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5oaWdobGlnaHRDb2xvciA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0fSlcblx0XHRcdCk7XG5cblx0XHQvLyBsYW5ndWFnZVxuXHRcdGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMicsIHsgdGV4dDogJ0xhbmd1YWdlIEluZGljYXRvcicgfSk7XG5cblx0XHRuZXcgU2V0dGluZyhjb250YWluZXJFbClcblx0XHRcdC5zZXROYW1lKCdVc2UgTGFuZ3VhZ2UgSW5kaWNhdG9yJylcblx0XHRcdC5zZXREZXNjKGZyYWdXaXRoSFRNTChgLSA8Yj5hbHdheXMgb248L2I+IDogbGFuZ3VhZ2UgaW5kaWNhdG9yIHdpbGwgYWx3YXlzIGJlIHNob3duXG5cdFx0XHRcdC0gPGI+ZGVmYXVsdCBvbiwgYnV0IG9mZiB3aGVuIHNwZWNpZmllZDwvYj4gOiBsYW5ndWFnZSBpbmRpY2F0b3Igd2lsbCBhbHdheXMgYmUgc2hvd24sIGJ1dCB3aWxsIG5vdCBiZSBzaG93biBpZiB0aGUgbGFuZ3VhZ2UgaW5kaWNhdG9yIHN0YXRlbWVudCBpcyBzcGVjaWZpZWQgYXMgZmFsc2Vcblx0XHRcdFx0LSA8Yj5kZWZhdWx0IG9mZiwgYnV0IG9uIHdoZW4gc3BlY2lmaWVkPC9iPiA6IGxhbmd1YWdlIGluZGljYXRvciB3aWxsIG9ubHkgYmUgc2hvd24gaWYgdGhlIGxhbmd1YWdlIGluZGljYXRvciBzdGF0ZW1lbnQgaXMgc3BlY2lmaWVkIGFzIHRydWVcblx0XHRcdFx0LSA8Yj5hbHdheXMgb2ZmPC9iPiA6IGxhbmd1YWdlIGluZGljYXRvciB3aWxsIG5ldmVyIGJlIHNob3duYCkpXG5cdFx0XHQuYWRkRHJvcGRvd24odGMgPT5cblx0XHRcdFx0dGMuYWRkT3B0aW9ucyh7XG5cdFx0XHRcdFx0XCJhbHdheXMgb25cIjogXCJhbHdheXMgb25cIixcblx0XHRcdFx0XHRcImRlZmF1bHQgb24sIGJ1dCBvZmYgd2hlbiBzcGVjaWZpZWRcIjogXCJkZWZhdWx0IG9uLCBidXQgb2ZmIHdoZW4gc3BlY2lmaWVkXCIsXG5cdFx0XHRcdFx0XCJkZWZhdWx0IG9mZiwgYnV0IG9uIHdoZW4gc3BlY2lmaWVkXCI6IFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiLFxuXHRcdFx0XHRcdFwiYWx3YXlzIG9mZlwiOiBcImFsd2F5cyBvZmZcIixcblx0XHRcdFx0fSlcblx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MudXNlTGFuZ3VhZ2VHbG9iYWwpXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy51c2VMYW5ndWFnZUdsb2JhbCA9IHZhbHVlIGFzIChcImFsd2F5cyBvblwiIHwgXCJkZWZhdWx0IG9uLCBidXQgb2ZmIHdoZW4gc3BlY2lmaWVkXCIgfCBcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIiB8IFwiYWx3YXlzIG9mZlwiKTtcblx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdH0pXG5cdFx0XHQpO1xuXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG5cdFx0XHQuc2V0TmFtZSgnRGVmYXVsdCBMYW5ndWFnZScpXG5cdFx0XHQuc2V0RGVzYygnVGhlIGRlZmF1bHQgbGFuZ3VhZ2UgbmFtZSBvZiB0aGUgY29kZSBibG9jayBpZiB0aGUgbGFuZ3VhZ2UgaXMgbm90IHNwZWNpZmllZC4nKVxuXHRcdFx0LmFkZFRleHQodGMgPT5cblx0XHRcdFx0dGMuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZGVmYXVsdExhbmd1YWdlKVxuXHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWU6IHN0cmluZykgPT4ge1xuXHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuZGVmYXVsdExhbmd1YWdlID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHR9KVxuXHRcdFx0KTtcblx0XHRcblx0XHQvLyBjb3B5IGJ1dHRvblxuXHRcdGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMicsIHsgdGV4dDogJ0NvcHkgQnV0dG9uJyB9KTtcblxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdFx0LnNldE5hbWUoJ1VzZSBDb3B5IEJ1dHRvbicpXG5cdFx0XHQuc2V0RGVzYyhmcmFnV2l0aEhUTUwoYC0gPGI+YWx3YXlzIG9uPC9iPiA6IGNvcHkgYnV0dG9uIHdpbGwgYWx3YXlzIGJlIHNob3duXG5cdFx0XHRcdC0gPGI+ZGVmYXVsdCBvbiwgYnV0IG9mZiB3aGVuIHNwZWNpZmllZDwvYj4gOiBjb3B5IGJ1dHRvbiB3aWxsIGFsd2F5cyBiZSBzaG93biwgYnV0IHdpbGwgbm90IGJlIHNob3duIGlmIHRoZSBjb3B5IGJ1dHRvbiBzdGF0ZW1lbnQgaXMgc3BlY2lmaWVkIGFzIGZhbHNlXG5cdFx0XHRcdC0gPGI+ZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZDwvYj4gOiBjb3B5IGJ1dHRvbiB3aWxsIG9ubHkgYmUgc2hvd24gaWYgdGhlIGNvcHkgYnV0dG9uIHN0YXRlbWVudCBpcyBzcGVjaWZpZWQgYXMgdHJ1ZVxuXHRcdFx0XHQtIDxiPmFsd2F5cyBvZmY8L2I+IDogY29weSBidXR0b24gd2lsbCBuZXZlciBiZSBzaG93bmApKVxuXHRcdFx0LmFkZERyb3Bkb3duKHRjID0+XG5cdFx0XHRcdHRjLmFkZE9wdGlvbnMoe1xuXHRcdFx0XHRcdFwiYWx3YXlzIG9uXCI6IFwiYWx3YXlzIG9uXCIsXG5cdFx0XHRcdFx0XCJkZWZhdWx0IG9uLCBidXQgb2ZmIHdoZW4gc3BlY2lmaWVkXCI6IFwiZGVmYXVsdCBvbiwgYnV0IG9mZiB3aGVuIHNwZWNpZmllZFwiLFxuXHRcdFx0XHRcdFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiOiBcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIixcblx0XHRcdFx0XHRcImFsd2F5cyBvZmZcIjogXCJhbHdheXMgb2ZmXCIsXG5cdFx0XHRcdH0pXG5cdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnVzZUNvcHlCdG5HbG9iYWwpXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy51c2VDb3B5QnRuR2xvYmFsID0gdmFsdWUgYXMgKFwiYWx3YXlzIG9uXCIgfCBcImRlZmF1bHQgb24sIGJ1dCBvZmYgd2hlbiBzcGVjaWZpZWRcIiB8IFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiIHwgXCJhbHdheXMgb2ZmXCIpO1xuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0fSlcblx0XHRcdCk7XG5cblx0XHQvLyBwcm9tcHRcblx0XHRjb250YWluZXJFbC5jcmVhdGVFbCgnaDInLCB7IHRleHQ6ICdQcm9tcHQnIH0pO1xuXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG5cdFx0XHQuc2V0TmFtZSgnVXNlIFByb21wdCcpXG5cdFx0XHQuc2V0RGVzYyhmcmFnV2l0aEhUTUwoYC0gPGI+YWx3YXlzIG9uPC9iPiA6IHByb21wdCB3aWxsIGFsd2F5cyBiZSBzaG93blxuXHRcdFx0XHQtIDxiPmRlZmF1bHQgb24sIGJ1dCBvZmYgd2hlbiBzcGVjaWZpZWQ8L2I+IDogcHJvbXB0IHdpbGwgYWx3YXlzIGJlIHNob3duLCBidXQgd2lsbCBub3QgYmUgc2hvd24gaWYgdGhlIHByb21wdCBzdGF0ZW1lbnQgaXMgc3BlY2lmaWVkIGFzIGZhbHNlXG5cdFx0XHRcdC0gPGI+ZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZDwvYj4gOiBwcm9tcHQgd2lsbCBvbmx5IGJlIHNob3duIGlmIHRoZSBwcm9tcHQgc3RhdGVtZW50IGlzIHNwZWNpZmllZCBhcyB0cnVlXG5cdFx0XHRcdC0gPGI+YWx3YXlzIG9mZjwvYj4gOiBwcm9tcHQgd2lsbCBuZXZlciBiZSBzaG93blxuXHRcdFx0XHRZb3UgY2FuIGFsc28gc3BlY2lmeSB0aGUgcHJvbXB0IGJ5IHRoZSBzdGF0ZW1lbnQgbGlrZSBcXGBwcm9tcHQ6XCJNeSBQcm9tcHRcIlxcYC4gKGRlZmF1bHQ6IFwiJFwiKWApKVxuXHRcdFx0LmFkZERyb3Bkb3duKHRjID0+XG5cdFx0XHRcdHRjLmFkZE9wdGlvbnMoe1xuXHRcdFx0XHRcdFwiYWx3YXlzIG9uXCI6IFwiYWx3YXlzIG9uXCIsXG5cdFx0XHRcdFx0XCJkZWZhdWx0IG9uLCBidXQgb2ZmIHdoZW4gc3BlY2lmaWVkXCI6IFwiZGVmYXVsdCBvbiwgYnV0IG9mZiB3aGVuIHNwZWNpZmllZFwiLFxuXHRcdFx0XHRcdFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiOiBcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIixcblx0XHRcdFx0XHRcImFsd2F5cyBvZmZcIjogXCJhbHdheXMgb2ZmXCIsXG5cdFx0XHRcdH0pXG5cdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnVzZVByb21wdEdsb2JhbClcblx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBzdHJpbmcpID0+IHtcblx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnVzZVByb21wdEdsb2JhbCA9IHZhbHVlIGFzIChcImFsd2F5cyBvblwiIHwgXCJkZWZhdWx0IG9uLCBidXQgb2ZmIHdoZW4gc3BlY2lmaWVkXCIgfCBcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIiB8IFwiYWx3YXlzIG9mZlwiKTtcblx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdH0pXG5cdFx0XHQpO1xuXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG5cdFx0XHQuc2V0TmFtZSgnUHJvbXB0aW5nIExhbmd1YWdlcycpXG5cdFx0XHQuc2V0RGVzYygnVGhlIGxhbmd1YWdlcyB0aGF0IHdpbGwgYmUgcHJvbXB0ZWQgYnkgZGVmYXVsdC4gWW91IGNhbiBzcGVjaWZ5IG11bHRpcGxlIGxhbmd1YWdlcyBieSBzZXBhcmF0aW5nIHRoZW0gd2l0aCBlbnRlcnMuJylcblx0XHRcdC5hZGRUZXh0QXJlYSh0YyA9PlxuXHRcdFx0XHR0Yy5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5wcm9tcHRpbmdMYW5ndWFnZXMuam9pbihcIlxcblwiKSlcblx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlOiBzdHJpbmcpID0+IHtcblx0XHRcdFx0XHRcdGNvbnN0IGxpbmVzID0gdmFsdWUuc3BsaXQoXCJcXG5cIikuZmlsdGVyKGxpbmUgPT4gbGluZS50cmltKCkgIT09IFwiXCIpO1xuXHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MucHJvbXB0aW5nTGFuZ3VhZ2VzID0gbGluZXM7XG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHR9KVxuXHRcdFx0KTtcblxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdFx0LnNldE5hbWUoXCJEZWZhdWx0IFByb21wdFwiKVxuXHRcdFx0LnNldERlc2MoXCJUaGUgZGVmYXVsdCBwcm9tcHQgb2YgdGhlIGJhc2ggY29kZSBibG9jay5cIilcblx0XHRcdC5hZGRUZXh0KHRjID0+XG5cdFx0XHRcdHRjLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmRlZmF1bHRQcm9tcHQpXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5kZWZhdWx0UHJvbXB0ID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHR9KVxuXHRcdFx0KTtcblxuXHRcdC8vIHJlc3VsdFxuXHRcdGNvbnRhaW5lckVsLmNyZWF0ZUVsKCdoMicsIHsgdGV4dDogJ1Jlc3VsdCcgfSk7XG5cblx0XHRuZXcgU2V0dGluZyhjb250YWluZXJFbClcblx0XHRcdC5zZXROYW1lKCdVc2UgUmVzdWx0Jylcblx0XHRcdC5zZXREZXNjKGZyYWdXaXRoSFRNTChgLSA8Yj5lbmFibGU8L2I+IDogdHJlYXQgdGhlIGNvZGUgYmxvY2sgc3RhcnRzIGxpa2UgXFxgXFxgXFxgXFxgcmVzdWx0XFxgIGFzIHRoZSByZXN1bHQgb2YgdGhlIGFkamFjZW50IHByZXZpb3VzIGNvZGUgYmxvY2tcblx0XHRcdFx0LSA8Yj5kaXNhYmxlPC9iPiA6IHRyZWF0IHRoZSBjb2RlIGJsb2NrIHdpdGggXFxgcmVzdWx0XFxgIGFzIGl0cyBsYW5ndWFnZSBuYW1lIGFzIGEgbm9ybWFsIGNvZGUgYmxvY2tgKSlcblx0XHRcdC5hZGREcm9wZG93bih0YyA9PlxuXHRcdFx0XHR0Yy5hZGRPcHRpb25zKHtcblx0XHRcdFx0XHRcImVuYWJsZVwiOiBcImVuYWJsZVwiLFxuXHRcdFx0XHRcdFwiZGlzYWJsZVwiOiBcImRpc2FibGVcIixcblx0XHRcdFx0fSlcblx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MudXNlUmVzdWx0R2xvYmFsKVxuXHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWU6IHN0cmluZykgPT4ge1xuXHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MudXNlUmVzdWx0R2xvYmFsID0gdmFsdWUgYXMgKFwiZW5hYmxlXCIgfCBcImRpc2FibGVcIik7XG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHR9KVxuXHRcdFx0KTtcblxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdFx0LnNldE5hbWUoXCJEZWZhdWx0IFJlc3VsdCBQcm9tcHRcIilcblx0XHRcdC5zZXREZXNjKFwiVGhlIGRlZmF1bHQgcHJvbXB0IG9mIHRoZSByZXN1bHQgY29kZSBibG9jay5cIilcblx0XHRcdC5hZGRUZXh0KHRjID0+XG5cdFx0XHRcdHRjLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmRlZmF1bHRSZXN1bHRQcm9tcHQpXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5kZWZhdWx0UmVzdWx0UHJvbXB0ID0gdmFsdWU7XG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlU2V0dGluZ3MoKTtcblx0XHRcdFx0XHR9KVxuXHRcdFx0KTtcblxuXHRcdC8vIGZvciBkZXZlbG9wZXJzXG5cdFx0Y29udGFpbmVyRWwuY3JlYXRlRWwoJ2gyJywgeyB0ZXh0OiAnRGV2ZWxvcGVycycgfSk7XG5cblx0XHRuZXcgU2V0dGluZyhjb250YWluZXJFbClcblx0XHRcdC5zZXROYW1lKCdEZWJ1ZyBNb2RlJylcblx0XHRcdC5zZXREZXNjKCdTaG93IGxvZ3MgaW4gdGhlIGNvbnNvbGUuJylcblx0XHRcdC5hZGRUb2dnbGUodGMgPT5cblx0XHRcdFx0dGMuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MuZGVidWdNb2RlKVxuXHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWU6IGJvb2xlYW4pID0+IHtcblx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmRlYnVnTW9kZSA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0fSlcblx0XHRcdCk7XG5cdH1cbn0iLCAiaW1wb3J0IHsgTWFya2Rvd25WaWV3IH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5pbXBvcnQgdHlwZSB7IE1hcmtkb3duUG9zdFByb2Nlc3NvckNvbnRleHQsIE1hcmtkb3duU2VjdGlvbkluZm9ybWF0aW9uIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5cbmltcG9ydCBIS0NvZGVCbG9ja1BsdWdpbiBmcm9tIFwiLi9tYWluXCI7XG5pbXBvcnQgdHlwZSB7IEhLQ29kZUJsb2NrU2V0dGluZ3MgfSBmcm9tIFwiLi9IS0NvZGVCbG9ja1NldHRpbmdzXCI7XG5cbmNvbnN0IFJFR0VYID0ge1xuICBUSVRMRTogL1xcc3RpdGxlOig/OicoLio/KSd8XCIoLio/KVwiKVxccy8sXG4gIExJTkVOT1NfU0lNUExFOiAvXFxzbGluZW5vc1xccy8sXG4gIExJTkVOT1NfQ09NUExJQ0FURTogL1xcc2xpbmVub3M6KHRydWV8ZmFsc2V8KC17MCwxfVxcZCspKVxccy8sXG4gIEhJR0hMSUdIVDogL1xcc2hpZ2hsaWdodDooPzonKC4qPyknfFwiKC4qPylcIilcXHMvLFxuICBMQU5HVUFHRV9GUk9NX0NMQVNTOiAvXmxhbmd1YWdlLShcXHcrKSQvLFxuICBMQU5HVUFHRV9TSU1QTEU6IC9cXHNsYW5ndWFnZVxccy8sXG4gIExBTkdVQUdFX0NPTVBMSUNBVEU6IC9cXHNsYW5ndWFnZToodHJ1ZXxmYWxzZXwnKC4qPyknfFwiKC4qPylcIilcXHMvLFxuICBDT1BZQlROX1NJTVBMRTogL1xcc2NvcHlidG5cXHMvLFxuICBDT1BZQlROX0NPTVBMSUNBVEU6IC9cXHNjb3B5YnRuOih0cnVlfGZhbHNlKVxccy8sXG4gIFJFU1VMVDogL15gYGByZXN1bHRcXHMvLFxuICBQUk9NUFRfU0lNUExFOiAvXFxzcHJvbXB0XFxzLyxcbiAgUFJPTVBUX0NPTVBMSUNBVEU6IC9cXHNwcm9tcHQ6KHRydWV8ZmFsc2V8JyguKj8pJ3xcIiguKj8pXCIpXFxzLyxcbn1cblxuZnVuY3Rpb24gZ2V0TWV0YSh2aWV3OiBNYXJrZG93blZpZXcsIGVsZW1fY29kZTogSFRNTEVsZW1lbnQsIHNlY3Rpb25fY29kZTogTWFya2Rvd25TZWN0aW9uSW5mb3JtYXRpb24sIHNldHRpbmdzOiBIS0NvZGVCbG9ja1NldHRpbmdzKToge1xuICBzaG93VGl0bGU6IChib29sZWFuIHwgdW5kZWZpbmVkKSxcbiAgdGl0bGU6IHN0cmluZyxcbiAgc2hvd0xpbmVub3M6IChib29sZWFuIHwgdW5kZWZpbmVkKSxcbiAgbGluZW5vc1N0YXJ0OiBudW1iZXIsXG4gIGxpbmVub3NOdW06IG51bWJlcixcbiAgc2hvd0hpZ2hsaWdodDogKGJvb2xlYW4gfCB1bmRlZmluZWQpLFxuICBoaWdobGlnaHRMaW5lczogbnVtYmVyW10sXG4gIHNob3dMYW5ndWFnZTogKGJvb2xlYW4gfCB1bmRlZmluZWQpLFxuICBsYW5ndWFnZTogc3RyaW5nLFxuICBzaG93Q29weUJ0bjogKGJvb2xlYW4gfCB1bmRlZmluZWQpLFxuICBpc1Jlc3VsdDogYm9vbGVhbixcbiAgcmVzdWx0UHJvbXB0OiBzdHJpbmcsXG4gIHNob3dQcm9tcHQ6IChib29sZWFuIHwgdW5kZWZpbmVkKSxcbiAgcHJvbXB0OiBzdHJpbmdcbn0ge1xuICBjb25zdCBmaXJzdGxpbmUgPSB2aWV3LmVkaXRvci5nZXRMaW5lKHNlY3Rpb25fY29kZS5saW5lU3RhcnQpICsgXCIgXCI7IC8vIGFkZCBhIHNwYWNlIHRvIHRoZSBlbmQgb2YgdGhlIGxpbmUgdG8gbWFrZSBzdXJlIHRoZSByZWdleCB3b3Jrc1xuXG4gIC8vIHRpdGxlXG4gIGxldCBzaG93VGl0bGU6IChib29sZWFuIHwgdW5kZWZpbmVkKSA9IHVuZGVmaW5lZDtcbiAgbGV0IHRpdGxlID0gXCJcIjtcbiAgY29uc3QgcmVnZXhSZXN1bHRfdGl0bGUgPSBSRUdFWC5USVRMRS5leGVjKGZpcnN0bGluZSk7XG4gIGlmIChyZWdleFJlc3VsdF90aXRsZSkge1xuICAgIHNob3dUaXRsZSA9IHRydWU7XG4gICAgdGl0bGUgPSByZWdleFJlc3VsdF90aXRsZVsxXSB8fCByZWdleFJlc3VsdF90aXRsZVsyXTtcbiAgfVxuXG4gIC8vIGxpbmVub3NcbiAgbGV0IHNob3dMaW5lbm9zOiAoYm9vbGVhbiB8IHVuZGVmaW5lZCkgPSB1bmRlZmluZWQ7XG4gIGxldCBsaW5lbm9zU3RhcnQgPSBzZXR0aW5ncy5kZWZhdWx0TGluZW5vc1N0YXJ0O1xuICBjb25zdCBsaW5lbm9zTnVtID0gc2VjdGlvbl9jb2RlLmxpbmVFbmQgLSBzZWN0aW9uX2NvZGUubGluZVN0YXJ0IC0gMTtcbiAgY29uc3QgcmVnZXhSZXN1bHRfbGluZW5vc1NpbXBsZSA9IFJFR0VYLkxJTkVOT1NfU0lNUExFLmV4ZWMoZmlyc3RsaW5lKTtcbiAgY29uc3QgcmVnZXhSZXN1bHRfbGluZW5vc0NvbXBsaWNhdGUgPSBSRUdFWC5MSU5FTk9TX0NPTVBMSUNBVEUuZXhlYyhmaXJzdGxpbmUpO1xuICBpZiAocmVnZXhSZXN1bHRfbGluZW5vc1NpbXBsZSkge1xuICAgIHNob3dMaW5lbm9zID0gdHJ1ZTtcbiAgfSBlbHNlIGlmIChyZWdleFJlc3VsdF9saW5lbm9zQ29tcGxpY2F0ZSkge1xuICAgIGlmIChyZWdleFJlc3VsdF9saW5lbm9zQ29tcGxpY2F0ZVsxXSA9PT0gXCJ0cnVlXCIpIHtcbiAgICAgIHNob3dMaW5lbm9zID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHJlZ2V4UmVzdWx0X2xpbmVub3NDb21wbGljYXRlWzFdID09PSBcImZhbHNlXCIpIHtcbiAgICAgIHNob3dMaW5lbm9zID0gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNob3dMaW5lbm9zID0gdHJ1ZTtcbiAgICAgIGxpbmVub3NTdGFydCA9IHBhcnNlSW50KHJlZ2V4UmVzdWx0X2xpbmVub3NDb21wbGljYXRlWzJdKSB8fCAxO1xuICAgIH1cbiAgfVxuXG4gIC8vIGhpZ2hsaWdodFxuICBsZXQgc2hvd0hpZ2hsaWdodDogKGJvb2xlYW4gfCB1bmRlZmluZWQpID0gdW5kZWZpbmVkO1xuICBsZXQgaGlnaGxpZ2h0TGluZXM6IG51bWJlcltdID0gW107XG4gIGNvbnN0IHJlZ2V4UmVzdWx0X2hpZ2hsaWdodCA9IFJFR0VYLkhJR0hMSUdIVC5leGVjKGZpcnN0bGluZSk7XG4gIGlmIChyZWdleFJlc3VsdF9oaWdobGlnaHQpIHtcbiAgICBzaG93SGlnaGxpZ2h0ID0gdHJ1ZTtcbiAgICBjb25zdCBoaWdobGlnaHRMaW5lc19zdHIgPSByZWdleFJlc3VsdF9oaWdobGlnaHRbMV0gfHwgcmVnZXhSZXN1bHRfaGlnaGxpZ2h0WzJdO1xuICAgIGhpZ2hsaWdodExpbmVzID0gaGlnaGxpZ2h0TGluZXNfc3RyLnNwbGl0KFwiLFwiKS5tYXAoKGxpbmUpID0+IHBhcnNlSW50KGxpbmUpKTtcblxuICAgIGlmIChoaWdobGlnaHRMaW5lcy5zb21lKChsaW5lKSA9PiBpc05hTihsaW5lKSkpIHtcbiAgICAgIC8vIGlmIGFueSBlbGVtZW50IGlzIG5hbiwgdGhlbiBzZXQgc2hvd0hpZ2hsaWdodCB0byBmYWxzZVxuICAgICAgc2hvd0hpZ2hsaWdodCA9IHVuZGVmaW5lZDtcbiAgICAgIGhpZ2hsaWdodExpbmVzID0gW107XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHVzZSBvbmx5IHZhbGlkIGxpbmUgbnVtYmVyc1xuICAgICAgaGlnaGxpZ2h0TGluZXMgPSBoaWdobGlnaHRMaW5lcy5maWx0ZXIoKGxpbmUpID0+IGxpbmUgPj0gbGluZW5vc1N0YXJ0ICYmIGxpbmUgPCBsaW5lbm9zU3RhcnQgKyBsaW5lbm9zTnVtKTtcbiAgICB9XG4gIH1cblxuICAvLyBsYW5ndWFnZVxuICBsZXQgc2hvd0xhbmd1YWdlOiAoYm9vbGVhbiB8IHVuZGVmaW5lZCkgPSB1bmRlZmluZWQ7XG4gIGxldCBsYW5ndWFnZSA9ICgoKSA9PiB7XG4gICAgbGV0IGxhbmd1YWdlID0gc2V0dGluZ3MuZGVmYXVsdExhbmd1YWdlO1xuICAgIGVsZW1fY29kZS5jbGFzc0xpc3QuZm9yRWFjaCgoY2xhc3NOYW1lKSA9PiB7XG4gICAgICBjb25zdCByZWdleFJlc3VsdF9sYW5ndWFnZUZyb21DbGFzcyA9IFJFR0VYLkxBTkdVQUdFX0ZST01fQ0xBU1MuZXhlYyhjbGFzc05hbWUudHJpbSgpKTtcbiAgICAgIGlmIChyZWdleFJlc3VsdF9sYW5ndWFnZUZyb21DbGFzcykgbGFuZ3VhZ2UgPSByZWdleFJlc3VsdF9sYW5ndWFnZUZyb21DbGFzc1sxXTtcbiAgICB9KTtcblxuICAgIHJldHVybiBsYW5ndWFnZTtcbiAgfSkoKTtcbiAgY29uc3QgcmVnZXhSZXN1bHRfbGFuZ3VhZ2VTaW1wbGUgPSBSRUdFWC5MQU5HVUFHRV9TSU1QTEUuZXhlYyhmaXJzdGxpbmUpO1xuICBjb25zdCByZWdleFJlc3VsdF9sYW5ndWFnZUNvbXBsaWNhdGUgPSBSRUdFWC5MQU5HVUFHRV9DT01QTElDQVRFLmV4ZWMoZmlyc3RsaW5lKTtcbiAgaWYgKHJlZ2V4UmVzdWx0X2xhbmd1YWdlU2ltcGxlKSB7XG4gICAgc2hvd0xhbmd1YWdlID0gdHJ1ZTtcbiAgfSBlbHNlIGlmIChyZWdleFJlc3VsdF9sYW5ndWFnZUNvbXBsaWNhdGUpIHtcbiAgICBpZiAocmVnZXhSZXN1bHRfbGFuZ3VhZ2VDb21wbGljYXRlWzFdID09PSBcInRydWVcIikge1xuICAgICAgc2hvd0xhbmd1YWdlID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHJlZ2V4UmVzdWx0X2xhbmd1YWdlQ29tcGxpY2F0ZVsxXSA9PT0gXCJmYWxzZVwiKSB7XG4gICAgICBzaG93TGFuZ3VhZ2UgPSBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2hvd0xhbmd1YWdlID0gdHJ1ZTtcbiAgICAgIGxhbmd1YWdlID0gcmVnZXhSZXN1bHRfbGFuZ3VhZ2VDb21wbGljYXRlWzJdIHx8IHJlZ2V4UmVzdWx0X2xhbmd1YWdlQ29tcGxpY2F0ZVszXTtcbiAgICB9XG4gIH1cblxuICAvLyBjb3B5IGJ1dHRvblxuICBsZXQgc2hvd0NvcHlCdG46IChib29sZWFuIHwgdW5kZWZpbmVkKSA9IHVuZGVmaW5lZDtcbiAgY29uc3QgcmVnZXhSZXN1bHRfY29weUJ0blNpbXBsZSA9IFJFR0VYLkNPUFlCVE5fU0lNUExFLmV4ZWMoZmlyc3RsaW5lKTtcbiAgY29uc3QgcmVnZXhSZXN1bHRfY29weUJ0bkNvbXBsaWNhdGUgPSBSRUdFWC5DT1BZQlROX0NPTVBMSUNBVEUuZXhlYyhmaXJzdGxpbmUpO1xuICBpZiAocmVnZXhSZXN1bHRfY29weUJ0blNpbXBsZSkge1xuICAgIHNob3dDb3B5QnRuID0gdHJ1ZTtcbiAgfSBlbHNlIGlmIChyZWdleFJlc3VsdF9jb3B5QnRuQ29tcGxpY2F0ZSkge1xuICAgIGlmIChyZWdleFJlc3VsdF9jb3B5QnRuQ29tcGxpY2F0ZVsxXSA9PT0gXCJ0cnVlXCIpIHtcbiAgICAgIHNob3dDb3B5QnRuID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHJlZ2V4UmVzdWx0X2NvcHlCdG5Db21wbGljYXRlWzFdID09PSBcImZhbHNlXCIpIHtcbiAgICAgIHNob3dDb3B5QnRuID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLy8gcHJvbXB0XG4gIGxldCBzaG93UHJvbXB0OiAoYm9vbGVhbiB8IHVuZGVmaW5lZCkgPSB1bmRlZmluZWQ7XG4gIGxldCBwcm9tcHQgPSBzZXR0aW5ncy5kZWZhdWx0UHJvbXB0O1xuICBjb25zdCByZWdleFJlc3VsdF9wcm9tcHRTaW1wbGUgPSBSRUdFWC5QUk9NUFRfU0lNUExFLmV4ZWMoZmlyc3RsaW5lKTtcbiAgY29uc3QgcmVnZXhSZXN1bHRfcHJvbXB0Q29tcGxpY2F0ZSA9IFJFR0VYLlBST01QVF9DT01QTElDQVRFLmV4ZWMoZmlyc3RsaW5lKTtcbiAgaWYgKHJlZ2V4UmVzdWx0X3Byb21wdFNpbXBsZSkge1xuICAgIHNob3dQcm9tcHQgPSB0cnVlO1xuICB9IGVsc2UgaWYgKHJlZ2V4UmVzdWx0X3Byb21wdENvbXBsaWNhdGUpIHtcbiAgICBpZiAocmVnZXhSZXN1bHRfcHJvbXB0Q29tcGxpY2F0ZVsxXSA9PT0gXCJ0cnVlXCIpIHtcbiAgICAgIHNob3dQcm9tcHQgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAocmVnZXhSZXN1bHRfcHJvbXB0Q29tcGxpY2F0ZVsxXSA9PT0gXCJmYWxzZVwiKSB7XG4gICAgICBzaG93UHJvbXB0ID0gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNob3dQcm9tcHQgPSB0cnVlO1xuICAgICAgcHJvbXB0ID0gcmVnZXhSZXN1bHRfcHJvbXB0Q29tcGxpY2F0ZVsyXSB8fCByZWdleFJlc3VsdF9wcm9tcHRDb21wbGljYXRlWzNdO1xuICAgIH1cbiAgfVxuXG4gIC8vIHJlc3VsdFxuICBsZXQgaXNSZXN1bHQgPSBmYWxzZTtcbiAgbGV0IHJlc3VsdFByb21wdCA9IHNldHRpbmdzLmRlZmF1bHRSZXN1bHRQcm9tcHQ7XG4gIGNvbnN0IHJlZ2V4UmVzdWx0X3Jlc3VsdCA9IFJFR0VYLlJFU1VMVC5leGVjKGZpcnN0bGluZSk7XG4gIGNvbnN0IHJlZ2V4UmVzdWx0UHJvbXB0X3Jlc3VsdCA9IFJFR0VYLlBST01QVF9DT01QTElDQVRFLmV4ZWMoZmlyc3RsaW5lKTtcbiAgaWYgKHJlZ2V4UmVzdWx0X3Jlc3VsdCkge1xuICAgIGlzUmVzdWx0ID0gdHJ1ZTtcbiAgICBcbiAgICAvLyBvdmVycmlkZSBvdGhlciBtZXRhIGRhdGEgOiBvbmx5IGxpbmVub3MsIGhpZ2hsaWdodCBhcmUgYXZhaWxhYmxlXG4gICAgc2hvd1RpdGxlID0gZmFsc2U7XG4gICAgc2hvd0xhbmd1YWdlID0gZmFsc2U7XG4gICAgc2hvd0NvcHlCdG4gPSBmYWxzZTtcbiAgICBzaG93UHJvbXB0ID0gZmFsc2U7XG5cbiAgICBpZiAocmVnZXhSZXN1bHRQcm9tcHRfcmVzdWx0KSB7XG4gICAgICByZXN1bHRQcm9tcHQgPSByZWdleFJlc3VsdFByb21wdF9yZXN1bHRbMl0gfHwgcmVnZXhSZXN1bHRQcm9tcHRfcmVzdWx0WzNdO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgc2hvd1RpdGxlOiBzaG93VGl0bGUsXG4gICAgdGl0bGU6IHRpdGxlLFxuICAgIHNob3dMaW5lbm9zOiBzaG93TGluZW5vcyxcbiAgICBsaW5lbm9zU3RhcnQ6IGxpbmVub3NTdGFydCxcbiAgICBsaW5lbm9zTnVtOiBsaW5lbm9zTnVtLFxuICAgIHNob3dIaWdobGlnaHQ6IHNob3dIaWdobGlnaHQsXG4gICAgaGlnaGxpZ2h0TGluZXM6IGhpZ2hsaWdodExpbmVzLFxuICAgIHNob3dMYW5ndWFnZTogc2hvd0xhbmd1YWdlLFxuICAgIGxhbmd1YWdlOiBsYW5ndWFnZSxcbiAgICBzaG93Q29weUJ0bjogc2hvd0NvcHlCdG4sXG4gICAgaXNSZXN1bHQ6IGlzUmVzdWx0LFxuICAgIHJlc3VsdFByb21wdDogcmVzdWx0UHJvbXB0LFxuICAgIHNob3dQcm9tcHQ6IHNob3dQcm9tcHQsXG4gICAgcHJvbXB0OiBwcm9tcHRcbiAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIEhLQ29kZUJsb2NrUHJvY2Vzc29yKFxuICBlbDogSFRNTEVsZW1lbnQsXG4gIGNvbnRleHQ6IE1hcmtkb3duUG9zdFByb2Nlc3NvckNvbnRleHQsXG4gIHBsdWdpbjogSEtDb2RlQmxvY2tQbHVnaW5cbikge1xuICBjb25zdCBzZXR0aW5ncyA9IHBsdWdpbi5zZXR0aW5ncztcblxuICBjb25zdCB2aWV3ID0gYXBwLndvcmtzcGFjZS5nZXRBY3RpdmVWaWV3T2ZUeXBlKE1hcmtkb3duVmlldyk7XG4gIGlmICghdmlldykgcmV0dXJuO1xuXG4gIGNvbnN0IGVsZW1fY29kZTogKEhUTUxFbGVtZW50IHwgbnVsbCkgPSBlbC5xdWVyeVNlbGVjdG9yKFwicHJlOm5vdCguZnJvbnRtYXR0ZXIpID4gY29kZVwiKTtcbiAgaWYgKCFlbGVtX2NvZGUpIHJldHVybjtcblxuICBjb25zdCBlbGVtX3ByZTogKEhUTUxFbGVtZW50IHwgbnVsbCkgPSBlbGVtX2NvZGUucGFyZW50RWxlbWVudDtcbiAgaWYgKCFlbGVtX3ByZSkgcmV0dXJuO1xuXG4gIGNvbnN0IGVsZW1fZGl2OiAoSFRNTEVsZW1lbnQgfCBudWxsKSA9IGVsZW1fcHJlLnBhcmVudEVsZW1lbnQ7XG4gIGlmICghZWxlbV9kaXYpIHJldHVybjtcblxuICBjb25zdCBlbGVtX2NvcHlCdG46IChIVE1MRWxlbWVudCB8IG51bGwpID0gZWxlbV9kaXYucXVlcnlTZWxlY3RvcihcIi5jb3B5LWNvZGUtYnV0dG9uXCIpO1xuICBpZiAoIWVsZW1fY29weUJ0bikgcmV0dXJuO1xuXG4gIGNvbnN0IHNlY3Rpb25fY29kZTogKE1hcmtkb3duU2VjdGlvbkluZm9ybWF0aW9uIHwgbnVsbCkgPSBjb250ZXh0LmdldFNlY3Rpb25JbmZvKGVsZW1fY29kZSk7XG4gIGlmICghc2VjdGlvbl9jb2RlKSByZXR1cm47XG5cbiAgLy8gZ2V0IG1ldGFkYXRhXG4gIGNvbnN0IHsgXG4gICAgc2hvd1RpdGxlLFxuICAgIHRpdGxlLFxuICAgIHNob3dMaW5lbm9zLFxuICAgIGxpbmVub3NTdGFydCxcbiAgICBsaW5lbm9zTnVtLFxuICAgIHNob3dIaWdobGlnaHQsXG4gICAgaGlnaGxpZ2h0TGluZXMsXG4gICAgc2hvd0xhbmd1YWdlLFxuICAgIGxhbmd1YWdlLFxuICAgIHNob3dDb3B5QnRuLFxuICAgIGlzUmVzdWx0LFxuICAgIHJlc3VsdFByb21wdCxcbiAgICBzaG93UHJvbXB0LFxuICAgIHByb21wdFxuICB9ID0gZ2V0TWV0YSh2aWV3LCBlbGVtX2NvZGUsIHNlY3Rpb25fY29kZSwgc2V0dGluZ3MpO1xuXG4gIGlmIChzZXR0aW5ncy5kZWJ1Z01vZGUpIHtcbiAgICBjb25zb2xlLmxvZyh7IFxuICAgICAgc2hvd1RpdGxlOiBzaG93VGl0bGUsXG4gICAgICB0aXRsZTogdGl0bGUsXG4gICAgICBzaG93TGluZW5vczogc2hvd0xpbmVub3MsXG4gICAgICBsaW5lbm9zU3RhcnQ6IGxpbmVub3NTdGFydCxcbiAgICAgIGxpbmVub3NOdW06IGxpbmVub3NOdW0sXG4gICAgICBzaG93SGlnaGxpZ2h0OiBzaG93SGlnaGxpZ2h0LFxuICAgICAgaGlnaGxpZ2h0TGluZXM6IGhpZ2hsaWdodExpbmVzLFxuICAgICAgc2hvd0xhbmd1YWdlOiBzaG93TGFuZ3VhZ2UsXG4gICAgICBsYW5ndWFnZTogbGFuZ3VhZ2UsXG4gICAgICBzaG93Q29weUJ0bjogc2hvd0NvcHlCdG4sXG4gICAgICBpc1Jlc3VsdDogaXNSZXN1bHQsXG4gICAgICByZXN1bHRQcm9tcHQ6IHJlc3VsdFByb21wdCxcbiAgICAgIHNob3dQcm9tcHQ6IHNob3dQcm9tcHQsXG4gICAgICBwcm9tcHQ6IHByb21wdCxcbiAgICB9KVxuICB9XG5cbiAgLy8gY3JlYXRlIEhUTUwgZWxlbWVudHNcbiAgZWxlbV9kaXYuY2xhc3NMaXN0LmFkZChcImhrLWNvZGVibG9ja1wiKTtcbiAgZWxlbV9jb2RlLmNsYXNzTGlzdC5hZGQoXCJoay1jb2RlYmxvY2stY29kZVwiKTtcbiAgZWxlbV9jb3B5QnRuLnJlbW92ZSgpOyAvLyByZW1vdmUgdGhlIG9yaWdpbmFsIGNvcHkgYnV0dG9uIGFzIGRlZmF1bHRcblxuICBpZiAoc2V0dGluZ3MudXNlVGl0bGVHbG9iYWwgPT09IFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiICYmIChzaG93VGl0bGUgPT09IHRydWUpKSB7XG4gICAgZWxlbV9kaXYuY2xhc3NMaXN0LmFkZChcImhrLWNvZGVibG9jay1zaG93LXRpdGxlXCIpO1xuXG4gICAgY29uc3QgZWxlbV90aXRsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgZWxlbV90aXRsZS5jbGFzc0xpc3QuYWRkKFwiaGstY29kZWJsb2NrLXRpdGxlXCIpO1xuICAgIGVsZW1fdGl0bGUuaW5uZXJIVE1MID0gdGl0bGU7XG4gICAgZWxlbV9kaXYuaW5zZXJ0QmVmb3JlKGVsZW1fdGl0bGUsIGVsZW1fcHJlKTtcbiAgfVxuXG4gIGlmIChcbiAgICAoc2V0dGluZ3MudXNlTGluZW5vc0dsb2JhbCA9PT0gXCJhbHdheXMgb25cIikgfHxcbiAgICAoc2V0dGluZ3MudXNlTGluZW5vc0dsb2JhbCA9PT0gXCJkZWZhdWx0IG9uLCBidXQgb2ZmIHdoZW4gc3BlY2lmaWVkXCIgJiYgKHNob3dMaW5lbm9zID09PSB1bmRlZmluZWQgfHwgc2hvd0xpbmVub3MgPT09IHRydWUpKSB8fFxuICAgIChzZXR0aW5ncy51c2VMaW5lbm9zR2xvYmFsID09PSBcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIiAmJiAoc2hvd0xpbmVub3MgPT09IHRydWUpKVxuICApIHtcbiAgICBlbGVtX2Rpdi5jbGFzc0xpc3QuYWRkKFwiaGstY29kZWJsb2NrLXNob3ctbGluZW5vc1wiKTtcblxuICAgIGNvbnN0IGVsZW1fbGluZW5vcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjb2RlXCIpO1xuICAgIGVsZW1fbGluZW5vcy5jbGFzc0xpc3QuYWRkKFwiaGstY29kZWJsb2NrLWxpbmVub3NcIik7XG4gICAgZWxlbV9saW5lbm9zLmlubmVyVGV4dCA9IEFycmF5KGxpbmVub3NOdW0pLmZpbGwoMCkubWFwKChfLCBpZHgpID0+IGlkeCArIGxpbmVub3NTdGFydCkuam9pbihcIlxcblwiKTtcbiAgICBlbGVtX3ByZS5pbnNlcnRCZWZvcmUoZWxlbV9saW5lbm9zLCBlbGVtX2NvZGUpO1xuXG4gICAgaWYgKHNldHRpbmdzLnNob3dMaW5lbm9zU3BsaXR0ZXIpIHtcbiAgICAgIGVsZW1fbGluZW5vcy5jbGFzc0xpc3QuYWRkKFwic2hvdy1zcGxpdHRlclwiKTtcbiAgICB9XG4gIH1cblxuICBpZiAoc2V0dGluZ3MudXNlSGlnaGxpZ2h0R2xvYmFsID09PSBcImRlZmF1bHQgb2ZmLCBidXQgb24gd2hlbiBzcGVjaWZpZWRcIiAmJiAoc2hvd0hpZ2hsaWdodCA9PT0gdHJ1ZSkpIHtcbiAgICBlbGVtX2Rpdi5jbGFzc0xpc3QuYWRkKFwiaGstY29kZWJsb2NrLXNob3ctaGlnaGxpZ2h0XCIpO1xuXG4gICAgZWxlbV9kaXYuc3R5bGUuc2V0UHJvcGVydHkoXCItLWhrLWNvZGVibG9jay1oaWdobGlnaHQtYmFja2dyb3VuZC1jb2xvclwiLCBzZXR0aW5ncy5oaWdobGlnaHRDb2xvcik7XG5cbiAgICBjb25zdCBlbGVtX2hpZ2hsaWdodCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJjb2RlXCIpO1xuICAgIGVsZW1faGlnaGxpZ2h0LmNsYXNzTGlzdC5hZGQoXCJoay1jb2RlYmxvY2staGlnaGxpZ2h0XCIpO1xuICAgIGVsZW1faGlnaGxpZ2h0LmlubmVySFRNTCA9IEFycmF5KGxpbmVub3NOdW0pLmZpbGwoMCkubWFwKChfLCBpZHgpID0+IHtcbiAgICAgIGNvbnN0IGNsYXNzTmFtZXM6IHN0cmluZ1tdID0gW107XG4gICAgICBpZiAoaGlnaGxpZ2h0TGluZXMuaW5jbHVkZXMoaWR4ICsgbGluZW5vc1N0YXJ0KSkgY2xhc3NOYW1lcy5wdXNoKFwiaGlnaGxpZ2h0XCIpO1xuICAgICAgcmV0dXJuIGA8c3BhbiBjbGFzcz1cImxpbmUgbGluZS0ke2lkeCArIGxpbmVub3NTdGFydH0gJHtjbGFzc05hbWVzLmpvaW4oXCIgXCIpfVwiPiA8L3NwYW4+YDtcbiAgICB9KS5qb2luKFwiXFxuXCIpO1xuICAgIGVsZW1fcHJlLmluc2VydEJlZm9yZShlbGVtX2hpZ2hsaWdodCwgZWxlbV9jb2RlKTtcbiAgfVxuXG4gIGlmIChcbiAgICAoc2V0dGluZ3MudXNlTGFuZ3VhZ2VHbG9iYWwgPT09IFwiYWx3YXlzIG9uXCIpIHx8XG4gICAgKHNldHRpbmdzLnVzZUxhbmd1YWdlR2xvYmFsID09PSBcImRlZmF1bHQgb24sIGJ1dCBvZmYgd2hlbiBzcGVjaWZpZWRcIiAmJiAoc2hvd0xhbmd1YWdlID09PSB1bmRlZmluZWQgfHwgc2hvd0xhbmd1YWdlID09PSB0cnVlKSkgfHxcbiAgICAoc2V0dGluZ3MudXNlTGFuZ3VhZ2VHbG9iYWwgPT09IFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiICYmIChzaG93TGFuZ3VhZ2UgPT09IHRydWUpKVxuICApIHtcbiAgICBlbGVtX2Rpdi5jbGFzc0xpc3QuYWRkKFwiaGstY29kZWJsb2NrLXNob3ctbGFuZ3VhZ2VcIik7XG5cbiAgICBjb25zdCBlbGVtX2xhbmd1YWdlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICBlbGVtX2xhbmd1YWdlLmNsYXNzTGlzdC5hZGQoXCJoay1jb2RlYmxvY2stbGFuZ3VhZ2VcIik7XG4gICAgZWxlbV9sYW5ndWFnZS5pbm5lclRleHQgPSBsYW5ndWFnZTtcbiAgICBlbGVtX3ByZS5wcmVwZW5kKGVsZW1fbGFuZ3VhZ2UpO1xuICB9XG5cbiAgaWYgKFxuICAgIChzZXR0aW5ncy51c2VDb3B5QnRuR2xvYmFsID09PSBcImFsd2F5cyBvblwiKSB8fFxuICAgIChzZXR0aW5ncy51c2VDb3B5QnRuR2xvYmFsID09PSBcImRlZmF1bHQgb24sIGJ1dCBvZmYgd2hlbiBzcGVjaWZpZWRcIiAmJiAoc2hvd0NvcHlCdG4gPT09IHVuZGVmaW5lZCB8fCBzaG93Q29weUJ0biA9PT0gdHJ1ZSkpIHx8XG4gICAgKHNldHRpbmdzLnVzZUNvcHlCdG5HbG9iYWwgPT09IFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiICYmIChzaG93Q29weUJ0biA9PT0gdHJ1ZSkpXG4gICkge1xuICAgIGVsZW1fZGl2LmNsYXNzTGlzdC5hZGQoXCJoay1jb2RlYmxvY2stc2hvdy1jb3B5YnRuXCIpO1xuXG4gICAgZWxlbV9wcmUuYXBwZW5kQ2hpbGQoZWxlbV9jb3B5QnRuKTtcbiAgfVxuXG4gIGlmIChcbiAgICAoc2V0dGluZ3MudXNlUHJvbXB0R2xvYmFsID09PSBcImFsd2F5cyBvblwiICYmIHNldHRpbmdzLnByb21wdGluZ0xhbmd1YWdlcy5pbmNsdWRlcyhsYW5ndWFnZSkpIHx8XG4gICAgKHNldHRpbmdzLnVzZVByb21wdEdsb2JhbCA9PT0gXCJkZWZhdWx0IG9uLCBidXQgb2ZmIHdoZW4gc3BlY2lmaWVkXCIgJiYgc2V0dGluZ3MucHJvbXB0aW5nTGFuZ3VhZ2VzLmluY2x1ZGVzKGxhbmd1YWdlKSAmJiAoc2hvd1Byb21wdCA9PT0gdW5kZWZpbmVkIHx8IHNob3dQcm9tcHQgPT09IHRydWUpKSB8fFxuICAgIChzZXR0aW5ncy51c2VQcm9tcHRHbG9iYWwgPT09IFwiZGVmYXVsdCBvZmYsIGJ1dCBvbiB3aGVuIHNwZWNpZmllZFwiICYmIChzaG93UHJvbXB0ID09PSB0cnVlKSlcbiAgKSB7XG4gICAgZWxlbV9kaXYuY2xhc3NMaXN0LmFkZChcImhrLWNvZGVibG9jay1zaG93LXByb21wdFwiKTtcblxuICAgIC8vIHVzaW5nIFByaXNtLmpzIGNvbW1hbmQtbGluZSBwbHVnaW5cbiAgICBsZXQgY29kZV9saW5lcyA9IGVsZW1fY29kZS5pbm5lclRleHQuc3BsaXQoXCJcXG5cIik7XG4gICAgaWYgKGNvZGVfbGluZXNbY29kZV9saW5lcy5sZW5ndGggLSAxXS50cmltKCkubGVuZ3RoID09IDApIGNvZGVfbGluZXMucG9wKCk7IC8vIHJlbW92ZSBsYXN0IGxpbmUgaWYgZW1wdHlcblxuICAgIGNvbnN0IG5vX3Byb21wdF9saW5lX2lkeHMgPSBjb2RlX2xpbmVzLm1hcCgobGluZSwgaWR4KSA9PiB7XG4gICAgICBpZiAobGluZS50cmltKCkubGVuZ3RoID09IDApIHJldHVybiAoaWR4ICsgMSk7IC8vIGVtcHR5IGxpbmVcbiAgICAgIGlmIChsaW5lLnN0YXJ0c1dpdGgoXCIjXCIpKSByZXR1cm4gKGlkeCArIDEpOyAvLyBjb21tZW50IGxpbmVcbiAgICAgIHJldHVybiAtMTtcbiAgICB9KS5maWx0ZXIoKGlkeCkgPT4gaWR4ICE9IC0xKTtcblxuICAgIGVsZW1fcHJlLmNsYXNzTGlzdC5hZGQoXCJjb21tYW5kLWxpbmVcIik7XG4gICAgZWxlbV9wcmUuc2V0QXR0cmlidXRlKFwiZGF0YS1wcm9tcHRcIiwgcHJvbXB0KTtcbiAgICBlbGVtX3ByZS5zZXRBdHRyaWJ1dGUoXCJkYXRhLWNvbnRpbnVhdGlvbi1zdHJcIiwgXCJcXFxcXCIpO1xuICAgIGVsZW1fcHJlLnNldEF0dHJpYnV0ZShcImRhdGEtY29udGludWF0aW9uLXByb21wdFwiLCBcIiBcIi5yZXBlYXQocHJvbXB0Lmxlbmd0aCkpOyAgLy8gdXNlIHNwYWNlcyB0byBhbGlnbiBjb250aW51YXRpb24gcHJvbXB0XG4gICAgZWxlbV9wcmUuc2V0QXR0cmlidXRlKFwiZGF0YS1vdXRwdXRcIiwgbm9fcHJvbXB0X2xpbmVfaWR4cy5qb2luKFwiLCBcIikpO1xuICB9XG5cbiAgaWYoc2V0dGluZ3MudXNlUmVzdWx0R2xvYmFsID09PSBcImVuYWJsZVwiICYmIChpc1Jlc3VsdCA9PT0gdHJ1ZSkpIHtcbiAgICBlbGVtX2Rpdi5jbGFzc0xpc3QuYWRkKFwiaGstY29kZWJsb2NrLXJlc3VsdFwiKTtcbiAgICBlbGVtX2NvZGUuY2xhc3NMaXN0LmFkZChcImhrLWNvZGVibG9jay1yZXN1bHQtY29kZVwiKTtcblxuICAgIGVsZW1fZGl2LnNldEF0dHJpYnV0ZShcImRhdGEtcmVzdWx0LXByb21wdFwiLCByZXN1bHRQcm9tcHQpO1xuICB9XG59IiwgImV4cG9ydCBmdW5jdGlvbiBQcmlzbVBsdWdpbl9Db21tYW5kTGluZShQcmlzbSkge1xuXG5cdGlmICh0eXBlb2YgUHJpc20gPT09ICd1bmRlZmluZWQnIHx8IHR5cGVvZiBkb2N1bWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHR2YXIgQ0xBU1NfUEFUVEVSTiA9IC8oPzpefFxccyljb21tYW5kLWxpbmUoPzpcXHN8JCkvO1xuXHR2YXIgUFJPTVBUX0NMQVNTID0gJ2NvbW1hbmQtbGluZS1wcm9tcHQnO1xuXG5cdC8qKiBAdHlwZSB7KHN0cjogc3RyaW5nLCBwcmVmaXg6IHN0cmluZykgPT4gYm9vbGVhbn0gKi9cblx0dmFyIHN0YXJ0c1dpdGggPSAnJy5zdGFydHNXaXRoXG5cdFx0PyBmdW5jdGlvbiAocywgcCkgeyByZXR1cm4gcy5zdGFydHNXaXRoKHApOyB9XG5cdFx0OiBmdW5jdGlvbiAocywgcCkgeyByZXR1cm4gcy5pbmRleE9mKHApID09PSAwOyB9O1xuXG5cdC8vIFN1cHBvcnQgZm9yIElFMTEgdGhhdCBoYXMgbm8gZW5kc1dpdGgoKVxuXHQvKiogQHR5cGUgeyhzdHI6IHN0cmluZywgc3VmZml4OiBzdHJpbmcpID0+IGJvb2xlYW59ICovXG5cdHZhciBlbmRzV2l0aCA9ICcnLmVuZHNXaXRoXG5cdFx0PyBmdW5jdGlvbiAoc3RyLCBzdWZmaXgpIHtcblx0XHRcdHJldHVybiBzdHIuZW5kc1dpdGgoc3VmZml4KTtcblx0XHR9XG5cdFx0OiBmdW5jdGlvbiAoc3RyLCBzdWZmaXgpIHtcblx0XHRcdHZhciBsZW4gPSBzdHIubGVuZ3RoO1xuXHRcdFx0cmV0dXJuIHN0ci5zdWJzdHJpbmcobGVuIC0gc3VmZml4Lmxlbmd0aCwgbGVuKSA9PT0gc3VmZml4O1xuXHRcdH07XG5cblx0LyoqXG5cdCAqIFJldHVybnMgd2hldGhlciB0aGUgZ2l2ZW4gaG9vayBlbnZpcm9ubWVudCBoYXMgYSBjb21tYW5kIGxpbmUgaW5mbyBvYmplY3QuXG5cdCAqXG5cdCAqIEBwYXJhbSB7YW55fSBlbnZcblx0ICogQHJldHVybnMge2Jvb2xlYW59XG5cdCAqL1xuXHRmdW5jdGlvbiBoYXNDb21tYW5kTGluZUluZm8oZW52KSB7XG5cdFx0dmFyIHZhcnMgPSBlbnYudmFycyA9IGVudi52YXJzIHx8IHt9O1xuXHRcdHJldHVybiAnY29tbWFuZC1saW5lJyBpbiB2YXJzO1xuXHR9XG5cdC8qKlxuXHQgKiBSZXR1cm5zIHRoZSBjb21tYW5kIGxpbmUgaW5mbyBvYmplY3QgZnJvbSB0aGUgZ2l2ZW4gaG9vayBlbnZpcm9ubWVudC5cblx0ICpcblx0ICogQHBhcmFtIHthbnl9IGVudlxuXHQgKiBAcmV0dXJucyB7Q29tbWFuZExpbmVJbmZvfVxuXHQgKlxuXHQgKiBAdHlwZWRlZiBDb21tYW5kTGluZUluZm9cblx0ICogQHByb3BlcnR5IHtib29sZWFufSBbY29tcGxldGVdXG5cdCAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBbbnVtYmVyT2ZMaW5lc11cblx0ICogQHByb3BlcnR5IHtzdHJpbmdbXX0gW291dHB1dExpbmVzXVxuXHQgKi9cblx0ZnVuY3Rpb24gZ2V0Q29tbWFuZExpbmVJbmZvKGVudikge1xuXHRcdHZhciB2YXJzID0gZW52LnZhcnMgPSBlbnYudmFycyB8fCB7fTtcblx0XHRyZXR1cm4gdmFyc1snY29tbWFuZC1saW5lJ10gPSB2YXJzWydjb21tYW5kLWxpbmUnXSB8fCB7fTtcblx0fVxuXG5cblx0UHJpc20uaG9va3MuYWRkKCdiZWZvcmUtaGlnaGxpZ2h0JywgZnVuY3Rpb24gKGVudikge1xuXHRcdHZhciBjb21tYW5kTGluZSA9IGdldENvbW1hbmRMaW5lSW5mbyhlbnYpO1xuXG5cdFx0aWYgKGNvbW1hbmRMaW5lLmNvbXBsZXRlIHx8ICFlbnYuY29kZSkge1xuXHRcdFx0Y29tbWFuZExpbmUuY29tcGxldGUgPSB0cnVlO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIFdvcmtzIG9ubHkgZm9yIDxjb2RlPiB3cmFwcGVkIGluc2lkZSA8cHJlPiAobm90IGlubGluZSkuXG5cdFx0dmFyIHByZSA9IGVudi5lbGVtZW50LnBhcmVudEVsZW1lbnQ7XG5cdFx0aWYgKCFwcmUgfHwgIS9wcmUvaS50ZXN0KHByZS5ub2RlTmFtZSkgfHwgLy8gQWJvcnQgb25seSBpZiBuZWl0aGVyIHRoZSA8cHJlPiBub3IgdGhlIDxjb2RlPiBoYXZlIHRoZSBjbGFzc1xuXHRcdFx0KCFDTEFTU19QQVRURVJOLnRlc3QocHJlLmNsYXNzTmFtZSkgJiYgIUNMQVNTX1BBVFRFUk4udGVzdChlbnYuZWxlbWVudC5jbGFzc05hbWUpKSkge1xuXHRcdFx0Y29tbWFuZExpbmUuY29tcGxldGUgPSB0cnVlO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIFRoZSBlbGVtZW50IG1pZ2h0IGJlIGhpZ2hsaWdodGVkIG11bHRpcGxlIHRpbWVzLCBzbyB3ZSBqdXN0IHJlbW92ZSB0aGUgcHJldmlvdXMgcHJvbXB0XG5cdFx0dmFyIGV4aXN0aW5nUHJvbXB0ID0gZW52LmVsZW1lbnQucXVlcnlTZWxlY3RvcignLicgKyBQUk9NUFRfQ0xBU1MpO1xuXHRcdGlmIChleGlzdGluZ1Byb21wdCkge1xuXHRcdFx0ZXhpc3RpbmdQcm9tcHQucmVtb3ZlKCk7XG5cdFx0fVxuXG5cdFx0dmFyIGNvZGVMaW5lcyA9IGVudi5jb2RlLnNwbGl0KCdcXG4nKTtcblxuXHRcdGlmKGNvZGVMaW5lc1tjb2RlTGluZXMubGVuZ3RoIC0gMV0udHJpbSgpLmxlbmd0aCA9PT0gMCkgeyAvLyBkbyBub3QgY291bnQgdGhlIGxhc3QgbGluZSBpZiBpdCBpcyBlbXB0eVxuXHRcdFx0Y29tbWFuZExpbmUubnVtYmVyT2ZMaW5lcyA9IGNvZGVMaW5lcy5sZW5ndGggLSAxO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb21tYW5kTGluZS5udW1iZXJPZkxpbmVzID0gY29kZUxpbmVzLmxlbmd0aDtcblx0XHR9XG5cdFx0LyoqIEB0eXBlIHtzdHJpbmdbXX0gKi9cblx0XHR2YXIgb3V0cHV0TGluZXMgPSBjb21tYW5kTGluZS5vdXRwdXRMaW5lcyA9IFtdO1xuXG5cdFx0dmFyIG91dHB1dFNlY3Rpb25zID0gcHJlLmdldEF0dHJpYnV0ZSgnZGF0YS1vdXRwdXQnKTtcblx0XHR2YXIgb3V0cHV0RmlsdGVyID0gcHJlLmdldEF0dHJpYnV0ZSgnZGF0YS1maWx0ZXItb3V0cHV0Jyk7XG5cdFx0aWYgKG91dHB1dFNlY3Rpb25zICE9PSBudWxsKSB7IC8vIFRoZSB1c2VyIHNwZWNpZmllZCB0aGUgb3V0cHV0IGxpbmVzLiAtLSBjd2VsbHNcblx0XHRcdG91dHB1dFNlY3Rpb25zLnNwbGl0KCcsJykuZm9yRWFjaChmdW5jdGlvbiAoc2VjdGlvbikge1xuXHRcdFx0XHR2YXIgcmFuZ2UgPSBzZWN0aW9uLnNwbGl0KCctJyk7XG5cdFx0XHRcdHZhciBvdXRwdXRTdGFydCA9IHBhcnNlSW50KHJhbmdlWzBdLCAxMCk7XG5cdFx0XHRcdHZhciBvdXRwdXRFbmQgPSByYW5nZS5sZW5ndGggPT09IDIgPyBwYXJzZUludChyYW5nZVsxXSwgMTApIDogb3V0cHV0U3RhcnQ7XG5cblx0XHRcdFx0aWYgKCFpc05hTihvdXRwdXRTdGFydCkgJiYgIWlzTmFOKG91dHB1dEVuZCkpIHtcblx0XHRcdFx0XHRpZiAob3V0cHV0U3RhcnQgPCAxKSB7XG5cdFx0XHRcdFx0XHRvdXRwdXRTdGFydCA9IDE7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmIChvdXRwdXRFbmQgPiBjb2RlTGluZXMubGVuZ3RoKSB7XG5cdFx0XHRcdFx0XHRvdXRwdXRFbmQgPSBjb2RlTGluZXMubGVuZ3RoO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHQvLyBDb252ZXJ0IHN0YXJ0IGFuZCBlbmQgdG8gMC1iYXNlZCB0byBzaW1wbGlmeSB0aGUgYXJyYXlzLiAtLSBjd2VsbHNcblx0XHRcdFx0XHRvdXRwdXRTdGFydC0tO1xuXHRcdFx0XHRcdG91dHB1dEVuZC0tO1xuXHRcdFx0XHRcdC8vIFNhdmUgdGhlIG91dHB1dCBsaW5lIGluIGFuIGFycmF5IGFuZCBjbGVhciBpdCBpbiB0aGUgY29kZSBzbyBpdCdzIG5vdCBoaWdobGlnaHRlZC4gLS0gY3dlbGxzXG5cdFx0XHRcdFx0Zm9yICh2YXIgaiA9IG91dHB1dFN0YXJ0OyBqIDw9IG91dHB1dEVuZDsgaisrKSB7XG5cdFx0XHRcdFx0XHRvdXRwdXRMaW5lc1tqXSA9IGNvZGVMaW5lc1tqXTtcblx0XHRcdFx0XHRcdGNvZGVMaW5lc1tqXSA9ICcnO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSBlbHNlIGlmIChvdXRwdXRGaWx0ZXIpIHsgLy8gVHJlYXQgbGluZXMgYmVnaW5uaW5nIHdpdGggdGhpcyBzdHJpbmcgYXMgb3V0cHV0LiAtLSBjd2VsbHNcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgY29kZUxpbmVzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGlmIChzdGFydHNXaXRoKGNvZGVMaW5lc1tpXSwgb3V0cHV0RmlsdGVyKSkgeyAvLyBUaGlzIGxpbmUgaXMgb3V0cHV0LiAtLSBjd2VsbHNcblx0XHRcdFx0XHRvdXRwdXRMaW5lc1tpXSA9IGNvZGVMaW5lc1tpXS5zbGljZShvdXRwdXRGaWx0ZXIubGVuZ3RoKTtcblx0XHRcdFx0XHRjb2RlTGluZXNbaV0gPSAnJztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHZhciBjb250aW51YXRpb25MaW5lSW5kaWNpZXMgPSBjb21tYW5kTGluZS5jb250aW51YXRpb25MaW5lSW5kaWNpZXMgPSBuZXcgU2V0KCk7XG5cdFx0dmFyIGxpbmVDb250aW51YXRpb25TdHIgPSBwcmUuZ2V0QXR0cmlidXRlKCdkYXRhLWNvbnRpbnVhdGlvbi1zdHInKTtcblx0XHR2YXIgY29udGludWF0aW9uRmlsdGVyID0gcHJlLmdldEF0dHJpYnV0ZSgnZGF0YS1maWx0ZXItY29udGludWF0aW9uJyk7XG5cblx0XHQvLyBJZGVudGlmeSBjb2RlIGxpbmVzIHdoZXJlIHRoZSBjb21tYW5kIGhhcyBjb250aW51ZWQgb250byBzdWJzZXF1ZW50XG5cdFx0Ly8gbGluZXMgYW5kIHRodXMgbmVlZCBhIGRpZmZlcmVudCBwcm9tcHQuIE5lZWQgdG8gZG8gdGhpcyBhZnRlciB0aGUgb3V0cHV0XG5cdFx0Ly8gbGluZXMgaGF2ZSBiZWVuIHJlbW92ZWQgdG8gZW5zdXJlIHdlIGRvbid0IHBpY2sgdXAgYSBjb250aW51YXRpb24gc3RyaW5nXG5cdFx0Ly8gaW4gYW4gb3V0cHV0IGxpbmUuXG5cdFx0Zm9yICh2YXIgaiA9IDA7IGogPCBjb2RlTGluZXMubGVuZ3RoOyBqKyspIHtcblx0XHRcdHZhciBsaW5lID0gY29kZUxpbmVzW2pdO1xuXHRcdFx0aWYgKCFsaW5lKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZWNvcmQgdGhlIG5leHQgbGluZSBhcyBhIGNvbnRpbnVhdGlvbiBpZiB0aGlzIG9uZSBlbmRzIGluIGEgY29udGludWF0aW9uIHN0ci5cblx0XHRcdGlmIChsaW5lQ29udGludWF0aW9uU3RyICYmIGVuZHNXaXRoKGxpbmUsIGxpbmVDb250aW51YXRpb25TdHIpKSB7XG5cdFx0XHRcdGNvbnRpbnVhdGlvbkxpbmVJbmRpY2llcy5hZGQoaiArIDEpO1xuXHRcdFx0fVxuXHRcdFx0Ly8gUmVjb3JkIHRoaXMgbGluZSBhcyBhIGNvbnRpbnVhdGlvbiBpZiBtYXJrZWQgd2l0aCBhIGNvbnRpbnVhdGlvbiBwcmVmaXhcblx0XHRcdC8vICh0aGF0IHdlIHdpbGwgcmVtb3ZlKS5cblx0XHRcdGlmIChqID4gMCAmJiBjb250aW51YXRpb25GaWx0ZXIgJiYgc3RhcnRzV2l0aChsaW5lLCBjb250aW51YXRpb25GaWx0ZXIpKSB7XG5cdFx0XHRcdGNvZGVMaW5lc1tqXSA9IGxpbmUuc2xpY2UoY29udGludWF0aW9uRmlsdGVyLmxlbmd0aCk7XG5cdFx0XHRcdGNvbnRpbnVhdGlvbkxpbmVJbmRpY2llcy5hZGQoaik7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0ZW52LmNvZGUgPSBjb2RlTGluZXMuam9pbignXFxuJyk7XG5cdH0pO1xuXG5cdFByaXNtLmhvb2tzLmFkZCgnYmVmb3JlLWluc2VydCcsIGZ1bmN0aW9uIChlbnYpIHtcblx0XHR2YXIgY29tbWFuZExpbmUgPSBnZXRDb21tYW5kTGluZUluZm8oZW52KTtcblxuXHRcdGlmIChjb21tYW5kTGluZS5jb21wbGV0ZSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIFJlaW5zZXJ0IHRoZSBvdXRwdXQgbGluZXMgaW50byB0aGUgaGlnaGxpZ2h0ZWQgY29kZS4gLS0gY3dlbGxzXG5cdFx0dmFyIGNvZGVMaW5lcyA9IGVudi5oaWdobGlnaHRlZENvZGUuc3BsaXQoJ1xcbicpO1xuXHRcdHZhciBvdXRwdXRMaW5lcyA9IGNvbW1hbmRMaW5lLm91dHB1dExpbmVzIHx8IFtdO1xuXHRcdGZvciAodmFyIGkgPSAwLCBsID0gY29kZUxpbmVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuXHRcdFx0Ly8gQWRkIHNwYW5zIHRvIGFsbG93IGRpc3RpbmN0aW9uIG9mIGlucHV0L291dHB1dCB0ZXh0IGZvciBzdHlsaW5nXG5cdFx0XHRpZiAob3V0cHV0TGluZXMuaGFzT3duUHJvcGVydHkoaSkpIHtcblx0XHRcdFx0Ly8gb3V0cHV0TGluZXMgd2VyZSByZW1vdmVkIGZyb20gY29kZUxpbmVzIHNvIG1pc3NlZCBvdXQgb24gZXNjYXBpbmdcblx0XHRcdFx0Ly8gb2YgbWFya3VwIHNvIGRvIGl0IGhlcmUuXG5cdFx0XHRcdGNvZGVMaW5lc1tpXSA9ICc8c3BhbiBjbGFzcz1cInRva2VuIG91dHB1dFwiPidcblx0XHRcdFx0XHQrIFByaXNtLnV0aWwuZW5jb2RlKG91dHB1dExpbmVzW2ldKSArICc8L3NwYW4+Jztcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNvZGVMaW5lc1tpXSA9ICc8c3BhbiBjbGFzcz1cInRva2VuIGNvbW1hbmRcIj4nXG5cdFx0XHRcdFx0KyBjb2RlTGluZXNbaV0gKyAnPC9zcGFuPic7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGVudi5oaWdobGlnaHRlZENvZGUgPSBjb2RlTGluZXMuam9pbignXFxuJyk7XG5cdH0pO1xuXG5cdFByaXNtLmhvb2tzLmFkZCgnY29tcGxldGUnLCBmdW5jdGlvbiAoZW52KSB7XG5cdFx0aWYgKCFoYXNDb21tYW5kTGluZUluZm8oZW52KSkge1xuXHRcdFx0Ly8gdGhlIHByZXZpb3VzIGhvb2tzIG5ldmVyIHJhblxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBjb21tYW5kTGluZSA9IGdldENvbW1hbmRMaW5lSW5mbyhlbnYpO1xuXG5cdFx0aWYgKGNvbW1hbmRMaW5lLmNvbXBsZXRlKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIHByZSA9IGVudi5lbGVtZW50LnBhcmVudEVsZW1lbnQ7XG5cdFx0aWYgKENMQVNTX1BBVFRFUk4udGVzdChlbnYuZWxlbWVudC5jbGFzc05hbWUpKSB7IC8vIFJlbW92ZSB0aGUgY2xhc3MgXCJjb21tYW5kLWxpbmVcIiBmcm9tIHRoZSA8Y29kZT5cblx0XHRcdGVudi5lbGVtZW50LmNsYXNzTmFtZSA9IGVudi5lbGVtZW50LmNsYXNzTmFtZS5yZXBsYWNlKENMQVNTX1BBVFRFUk4sICcgJyk7XG5cdFx0fVxuXHRcdGlmICghQ0xBU1NfUEFUVEVSTi50ZXN0KHByZS5jbGFzc05hbWUpKSB7IC8vIEFkZCB0aGUgY2xhc3MgXCJjb21tYW5kLWxpbmVcIiB0byB0aGUgPHByZT5cblx0XHRcdHByZS5jbGFzc05hbWUgKz0gJyBjb21tYW5kLWxpbmUnO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGdldEF0dHJpYnV0ZShrZXksIGRlZmF1bHRWYWx1ZSkge1xuXHRcdFx0cmV0dXJuIChwcmUuZ2V0QXR0cmlidXRlKGtleSkgfHwgZGVmYXVsdFZhbHVlKS5yZXBsYWNlKC9cIi9nLCAnJnF1b3QnKTtcblx0XHR9XG5cblx0XHQvLyBDcmVhdGUgdGhlIFwicm93c1wiIHRoYXQgd2lsbCBiZWNvbWUgdGhlIGNvbW1hbmQtbGluZSBwcm9tcHRzLiAtLSBjd2VsbHNcblx0XHR2YXIgcHJvbXB0TGluZXMgPSAnJztcblx0XHR2YXIgcm93Q291bnQgPSBjb21tYW5kTGluZS5udW1iZXJPZkxpbmVzIHx8IDA7XG5cdFx0dmFyIHByb21wdFRleHQgPSBnZXRBdHRyaWJ1dGUoJ2RhdGEtcHJvbXB0JywgJycpO1xuXHRcdHZhciBwcm9tcHRMaW5lO1xuXHRcdGlmIChwcm9tcHRUZXh0ICE9PSAnJykge1xuXHRcdFx0cHJvbXB0TGluZSA9ICc8c3BhbiBkYXRhLXByb21wdD1cIicgKyBwcm9tcHRUZXh0ICsgJ1wiPjwvc3Bhbj4nO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR2YXIgdXNlciA9IGdldEF0dHJpYnV0ZSgnZGF0YS11c2VyJywgJ3VzZXInKTtcblx0XHRcdHZhciBob3N0ID0gZ2V0QXR0cmlidXRlKCdkYXRhLWhvc3QnLCAnbG9jYWxob3N0Jyk7XG5cdFx0XHRwcm9tcHRMaW5lID0gJzxzcGFuIGRhdGEtdXNlcj1cIicgKyB1c2VyICsgJ1wiIGRhdGEtaG9zdD1cIicgKyBob3N0ICsgJ1wiPjwvc3Bhbj4nO1xuXHRcdH1cblxuXHRcdHZhciBjb250aW51YXRpb25MaW5lSW5kaWNpZXMgPSBjb21tYW5kTGluZS5jb250aW51YXRpb25MaW5lSW5kaWNpZXMgfHwgbmV3IFNldCgpO1xuXHRcdHZhciBjb250aW51YXRpb25Qcm9tcHRUZXh0ID0gZ2V0QXR0cmlidXRlKCdkYXRhLWNvbnRpbnVhdGlvbi1wcm9tcHQnLCAnPicpO1xuXHRcdHZhciBjb250aW51YXRpb25Qcm9tcHRMaW5lID0gJzxzcGFuIGRhdGEtY29udGludWF0aW9uLXByb21wdD1cIicgKyBjb250aW51YXRpb25Qcm9tcHRUZXh0ICsgJ1wiPjwvc3Bhbj4nO1xuXG5cdFx0Ly8gQXNzZW1ibGUgYWxsIHRoZSBhcHByb3ByaWF0ZSBwcm9tcHQvY29udGludWF0aW9uIGxpbmVzXG5cdFx0Zm9yICh2YXIgaiA9IDA7IGogPCByb3dDb3VudDsgaisrKSB7XG5cdFx0XHRpZiAoY29udGludWF0aW9uTGluZUluZGljaWVzLmhhcyhqKSkge1xuXHRcdFx0XHRwcm9tcHRMaW5lcyArPSBjb250aW51YXRpb25Qcm9tcHRMaW5lO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cHJvbXB0TGluZXMgKz0gcHJvbXB0TGluZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDcmVhdGUgdGhlIHdyYXBwZXIgZWxlbWVudC4gLS0gY3dlbGxzXG5cdFx0dmFyIHByb21wdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3NwYW4nKTtcblx0XHRwcm9tcHQuY2xhc3NOYW1lID0gUFJPTVBUX0NMQVNTO1xuXHRcdHByb21wdC5pbm5lckhUTUwgPSBwcm9tcHRMaW5lcztcblxuXHRcdC8vIFJlbW92ZSB0aGUgcHJvbXB0IGZyb20gdGhlIG91dHB1dCBsaW5lcy4gLS0gY3dlbGxzXG5cdFx0dmFyIG91dHB1dExpbmVzID0gY29tbWFuZExpbmUub3V0cHV0TGluZXMgfHwgW107XG5cdFx0Zm9yICh2YXIgaSA9IDAsIGwgPSBvdXRwdXRMaW5lcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcblx0XHRcdGlmIChvdXRwdXRMaW5lcy5oYXNPd25Qcm9wZXJ0eShpKSkge1xuXHRcdFx0XHR2YXIgbm9kZSA9IHByb21wdC5jaGlsZHJlbltpXTtcblx0XHRcdFx0bm9kZS5yZW1vdmVBdHRyaWJ1dGUoJ2RhdGEtdXNlcicpO1xuXHRcdFx0XHRub2RlLnJlbW92ZUF0dHJpYnV0ZSgnZGF0YS1ob3N0Jyk7XG5cdFx0XHRcdG5vZGUucmVtb3ZlQXR0cmlidXRlKCdkYXRhLXByb21wdCcpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGVudi5lbGVtZW50Lmluc2VydEJlZm9yZShwcm9tcHQsIGVudi5lbGVtZW50LmZpcnN0Q2hpbGQpO1xuXHRcdGNvbW1hbmRMaW5lLmNvbXBsZXRlID0gdHJ1ZTtcblx0fSk7XG5cbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxJQUFBQSxtQkFBa0M7OztBQ3lCM0IsSUFBTSxtQkFBd0M7QUFBQSxFQUNwRCxnQkFBZ0I7QUFBQSxFQUVoQixrQkFBa0I7QUFBQSxFQUNsQixxQkFBcUI7QUFBQSxFQUNyQixxQkFBcUI7QUFBQSxFQUVyQixvQkFBb0I7QUFBQSxFQUNwQixnQkFBZ0I7QUFBQSxFQUVoQixtQkFBbUI7QUFBQSxFQUNuQixpQkFBaUI7QUFBQSxFQUVqQixrQkFBa0I7QUFBQSxFQUVsQixpQkFBaUI7QUFBQSxFQUNqQixvQkFBb0IsQ0FBQyxNQUFNO0FBQUEsRUFDM0IsZUFBZTtBQUFBLEVBRWYsaUJBQWlCO0FBQUEsRUFDakIscUJBQXFCO0FBQUEsRUFFckIsV0FBVztBQUNaOzs7QUNoREEsc0JBQStDO0FBSXhDLElBQU0sZUFBZSxDQUFDLFNBQWlCO0FBQzdDLFNBQU8sZUFBZSxDQUFDLFNBQVM7QUFDL0IsU0FBSyxVQUFVLEVBQUUsWUFBWSxLQUFLLE1BQU0sSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLEtBQUssS0FBSyxDQUFDLEVBQUUsS0FBSyxNQUFNO0FBQUEsRUFDckYsQ0FBQztBQUNGO0FBRU8sSUFBTSx3QkFBTixjQUFvQyxpQ0FBaUI7QUFBQSxFQUczRCxZQUFZQyxNQUFVLFFBQTJCO0FBQ2hELFVBQU1BLE1BQUssTUFBTTtBQUNqQixT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UUFBUSxVQUFVO0FBQ3ZELGdCQUFZLFdBQVc7QUFBQSxFQUN4QixDQUFDO0FBRUY7OztBSnpPQSxJQUFxQixvQkFBckIsY0FBK0Msd0JBQU87QUFBQSxFQUdyRCxNQUFNLFNBQVM7QUFDZCxVQUFNLEtBQUssYUFBYTtBQUN4QixRQUFJLEtBQUssU0FBUyxXQUFXO0FBQzVCLGNBQVEsSUFBSSw0QkFBNEI7QUFBQSxJQUN6QztBQUVBLFVBQU0sUUFBUSxVQUFNLDRCQUFVO0FBRzlCLDRCQUF3QixLQUFLO0FBRzdCLFNBQUssY0FBYyxJQUFJLHNCQUFzQixLQUFLLEtBQUssSUFBSSxDQUFDO0FBRzVELFVBQU0sWUFBWSxLQUFLLDhCQUE4QixDQUFDLElBQUksUUFBUTtBQUNqRSwyQkFBcUIsSUFBSSxLQUFLLElBQUk7QUFBQSxJQUNuQyxDQUFDO0FBRUQsY0FBVSxZQUFZO0FBQUEsRUFDdkI7QUFBQSxFQUVBLFdBQVc7QUFDVixRQUFJLEtBQUssU0FBUyxXQUFXO0FBQzVCLGNBQVEsSUFBSSw4QkFBOEI7QUFBQSxJQUMzQztBQUFBLEVBQ0Q7QUFBQSxFQUVBLE1BQU0sZUFBZTtBQUNwQixTQUFLLFdBQVcsT0FBTyxPQUFPLENBQUMsR0FBRyxrQkFBa0IsTUFBTSxLQUFLLFNBQVMsQ0FBQztBQUFBLEVBQzFFO0FBQUEsRUFFQSxNQUFNLGVBQWU7QUFDcEIsVUFBTSxLQUFLLFNBQVMsS0FBSyxRQUFRO0FBQUEsRUFDbEM7QUFDRDsiLAogICJuYW1lcyI6IFsiaW1wb3J0X29ic2lkaWFuIiwgImFwcCIsICJpbXBvcnRfb2JzaWRpYW4iLCAibGFuZ3VhZ2UiLCAiaiJdCn0K
diff --git a/dist/manifest.json b/dist/manifest.json
new file mode 100644
index 0000000..21bfcc3
--- /dev/null
+++ b/dist/manifest.json
@@ -0,0 +1,11 @@
+{
+	"id": "obsidian-hk-code-block",
+	"name": "HK Code Block",
+	"version": "0.1.0",
+	"minAppVersion": "1.0.0",
+	"description": "Obsidian plugin developed by Heekang Park; Make code block looking good on reading view",
+	"author": "Heekang Park",
+	"authorUrl": "https://github.com/HeekangPark",
+	"fundingUrl": "",
+	"isDesktopOnly": false
+}
diff --git a/dist/styles.css b/dist/styles.css
new file mode 100644
index 0000000..89a2ed2
--- /dev/null
+++ b/dist/styles.css
@@ -0,0 +1,140 @@
+/* src/styles.scss */
+.hk-codeblock {
+  position: relative;
+  background-color: var(--hk-codeblock-background-color);
+  margin-bottom: var(--hk-codeblock-margin);
+}
+.hk-codeblock {
+  --hk-codeblock-margin: 1em;
+  --hk-codeblock-horizontal-padding: 16px;
+  --hk-codeblock-vertical-padding: 8px;
+  --hk-codeblock-background-color: var(--code-background);
+  --hk-codeblock-border-color: var(--divider-color);
+  --hk-codeblock-title-text-color: var(--text-normal);
+  --hk-codeblock-linenos-text-color: var(--code-normal);
+  --hk-codeblock-language-text-color: var(--text-muted);
+  --hk-codeblock-language-text-size: var(--font-ui-smaller);
+  --hk-codeblock-language-text-font: var(--font-interface);
+  --hk-codeblock-prompt-text-color: var(--code-normal);
+  --hk-codeblock-result-text-color: var(--text-normal);
+}
+.hk-codeblock pre {
+  position: relative;
+  display: flex;
+  flex-direction: row;
+  margin: 0;
+  padding-top: var(--hk-codeblock-vertical-padding);
+  padding-bottom: var(--hk-codeblock-vertical-padding);
+  padding-left: var(--hk-codeblock-horizontal-padding);
+  padding-right: var(--hk-codeblock-horizontal-padding);
+  background-color: var(--hk-codeblock-background-color);
+}
+.hk-codeblock pre code.hk-codeblock-code {
+  white-space: pre;
+  overflow-x: auto;
+  padding: 0;
+}
+.hk-codeblock.hk-codeblock-show-title .hk-codeblock-title {
+  padding-left: var(--hk-codeblock-horizontal-padding);
+  padding-right: var(--hk-codeblock-horizontal-padding);
+  padding-top: var(--hk-codeblock-vertical-padding);
+  padding-bottom: var(--hk-codeblock-vertical-padding);
+  background-color: var(--hk-codeblock-background-color);
+  border-bottom: 1px solid var(--hk-codeblock-border-color);
+  color: var(--hk-codeblock-title-text-color);
+}
+.hk-codeblock.hk-codeblock-show-title .hk-codeblock-title ~ pre {
+  margin-top: 0;
+}
+.hk-codeblock.hk-codeblock-show-linenos pre code.hk-codeblock-linenos {
+  flex-shrink: 0;
+  flex-grow: 0;
+  text-align: right;
+  padding-right: 1em;
+  opacity: 0.6;
+  user-select: none;
+  color: var(--hk-codeblock-linenos-text-color);
+}
+.hk-codeblock.hk-codeblock-show-linenos pre code.hk-codeblock-linenos.show-splitter {
+  border-right: 1px solid var(--hk-codeblock-border-color);
+  margin-right: 1em;
+}
+.hk-codeblock.hk-codeblock-show-highlight pre code.hk-codeblock-highlight {
+  display: flex;
+  flex-direction: column;
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  pointer-events: none;
+  user-select: none;
+  padding-top: var(--hk-codeblock-vertical-padding);
+  padding-bottom: var(--hk-codeblock-vertical-padding);
+  opacity: 0.2;
+}
+.hk-codeblock.hk-codeblock-show-highlight pre code.hk-codeblock-highlight .line.highlight {
+  background-color: var(--hk-codeblock-highlight-background-color);
+}
+.hk-codeblock.hk-codeblock-show-language pre .hk-codeblock-language {
+  opacity: 0.4;
+  user-select: none;
+  z-index: 1;
+  margin: 6px;
+  padding: 6px 8px;
+  background-color: transparent;
+  box-shadow: none;
+  color: var(--hk-codeblock-language-text-color);
+  font-size: var(--hk-codeblock-language-text-size);
+  font-family: var(--hk-codeblock-language-text-font);
+  position: absolute;
+  top: 0;
+  right: 0;
+}
+.hk-codeblock.hk-codeblock-show-language pre:hover .hk-codeblock-language {
+  display: none;
+}
+.hk-codeblock.hk-codeblock-show-copybtn pre .copy-code-button {
+  cursor: pointer;
+}
+.hk-codeblock.hk-codeblock-show-prompt pre code.hk-codeblock-code .command-line-prompt {
+  display: block;
+  float: left;
+  font-size: 100%;
+  text-align: right;
+  user-select: none;
+}
+.hk-codeblock.hk-codeblock-show-prompt pre code.hk-codeblock-code .command-line-prompt > span::before {
+  opacity: 0.6;
+  content: " ";
+  display: block;
+  margin-right: 0.6em;
+  color: var(--hk-codeblock-prompt-text-color);
+}
+.hk-codeblock.hk-codeblock-show-prompt pre code.hk-codeblock-code .command-line-prompt > span[data-prompt]::before {
+  content: attr(data-prompt);
+}
+.hk-codeblock.hk-codeblock-show-prompt pre code.hk-codeblock-code .command-line-prompt > span[data-continuation-prompt]::before {
+  content: attr(data-continuation-prompt);
+}
+.hk-codeblock + .hk-codeblock.hk-codeblock-result {
+  margin-top: calc(var(--hk-codeblock-margin) * -1);
+  border-top: 1px solid var(--hk-codeblock-border-color);
+}
+.hk-codeblock + .hk-codeblock.hk-codeblock-result::before {
+  content: attr(data-result-prompt);
+  display: block;
+  color: var(--hk-codeblock-result-text-color);
+  opacity: 0.6;
+  font-size: 0.8em;
+  padding-top: var(--hk-codeblock-vertical-padding);
+  padding-left: var(--hk-codeblock-horizontal-padding);
+  padding-right: var(--hk-codeblock-horizontal-padding);
+}
+.hk-codeblock + .hk-codeblock.hk-codeblock-result pre {
+  margin-top: 0;
+}
+.hk-codeblock + .hk-codeblock.hk-codeblock-result pre .hk-codeblock-result-code {
+  color: var(--hk-codeblock-result-text-color);
+}
+/*# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL3N0eWxlcy5zY3NzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIuaGstY29kZWJsb2NrIHtcbiAgJiB7XG4gICAgLy8gdmFyaWFibGVzXG4gICAgLS1oay1jb2RlYmxvY2stbWFyZ2luOiAxZW07XG4gICAgLS1oay1jb2RlYmxvY2staG9yaXpvbnRhbC1wYWRkaW5nOiAxNnB4O1xuICAgIC0taGstY29kZWJsb2NrLXZlcnRpY2FsLXBhZGRpbmc6IDhweDtcbiAgICAtLWhrLWNvZGVibG9jay1iYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1jb2RlLWJhY2tncm91bmQpO1xuICAgIC0taGstY29kZWJsb2NrLWJvcmRlci1jb2xvcjogdmFyKC0tZGl2aWRlci1jb2xvcik7IC8vIGFwcGxpZWQgdG8gdGl0bGUsIGxpbmVub3MsIGFuZCByZXN1bHRcbiAgICAtLWhrLWNvZGVibG9jay10aXRsZS10ZXh0LWNvbG9yOiB2YXIoLS10ZXh0LW5vcm1hbCk7XG4gICAgLS1oay1jb2RlYmxvY2stbGluZW5vcy10ZXh0LWNvbG9yOiB2YXIoLS1jb2RlLW5vcm1hbCk7XG4gICAgLS1oay1jb2RlYmxvY2stbGFuZ3VhZ2UtdGV4dC1jb2xvcjogdmFyKC0tdGV4dC1tdXRlZCk7IC8vIHNhbWUgd2l0aCBjb3B5IGJ1dHRvblxuICAgIC0taGstY29kZWJsb2NrLWxhbmd1YWdlLXRleHQtc2l6ZTogdmFyKC0tZm9udC11aS1zbWFsbGVyKTsgLy8gc2FtZSB3aXRoIGNvcHkgYnV0dG9uXG4gICAgLS1oay1jb2RlYmxvY2stbGFuZ3VhZ2UtdGV4dC1mb250OiB2YXIoLS1mb250LWludGVyZmFjZSk7IC8vIHNhbWUgd2l0aCBjb3B5IGJ1dHRvblxuICAgIC0taGstY29kZWJsb2NrLXByb21wdC10ZXh0LWNvbG9yOiB2YXIoLS1jb2RlLW5vcm1hbCk7XG4gICAgLS1oay1jb2RlYmxvY2stcmVzdWx0LXRleHQtY29sb3I6IHZhcigtLXRleHQtbm9ybWFsKTtcbiAgfVxuXG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgYmFja2dyb3VuZC1jb2xvcjogdmFyKC0taGstY29kZWJsb2NrLWJhY2tncm91bmQtY29sb3IpO1xuICBtYXJnaW4tYm90dG9tOiB2YXIoLS1oay1jb2RlYmxvY2stbWFyZ2luKTtcblxuICBwcmUge1xuICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gICAgbWFyZ2luOiAwO1xuICAgIHBhZGRpbmctdG9wOiB2YXIoLS1oay1jb2RlYmxvY2stdmVydGljYWwtcGFkZGluZyk7XG4gICAgcGFkZGluZy1ib3R0b206IHZhcigtLWhrLWNvZGVibG9jay12ZXJ0aWNhbC1wYWRkaW5nKTtcbiAgICBwYWRkaW5nLWxlZnQ6IHZhcigtLWhrLWNvZGVibG9jay1ob3Jpem9udGFsLXBhZGRpbmcpO1xuICAgIHBhZGRpbmctcmlnaHQ6IHZhcigtLWhrLWNvZGVibG9jay1ob3Jpem9udGFsLXBhZGRpbmcpO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWhrLWNvZGVibG9jay1iYWNrZ3JvdW5kLWNvbG9yKTtcblxuICAgIGNvZGUuaGstY29kZWJsb2NrLWNvZGUge1xuICAgICAgd2hpdGUtc3BhY2U6IHByZTtcbiAgICAgIG92ZXJmbG93LXg6IGF1dG87XG4gICAgICBwYWRkaW5nOiAwO1xuICAgIH1cbiAgfVxufVxuXG4vKiB0aXRsZSAqL1xuLmhrLWNvZGVibG9jay5oay1jb2RlYmxvY2stc2hvdy10aXRsZSB7XG4gIC5oay1jb2RlYmxvY2stdGl0bGUge1xuICAgIHBhZGRpbmctbGVmdDogdmFyKC0taGstY29kZWJsb2NrLWhvcml6b250YWwtcGFkZGluZyk7XG4gICAgcGFkZGluZy1yaWdodDogdmFyKC0taGstY29kZWJsb2NrLWhvcml6b250YWwtcGFkZGluZyk7XG4gICAgcGFkZGluZy10b3A6IHZhcigtLWhrLWNvZGVibG9jay12ZXJ0aWNhbC1wYWRkaW5nKTtcbiAgICBwYWRkaW5nLWJvdHRvbTogdmFyKC0taGstY29kZWJsb2NrLXZlcnRpY2FsLXBhZGRpbmcpO1xuICAgIGJhY2tncm91bmQtY29sb3I6IHZhcigtLWhrLWNvZGVibG9jay1iYWNrZ3JvdW5kLWNvbG9yKTtcbiAgICBib3JkZXItYm90dG9tOiAxcHggc29saWQgdmFyKC0taGstY29kZWJsb2NrLWJvcmRlci1jb2xvcik7XG4gICAgY29sb3I6IHZhcigtLWhrLWNvZGVibG9jay10aXRsZS10ZXh0LWNvbG9yKTtcbiAgfVxuXG4gIC5oay1jb2RlYmxvY2stdGl0bGV+cHJlIHtcbiAgICBtYXJnaW4tdG9wOiAwO1xuICB9XG59XG5cbi8qIGxpbmVub3MgKi9cbi5oay1jb2RlYmxvY2suaGstY29kZWJsb2NrLXNob3ctbGluZW5vcyB7XG4gIHByZSB7XG4gICAgY29kZS5oay1jb2RlYmxvY2stbGluZW5vcyB7XG4gICAgICBmbGV4LXNocmluazogMDtcbiAgICAgIGZsZXgtZ3JvdzogMDtcbiAgICAgIHRleHQtYWxpZ246IHJpZ2h0O1xuICAgICAgcGFkZGluZy1yaWdodDogMWVtO1xuICAgICAgb3BhY2l0eTogMC42O1xuICAgICAgdXNlci1zZWxlY3Q6IG5vbmU7XG4gICAgICBjb2xvcjogdmFyKC0taGstY29kZWJsb2NrLWxpbmVub3MtdGV4dC1jb2xvcik7XG5cbiAgICAgICYuc2hvdy1zcGxpdHRlciB7XG4gICAgICAgIGJvcmRlci1yaWdodDogMXB4IHNvbGlkIHZhcigtLWhrLWNvZGVibG9jay1ib3JkZXItY29sb3IpO1xuICAgICAgICBtYXJnaW4tcmlnaHQ6IDFlbTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyogaGlnaGxpZ2h0ICovXG4uaGstY29kZWJsb2NrLmhrLWNvZGVibG9jay1zaG93LWhpZ2hsaWdodCB7XG4gIHByZSB7XG4gICAgY29kZS5oay1jb2RlYmxvY2staGlnaGxpZ2h0IHtcbiAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgdG9wOiAwO1xuICAgICAgbGVmdDogMDtcbiAgICAgIHJpZ2h0OiAwO1xuICAgICAgYm90dG9tOiAwO1xuICAgICAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG4gICAgICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgICAgIHBhZGRpbmctdG9wOiB2YXIoLS1oay1jb2RlYmxvY2stdmVydGljYWwtcGFkZGluZyk7XG4gICAgICBwYWRkaW5nLWJvdHRvbTogdmFyKC0taGstY29kZWJsb2NrLXZlcnRpY2FsLXBhZGRpbmcpO1xuICAgICAgb3BhY2l0eTogMC4yO1xuXG4gICAgICAubGluZS5oaWdobGlnaHQge1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB2YXIoLS1oay1jb2RlYmxvY2staGlnaGxpZ2h0LWJhY2tncm91bmQtY29sb3IpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG4vKiBsYW5ndWFnZSAqL1xuLmhrLWNvZGVibG9jay5oay1jb2RlYmxvY2stc2hvdy1sYW5ndWFnZSB7XG4gIHByZSB7XG4gICAgLmhrLWNvZGVibG9jay1sYW5ndWFnZSB7XG4gICAgICBvcGFjaXR5OiAwLjQ7XG4gICAgICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgICAgIHotaW5kZXg6IDE7XG4gICAgICBtYXJnaW46IDZweDtcbiAgICAgIHBhZGRpbmc6IDZweCA4cHg7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiB0cmFuc3BhcmVudDtcbiAgICAgIGJveC1zaGFkb3c6IG5vbmU7XG4gICAgICBjb2xvcjogdmFyKC0taGstY29kZWJsb2NrLWxhbmd1YWdlLXRleHQtY29sb3IpO1xuICAgICAgZm9udC1zaXplOiB2YXIoLS1oay1jb2RlYmxvY2stbGFuZ3VhZ2UtdGV4dC1zaXplKTtcbiAgICAgIGZvbnQtZmFtaWx5OiB2YXIoLS1oay1jb2RlYmxvY2stbGFuZ3VhZ2UtdGV4dC1mb250KTtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIHRvcDogMDtcbiAgICAgIHJpZ2h0OiAwO1xuICAgIH1cblxuICAgICY6aG92ZXIgLmhrLWNvZGVibG9jay1sYW5ndWFnZSB7XG4gICAgICBkaXNwbGF5OiBub25lO1xuICAgIH1cbiAgfVxufVxuXG4vKiBjb3B5IGJ1dHRvbiAqL1xuLmhrLWNvZGVibG9jay5oay1jb2RlYmxvY2stc2hvdy1jb3B5YnRuIHtcbiAgcHJlIHtcbiAgICAuY29weS1jb2RlLWJ1dHRvbiB7XG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgfVxuICB9XG59XG5cbi8qIHByb21wdCAqL1xuLmhrLWNvZGVibG9jay5oay1jb2RlYmxvY2stc2hvdy1wcm9tcHQge1xuICBwcmUge1xuICAgIGNvZGUuaGstY29kZWJsb2NrLWNvZGUge1xuICAgICAgLmNvbW1hbmQtbGluZS1wcm9tcHQge1xuICAgICAgICBkaXNwbGF5OiBibG9jaztcbiAgICAgICAgZmxvYXQ6IGxlZnQ7XG4gICAgICAgIGZvbnQtc2l6ZTogMTAwJTtcbiAgICAgICAgdGV4dC1hbGlnbjogcmlnaHQ7XG4gICAgICAgIHVzZXItc2VsZWN0OiBub25lO1xuXG4gICAgICAgICY+c3Bhbjo6YmVmb3JlIHtcbiAgICAgICAgICBvcGFjaXR5OiAwLjY7XG4gICAgICAgICAgY29udGVudDogJyAnO1xuICAgICAgICAgIGRpc3BsYXk6IGJsb2NrO1xuICAgICAgICAgIG1hcmdpbi1yaWdodDogMC42ZW07XG4gICAgICAgICAgY29sb3I6IHZhcigtLWhrLWNvZGVibG9jay1wcm9tcHQtdGV4dC1jb2xvcik7XG4gICAgICAgIH1cblxuICAgICAgICAmPnNwYW5bZGF0YS1wcm9tcHRdOjpiZWZvcmUge1xuICAgICAgICAgIGNvbnRlbnQ6IGF0dHIoZGF0YS1wcm9tcHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgJj5zcGFuW2RhdGEtY29udGludWF0aW9uLXByb21wdF06OmJlZm9yZSB7XG4gICAgICAgICAgY29udGVudDogYXR0cihkYXRhLWNvbnRpbnVhdGlvbi1wcm9tcHQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8qIHJlc3VsdCAqL1xuLmhrLWNvZGVibG9jaysuaGstY29kZWJsb2NrLmhrLWNvZGVibG9jay1yZXN1bHQge1xuICBtYXJnaW4tdG9wOiBjYWxjKHZhcigtLWhrLWNvZGVibG9jay1tYXJnaW4pICogKC0xKSk7XG4gIGJvcmRlci10b3A6IDFweCBzb2xpZCB2YXIoLS1oay1jb2RlYmxvY2stYm9yZGVyLWNvbG9yKTtcblxuICAmOjpiZWZvcmUge1xuICAgIGNvbnRlbnQ6IGF0dHIoZGF0YS1yZXN1bHQtcHJvbXB0KTtcbiAgICBkaXNwbGF5OiBibG9jaztcbiAgICBjb2xvcjogdmFyKC0taGstY29kZWJsb2NrLXJlc3VsdC10ZXh0LWNvbG9yKTtcbiAgICBvcGFjaXR5OiAwLjY7XG4gICAgZm9udC1zaXplOiAwLjhlbTtcbiAgICBwYWRkaW5nLXRvcDogdmFyKC0taGstY29kZWJsb2NrLXZlcnRpY2FsLXBhZGRpbmcpO1xuICAgIHBhZGRpbmctbGVmdDogdmFyKC0taGstY29kZWJsb2NrLWhvcml6b250YWwtcGFkZGluZyk7XG4gICAgcGFkZGluZy1yaWdodDogdmFyKC0taGstY29kZWJsb2NrLWhvcml6b250YWwtcGFkZGluZyk7XG4gIH1cblxuICBwcmUge1xuICAgIG1hcmdpbi10b3A6IDA7XG5cbiAgICAuaGstY29kZWJsb2NrLXJlc3VsdC1jb2RlIHtcbiAgICAgIGNvbG9yOiB2YXIoLS1oay1jb2RlYmxvY2stcmVzdWx0LXRleHQtY29sb3IpO1xuICAgIH1cbiAgfVxufSJdLAogICJtYXBwaW5ncyI6ICI7QUFBQTtBQWlCRTtBQUNBO0FBQ0E7O0FBbEJBO0FBRUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQU9GO0FBQ0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0U7QUFDQTtBQUNBOztBQU9KO0FBQ0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBR0Y7QUFDRTs7QUFPQTtBQUNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0U7QUFDQTs7QUFTSjtBQUNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNFOztBQVNKO0FBQ0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBR0Y7QUFDRTs7QUFRRjtBQUNFOztBQVNBO0FBQ0U7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBR0Y7QUFDRTs7QUFHRjtBQUNFOztBQVFWO0FBQ0U7QUFDQTs7QUFFQTtBQUNFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBR0Y7QUFDRTs7QUFFQTtBQUNFOzsiLAogICJuYW1lcyI6IFtdCn0K */
diff --git a/dist/versions.json b/dist/versions.json
new file mode 100644
index 0000000..9be1f3d
--- /dev/null
+++ b/dist/versions.json
@@ -0,0 +1,3 @@
+{
+	"0.1.0": "0.15.0"
+}
diff --git a/esbuild.config.mjs b/esbuild.config.mjs
index b13282b..8bc1049 100644
--- a/esbuild.config.mjs
+++ b/esbuild.config.mjs
@@ -1,9 +1,10 @@
 import esbuild from "esbuild";
 import process from "process";
 import builtins from "builtin-modules";
+import { sassPlugin } from "esbuild-sass-plugin";
 
 const banner =
-`/*
+	`/*
 THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
 if you want to view the source, please visit the github repository of this plugin
 */
@@ -15,7 +16,10 @@ const context = await esbuild.context({
 	banner: {
 		js: banner,
 	},
-	entryPoints: ["main.ts"],
+	entryPoints: [
+		"./src/styles.scss",
+		"./src/main.ts"
+	],
 	bundle: true,
 	external: [
 		"obsidian",
@@ -37,7 +41,8 @@ const context = await esbuild.context({
 	logLevel: "info",
 	sourcemap: prod ? false : "inline",
 	treeShaking: true,
-	outfile: "main.js",
+	outdir: "./dist",
+	plugins: [sassPlugin()]
 });
 
 if (prod) {
diff --git a/imgs/copybtn.png b/imgs/copybtn.png
new file mode 100644
index 0000000000000000000000000000000000000000..6c942af277707a956a40bb137e8763cf8a867b9a
GIT binary patch
literal 6021
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�!#y$epWo(^_=Y7#$ng0^xkw{y
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
Z+30(jx7D>z&%c@=Da)(NRm)g>`WF)DH%kBj

literal 0
HcmV?d00001

diff --git a/imgs/language1.png b/imgs/language1.png
new file mode 100644
index 0000000000000000000000000000000000000000..29881408f6c5c721c759fc2b5c3832d1af0439b5
GIT binary patch
literal 5925
zcmb7|XHXMNyM_@3DT2~FNRf_FKzcx$2m+C!NDUoDdJTk-7YQIBy|*B~h%^I8mC%cH
zLhmF3La3qFP!8{$KWFC5_kHL5*z(LgyF0VHbKi44kuUYNXsFn!NJvO%w4ZAjl91d`
zyPkibAiwUVBwMquha298T52SyLC&@7;FgoBo+=4RMI80H4cT=}>G9mun}me6{hxND
z%e~N^goL?XTSL_tVzre6c43@s>}qb*yDviRW*gyFm!Mg3ldQzxdD0pE@)vWvct
zFJfoE3F~na6jF4+Q5I~cls06;X&=TQ+v=mjpwJe;muM`ewhBtEX%T(o*==>Yn&fi1)xywE)c5wtj4D|b>14um3Vf?CUUGm(swn^SV4_AS&ako&8HcYh3yCm
zq!6@-n~xL}6^Ao)W)0Pze-9D~E4SOGvwwCJi8EGVZgX_?`TUcz+v>c9fFp5}*^Y~+
z8sfh`6S;bI_Gv}oY$l-`T_+vVN&vD}qSqfEy7zFA4eG3}guAY5`rK^ie+u$1F>!Ql
zX_T=yp`1msuW4-W`w9KEGAQ8UQjU(YE33+343`AHr5T$RdlB0l)uR`eR?gN0W@aFw
z%kk;+zK^#i!+S1nhgjh=JrpT3Z?3FL!G
zx3$)#din2!8HzA4~ueiplwr6JPPv%o}%pX#dd3n|%en>-lRb_avtoT<7B``v
za3PPO?4_vB`o_>4od1Kw-L>QyWFlDfuUM|o1NSm_-22K2Hz5RS&noK3yg*SzZNVam
z11c)qs=Pxyd=9xo_6sk}KG4^a7hca+b>(Gemdkc}Df+CVNi^F?^7Uo~$zI|rj&xL+
zv2`X=5HXvTkX$=qffCa2Fg%J8=R*IjiF->x#4oAyiPN}FF|*#24DfQFlBO-GV-$Je
zGUG@l9meAyHbjqOzz#ks@!1k{L*TN;#kT3uPXFes4k)qFy7z=lPDltDVbp
zQ%=y~sk8!}p25R`Jo_0OMR{Xcu&8aV^;_nUkA5Q}8+jS6%d~B_5QYa8U%@V#mU13o
z!PFvo5xp;_VAh$`^;hz~{e@ji;mc%@4@$npRQ7SicKvY1O2S1jNr4w@f`v(`6l4Fa}S?
zes?{sg%{O`N8>{nUohnpSmFv=>^wzat`|iMR!nDGq0w#>*6#ENZ3=VpE&bP=b9u1S
zK59_+AvaM=tK`wLRW%UELoHp&X#$FrOpn(^(TEo(Z@72T;7dNAK?CHMCfxjYd2s~6
z+eOrFZa%iN(rMI(-mM``ARA%EqlqzEox=G6KJ$#1N`_#j93w-#2csaKDJt*b{biQu
zep{o5hLqg=0enz|wk-ThuC^R+X!t<8)BN0Pl^HBYDQ}QO{!k4{GFKc>-W0!f>bG29
z%Eh*m>E5%FxV(6}ZX2g)9X+LyRJ*=4y>UZy<-L7*T)#~OTrXE}bsoe$w#40W%L2`|
zSqG^Lf~@FLT(OtM@d*q+X^`dixD3u{dX_ED5``BmMuM&KZ;p8Y4r>}y-dwS>nX_Cp
zShF`?_Cg1dwR;;!>NYs{Up+&%+Im}`v$=k)t_PvBG;6#Te6B^IwDMD#tyRHHQef8k
zO5(}ys};mmG}pCx8E0HOMLdA#-#OR+!{q)isSIoI3iBG5j0;T)URj~ZGH`7(Ri4&=
zvd{mpvzsXI`ECvFcjG)@X%$xUnc&hgin(A{fsYZ`6W?-PDia7VNX*SWYtP++dbu+J
z6IioK;9s*Y6&MMa`PSoUS^?KJy{BP#s>GIFT%GIs78J8l)!1%_Zii`fpMQ+hI-#&S
z$?YXQn63L)eSi%7?D2&~Osq3fBxr13q2O*#>l5=od!3gI>8VRRO*z#M
zWGR`D@0-pEtGUAmC*F|2za{S5Bj=3OPG*-d)}tXjHh6T+XQa}Z_xbNE{LV}WZkjY#
z90k6C!hB@SiO1Dn$wEJhlb8l6-?qqlwd+5FUA|!1i8gWC9Wnw%-vxD_o94sgUIKqO
z{WTdJhepmt`WCpb^WQ#uWF5S*o4bfoxug)1ZTLi}HuGa*002Y3IUO7)$<@y`4@#Ky
z&SGbmW~seSbJS1bmfUB6G?DP|U$`rQdfCFl<64IFwSe2X(_cPFR&GaBoAz@lgop`k
zqT<36RV>3mmWs6Oe7I2`@=>(+-7OoGdEBxe%jh;E(g-n28^q(^k8IH*T80eA`-r7p
zEco^}3Zs`@@axbUVjV=wA_tSf-|bEXJ7MyzhI>Dy|5Q(!qByIMV{~I+&ushXPmd`~
zK40`~FD#`6+c(rFtW~cP0!Fy^-yE;@O4E%cr?3O_-Oa{=A4m%DG7V^m^TWlS_W
zG!X0c6dx-jY`q<}Zjzl=*#_}qC-w@w@R}7l8eVS(A7cc&Oi)_t`Ex~7gqv@UYFLgy
z$Js5}5ZJgkyL%&?ZG!;qCnSCCJv-bOs7W>*8#3&WOpMfO)Az0-81)|OUv4hFUyZH?-t)bp}zTJxj|+3Pfh6!EOWvRu!RNFoe#3r
zOS5ydH=18pTOif;-78*0&9%87wmHPdl?Xs|@jPtN@mdzrC
zV3t}c-Ue|7vU`&A+-?}2kpoImOJfIiAd#LJ;PLM!BD0I8w`yI5d|SBUkS$ykuitDB
zr`$fW8NE`Dz|G8u*{lEPxhxK2qYQ;%v}Ne-EN|Kr^u-B+I3DEb}AJbBGQBUezOCSi7hxpF2
z*R#<*4N3v@WHj$&-R3@S2jLYVe-gBYu-I4)KAQ$*iT%mDRhxMc+->1B9OZsnW~FA;
zRCiU*9}(&|9(tdbfG?Z}!=X8sYiS!Rfr)46uU|Xoq=HJZbN6|J=(Tt(qx+n27L0MA
z_T{@OWD~9wD+1o)@lLzbV1ewQog1Zd&eZGOEK4jN67gv-zAUufLY?zgSsR3#KZwG_
zM&o6(TB5G3!j>nfOCz=t3uWuQXxwUDy=FsZ8ts>QFfhcZU#|Ea|2fawgSjekvbZ3I
z+~6~jiSOnS(JX+)+^cgTc6RoDdGOWQr03SmlWb)e`{?LsUC^l{HgH2C=zO%H;%g-Jx
zD*A3D&na>pc;ts*Ug}0*j2mp#p~@MHu2fDoWCd6NHwJ0
zjZ|J}fAMU0IL}42i3ase2yO|9wKceyKps|H?9MKF%*YInZ)CjlHcfG9Y3DFmm_sjM
za-KJ4
z-k1U7vf9gncS(V5WF5zYgW2+Smt*(dw1W@N84qd4M;W+UuW#Rk--lhM@B<`(MhS<)Y$3#Wi5ze62c)ie!&a=GyHC7$bt
zY*gftKwliq-i&_G`Le;-;$R(KW7VQst?GL+?Q>{_
z8~sTCTON6hm5kvXM9#no0zJLaD%~~AV@xu$vaTH9XcbE?xY_M8z=)NwsX0Yu
zD#sUy7*UlxakL-ubG|J0zQ<5`6#w~VKD_Uf57N7#=-YGQ=_n)-G~*rqczh@}m~!CE
zB#yk-Pd@K6+uJO`#)b?xqEP(iL#DwP8<4*cc~>P?U}WEtPW+uvjMX%zX0!VN%IF=4
z6-`c?Qk9|8m!FXm;_gZti-EAPJP6}iL5`wTY7X$*0EhN3Fh{D`V
zg06H*P~SYFQzM|sBvu>R2V&v}VqiZ7^4+pPrbNxN2SQZAT+bYbuqF?8%aW9)taA7R
z{qMpGbo~u)wQ(o8LSA=u#aq0q;7jL;$l;p+wx%V&gv}=-vMZ@s_gwp=YP(qFDOkXI2v(9i;bYGG?I};)sO|@ox4=v(ku!oLLS@M%a58(fm9WQS
zfC7yA*8VkMZ(Rd6GaUKfl$_Y|r16OROqY`G&*#Zh{i2t(wv|jLV+@OwxhiG!%e%ME>V@f;
z*xokJ9Xfu7pL&iSP5HtmznD%)t1#nBJ_PVufDf-Q5xd&}L8m)qwrOkqRvM8LA>D2i
zZ(zZU6;Y`fsLw0Su{1h3>+2-FeYm3ijQx0ceXd}kF3S2bCP$nqf#t=BNY~+H>nqH5
zQ7@nSvBm0w%d2Mjzo$+~yixuJlnhqRg-KNmWmWexhd^oqb!%bH1g6hcu9A1prB&a0
z19LfkUDNT6OmK2{VIJLaAlV=Cm&?T!X`xa-xm4_jY8_Q6#9eUVHQ{{j)6Q~!R_B>P
zZ;hqswtP0{mzT@`oSLEk4h&#l_vz7~4);`5D0fYQXe@<>l%oXK#|8KEjC0c#uCch6
zU!%uK$EFfeFU7J)`Z}HdCrb>f)EN_GnC{$W_e^HM+5>*4RLC?+eD_gRcx`+t=T8qMsKHOiix7x}D3
zD#<)rmx%qDfT;S}{3c(%dxG%$L%3-<{WhUIAOKQCQFU;OIjmp)sP?+N6oB|u{^``x
zyce-g*9ALcvP5i922q=pmPs#CMdz_-o)E3fI%^q}o~^vFk9+ja%SHzOCD&0-%=}cp
zs!IxsXE~%8r*hp8-S62W-Js4ux|{6u&LpV9^U<%AYC-eyJ2XQ#n?IE{d(V~`WZR>OgrrIj-Q26HU~r4YA>Xm#)tDX
zK=rWrb{AbYEHecx>t0YqvGg5}nGO=owk`bXro+s@?>)5u9-X9>%N1kdAE{$$-TVQj
zIPqP>Nt=xI9WVzgL5GPS#zI$d*J|ILmMrRxK-}9~4*icc-G6Uf-hW-)){ux-%efO>
Ra9!Fa(bm-0K&e@O_%9cViB13j

literal 0
HcmV?d00001

diff --git a/imgs/language2.png b/imgs/language2.png
new file mode 100644
index 0000000000000000000000000000000000000000..27fc34fe9feaf43528042382c71a1e2d18424ada
GIT binary patch
literal 6016
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

literal 0
HcmV?d00001

diff --git a/imgs/linenos3.png b/imgs/linenos3.png
new file mode 100644
index 0000000000000000000000000000000000000000..f5bbad8fcfede7fd9978b854f8f77d95db358525
GIT binary patch
literal 6385
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

literal 0
HcmV?d00001

diff --git a/imgs/prompt1.png b/imgs/prompt1.png
new file mode 100644
index 0000000000000000000000000000000000000000..e1ea7ceca26e5935e3fb4166d64c476e39e1b52b
GIT binary patch
literal 5197
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
a^JjM5k5amYkB?9S1gI%%D^-JDhyDvPXU~EF

literal 0
HcmV?d00001

diff --git a/imgs/prompt2.png b/imgs/prompt2.png
new file mode 100644
index 0000000000000000000000000000000000000000..0a9c05089bbaf6d7bd4d336c3c4b3c6392407580
GIT binary patch
literal 5131
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

literal 0
HcmV?d00001

diff --git a/imgs/result1.png b/imgs/result1.png
new file mode 100644
index 0000000000000000000000000000000000000000..ffedc2c95340f61367ffd5d9c13d142a5b1d3d24
GIT binary patch
literal 7605
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

literal 0
HcmV?d00001

diff --git a/imgs/title.png b/imgs/title.png
new file mode 100644
index 0000000000000000000000000000000000000000..dee37e4b97b7f9a889c31beabcbc575811ef77e4
GIT binary patch
literal 7345
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 {
-			// Called when the user clicks the icon.
-			new Notice('This is a notice!');
-		});
-		// Perform additional things with the ribbon
-		ribbonIconEl.addClass('my-plugin-ribbon-class');
-
-		// This adds a status bar item to the bottom of the app. Does not work on mobile apps.
-		const statusBarItemEl = this.addStatusBarItem();
-		statusBarItemEl.setText('Status Bar Text');
-
-		// This adds a simple command that can be triggered anywhere
-		this.addCommand({
-			id: 'open-sample-modal-simple',
-			name: 'Open sample modal (simple)',
-			callback: () => {
-				new SampleModal(this.app).open();
-			}
-		});
-		// This adds an editor command that can perform some operation on the current editor instance
-		this.addCommand({
-			id: 'sample-editor-command',
-			name: 'Sample editor command',
-			editorCallback: (editor: Editor, view: MarkdownView) => {
-				console.log(editor.getSelection());
-				editor.replaceSelection('Sample Editor Command');
-			}
-		});
-		// This adds a complex command that can check whether the current state of the app allows execution of the command
-		this.addCommand({
-			id: 'open-sample-modal-complex',
-			name: 'Open sample modal (complex)',
-			checkCallback: (checking: boolean) => {
-				// Conditions to check
-				const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView);
-				if (markdownView) {
-					// If checking is true, we're simply "checking" if the command can be run.
-					// If checking is false, then we want to actually perform the operation.
-					if (!checking) {
-						new SampleModal(this.app).open();
-					}
-
-					// This command will only show up in Command Palette when the check function returns true
-					return true;
-				}
-			}
-		});
-
-		// This adds a settings tab so the user can configure various aspects of the plugin
-		this.addSettingTab(new SampleSettingTab(this.app, this));
-
-		// If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin)
-		// Using this function will automatically remove the event listener when this plugin is disabled.
-		this.registerDomEvent(document, 'click', (evt: MouseEvent) => {
-			console.log('click', evt);
-		});
-
-		// When registering intervals, this function will automatically clear the interval when the plugin is disabled.
-		this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000));
-	}
-
-	onunload() {
-
-	}
-
-	async loadSettings() {
-		this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
-	}
-
-	async saveSettings() {
-		await this.saveData(this.settings);
-	}
-}
-
-class SampleModal extends Modal {
-	constructor(app: App) {
-		super(app);
-	}
-
-	onOpen() {
-		const {contentEl} = this;
-		contentEl.setText('Woah!');
-	}
-
-	onClose() {
-		const {contentEl} = this;
-		contentEl.empty();
-	}
-}
-
-class SampleSettingTab extends PluginSettingTab {
-	plugin: MyPlugin;
-
-	constructor(app: App, plugin: MyPlugin) {
-		super(app, plugin);
-		this.plugin = plugin;
-	}
-
-	display(): void {
-		const {containerEl} = this;
-
-		containerEl.empty();
-
-		containerEl.createEl('h2', {text: 'Settings for my awesome plugin.'});
-
-		new Setting(containerEl)
-			.setName('Setting #1')
-			.setDesc('It\'s a secret')
-			.addText(text => text
-				.setPlaceholder('Enter your secret')
-				.setValue(this.plugin.settings.mySetting)
-				.onChange(async (value) => {
-					console.log('Secret: ' + value);
-					this.plugin.settings.mySetting = value;
-					await this.plugin.saveSettings();
-				}));
-	}
-}
diff --git a/manifest.json b/manifest.json
deleted file mode 100644
index 0897aff..0000000
--- a/manifest.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-	"id": "obsidian-sample-plugin",
-	"name": "Sample Plugin",
-	"version": "1.0.0",
-	"minAppVersion": "0.15.0",
-	"description": "This is a sample plugin for Obsidian. This plugin demonstrates some of the capabilities of the Obsidian API.",
-	"author": "Obsidian",
-	"authorUrl": "https://obsidian.md",
-	"fundingUrl": "https://obsidian.md/pricing",
-	"isDesktopOnly": false
-}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..24ba3ba
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,4582 @@
+{
+	"name": "obsidian-hk-code-block",
+	"version": "1.0.0",
+	"lockfileVersion": 2,
+	"requires": true,
+	"packages": {
+		"": {
+			"name": "obsidian-hk-code-block",
+			"version": "1.0.0",
+			"license": "MIT",
+			"devDependencies": {
+				"@types/node": "^16.11.6",
+				"@typescript-eslint/eslint-plugin": "5.29.0",
+				"@typescript-eslint/parser": "5.29.0",
+				"builtin-modules": "3.3.0",
+				"esbuild": "0.17.3",
+				"esbuild-sass-plugin": "^2.4.5",
+				"obsidian": "latest",
+				"tslib": "2.4.0",
+				"typescript": "4.7.4"
+			}
+		},
+		"node_modules/@codemirror/state": {
+			"version": "6.2.0",
+			"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.0.tgz",
+			"integrity": "sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/@codemirror/view": {
+			"version": "6.7.3",
+			"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.7.3.tgz",
+			"integrity": "sha512-Lt+4POnhXrZFfHOdPzXEHxrzwdy7cjqYlMkOWvoFGi6/bAsjzlFfr0NY3B15B/PGx+cDFgM1hlc12wvYeZbGLw==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"@codemirror/state": "^6.1.4",
+				"style-mod": "^4.0.0",
+				"w3c-keyname": "^2.2.4"
+			}
+		},
+		"node_modules/@esbuild/android-arm": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.3.tgz",
+			"integrity": "sha512-1Mlz934GvbgdDmt26rTLmf03cAgLg5HyOgJN+ZGCeP3Q9ynYTNMn2/LQxIl7Uy+o4K6Rfi2OuLsr12JQQR8gNg==",
+			"cpu": [
+				"arm"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"android"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/android-arm64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.3.tgz",
+			"integrity": "sha512-XvJsYo3dO3Pi4kpalkyMvfQsjxPWHYjoX4MDiB/FUM4YMfWcXa5l4VCwFWVYI1+92yxqjuqrhNg0CZg3gSouyQ==",
+			"cpu": [
+				"arm64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"android"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/android-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.3.tgz",
+			"integrity": "sha512-nuV2CmLS07Gqh5/GrZLuqkU9Bm6H6vcCspM+zjp9TdQlxJtIe+qqEXQChmfc7nWdyr/yz3h45Utk1tUn8Cz5+A==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"android"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/darwin-arm64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.3.tgz",
+			"integrity": "sha512-01Hxaaat6m0Xp9AXGM8mjFtqqwDjzlMP0eQq9zll9U85ttVALGCGDuEvra5Feu/NbP5AEP1MaopPwzsTcUq1cw==",
+			"cpu": [
+				"arm64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"darwin"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/darwin-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.3.tgz",
+			"integrity": "sha512-Eo2gq0Q/er2muf8Z83X21UFoB7EU6/m3GNKvrhACJkjVThd0uA+8RfKpfNhuMCl1bKRfBzKOk6xaYKQZ4lZqvA==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"darwin"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/freebsd-arm64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.3.tgz",
+			"integrity": "sha512-CN62ESxaquP61n1ZjQP/jZte8CE09M6kNn3baos2SeUfdVBkWN5n6vGp2iKyb/bm/x4JQzEvJgRHLGd5F5b81w==",
+			"cpu": [
+				"arm64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"freebsd"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/freebsd-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.3.tgz",
+			"integrity": "sha512-feq+K8TxIznZE+zhdVurF3WNJ/Sa35dQNYbaqM/wsCbWdzXr5lyq+AaTUSER2cUR+SXPnd/EY75EPRjf4s1SLg==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"freebsd"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/linux-arm": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.3.tgz",
+			"integrity": "sha512-CLP3EgyNuPcg2cshbwkqYy5bbAgK+VhyfMU7oIYyn+x4Y67xb5C5ylxsNUjRmr8BX+MW3YhVNm6Lq6FKtRTWHQ==",
+			"cpu": [
+				"arm"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/linux-arm64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.3.tgz",
+			"integrity": "sha512-JHeZXD4auLYBnrKn6JYJ0o5nWJI9PhChA/Nt0G4MvLaMrvXuWnY93R3a7PiXeJQphpL1nYsaMcoV2QtuvRnF/g==",
+			"cpu": [
+				"arm64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/linux-ia32": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.3.tgz",
+			"integrity": "sha512-FyXlD2ZjZqTFh0sOQxFDiWG1uQUEOLbEh9gKN/7pFxck5Vw0qjWSDqbn6C10GAa1rXJpwsntHcmLqydY9ST9ZA==",
+			"cpu": [
+				"ia32"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/linux-loong64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.3.tgz",
+			"integrity": "sha512-OrDGMvDBI2g7s04J8dh8/I7eSO+/E7nMDT2Z5IruBfUO/RiigF1OF6xoH33Dn4W/OwAWSUf1s2nXamb28ZklTA==",
+			"cpu": [
+				"loong64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/linux-mips64el": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.3.tgz",
+			"integrity": "sha512-DcnUpXnVCJvmv0TzuLwKBC2nsQHle8EIiAJiJ+PipEVC16wHXaPEKP0EqN8WnBe0TPvMITOUlP2aiL5YMld+CQ==",
+			"cpu": [
+				"mips64el"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/linux-ppc64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.3.tgz",
+			"integrity": "sha512-BDYf/l1WVhWE+FHAW3FzZPtVlk9QsrwsxGzABmN4g8bTjmhazsId3h127pliDRRu5674k1Y2RWejbpN46N9ZhQ==",
+			"cpu": [
+				"ppc64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/linux-riscv64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.3.tgz",
+			"integrity": "sha512-WViAxWYMRIi+prTJTyV1wnqd2mS2cPqJlN85oscVhXdb/ZTFJdrpaqm/uDsZPGKHtbg5TuRX/ymKdOSk41YZow==",
+			"cpu": [
+				"riscv64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/linux-s390x": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.3.tgz",
+			"integrity": "sha512-Iw8lkNHUC4oGP1O/KhumcVy77u2s6+KUjieUqzEU3XuWJqZ+AY7uVMrrCbAiwWTkpQHkr00BuXH5RpC6Sb/7Ug==",
+			"cpu": [
+				"s390x"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/linux-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.3.tgz",
+			"integrity": "sha512-0AGkWQMzeoeAtXQRNB3s4J1/T2XbigM2/Mn2yU1tQSmQRmHIZdkGbVq2A3aDdNslPyhb9/lH0S5GMTZ4xsjBqg==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/netbsd-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.3.tgz",
+			"integrity": "sha512-4+rR/WHOxIVh53UIQIICryjdoKdHsFZFD4zLSonJ9RRw7bhKzVyXbnRPsWSfwybYqw9sB7ots/SYyufL1mBpEg==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"netbsd"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/openbsd-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.3.tgz",
+			"integrity": "sha512-cVpWnkx9IYg99EjGxa5Gc0XmqumtAwK3aoz7O4Dii2vko+qXbkHoujWA68cqXjhh6TsLaQelfDO4MVnyr+ODeA==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"openbsd"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/sunos-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.3.tgz",
+			"integrity": "sha512-RxmhKLbTCDAY2xOfrww6ieIZkZF+KBqG7S2Ako2SljKXRFi+0863PspK74QQ7JpmWwncChY25JTJSbVBYGQk2Q==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"sunos"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/win32-arm64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.3.tgz",
+			"integrity": "sha512-0r36VeEJ4efwmofxVJRXDjVRP2jTmv877zc+i+Pc7MNsIr38NfsjkQj23AfF7l0WbB+RQ7VUb+LDiqC/KY/M/A==",
+			"cpu": [
+				"arm64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"win32"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/win32-ia32": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.3.tgz",
+			"integrity": "sha512-wgO6rc7uGStH22nur4aLFcq7Wh86bE9cOFmfTr/yxN3BXvDEdCSXyKkO+U5JIt53eTOgC47v9k/C1bITWL/Teg==",
+			"cpu": [
+				"ia32"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"win32"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@esbuild/win32-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.3.tgz",
+			"integrity": "sha512-FdVl64OIuiKjgXBjwZaJLKp0eaEckifbhn10dXWhysMJkWblg3OEEGKSIyhiD5RSgAya8WzP3DNkngtIg3Nt7g==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"win32"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/@eslint/eslintrc": {
+			"version": "1.4.1",
+			"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz",
+			"integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"ajv": "^6.12.4",
+				"debug": "^4.3.2",
+				"espree": "^9.4.0",
+				"globals": "^13.19.0",
+				"ignore": "^5.2.0",
+				"import-fresh": "^3.2.1",
+				"js-yaml": "^4.1.0",
+				"minimatch": "^3.1.2",
+				"strip-json-comments": "^3.1.1"
+			},
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			},
+			"funding": {
+				"url": "https://opencollective.com/eslint"
+			}
+		},
+		"node_modules/@humanwhocodes/config-array": {
+			"version": "0.11.8",
+			"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
+			"integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"@humanwhocodes/object-schema": "^1.2.1",
+				"debug": "^4.1.1",
+				"minimatch": "^3.0.5"
+			},
+			"engines": {
+				"node": ">=10.10.0"
+			}
+		},
+		"node_modules/@humanwhocodes/module-importer": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+			"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=12.22"
+			},
+			"funding": {
+				"type": "github",
+				"url": "https://github.com/sponsors/nzakas"
+			}
+		},
+		"node_modules/@humanwhocodes/object-schema": {
+			"version": "1.2.1",
+			"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+			"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/@nodelib/fs.scandir": {
+			"version": "2.1.5",
+			"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+			"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+			"dev": true,
+			"dependencies": {
+				"@nodelib/fs.stat": "2.0.5",
+				"run-parallel": "^1.1.9"
+			},
+			"engines": {
+				"node": ">= 8"
+			}
+		},
+		"node_modules/@nodelib/fs.stat": {
+			"version": "2.0.5",
+			"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+			"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+			"dev": true,
+			"engines": {
+				"node": ">= 8"
+			}
+		},
+		"node_modules/@nodelib/fs.walk": {
+			"version": "1.2.8",
+			"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+			"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+			"dev": true,
+			"dependencies": {
+				"@nodelib/fs.scandir": "2.1.5",
+				"fastq": "^1.6.0"
+			},
+			"engines": {
+				"node": ">= 8"
+			}
+		},
+		"node_modules/@types/codemirror": {
+			"version": "0.0.108",
+			"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz",
+			"integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==",
+			"dev": true,
+			"dependencies": {
+				"@types/tern": "*"
+			}
+		},
+		"node_modules/@types/estree": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
+			"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
+			"dev": true
+		},
+		"node_modules/@types/json-schema": {
+			"version": "7.0.11",
+			"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+			"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+			"dev": true
+		},
+		"node_modules/@types/node": {
+			"version": "16.18.12",
+			"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz",
+			"integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==",
+			"dev": true
+		},
+		"node_modules/@types/tern": {
+			"version": "0.23.4",
+			"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
+			"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
+			"dev": true,
+			"dependencies": {
+				"@types/estree": "*"
+			}
+		},
+		"node_modules/@typescript-eslint/eslint-plugin": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz",
+			"integrity": "sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/scope-manager": "5.29.0",
+				"@typescript-eslint/type-utils": "5.29.0",
+				"@typescript-eslint/utils": "5.29.0",
+				"debug": "^4.3.4",
+				"functional-red-black-tree": "^1.0.1",
+				"ignore": "^5.2.0",
+				"regexpp": "^3.2.0",
+				"semver": "^7.3.7",
+				"tsutils": "^3.21.0"
+			},
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependencies": {
+				"@typescript-eslint/parser": "^5.0.0",
+				"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+			},
+			"peerDependenciesMeta": {
+				"typescript": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@typescript-eslint/parser": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz",
+			"integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/scope-manager": "5.29.0",
+				"@typescript-eslint/types": "5.29.0",
+				"@typescript-eslint/typescript-estree": "5.29.0",
+				"debug": "^4.3.4"
+			},
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependencies": {
+				"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+			},
+			"peerDependenciesMeta": {
+				"typescript": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@typescript-eslint/scope-manager": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz",
+			"integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "5.29.0",
+				"@typescript-eslint/visitor-keys": "5.29.0"
+			},
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/@typescript-eslint/type-utils": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz",
+			"integrity": "sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/utils": "5.29.0",
+				"debug": "^4.3.4",
+				"tsutils": "^3.21.0"
+			},
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependencies": {
+				"eslint": "*"
+			},
+			"peerDependenciesMeta": {
+				"typescript": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@typescript-eslint/types": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz",
+			"integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==",
+			"dev": true,
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/@typescript-eslint/typescript-estree": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz",
+			"integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "5.29.0",
+				"@typescript-eslint/visitor-keys": "5.29.0",
+				"debug": "^4.3.4",
+				"globby": "^11.1.0",
+				"is-glob": "^4.0.3",
+				"semver": "^7.3.7",
+				"tsutils": "^3.21.0"
+			},
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependenciesMeta": {
+				"typescript": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/@typescript-eslint/utils": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz",
+			"integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==",
+			"dev": true,
+			"dependencies": {
+				"@types/json-schema": "^7.0.9",
+				"@typescript-eslint/scope-manager": "5.29.0",
+				"@typescript-eslint/types": "5.29.0",
+				"@typescript-eslint/typescript-estree": "5.29.0",
+				"eslint-scope": "^5.1.1",
+				"eslint-utils": "^3.0.0"
+			},
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			},
+			"peerDependencies": {
+				"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+			}
+		},
+		"node_modules/@typescript-eslint/visitor-keys": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz",
+			"integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==",
+			"dev": true,
+			"dependencies": {
+				"@typescript-eslint/types": "5.29.0",
+				"eslint-visitor-keys": "^3.3.0"
+			},
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			},
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/typescript-eslint"
+			}
+		},
+		"node_modules/acorn": {
+			"version": "8.8.2",
+			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
+			"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+			"dev": true,
+			"peer": true,
+			"bin": {
+				"acorn": "bin/acorn"
+			},
+			"engines": {
+				"node": ">=0.4.0"
+			}
+		},
+		"node_modules/acorn-jsx": {
+			"version": "5.3.2",
+			"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+			"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+			"dev": true,
+			"peer": true,
+			"peerDependencies": {
+				"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+			}
+		},
+		"node_modules/ajv": {
+			"version": "6.12.6",
+			"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+			"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"fast-deep-equal": "^3.1.1",
+				"fast-json-stable-stringify": "^2.0.0",
+				"json-schema-traverse": "^0.4.1",
+				"uri-js": "^4.2.2"
+			},
+			"funding": {
+				"type": "github",
+				"url": "https://github.com/sponsors/epoberezkin"
+			}
+		},
+		"node_modules/ansi-regex": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+			"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/ansi-styles": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+			"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"color-convert": "^2.0.1"
+			},
+			"engines": {
+				"node": ">=8"
+			},
+			"funding": {
+				"url": "https://github.com/chalk/ansi-styles?sponsor=1"
+			}
+		},
+		"node_modules/anymatch": {
+			"version": "3.1.3",
+			"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+			"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+			"dev": true,
+			"dependencies": {
+				"normalize-path": "^3.0.0",
+				"picomatch": "^2.0.4"
+			},
+			"engines": {
+				"node": ">= 8"
+			}
+		},
+		"node_modules/argparse": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+			"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/array-union": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+			"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+			"dev": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/balanced-match": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+			"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/binary-extensions": {
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+			"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+			"dev": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/brace-expansion": {
+			"version": "1.1.11",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+			"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"balanced-match": "^1.0.0",
+				"concat-map": "0.0.1"
+			}
+		},
+		"node_modules/braces": {
+			"version": "3.0.2",
+			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+			"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+			"dev": true,
+			"dependencies": {
+				"fill-range": "^7.0.1"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/builtin-modules": {
+			"version": "3.3.0",
+			"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
+			"integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
+			"dev": true,
+			"engines": {
+				"node": ">=6"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/callsites": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+			"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=6"
+			}
+		},
+		"node_modules/chalk": {
+			"version": "4.1.2",
+			"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+			"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"ansi-styles": "^4.1.0",
+				"supports-color": "^7.1.0"
+			},
+			"engines": {
+				"node": ">=10"
+			},
+			"funding": {
+				"url": "https://github.com/chalk/chalk?sponsor=1"
+			}
+		},
+		"node_modules/chokidar": {
+			"version": "3.5.3",
+			"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+			"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+			"dev": true,
+			"funding": [
+				{
+					"type": "individual",
+					"url": "https://paulmillr.com/funding/"
+				}
+			],
+			"dependencies": {
+				"anymatch": "~3.1.2",
+				"braces": "~3.0.2",
+				"glob-parent": "~5.1.2",
+				"is-binary-path": "~2.1.0",
+				"is-glob": "~4.0.1",
+				"normalize-path": "~3.0.0",
+				"readdirp": "~3.6.0"
+			},
+			"engines": {
+				"node": ">= 8.10.0"
+			},
+			"optionalDependencies": {
+				"fsevents": "~2.3.2"
+			}
+		},
+		"node_modules/chokidar/node_modules/glob-parent": {
+			"version": "5.1.2",
+			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+			"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+			"dev": true,
+			"dependencies": {
+				"is-glob": "^4.0.1"
+			},
+			"engines": {
+				"node": ">= 6"
+			}
+		},
+		"node_modules/color-convert": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+			"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"color-name": "~1.1.4"
+			},
+			"engines": {
+				"node": ">=7.0.0"
+			}
+		},
+		"node_modules/color-name": {
+			"version": "1.1.4",
+			"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+			"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/concat-map": {
+			"version": "0.0.1",
+			"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+			"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/cross-spawn": {
+			"version": "7.0.3",
+			"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+			"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"path-key": "^3.1.0",
+				"shebang-command": "^2.0.0",
+				"which": "^2.0.1"
+			},
+			"engines": {
+				"node": ">= 8"
+			}
+		},
+		"node_modules/debug": {
+			"version": "4.3.4",
+			"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+			"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+			"dev": true,
+			"dependencies": {
+				"ms": "2.1.2"
+			},
+			"engines": {
+				"node": ">=6.0"
+			},
+			"peerDependenciesMeta": {
+				"supports-color": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/deep-is": {
+			"version": "0.1.4",
+			"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+			"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/dir-glob": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+			"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+			"dev": true,
+			"dependencies": {
+				"path-type": "^4.0.0"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/doctrine": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+			"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"esutils": "^2.0.2"
+			},
+			"engines": {
+				"node": ">=6.0.0"
+			}
+		},
+		"node_modules/esbuild": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.3.tgz",
+			"integrity": "sha512-9n3AsBRe6sIyOc6kmoXg2ypCLgf3eZSraWFRpnkto+svt8cZNuKTkb1bhQcitBcvIqjNiK7K0J3KPmwGSfkA8g==",
+			"dev": true,
+			"hasInstallScript": true,
+			"bin": {
+				"esbuild": "bin/esbuild"
+			},
+			"engines": {
+				"node": ">=12"
+			},
+			"optionalDependencies": {
+				"@esbuild/android-arm": "0.17.3",
+				"@esbuild/android-arm64": "0.17.3",
+				"@esbuild/android-x64": "0.17.3",
+				"@esbuild/darwin-arm64": "0.17.3",
+				"@esbuild/darwin-x64": "0.17.3",
+				"@esbuild/freebsd-arm64": "0.17.3",
+				"@esbuild/freebsd-x64": "0.17.3",
+				"@esbuild/linux-arm": "0.17.3",
+				"@esbuild/linux-arm64": "0.17.3",
+				"@esbuild/linux-ia32": "0.17.3",
+				"@esbuild/linux-loong64": "0.17.3",
+				"@esbuild/linux-mips64el": "0.17.3",
+				"@esbuild/linux-ppc64": "0.17.3",
+				"@esbuild/linux-riscv64": "0.17.3",
+				"@esbuild/linux-s390x": "0.17.3",
+				"@esbuild/linux-x64": "0.17.3",
+				"@esbuild/netbsd-x64": "0.17.3",
+				"@esbuild/openbsd-x64": "0.17.3",
+				"@esbuild/sunos-x64": "0.17.3",
+				"@esbuild/win32-arm64": "0.17.3",
+				"@esbuild/win32-ia32": "0.17.3",
+				"@esbuild/win32-x64": "0.17.3"
+			}
+		},
+		"node_modules/esbuild-android-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
+			"integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"android"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-android-arm64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
+			"integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
+			"cpu": [
+				"arm64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"android"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-darwin-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
+			"integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"darwin"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-darwin-arm64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
+			"integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
+			"cpu": [
+				"arm64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"darwin"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-freebsd-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
+			"integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"freebsd"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-freebsd-arm64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
+			"integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
+			"cpu": [
+				"arm64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"freebsd"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-linux-32": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
+			"integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
+			"cpu": [
+				"ia32"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-linux-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
+			"integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-linux-arm": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
+			"integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
+			"cpu": [
+				"arm"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-linux-arm64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
+			"integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
+			"cpu": [
+				"arm64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-linux-mips64le": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
+			"integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
+			"cpu": [
+				"mips64el"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-linux-ppc64le": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
+			"integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
+			"cpu": [
+				"ppc64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-linux-riscv64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
+			"integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
+			"cpu": [
+				"riscv64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-linux-s390x": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
+			"integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
+			"cpu": [
+				"s390x"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-netbsd-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
+			"integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"netbsd"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-openbsd-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
+			"integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"openbsd"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-sass-plugin": {
+			"version": "2.4.5",
+			"resolved": "https://registry.npmjs.org/esbuild-sass-plugin/-/esbuild-sass-plugin-2.4.5.tgz",
+			"integrity": "sha512-di2hLaIwhRXe513uaPPxv+5bjynxAgrS8R+u38lbBfvp1g1xOki4ACXV2aXip2CRPGTbAVDySSxujd9iArFV0w==",
+			"dev": true,
+			"dependencies": {
+				"esbuild": "^0.15.17",
+				"resolve": "^1.22.1",
+				"sass": "^1.56.1"
+			}
+		},
+		"node_modules/esbuild-sass-plugin/node_modules/@esbuild/android-arm": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
+			"integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
+			"cpu": [
+				"arm"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"android"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-sass-plugin/node_modules/@esbuild/linux-loong64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
+			"integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
+			"cpu": [
+				"loong64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"linux"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-sass-plugin/node_modules/esbuild": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
+			"integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
+			"dev": true,
+			"hasInstallScript": true,
+			"bin": {
+				"esbuild": "bin/esbuild"
+			},
+			"engines": {
+				"node": ">=12"
+			},
+			"optionalDependencies": {
+				"@esbuild/android-arm": "0.15.18",
+				"@esbuild/linux-loong64": "0.15.18",
+				"esbuild-android-64": "0.15.18",
+				"esbuild-android-arm64": "0.15.18",
+				"esbuild-darwin-64": "0.15.18",
+				"esbuild-darwin-arm64": "0.15.18",
+				"esbuild-freebsd-64": "0.15.18",
+				"esbuild-freebsd-arm64": "0.15.18",
+				"esbuild-linux-32": "0.15.18",
+				"esbuild-linux-64": "0.15.18",
+				"esbuild-linux-arm": "0.15.18",
+				"esbuild-linux-arm64": "0.15.18",
+				"esbuild-linux-mips64le": "0.15.18",
+				"esbuild-linux-ppc64le": "0.15.18",
+				"esbuild-linux-riscv64": "0.15.18",
+				"esbuild-linux-s390x": "0.15.18",
+				"esbuild-netbsd-64": "0.15.18",
+				"esbuild-openbsd-64": "0.15.18",
+				"esbuild-sunos-64": "0.15.18",
+				"esbuild-windows-32": "0.15.18",
+				"esbuild-windows-64": "0.15.18",
+				"esbuild-windows-arm64": "0.15.18"
+			}
+		},
+		"node_modules/esbuild-sunos-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
+			"integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"sunos"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-windows-32": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
+			"integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
+			"cpu": [
+				"ia32"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"win32"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-windows-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
+			"integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
+			"cpu": [
+				"x64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"win32"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/esbuild-windows-arm64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
+			"integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
+			"cpu": [
+				"arm64"
+			],
+			"dev": true,
+			"optional": true,
+			"os": [
+				"win32"
+			],
+			"engines": {
+				"node": ">=12"
+			}
+		},
+		"node_modules/escape-string-regexp": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+			"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=10"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/eslint": {
+			"version": "8.33.0",
+			"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz",
+			"integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"@eslint/eslintrc": "^1.4.1",
+				"@humanwhocodes/config-array": "^0.11.8",
+				"@humanwhocodes/module-importer": "^1.0.1",
+				"@nodelib/fs.walk": "^1.2.8",
+				"ajv": "^6.10.0",
+				"chalk": "^4.0.0",
+				"cross-spawn": "^7.0.2",
+				"debug": "^4.3.2",
+				"doctrine": "^3.0.0",
+				"escape-string-regexp": "^4.0.0",
+				"eslint-scope": "^7.1.1",
+				"eslint-utils": "^3.0.0",
+				"eslint-visitor-keys": "^3.3.0",
+				"espree": "^9.4.0",
+				"esquery": "^1.4.0",
+				"esutils": "^2.0.2",
+				"fast-deep-equal": "^3.1.3",
+				"file-entry-cache": "^6.0.1",
+				"find-up": "^5.0.0",
+				"glob-parent": "^6.0.2",
+				"globals": "^13.19.0",
+				"grapheme-splitter": "^1.0.4",
+				"ignore": "^5.2.0",
+				"import-fresh": "^3.0.0",
+				"imurmurhash": "^0.1.4",
+				"is-glob": "^4.0.0",
+				"is-path-inside": "^3.0.3",
+				"js-sdsl": "^4.1.4",
+				"js-yaml": "^4.1.0",
+				"json-stable-stringify-without-jsonify": "^1.0.1",
+				"levn": "^0.4.1",
+				"lodash.merge": "^4.6.2",
+				"minimatch": "^3.1.2",
+				"natural-compare": "^1.4.0",
+				"optionator": "^0.9.1",
+				"regexpp": "^3.2.0",
+				"strip-ansi": "^6.0.1",
+				"strip-json-comments": "^3.1.0",
+				"text-table": "^0.2.0"
+			},
+			"bin": {
+				"eslint": "bin/eslint.js"
+			},
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			},
+			"funding": {
+				"url": "https://opencollective.com/eslint"
+			}
+		},
+		"node_modules/eslint-scope": {
+			"version": "5.1.1",
+			"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+			"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+			"dev": true,
+			"dependencies": {
+				"esrecurse": "^4.3.0",
+				"estraverse": "^4.1.1"
+			},
+			"engines": {
+				"node": ">=8.0.0"
+			}
+		},
+		"node_modules/eslint-utils": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+			"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+			"dev": true,
+			"dependencies": {
+				"eslint-visitor-keys": "^2.0.0"
+			},
+			"engines": {
+				"node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/mysticatea"
+			},
+			"peerDependencies": {
+				"eslint": ">=5"
+			}
+		},
+		"node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+			"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+			"dev": true,
+			"engines": {
+				"node": ">=10"
+			}
+		},
+		"node_modules/eslint-visitor-keys": {
+			"version": "3.3.0",
+			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+			"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+			"dev": true,
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			}
+		},
+		"node_modules/eslint/node_modules/eslint-scope": {
+			"version": "7.1.1",
+			"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+			"integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"esrecurse": "^4.3.0",
+				"estraverse": "^5.2.0"
+			},
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			}
+		},
+		"node_modules/eslint/node_modules/estraverse": {
+			"version": "5.3.0",
+			"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+			"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=4.0"
+			}
+		},
+		"node_modules/espree": {
+			"version": "9.4.1",
+			"resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz",
+			"integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"acorn": "^8.8.0",
+				"acorn-jsx": "^5.3.2",
+				"eslint-visitor-keys": "^3.3.0"
+			},
+			"engines": {
+				"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+			},
+			"funding": {
+				"url": "https://opencollective.com/eslint"
+			}
+		},
+		"node_modules/esquery": {
+			"version": "1.4.0",
+			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+			"integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"estraverse": "^5.1.0"
+			},
+			"engines": {
+				"node": ">=0.10"
+			}
+		},
+		"node_modules/esquery/node_modules/estraverse": {
+			"version": "5.3.0",
+			"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+			"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=4.0"
+			}
+		},
+		"node_modules/esrecurse": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+			"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+			"dev": true,
+			"dependencies": {
+				"estraverse": "^5.2.0"
+			},
+			"engines": {
+				"node": ">=4.0"
+			}
+		},
+		"node_modules/esrecurse/node_modules/estraverse": {
+			"version": "5.3.0",
+			"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+			"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+			"dev": true,
+			"engines": {
+				"node": ">=4.0"
+			}
+		},
+		"node_modules/estraverse": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+			"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+			"dev": true,
+			"engines": {
+				"node": ">=4.0"
+			}
+		},
+		"node_modules/esutils": {
+			"version": "2.0.3",
+			"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+			"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/fast-deep-equal": {
+			"version": "3.1.3",
+			"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+			"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/fast-glob": {
+			"version": "3.2.12",
+			"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+			"integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+			"dev": true,
+			"dependencies": {
+				"@nodelib/fs.stat": "^2.0.2",
+				"@nodelib/fs.walk": "^1.2.3",
+				"glob-parent": "^5.1.2",
+				"merge2": "^1.3.0",
+				"micromatch": "^4.0.4"
+			},
+			"engines": {
+				"node": ">=8.6.0"
+			}
+		},
+		"node_modules/fast-glob/node_modules/glob-parent": {
+			"version": "5.1.2",
+			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+			"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+			"dev": true,
+			"dependencies": {
+				"is-glob": "^4.0.1"
+			},
+			"engines": {
+				"node": ">= 6"
+			}
+		},
+		"node_modules/fast-json-stable-stringify": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+			"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/fast-levenshtein": {
+			"version": "2.0.6",
+			"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+			"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/fastq": {
+			"version": "1.15.0",
+			"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+			"integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+			"dev": true,
+			"dependencies": {
+				"reusify": "^1.0.4"
+			}
+		},
+		"node_modules/file-entry-cache": {
+			"version": "6.0.1",
+			"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+			"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"flat-cache": "^3.0.4"
+			},
+			"engines": {
+				"node": "^10.12.0 || >=12.0.0"
+			}
+		},
+		"node_modules/fill-range": {
+			"version": "7.0.1",
+			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+			"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+			"dev": true,
+			"dependencies": {
+				"to-regex-range": "^5.0.1"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/find-up": {
+			"version": "5.0.0",
+			"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+			"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"locate-path": "^6.0.0",
+				"path-exists": "^4.0.0"
+			},
+			"engines": {
+				"node": ">=10"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/flat-cache": {
+			"version": "3.0.4",
+			"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+			"integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"flatted": "^3.1.0",
+				"rimraf": "^3.0.2"
+			},
+			"engines": {
+				"node": "^10.12.0 || >=12.0.0"
+			}
+		},
+		"node_modules/flatted": {
+			"version": "3.2.7",
+			"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+			"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/fs.realpath": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+			"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/fsevents": {
+			"version": "2.3.2",
+			"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+			"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+			"dev": true,
+			"hasInstallScript": true,
+			"optional": true,
+			"os": [
+				"darwin"
+			],
+			"engines": {
+				"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+			}
+		},
+		"node_modules/function-bind": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+			"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+			"dev": true
+		},
+		"node_modules/functional-red-black-tree": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+			"integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
+			"dev": true
+		},
+		"node_modules/glob": {
+			"version": "7.2.3",
+			"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+			"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"fs.realpath": "^1.0.0",
+				"inflight": "^1.0.4",
+				"inherits": "2",
+				"minimatch": "^3.1.1",
+				"once": "^1.3.0",
+				"path-is-absolute": "^1.0.0"
+			},
+			"engines": {
+				"node": "*"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/isaacs"
+			}
+		},
+		"node_modules/glob-parent": {
+			"version": "6.0.2",
+			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+			"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"is-glob": "^4.0.3"
+			},
+			"engines": {
+				"node": ">=10.13.0"
+			}
+		},
+		"node_modules/globals": {
+			"version": "13.20.0",
+			"resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+			"integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"type-fest": "^0.20.2"
+			},
+			"engines": {
+				"node": ">=8"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/globby": {
+			"version": "11.1.0",
+			"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+			"integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+			"dev": true,
+			"dependencies": {
+				"array-union": "^2.1.0",
+				"dir-glob": "^3.0.1",
+				"fast-glob": "^3.2.9",
+				"ignore": "^5.2.0",
+				"merge2": "^1.4.1",
+				"slash": "^3.0.0"
+			},
+			"engines": {
+				"node": ">=10"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/grapheme-splitter": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+			"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/has": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+			"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+			"dev": true,
+			"dependencies": {
+				"function-bind": "^1.1.1"
+			},
+			"engines": {
+				"node": ">= 0.4.0"
+			}
+		},
+		"node_modules/has-flag": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+			"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/ignore": {
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+			"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+			"dev": true,
+			"engines": {
+				"node": ">= 4"
+			}
+		},
+		"node_modules/immutable": {
+			"version": "4.2.4",
+			"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.4.tgz",
+			"integrity": "sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w==",
+			"dev": true
+		},
+		"node_modules/import-fresh": {
+			"version": "3.3.0",
+			"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+			"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"parent-module": "^1.0.0",
+				"resolve-from": "^4.0.0"
+			},
+			"engines": {
+				"node": ">=6"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/imurmurhash": {
+			"version": "0.1.4",
+			"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+			"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=0.8.19"
+			}
+		},
+		"node_modules/inflight": {
+			"version": "1.0.6",
+			"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+			"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"once": "^1.3.0",
+				"wrappy": "1"
+			}
+		},
+		"node_modules/inherits": {
+			"version": "2.0.4",
+			"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+			"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/is-binary-path": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+			"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+			"dev": true,
+			"dependencies": {
+				"binary-extensions": "^2.0.0"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/is-core-module": {
+			"version": "2.11.0",
+			"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+			"integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+			"dev": true,
+			"dependencies": {
+				"has": "^1.0.3"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/ljharb"
+			}
+		},
+		"node_modules/is-extglob": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+			"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/is-glob": {
+			"version": "4.0.3",
+			"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+			"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+			"dev": true,
+			"dependencies": {
+				"is-extglob": "^2.1.1"
+			},
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/is-number": {
+			"version": "7.0.0",
+			"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+			"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.12.0"
+			}
+		},
+		"node_modules/is-path-inside": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+			"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/isexe": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+			"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/js-sdsl": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
+			"integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==",
+			"dev": true,
+			"peer": true,
+			"funding": {
+				"type": "opencollective",
+				"url": "https://opencollective.com/js-sdsl"
+			}
+		},
+		"node_modules/js-yaml": {
+			"version": "4.1.0",
+			"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+			"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"argparse": "^2.0.1"
+			},
+			"bin": {
+				"js-yaml": "bin/js-yaml.js"
+			}
+		},
+		"node_modules/json-schema-traverse": {
+			"version": "0.4.1",
+			"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+			"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/json-stable-stringify-without-jsonify": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+			"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/levn": {
+			"version": "0.4.1",
+			"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+			"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"prelude-ls": "^1.2.1",
+				"type-check": "~0.4.0"
+			},
+			"engines": {
+				"node": ">= 0.8.0"
+			}
+		},
+		"node_modules/locate-path": {
+			"version": "6.0.0",
+			"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+			"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"p-locate": "^5.0.0"
+			},
+			"engines": {
+				"node": ">=10"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/lodash.merge": {
+			"version": "4.6.2",
+			"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+			"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/lru-cache": {
+			"version": "6.0.0",
+			"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+			"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+			"dev": true,
+			"dependencies": {
+				"yallist": "^4.0.0"
+			},
+			"engines": {
+				"node": ">=10"
+			}
+		},
+		"node_modules/merge2": {
+			"version": "1.4.1",
+			"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+			"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+			"dev": true,
+			"engines": {
+				"node": ">= 8"
+			}
+		},
+		"node_modules/micromatch": {
+			"version": "4.0.5",
+			"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+			"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+			"dev": true,
+			"dependencies": {
+				"braces": "^3.0.2",
+				"picomatch": "^2.3.1"
+			},
+			"engines": {
+				"node": ">=8.6"
+			}
+		},
+		"node_modules/minimatch": {
+			"version": "3.1.2",
+			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+			"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"brace-expansion": "^1.1.7"
+			},
+			"engines": {
+				"node": "*"
+			}
+		},
+		"node_modules/moment": {
+			"version": "2.29.4",
+			"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+			"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+			"dev": true,
+			"engines": {
+				"node": "*"
+			}
+		},
+		"node_modules/ms": {
+			"version": "2.1.2",
+			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+			"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+			"dev": true
+		},
+		"node_modules/natural-compare": {
+			"version": "1.4.0",
+			"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+			"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/normalize-path": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+			"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/obsidian": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.1.1.tgz",
+			"integrity": "sha512-GcxhsHNkPEkwHEjeyitfYNBcQuYGeAHFs1pEpZIv0CnzSfui8p8bPLm2YKLgcg20B764770B1sYGtxCvk9ptxg==",
+			"dev": true,
+			"dependencies": {
+				"@types/codemirror": "0.0.108",
+				"moment": "2.29.4"
+			},
+			"peerDependencies": {
+				"@codemirror/state": "^6.0.0",
+				"@codemirror/view": "^6.0.0"
+			}
+		},
+		"node_modules/once": {
+			"version": "1.4.0",
+			"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+			"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"wrappy": "1"
+			}
+		},
+		"node_modules/optionator": {
+			"version": "0.9.1",
+			"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+			"integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"deep-is": "^0.1.3",
+				"fast-levenshtein": "^2.0.6",
+				"levn": "^0.4.1",
+				"prelude-ls": "^1.2.1",
+				"type-check": "^0.4.0",
+				"word-wrap": "^1.2.3"
+			},
+			"engines": {
+				"node": ">= 0.8.0"
+			}
+		},
+		"node_modules/p-limit": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+			"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"yocto-queue": "^0.1.0"
+			},
+			"engines": {
+				"node": ">=10"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/p-locate": {
+			"version": "5.0.0",
+			"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+			"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"p-limit": "^3.0.2"
+			},
+			"engines": {
+				"node": ">=10"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/parent-module": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+			"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"callsites": "^3.0.0"
+			},
+			"engines": {
+				"node": ">=6"
+			}
+		},
+		"node_modules/path-exists": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+			"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/path-is-absolute": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+			"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/path-key": {
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+			"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/path-parse": {
+			"version": "1.0.7",
+			"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+			"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+			"dev": true
+		},
+		"node_modules/path-type": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+			"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+			"dev": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/picomatch": {
+			"version": "2.3.1",
+			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+			"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+			"dev": true,
+			"engines": {
+				"node": ">=8.6"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/jonschlinkert"
+			}
+		},
+		"node_modules/prelude-ls": {
+			"version": "1.2.1",
+			"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+			"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">= 0.8.0"
+			}
+		},
+		"node_modules/punycode": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+			"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=6"
+			}
+		},
+		"node_modules/queue-microtask": {
+			"version": "1.2.3",
+			"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+			"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+			"dev": true,
+			"funding": [
+				{
+					"type": "github",
+					"url": "https://github.com/sponsors/feross"
+				},
+				{
+					"type": "patreon",
+					"url": "https://www.patreon.com/feross"
+				},
+				{
+					"type": "consulting",
+					"url": "https://feross.org/support"
+				}
+			]
+		},
+		"node_modules/readdirp": {
+			"version": "3.6.0",
+			"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+			"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+			"dev": true,
+			"dependencies": {
+				"picomatch": "^2.2.1"
+			},
+			"engines": {
+				"node": ">=8.10.0"
+			}
+		},
+		"node_modules/regexpp": {
+			"version": "3.2.0",
+			"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+			"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+			"dev": true,
+			"engines": {
+				"node": ">=8"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/mysticatea"
+			}
+		},
+		"node_modules/resolve": {
+			"version": "1.22.1",
+			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+			"integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+			"dev": true,
+			"dependencies": {
+				"is-core-module": "^2.9.0",
+				"path-parse": "^1.0.7",
+				"supports-preserve-symlinks-flag": "^1.0.0"
+			},
+			"bin": {
+				"resolve": "bin/resolve"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/ljharb"
+			}
+		},
+		"node_modules/resolve-from": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+			"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=4"
+			}
+		},
+		"node_modules/reusify": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+			"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+			"dev": true,
+			"engines": {
+				"iojs": ">=1.0.0",
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/rimraf": {
+			"version": "3.0.2",
+			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+			"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"glob": "^7.1.3"
+			},
+			"bin": {
+				"rimraf": "bin.js"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/isaacs"
+			}
+		},
+		"node_modules/run-parallel": {
+			"version": "1.2.0",
+			"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+			"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+			"dev": true,
+			"funding": [
+				{
+					"type": "github",
+					"url": "https://github.com/sponsors/feross"
+				},
+				{
+					"type": "patreon",
+					"url": "https://www.patreon.com/feross"
+				},
+				{
+					"type": "consulting",
+					"url": "https://feross.org/support"
+				}
+			],
+			"dependencies": {
+				"queue-microtask": "^1.2.2"
+			}
+		},
+		"node_modules/sass": {
+			"version": "1.58.0",
+			"resolved": "https://registry.npmjs.org/sass/-/sass-1.58.0.tgz",
+			"integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==",
+			"dev": true,
+			"dependencies": {
+				"chokidar": ">=3.0.0 <4.0.0",
+				"immutable": "^4.0.0",
+				"source-map-js": ">=0.6.2 <2.0.0"
+			},
+			"bin": {
+				"sass": "sass.js"
+			},
+			"engines": {
+				"node": ">=12.0.0"
+			}
+		},
+		"node_modules/semver": {
+			"version": "7.3.8",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+			"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+			"dev": true,
+			"dependencies": {
+				"lru-cache": "^6.0.0"
+			},
+			"bin": {
+				"semver": "bin/semver.js"
+			},
+			"engines": {
+				"node": ">=10"
+			}
+		},
+		"node_modules/shebang-command": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+			"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"shebang-regex": "^3.0.0"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/shebang-regex": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+			"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/slash": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+			"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+			"dev": true,
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/source-map-js": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+			"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+			"dev": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/strip-ansi": {
+			"version": "6.0.1",
+			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+			"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"ansi-regex": "^5.0.1"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/strip-json-comments": {
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+			"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=8"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/style-mod": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz",
+			"integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/supports-color": {
+			"version": "7.2.0",
+			"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+			"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"has-flag": "^4.0.0"
+			},
+			"engines": {
+				"node": ">=8"
+			}
+		},
+		"node_modules/supports-preserve-symlinks-flag": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+			"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+			"dev": true,
+			"engines": {
+				"node": ">= 0.4"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/ljharb"
+			}
+		},
+		"node_modules/text-table": {
+			"version": "0.2.0",
+			"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+			"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/to-regex-range": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+			"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+			"dev": true,
+			"dependencies": {
+				"is-number": "^7.0.0"
+			},
+			"engines": {
+				"node": ">=8.0"
+			}
+		},
+		"node_modules/tslib": {
+			"version": "2.4.0",
+			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+			"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+			"dev": true
+		},
+		"node_modules/tsutils": {
+			"version": "3.21.0",
+			"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+			"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+			"dev": true,
+			"dependencies": {
+				"tslib": "^1.8.1"
+			},
+			"engines": {
+				"node": ">= 6"
+			},
+			"peerDependencies": {
+				"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+			}
+		},
+		"node_modules/tsutils/node_modules/tslib": {
+			"version": "1.14.1",
+			"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+			"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+			"dev": true
+		},
+		"node_modules/type-check": {
+			"version": "0.4.0",
+			"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+			"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"prelude-ls": "^1.2.1"
+			},
+			"engines": {
+				"node": ">= 0.8.0"
+			}
+		},
+		"node_modules/type-fest": {
+			"version": "0.20.2",
+			"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+			"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=10"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		},
+		"node_modules/typescript": {
+			"version": "4.7.4",
+			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+			"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
+			"dev": true,
+			"bin": {
+				"tsc": "bin/tsc",
+				"tsserver": "bin/tsserver"
+			},
+			"engines": {
+				"node": ">=4.2.0"
+			}
+		},
+		"node_modules/uri-js": {
+			"version": "4.4.1",
+			"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+			"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"punycode": "^2.1.0"
+			}
+		},
+		"node_modules/w3c-keyname": {
+			"version": "2.2.6",
+			"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
+			"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/which": {
+			"version": "2.0.2",
+			"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+			"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+			"dev": true,
+			"peer": true,
+			"dependencies": {
+				"isexe": "^2.0.0"
+			},
+			"bin": {
+				"node-which": "bin/node-which"
+			},
+			"engines": {
+				"node": ">= 8"
+			}
+		},
+		"node_modules/word-wrap": {
+			"version": "1.2.3",
+			"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+			"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=0.10.0"
+			}
+		},
+		"node_modules/wrappy": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+			"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+			"dev": true,
+			"peer": true
+		},
+		"node_modules/yallist": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+			"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+			"dev": true
+		},
+		"node_modules/yocto-queue": {
+			"version": "0.1.0",
+			"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+			"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+			"dev": true,
+			"peer": true,
+			"engines": {
+				"node": ">=10"
+			},
+			"funding": {
+				"url": "https://github.com/sponsors/sindresorhus"
+			}
+		}
+	},
+	"dependencies": {
+		"@codemirror/state": {
+			"version": "6.2.0",
+			"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.0.tgz",
+			"integrity": "sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA==",
+			"dev": true,
+			"peer": true
+		},
+		"@codemirror/view": {
+			"version": "6.7.3",
+			"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.7.3.tgz",
+			"integrity": "sha512-Lt+4POnhXrZFfHOdPzXEHxrzwdy7cjqYlMkOWvoFGi6/bAsjzlFfr0NY3B15B/PGx+cDFgM1hlc12wvYeZbGLw==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"@codemirror/state": "^6.1.4",
+				"style-mod": "^4.0.0",
+				"w3c-keyname": "^2.2.4"
+			}
+		},
+		"@esbuild/android-arm": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.3.tgz",
+			"integrity": "sha512-1Mlz934GvbgdDmt26rTLmf03cAgLg5HyOgJN+ZGCeP3Q9ynYTNMn2/LQxIl7Uy+o4K6Rfi2OuLsr12JQQR8gNg==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/android-arm64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.3.tgz",
+			"integrity": "sha512-XvJsYo3dO3Pi4kpalkyMvfQsjxPWHYjoX4MDiB/FUM4YMfWcXa5l4VCwFWVYI1+92yxqjuqrhNg0CZg3gSouyQ==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/android-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.3.tgz",
+			"integrity": "sha512-nuV2CmLS07Gqh5/GrZLuqkU9Bm6H6vcCspM+zjp9TdQlxJtIe+qqEXQChmfc7nWdyr/yz3h45Utk1tUn8Cz5+A==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/darwin-arm64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.3.tgz",
+			"integrity": "sha512-01Hxaaat6m0Xp9AXGM8mjFtqqwDjzlMP0eQq9zll9U85ttVALGCGDuEvra5Feu/NbP5AEP1MaopPwzsTcUq1cw==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/darwin-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.3.tgz",
+			"integrity": "sha512-Eo2gq0Q/er2muf8Z83X21UFoB7EU6/m3GNKvrhACJkjVThd0uA+8RfKpfNhuMCl1bKRfBzKOk6xaYKQZ4lZqvA==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/freebsd-arm64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.3.tgz",
+			"integrity": "sha512-CN62ESxaquP61n1ZjQP/jZte8CE09M6kNn3baos2SeUfdVBkWN5n6vGp2iKyb/bm/x4JQzEvJgRHLGd5F5b81w==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/freebsd-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.3.tgz",
+			"integrity": "sha512-feq+K8TxIznZE+zhdVurF3WNJ/Sa35dQNYbaqM/wsCbWdzXr5lyq+AaTUSER2cUR+SXPnd/EY75EPRjf4s1SLg==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/linux-arm": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.3.tgz",
+			"integrity": "sha512-CLP3EgyNuPcg2cshbwkqYy5bbAgK+VhyfMU7oIYyn+x4Y67xb5C5ylxsNUjRmr8BX+MW3YhVNm6Lq6FKtRTWHQ==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/linux-arm64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.3.tgz",
+			"integrity": "sha512-JHeZXD4auLYBnrKn6JYJ0o5nWJI9PhChA/Nt0G4MvLaMrvXuWnY93R3a7PiXeJQphpL1nYsaMcoV2QtuvRnF/g==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/linux-ia32": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.3.tgz",
+			"integrity": "sha512-FyXlD2ZjZqTFh0sOQxFDiWG1uQUEOLbEh9gKN/7pFxck5Vw0qjWSDqbn6C10GAa1rXJpwsntHcmLqydY9ST9ZA==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/linux-loong64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.3.tgz",
+			"integrity": "sha512-OrDGMvDBI2g7s04J8dh8/I7eSO+/E7nMDT2Z5IruBfUO/RiigF1OF6xoH33Dn4W/OwAWSUf1s2nXamb28ZklTA==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/linux-mips64el": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.3.tgz",
+			"integrity": "sha512-DcnUpXnVCJvmv0TzuLwKBC2nsQHle8EIiAJiJ+PipEVC16wHXaPEKP0EqN8WnBe0TPvMITOUlP2aiL5YMld+CQ==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/linux-ppc64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.3.tgz",
+			"integrity": "sha512-BDYf/l1WVhWE+FHAW3FzZPtVlk9QsrwsxGzABmN4g8bTjmhazsId3h127pliDRRu5674k1Y2RWejbpN46N9ZhQ==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/linux-riscv64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.3.tgz",
+			"integrity": "sha512-WViAxWYMRIi+prTJTyV1wnqd2mS2cPqJlN85oscVhXdb/ZTFJdrpaqm/uDsZPGKHtbg5TuRX/ymKdOSk41YZow==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/linux-s390x": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.3.tgz",
+			"integrity": "sha512-Iw8lkNHUC4oGP1O/KhumcVy77u2s6+KUjieUqzEU3XuWJqZ+AY7uVMrrCbAiwWTkpQHkr00BuXH5RpC6Sb/7Ug==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/linux-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.3.tgz",
+			"integrity": "sha512-0AGkWQMzeoeAtXQRNB3s4J1/T2XbigM2/Mn2yU1tQSmQRmHIZdkGbVq2A3aDdNslPyhb9/lH0S5GMTZ4xsjBqg==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/netbsd-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.3.tgz",
+			"integrity": "sha512-4+rR/WHOxIVh53UIQIICryjdoKdHsFZFD4zLSonJ9RRw7bhKzVyXbnRPsWSfwybYqw9sB7ots/SYyufL1mBpEg==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/openbsd-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.3.tgz",
+			"integrity": "sha512-cVpWnkx9IYg99EjGxa5Gc0XmqumtAwK3aoz7O4Dii2vko+qXbkHoujWA68cqXjhh6TsLaQelfDO4MVnyr+ODeA==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/sunos-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.3.tgz",
+			"integrity": "sha512-RxmhKLbTCDAY2xOfrww6ieIZkZF+KBqG7S2Ako2SljKXRFi+0863PspK74QQ7JpmWwncChY25JTJSbVBYGQk2Q==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/win32-arm64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.3.tgz",
+			"integrity": "sha512-0r36VeEJ4efwmofxVJRXDjVRP2jTmv877zc+i+Pc7MNsIr38NfsjkQj23AfF7l0WbB+RQ7VUb+LDiqC/KY/M/A==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/win32-ia32": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.3.tgz",
+			"integrity": "sha512-wgO6rc7uGStH22nur4aLFcq7Wh86bE9cOFmfTr/yxN3BXvDEdCSXyKkO+U5JIt53eTOgC47v9k/C1bITWL/Teg==",
+			"dev": true,
+			"optional": true
+		},
+		"@esbuild/win32-x64": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.3.tgz",
+			"integrity": "sha512-FdVl64OIuiKjgXBjwZaJLKp0eaEckifbhn10dXWhysMJkWblg3OEEGKSIyhiD5RSgAya8WzP3DNkngtIg3Nt7g==",
+			"dev": true,
+			"optional": true
+		},
+		"@eslint/eslintrc": {
+			"version": "1.4.1",
+			"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz",
+			"integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"ajv": "^6.12.4",
+				"debug": "^4.3.2",
+				"espree": "^9.4.0",
+				"globals": "^13.19.0",
+				"ignore": "^5.2.0",
+				"import-fresh": "^3.2.1",
+				"js-yaml": "^4.1.0",
+				"minimatch": "^3.1.2",
+				"strip-json-comments": "^3.1.1"
+			}
+		},
+		"@humanwhocodes/config-array": {
+			"version": "0.11.8",
+			"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
+			"integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"@humanwhocodes/object-schema": "^1.2.1",
+				"debug": "^4.1.1",
+				"minimatch": "^3.0.5"
+			}
+		},
+		"@humanwhocodes/module-importer": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+			"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+			"dev": true,
+			"peer": true
+		},
+		"@humanwhocodes/object-schema": {
+			"version": "1.2.1",
+			"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+			"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+			"dev": true,
+			"peer": true
+		},
+		"@nodelib/fs.scandir": {
+			"version": "2.1.5",
+			"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+			"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+			"dev": true,
+			"requires": {
+				"@nodelib/fs.stat": "2.0.5",
+				"run-parallel": "^1.1.9"
+			}
+		},
+		"@nodelib/fs.stat": {
+			"version": "2.0.5",
+			"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+			"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+			"dev": true
+		},
+		"@nodelib/fs.walk": {
+			"version": "1.2.8",
+			"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+			"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+			"dev": true,
+			"requires": {
+				"@nodelib/fs.scandir": "2.1.5",
+				"fastq": "^1.6.0"
+			}
+		},
+		"@types/codemirror": {
+			"version": "0.0.108",
+			"resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.108.tgz",
+			"integrity": "sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==",
+			"dev": true,
+			"requires": {
+				"@types/tern": "*"
+			}
+		},
+		"@types/estree": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz",
+			"integrity": "sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==",
+			"dev": true
+		},
+		"@types/json-schema": {
+			"version": "7.0.11",
+			"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
+			"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
+			"dev": true
+		},
+		"@types/node": {
+			"version": "16.18.12",
+			"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz",
+			"integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==",
+			"dev": true
+		},
+		"@types/tern": {
+			"version": "0.23.4",
+			"resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.4.tgz",
+			"integrity": "sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==",
+			"dev": true,
+			"requires": {
+				"@types/estree": "*"
+			}
+		},
+		"@typescript-eslint/eslint-plugin": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz",
+			"integrity": "sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==",
+			"dev": true,
+			"requires": {
+				"@typescript-eslint/scope-manager": "5.29.0",
+				"@typescript-eslint/type-utils": "5.29.0",
+				"@typescript-eslint/utils": "5.29.0",
+				"debug": "^4.3.4",
+				"functional-red-black-tree": "^1.0.1",
+				"ignore": "^5.2.0",
+				"regexpp": "^3.2.0",
+				"semver": "^7.3.7",
+				"tsutils": "^3.21.0"
+			}
+		},
+		"@typescript-eslint/parser": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz",
+			"integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==",
+			"dev": true,
+			"requires": {
+				"@typescript-eslint/scope-manager": "5.29.0",
+				"@typescript-eslint/types": "5.29.0",
+				"@typescript-eslint/typescript-estree": "5.29.0",
+				"debug": "^4.3.4"
+			}
+		},
+		"@typescript-eslint/scope-manager": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz",
+			"integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==",
+			"dev": true,
+			"requires": {
+				"@typescript-eslint/types": "5.29.0",
+				"@typescript-eslint/visitor-keys": "5.29.0"
+			}
+		},
+		"@typescript-eslint/type-utils": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz",
+			"integrity": "sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==",
+			"dev": true,
+			"requires": {
+				"@typescript-eslint/utils": "5.29.0",
+				"debug": "^4.3.4",
+				"tsutils": "^3.21.0"
+			}
+		},
+		"@typescript-eslint/types": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz",
+			"integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==",
+			"dev": true
+		},
+		"@typescript-eslint/typescript-estree": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz",
+			"integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==",
+			"dev": true,
+			"requires": {
+				"@typescript-eslint/types": "5.29.0",
+				"@typescript-eslint/visitor-keys": "5.29.0",
+				"debug": "^4.3.4",
+				"globby": "^11.1.0",
+				"is-glob": "^4.0.3",
+				"semver": "^7.3.7",
+				"tsutils": "^3.21.0"
+			}
+		},
+		"@typescript-eslint/utils": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz",
+			"integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==",
+			"dev": true,
+			"requires": {
+				"@types/json-schema": "^7.0.9",
+				"@typescript-eslint/scope-manager": "5.29.0",
+				"@typescript-eslint/types": "5.29.0",
+				"@typescript-eslint/typescript-estree": "5.29.0",
+				"eslint-scope": "^5.1.1",
+				"eslint-utils": "^3.0.0"
+			}
+		},
+		"@typescript-eslint/visitor-keys": {
+			"version": "5.29.0",
+			"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz",
+			"integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==",
+			"dev": true,
+			"requires": {
+				"@typescript-eslint/types": "5.29.0",
+				"eslint-visitor-keys": "^3.3.0"
+			}
+		},
+		"acorn": {
+			"version": "8.8.2",
+			"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
+			"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+			"dev": true,
+			"peer": true
+		},
+		"acorn-jsx": {
+			"version": "5.3.2",
+			"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+			"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+			"dev": true,
+			"peer": true,
+			"requires": {}
+		},
+		"ajv": {
+			"version": "6.12.6",
+			"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+			"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"fast-deep-equal": "^3.1.1",
+				"fast-json-stable-stringify": "^2.0.0",
+				"json-schema-traverse": "^0.4.1",
+				"uri-js": "^4.2.2"
+			}
+		},
+		"ansi-regex": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+			"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+			"dev": true,
+			"peer": true
+		},
+		"ansi-styles": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+			"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"color-convert": "^2.0.1"
+			}
+		},
+		"anymatch": {
+			"version": "3.1.3",
+			"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+			"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+			"dev": true,
+			"requires": {
+				"normalize-path": "^3.0.0",
+				"picomatch": "^2.0.4"
+			}
+		},
+		"argparse": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+			"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+			"dev": true,
+			"peer": true
+		},
+		"array-union": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+			"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+			"dev": true
+		},
+		"balanced-match": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+			"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+			"dev": true,
+			"peer": true
+		},
+		"binary-extensions": {
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+			"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+			"dev": true
+		},
+		"brace-expansion": {
+			"version": "1.1.11",
+			"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+			"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"balanced-match": "^1.0.0",
+				"concat-map": "0.0.1"
+			}
+		},
+		"braces": {
+			"version": "3.0.2",
+			"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+			"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+			"dev": true,
+			"requires": {
+				"fill-range": "^7.0.1"
+			}
+		},
+		"builtin-modules": {
+			"version": "3.3.0",
+			"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
+			"integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
+			"dev": true
+		},
+		"callsites": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+			"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+			"dev": true,
+			"peer": true
+		},
+		"chalk": {
+			"version": "4.1.2",
+			"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+			"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"ansi-styles": "^4.1.0",
+				"supports-color": "^7.1.0"
+			}
+		},
+		"chokidar": {
+			"version": "3.5.3",
+			"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+			"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+			"dev": true,
+			"requires": {
+				"anymatch": "~3.1.2",
+				"braces": "~3.0.2",
+				"fsevents": "~2.3.2",
+				"glob-parent": "~5.1.2",
+				"is-binary-path": "~2.1.0",
+				"is-glob": "~4.0.1",
+				"normalize-path": "~3.0.0",
+				"readdirp": "~3.6.0"
+			},
+			"dependencies": {
+				"glob-parent": {
+					"version": "5.1.2",
+					"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+					"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+					"dev": true,
+					"requires": {
+						"is-glob": "^4.0.1"
+					}
+				}
+			}
+		},
+		"color-convert": {
+			"version": "2.0.1",
+			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+			"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"color-name": "~1.1.4"
+			}
+		},
+		"color-name": {
+			"version": "1.1.4",
+			"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+			"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+			"dev": true,
+			"peer": true
+		},
+		"concat-map": {
+			"version": "0.0.1",
+			"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+			"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+			"dev": true,
+			"peer": true
+		},
+		"cross-spawn": {
+			"version": "7.0.3",
+			"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+			"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"path-key": "^3.1.0",
+				"shebang-command": "^2.0.0",
+				"which": "^2.0.1"
+			}
+		},
+		"debug": {
+			"version": "4.3.4",
+			"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+			"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+			"dev": true,
+			"requires": {
+				"ms": "2.1.2"
+			}
+		},
+		"deep-is": {
+			"version": "0.1.4",
+			"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+			"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+			"dev": true,
+			"peer": true
+		},
+		"dir-glob": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+			"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+			"dev": true,
+			"requires": {
+				"path-type": "^4.0.0"
+			}
+		},
+		"doctrine": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+			"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"esutils": "^2.0.2"
+			}
+		},
+		"esbuild": {
+			"version": "0.17.3",
+			"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.3.tgz",
+			"integrity": "sha512-9n3AsBRe6sIyOc6kmoXg2ypCLgf3eZSraWFRpnkto+svt8cZNuKTkb1bhQcitBcvIqjNiK7K0J3KPmwGSfkA8g==",
+			"dev": true,
+			"requires": {
+				"@esbuild/android-arm": "0.17.3",
+				"@esbuild/android-arm64": "0.17.3",
+				"@esbuild/android-x64": "0.17.3",
+				"@esbuild/darwin-arm64": "0.17.3",
+				"@esbuild/darwin-x64": "0.17.3",
+				"@esbuild/freebsd-arm64": "0.17.3",
+				"@esbuild/freebsd-x64": "0.17.3",
+				"@esbuild/linux-arm": "0.17.3",
+				"@esbuild/linux-arm64": "0.17.3",
+				"@esbuild/linux-ia32": "0.17.3",
+				"@esbuild/linux-loong64": "0.17.3",
+				"@esbuild/linux-mips64el": "0.17.3",
+				"@esbuild/linux-ppc64": "0.17.3",
+				"@esbuild/linux-riscv64": "0.17.3",
+				"@esbuild/linux-s390x": "0.17.3",
+				"@esbuild/linux-x64": "0.17.3",
+				"@esbuild/netbsd-x64": "0.17.3",
+				"@esbuild/openbsd-x64": "0.17.3",
+				"@esbuild/sunos-x64": "0.17.3",
+				"@esbuild/win32-arm64": "0.17.3",
+				"@esbuild/win32-ia32": "0.17.3",
+				"@esbuild/win32-x64": "0.17.3"
+			}
+		},
+		"esbuild-android-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz",
+			"integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-android-arm64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz",
+			"integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-darwin-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz",
+			"integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-darwin-arm64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz",
+			"integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-freebsd-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz",
+			"integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-freebsd-arm64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz",
+			"integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-linux-32": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz",
+			"integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-linux-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz",
+			"integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-linux-arm": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz",
+			"integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-linux-arm64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz",
+			"integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-linux-mips64le": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz",
+			"integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-linux-ppc64le": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz",
+			"integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-linux-riscv64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz",
+			"integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-linux-s390x": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz",
+			"integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-netbsd-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz",
+			"integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-openbsd-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz",
+			"integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-sass-plugin": {
+			"version": "2.4.5",
+			"resolved": "https://registry.npmjs.org/esbuild-sass-plugin/-/esbuild-sass-plugin-2.4.5.tgz",
+			"integrity": "sha512-di2hLaIwhRXe513uaPPxv+5bjynxAgrS8R+u38lbBfvp1g1xOki4ACXV2aXip2CRPGTbAVDySSxujd9iArFV0w==",
+			"dev": true,
+			"requires": {
+				"esbuild": "^0.15.17",
+				"resolve": "^1.22.1",
+				"sass": "^1.56.1"
+			},
+			"dependencies": {
+				"@esbuild/android-arm": {
+					"version": "0.15.18",
+					"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz",
+					"integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==",
+					"dev": true,
+					"optional": true
+				},
+				"@esbuild/linux-loong64": {
+					"version": "0.15.18",
+					"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz",
+					"integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==",
+					"dev": true,
+					"optional": true
+				},
+				"esbuild": {
+					"version": "0.15.18",
+					"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz",
+					"integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==",
+					"dev": true,
+					"requires": {
+						"@esbuild/android-arm": "0.15.18",
+						"@esbuild/linux-loong64": "0.15.18",
+						"esbuild-android-64": "0.15.18",
+						"esbuild-android-arm64": "0.15.18",
+						"esbuild-darwin-64": "0.15.18",
+						"esbuild-darwin-arm64": "0.15.18",
+						"esbuild-freebsd-64": "0.15.18",
+						"esbuild-freebsd-arm64": "0.15.18",
+						"esbuild-linux-32": "0.15.18",
+						"esbuild-linux-64": "0.15.18",
+						"esbuild-linux-arm": "0.15.18",
+						"esbuild-linux-arm64": "0.15.18",
+						"esbuild-linux-mips64le": "0.15.18",
+						"esbuild-linux-ppc64le": "0.15.18",
+						"esbuild-linux-riscv64": "0.15.18",
+						"esbuild-linux-s390x": "0.15.18",
+						"esbuild-netbsd-64": "0.15.18",
+						"esbuild-openbsd-64": "0.15.18",
+						"esbuild-sunos-64": "0.15.18",
+						"esbuild-windows-32": "0.15.18",
+						"esbuild-windows-64": "0.15.18",
+						"esbuild-windows-arm64": "0.15.18"
+					}
+				}
+			}
+		},
+		"esbuild-sunos-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz",
+			"integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-windows-32": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz",
+			"integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-windows-64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz",
+			"integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==",
+			"dev": true,
+			"optional": true
+		},
+		"esbuild-windows-arm64": {
+			"version": "0.15.18",
+			"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz",
+			"integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==",
+			"dev": true,
+			"optional": true
+		},
+		"escape-string-regexp": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+			"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+			"dev": true,
+			"peer": true
+		},
+		"eslint": {
+			"version": "8.33.0",
+			"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz",
+			"integrity": "sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"@eslint/eslintrc": "^1.4.1",
+				"@humanwhocodes/config-array": "^0.11.8",
+				"@humanwhocodes/module-importer": "^1.0.1",
+				"@nodelib/fs.walk": "^1.2.8",
+				"ajv": "^6.10.0",
+				"chalk": "^4.0.0",
+				"cross-spawn": "^7.0.2",
+				"debug": "^4.3.2",
+				"doctrine": "^3.0.0",
+				"escape-string-regexp": "^4.0.0",
+				"eslint-scope": "^7.1.1",
+				"eslint-utils": "^3.0.0",
+				"eslint-visitor-keys": "^3.3.0",
+				"espree": "^9.4.0",
+				"esquery": "^1.4.0",
+				"esutils": "^2.0.2",
+				"fast-deep-equal": "^3.1.3",
+				"file-entry-cache": "^6.0.1",
+				"find-up": "^5.0.0",
+				"glob-parent": "^6.0.2",
+				"globals": "^13.19.0",
+				"grapheme-splitter": "^1.0.4",
+				"ignore": "^5.2.0",
+				"import-fresh": "^3.0.0",
+				"imurmurhash": "^0.1.4",
+				"is-glob": "^4.0.0",
+				"is-path-inside": "^3.0.3",
+				"js-sdsl": "^4.1.4",
+				"js-yaml": "^4.1.0",
+				"json-stable-stringify-without-jsonify": "^1.0.1",
+				"levn": "^0.4.1",
+				"lodash.merge": "^4.6.2",
+				"minimatch": "^3.1.2",
+				"natural-compare": "^1.4.0",
+				"optionator": "^0.9.1",
+				"regexpp": "^3.2.0",
+				"strip-ansi": "^6.0.1",
+				"strip-json-comments": "^3.1.0",
+				"text-table": "^0.2.0"
+			},
+			"dependencies": {
+				"eslint-scope": {
+					"version": "7.1.1",
+					"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+					"integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+					"dev": true,
+					"peer": true,
+					"requires": {
+						"esrecurse": "^4.3.0",
+						"estraverse": "^5.2.0"
+					}
+				},
+				"estraverse": {
+					"version": "5.3.0",
+					"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+					"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+					"dev": true,
+					"peer": true
+				}
+			}
+		},
+		"eslint-scope": {
+			"version": "5.1.1",
+			"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+			"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+			"dev": true,
+			"requires": {
+				"esrecurse": "^4.3.0",
+				"estraverse": "^4.1.1"
+			}
+		},
+		"eslint-utils": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+			"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+			"dev": true,
+			"requires": {
+				"eslint-visitor-keys": "^2.0.0"
+			},
+			"dependencies": {
+				"eslint-visitor-keys": {
+					"version": "2.1.0",
+					"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+					"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+					"dev": true
+				}
+			}
+		},
+		"eslint-visitor-keys": {
+			"version": "3.3.0",
+			"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+			"integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+			"dev": true
+		},
+		"espree": {
+			"version": "9.4.1",
+			"resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz",
+			"integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"acorn": "^8.8.0",
+				"acorn-jsx": "^5.3.2",
+				"eslint-visitor-keys": "^3.3.0"
+			}
+		},
+		"esquery": {
+			"version": "1.4.0",
+			"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+			"integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"estraverse": "^5.1.0"
+			},
+			"dependencies": {
+				"estraverse": {
+					"version": "5.3.0",
+					"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+					"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+					"dev": true,
+					"peer": true
+				}
+			}
+		},
+		"esrecurse": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+			"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+			"dev": true,
+			"requires": {
+				"estraverse": "^5.2.0"
+			},
+			"dependencies": {
+				"estraverse": {
+					"version": "5.3.0",
+					"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+					"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+					"dev": true
+				}
+			}
+		},
+		"estraverse": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+			"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+			"dev": true
+		},
+		"esutils": {
+			"version": "2.0.3",
+			"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+			"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+			"dev": true,
+			"peer": true
+		},
+		"fast-deep-equal": {
+			"version": "3.1.3",
+			"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+			"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+			"dev": true,
+			"peer": true
+		},
+		"fast-glob": {
+			"version": "3.2.12",
+			"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
+			"integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
+			"dev": true,
+			"requires": {
+				"@nodelib/fs.stat": "^2.0.2",
+				"@nodelib/fs.walk": "^1.2.3",
+				"glob-parent": "^5.1.2",
+				"merge2": "^1.3.0",
+				"micromatch": "^4.0.4"
+			},
+			"dependencies": {
+				"glob-parent": {
+					"version": "5.1.2",
+					"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+					"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+					"dev": true,
+					"requires": {
+						"is-glob": "^4.0.1"
+					}
+				}
+			}
+		},
+		"fast-json-stable-stringify": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+			"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+			"dev": true,
+			"peer": true
+		},
+		"fast-levenshtein": {
+			"version": "2.0.6",
+			"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+			"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+			"dev": true,
+			"peer": true
+		},
+		"fastq": {
+			"version": "1.15.0",
+			"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+			"integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+			"dev": true,
+			"requires": {
+				"reusify": "^1.0.4"
+			}
+		},
+		"file-entry-cache": {
+			"version": "6.0.1",
+			"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+			"integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"flat-cache": "^3.0.4"
+			}
+		},
+		"fill-range": {
+			"version": "7.0.1",
+			"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+			"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+			"dev": true,
+			"requires": {
+				"to-regex-range": "^5.0.1"
+			}
+		},
+		"find-up": {
+			"version": "5.0.0",
+			"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+			"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"locate-path": "^6.0.0",
+				"path-exists": "^4.0.0"
+			}
+		},
+		"flat-cache": {
+			"version": "3.0.4",
+			"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+			"integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"flatted": "^3.1.0",
+				"rimraf": "^3.0.2"
+			}
+		},
+		"flatted": {
+			"version": "3.2.7",
+			"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+			"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+			"dev": true,
+			"peer": true
+		},
+		"fs.realpath": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+			"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+			"dev": true,
+			"peer": true
+		},
+		"fsevents": {
+			"version": "2.3.2",
+			"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+			"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+			"dev": true,
+			"optional": true
+		},
+		"function-bind": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+			"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+			"dev": true
+		},
+		"functional-red-black-tree": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+			"integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
+			"dev": true
+		},
+		"glob": {
+			"version": "7.2.3",
+			"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+			"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"fs.realpath": "^1.0.0",
+				"inflight": "^1.0.4",
+				"inherits": "2",
+				"minimatch": "^3.1.1",
+				"once": "^1.3.0",
+				"path-is-absolute": "^1.0.0"
+			}
+		},
+		"glob-parent": {
+			"version": "6.0.2",
+			"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+			"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"is-glob": "^4.0.3"
+			}
+		},
+		"globals": {
+			"version": "13.20.0",
+			"resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+			"integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"type-fest": "^0.20.2"
+			}
+		},
+		"globby": {
+			"version": "11.1.0",
+			"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+			"integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+			"dev": true,
+			"requires": {
+				"array-union": "^2.1.0",
+				"dir-glob": "^3.0.1",
+				"fast-glob": "^3.2.9",
+				"ignore": "^5.2.0",
+				"merge2": "^1.4.1",
+				"slash": "^3.0.0"
+			}
+		},
+		"grapheme-splitter": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+			"integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+			"dev": true,
+			"peer": true
+		},
+		"has": {
+			"version": "1.0.3",
+			"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+			"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+			"dev": true,
+			"requires": {
+				"function-bind": "^1.1.1"
+			}
+		},
+		"has-flag": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+			"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+			"dev": true,
+			"peer": true
+		},
+		"ignore": {
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+			"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+			"dev": true
+		},
+		"immutable": {
+			"version": "4.2.4",
+			"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.4.tgz",
+			"integrity": "sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w==",
+			"dev": true
+		},
+		"import-fresh": {
+			"version": "3.3.0",
+			"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+			"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"parent-module": "^1.0.0",
+				"resolve-from": "^4.0.0"
+			}
+		},
+		"imurmurhash": {
+			"version": "0.1.4",
+			"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+			"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+			"dev": true,
+			"peer": true
+		},
+		"inflight": {
+			"version": "1.0.6",
+			"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+			"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"once": "^1.3.0",
+				"wrappy": "1"
+			}
+		},
+		"inherits": {
+			"version": "2.0.4",
+			"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+			"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+			"dev": true,
+			"peer": true
+		},
+		"is-binary-path": {
+			"version": "2.1.0",
+			"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+			"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+			"dev": true,
+			"requires": {
+				"binary-extensions": "^2.0.0"
+			}
+		},
+		"is-core-module": {
+			"version": "2.11.0",
+			"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+			"integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+			"dev": true,
+			"requires": {
+				"has": "^1.0.3"
+			}
+		},
+		"is-extglob": {
+			"version": "2.1.1",
+			"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+			"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+			"dev": true
+		},
+		"is-glob": {
+			"version": "4.0.3",
+			"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+			"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+			"dev": true,
+			"requires": {
+				"is-extglob": "^2.1.1"
+			}
+		},
+		"is-number": {
+			"version": "7.0.0",
+			"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+			"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+			"dev": true
+		},
+		"is-path-inside": {
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+			"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+			"dev": true,
+			"peer": true
+		},
+		"isexe": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+			"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+			"dev": true,
+			"peer": true
+		},
+		"js-sdsl": {
+			"version": "4.3.0",
+			"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
+			"integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==",
+			"dev": true,
+			"peer": true
+		},
+		"js-yaml": {
+			"version": "4.1.0",
+			"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+			"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"argparse": "^2.0.1"
+			}
+		},
+		"json-schema-traverse": {
+			"version": "0.4.1",
+			"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+			"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+			"dev": true,
+			"peer": true
+		},
+		"json-stable-stringify-without-jsonify": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+			"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+			"dev": true,
+			"peer": true
+		},
+		"levn": {
+			"version": "0.4.1",
+			"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+			"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"prelude-ls": "^1.2.1",
+				"type-check": "~0.4.0"
+			}
+		},
+		"locate-path": {
+			"version": "6.0.0",
+			"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+			"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"p-locate": "^5.0.0"
+			}
+		},
+		"lodash.merge": {
+			"version": "4.6.2",
+			"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+			"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+			"dev": true,
+			"peer": true
+		},
+		"lru-cache": {
+			"version": "6.0.0",
+			"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+			"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+			"dev": true,
+			"requires": {
+				"yallist": "^4.0.0"
+			}
+		},
+		"merge2": {
+			"version": "1.4.1",
+			"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+			"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+			"dev": true
+		},
+		"micromatch": {
+			"version": "4.0.5",
+			"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+			"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+			"dev": true,
+			"requires": {
+				"braces": "^3.0.2",
+				"picomatch": "^2.3.1"
+			}
+		},
+		"minimatch": {
+			"version": "3.1.2",
+			"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+			"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"brace-expansion": "^1.1.7"
+			}
+		},
+		"moment": {
+			"version": "2.29.4",
+			"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+			"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+			"dev": true
+		},
+		"ms": {
+			"version": "2.1.2",
+			"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+			"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+			"dev": true
+		},
+		"natural-compare": {
+			"version": "1.4.0",
+			"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+			"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+			"dev": true,
+			"peer": true
+		},
+		"normalize-path": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+			"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+			"dev": true
+		},
+		"obsidian": {
+			"version": "1.1.1",
+			"resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.1.1.tgz",
+			"integrity": "sha512-GcxhsHNkPEkwHEjeyitfYNBcQuYGeAHFs1pEpZIv0CnzSfui8p8bPLm2YKLgcg20B764770B1sYGtxCvk9ptxg==",
+			"dev": true,
+			"requires": {
+				"@types/codemirror": "0.0.108",
+				"moment": "2.29.4"
+			}
+		},
+		"once": {
+			"version": "1.4.0",
+			"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+			"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"wrappy": "1"
+			}
+		},
+		"optionator": {
+			"version": "0.9.1",
+			"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+			"integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"deep-is": "^0.1.3",
+				"fast-levenshtein": "^2.0.6",
+				"levn": "^0.4.1",
+				"prelude-ls": "^1.2.1",
+				"type-check": "^0.4.0",
+				"word-wrap": "^1.2.3"
+			}
+		},
+		"p-limit": {
+			"version": "3.1.0",
+			"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+			"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"yocto-queue": "^0.1.0"
+			}
+		},
+		"p-locate": {
+			"version": "5.0.0",
+			"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+			"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"p-limit": "^3.0.2"
+			}
+		},
+		"parent-module": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+			"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"callsites": "^3.0.0"
+			}
+		},
+		"path-exists": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+			"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+			"dev": true,
+			"peer": true
+		},
+		"path-is-absolute": {
+			"version": "1.0.1",
+			"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+			"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+			"dev": true,
+			"peer": true
+		},
+		"path-key": {
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+			"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+			"dev": true,
+			"peer": true
+		},
+		"path-parse": {
+			"version": "1.0.7",
+			"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+			"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+			"dev": true
+		},
+		"path-type": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+			"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+			"dev": true
+		},
+		"picomatch": {
+			"version": "2.3.1",
+			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+			"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+			"dev": true
+		},
+		"prelude-ls": {
+			"version": "1.2.1",
+			"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+			"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+			"dev": true,
+			"peer": true
+		},
+		"punycode": {
+			"version": "2.3.0",
+			"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+			"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+			"dev": true,
+			"peer": true
+		},
+		"queue-microtask": {
+			"version": "1.2.3",
+			"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+			"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+			"dev": true
+		},
+		"readdirp": {
+			"version": "3.6.0",
+			"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+			"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+			"dev": true,
+			"requires": {
+				"picomatch": "^2.2.1"
+			}
+		},
+		"regexpp": {
+			"version": "3.2.0",
+			"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+			"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+			"dev": true
+		},
+		"resolve": {
+			"version": "1.22.1",
+			"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+			"integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+			"dev": true,
+			"requires": {
+				"is-core-module": "^2.9.0",
+				"path-parse": "^1.0.7",
+				"supports-preserve-symlinks-flag": "^1.0.0"
+			}
+		},
+		"resolve-from": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+			"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+			"dev": true,
+			"peer": true
+		},
+		"reusify": {
+			"version": "1.0.4",
+			"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+			"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+			"dev": true
+		},
+		"rimraf": {
+			"version": "3.0.2",
+			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+			"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"glob": "^7.1.3"
+			}
+		},
+		"run-parallel": {
+			"version": "1.2.0",
+			"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+			"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+			"dev": true,
+			"requires": {
+				"queue-microtask": "^1.2.2"
+			}
+		},
+		"sass": {
+			"version": "1.58.0",
+			"resolved": "https://registry.npmjs.org/sass/-/sass-1.58.0.tgz",
+			"integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==",
+			"dev": true,
+			"requires": {
+				"chokidar": ">=3.0.0 <4.0.0",
+				"immutable": "^4.0.0",
+				"source-map-js": ">=0.6.2 <2.0.0"
+			}
+		},
+		"semver": {
+			"version": "7.3.8",
+			"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
+			"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+			"dev": true,
+			"requires": {
+				"lru-cache": "^6.0.0"
+			}
+		},
+		"shebang-command": {
+			"version": "2.0.0",
+			"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+			"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"shebang-regex": "^3.0.0"
+			}
+		},
+		"shebang-regex": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+			"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+			"dev": true,
+			"peer": true
+		},
+		"slash": {
+			"version": "3.0.0",
+			"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+			"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+			"dev": true
+		},
+		"source-map-js": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+			"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+			"dev": true
+		},
+		"strip-ansi": {
+			"version": "6.0.1",
+			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+			"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"ansi-regex": "^5.0.1"
+			}
+		},
+		"strip-json-comments": {
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+			"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+			"dev": true,
+			"peer": true
+		},
+		"style-mod": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.0.tgz",
+			"integrity": "sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==",
+			"dev": true,
+			"peer": true
+		},
+		"supports-color": {
+			"version": "7.2.0",
+			"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+			"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"has-flag": "^4.0.0"
+			}
+		},
+		"supports-preserve-symlinks-flag": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+			"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+			"dev": true
+		},
+		"text-table": {
+			"version": "0.2.0",
+			"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+			"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+			"dev": true,
+			"peer": true
+		},
+		"to-regex-range": {
+			"version": "5.0.1",
+			"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+			"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+			"dev": true,
+			"requires": {
+				"is-number": "^7.0.0"
+			}
+		},
+		"tslib": {
+			"version": "2.4.0",
+			"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+			"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+			"dev": true
+		},
+		"tsutils": {
+			"version": "3.21.0",
+			"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+			"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+			"dev": true,
+			"requires": {
+				"tslib": "^1.8.1"
+			},
+			"dependencies": {
+				"tslib": {
+					"version": "1.14.1",
+					"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+					"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+					"dev": true
+				}
+			}
+		},
+		"type-check": {
+			"version": "0.4.0",
+			"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+			"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"prelude-ls": "^1.2.1"
+			}
+		},
+		"type-fest": {
+			"version": "0.20.2",
+			"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+			"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+			"dev": true,
+			"peer": true
+		},
+		"typescript": {
+			"version": "4.7.4",
+			"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
+			"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
+			"dev": true
+		},
+		"uri-js": {
+			"version": "4.4.1",
+			"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+			"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"punycode": "^2.1.0"
+			}
+		},
+		"w3c-keyname": {
+			"version": "2.2.6",
+			"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
+			"integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==",
+			"dev": true,
+			"peer": true
+		},
+		"which": {
+			"version": "2.0.2",
+			"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+			"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+			"dev": true,
+			"peer": true,
+			"requires": {
+				"isexe": "^2.0.0"
+			}
+		},
+		"word-wrap": {
+			"version": "1.2.3",
+			"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+			"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+			"dev": true,
+			"peer": true
+		},
+		"wrappy": {
+			"version": "1.0.2",
+			"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+			"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+			"dev": true,
+			"peer": true
+		},
+		"yallist": {
+			"version": "4.0.0",
+			"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+			"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+			"dev": true
+		},
+		"yocto-queue": {
+			"version": "0.1.0",
+			"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+			"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+			"dev": true,
+			"peer": true
+		}
+	}
+}
diff --git a/package.json b/package.json
index 6a00766..53d08ed 100644
--- a/package.json
+++ b/package.json
@@ -1,15 +1,20 @@
 {
-	"name": "obsidian-sample-plugin",
-	"version": "1.0.0",
-	"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
+	"name": "obsidian-hk-code-block",
+	"version": "0.1.0",
+	"description": "Obsidian plugin developed by Heekang Park; Make code block looking good on reading view",
 	"main": "main.js",
 	"scripts": {
 		"dev": "node esbuild.config.mjs",
 		"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
 		"version": "node version-bump.mjs && git add manifest.json versions.json"
 	},
-	"keywords": [],
-	"author": "",
+	"keywords": [
+		"Obsidian",
+		"Code Block",
+		"code-block",
+		"CodeBlock"
+	],
+	"author": "Heekang Park",
 	"license": "MIT",
 	"devDependencies": {
 		"@types/node": "^16.11.6",
@@ -19,6 +24,7 @@
 		"esbuild": "0.17.3",
 		"obsidian": "latest",
 		"tslib": "2.4.0",
-		"typescript": "4.7.4"
+		"typescript": "4.7.4",
+		"esbuild-sass-plugin": "^2.4.5"
 	}
 }
diff --git a/src/HKCodeBlockProcessor.ts b/src/HKCodeBlockProcessor.ts
new file mode 100755
index 0000000..773261d
--- /dev/null
+++ b/src/HKCodeBlockProcessor.ts
@@ -0,0 +1,343 @@
+import { MarkdownView } from "obsidian";
+import type { MarkdownPostProcessorContext, MarkdownSectionInformation } from "obsidian";
+
+import HKCodeBlockPlugin from "./main";
+import type { HKCodeBlockSettings } from "./HKCodeBlockSettings";
+
+const REGEX = {
+  TITLE: /\stitle:(?:'(.*?)'|"(.*?)")\s/,
+  LINENOS_SIMPLE: /\slinenos\s/,
+  LINENOS_COMPLICATE: /\slinenos:(true|false|(-{0,1}\d+))\s/,
+  HIGHLIGHT: /\shighlight:(?:'(.*?)'|"(.*?)")\s/,
+  LANGUAGE_FROM_CLASS: /^language-(\w+)$/,
+  LANGUAGE_SIMPLE: /\slanguage\s/,
+  LANGUAGE_COMPLICATE: /\slanguage:(true|false|'(.*?)'|"(.*?)")\s/,
+  COPYBTN_SIMPLE: /\scopybtn\s/,
+  COPYBTN_COMPLICATE: /\scopybtn:(true|false)\s/,
+  RESULT: /^```result\s/,
+  PROMPT_SIMPLE: /\sprompt\s/,
+  PROMPT_COMPLICATE: /\sprompt:(true|false|'(.*?)'|"(.*?)")\s/,
+}
+
+function getMeta(view: MarkdownView, elem_code: HTMLElement, section_code: MarkdownSectionInformation, settings: HKCodeBlockSettings): {
+  showTitle: (boolean | undefined),
+  title: string,
+  showLinenos: (boolean | undefined),
+  linenosStart: number,
+  linenosNum: number,
+  showHighlight: (boolean | undefined),
+  highlightLines: number[],
+  showLanguage: (boolean | undefined),
+  language: string,
+  showCopyBtn: (boolean | undefined),
+  isResult: boolean,
+  resultPrompt: string,
+  showPrompt: (boolean | undefined),
+  prompt: string
+} {
+  const firstline = view.editor.getLine(section_code.lineStart) + " "; // add a space to the end of the line to make sure the regex works
+
+  // title
+  let showTitle: (boolean | undefined) = undefined;
+  let title = "";
+  const regexResult_title = REGEX.TITLE.exec(firstline);
+  if (regexResult_title) {
+    showTitle = true;
+    title = regexResult_title[1] || regexResult_title[2];
+  }
+
+  // linenos
+  let showLinenos: (boolean | undefined) = undefined;
+  let linenosStart = settings.defaultLinenosStart;
+  const linenosNum = section_code.lineEnd - section_code.lineStart - 1;
+  const regexResult_linenosSimple = REGEX.LINENOS_SIMPLE.exec(firstline);
+  const regexResult_linenosComplicate = REGEX.LINENOS_COMPLICATE.exec(firstline);
+  if (regexResult_linenosSimple) {
+    showLinenos = true;
+  } else if (regexResult_linenosComplicate) {
+    if (regexResult_linenosComplicate[1] === "true") {
+      showLinenos = true;
+    } else if (regexResult_linenosComplicate[1] === "false") {
+      showLinenos = false;
+    } else {
+      showLinenos = true;
+      linenosStart = parseInt(regexResult_linenosComplicate[2]) || 1;
+    }
+  }
+
+  // highlight
+  let showHighlight: (boolean | undefined) = undefined;
+  let highlightLines: number[] = [];
+  const regexResult_highlight = REGEX.HIGHLIGHT.exec(firstline);
+  if (regexResult_highlight) {
+    showHighlight = true;
+    const highlightLines_str = regexResult_highlight[1] || regexResult_highlight[2];
+    highlightLines = highlightLines_str.split(",").map((line) => parseInt(line));
+
+    if (highlightLines.some((line) => isNaN(line))) {
+      // if any element is nan, then set showHighlight to false
+      showHighlight = undefined;
+      highlightLines = [];
+    } else {
+      // use only valid line numbers
+      highlightLines = highlightLines.filter((line) => line >= linenosStart && line < linenosStart + linenosNum);
+    }
+  }
+
+  // language
+  let showLanguage: (boolean | undefined) = undefined;
+  let language = (() => {
+    let language = settings.defaultLanguage;
+    elem_code.classList.forEach((className) => {
+      const regexResult_languageFromClass = REGEX.LANGUAGE_FROM_CLASS.exec(className.trim());
+      if (regexResult_languageFromClass) language = regexResult_languageFromClass[1];
+    });
+
+    return language;
+  })();
+  const regexResult_languageSimple = REGEX.LANGUAGE_SIMPLE.exec(firstline);
+  const regexResult_languageComplicate = REGEX.LANGUAGE_COMPLICATE.exec(firstline);
+  if (regexResult_languageSimple) {
+    showLanguage = true;
+  } else if (regexResult_languageComplicate) {
+    if (regexResult_languageComplicate[1] === "true") {
+      showLanguage = true;
+    } else if (regexResult_languageComplicate[1] === "false") {
+      showLanguage = false;
+    } else {
+      showLanguage = true;
+      language = regexResult_languageComplicate[2] || regexResult_languageComplicate[3];
+    }
+  }
+
+  // copy button
+  let showCopyBtn: (boolean | undefined) = undefined;
+  const regexResult_copyBtnSimple = REGEX.COPYBTN_SIMPLE.exec(firstline);
+  const regexResult_copyBtnComplicate = REGEX.COPYBTN_COMPLICATE.exec(firstline);
+  if (regexResult_copyBtnSimple) {
+    showCopyBtn = true;
+  } else if (regexResult_copyBtnComplicate) {
+    if (regexResult_copyBtnComplicate[1] === "true") {
+      showCopyBtn = true;
+    } else if (regexResult_copyBtnComplicate[1] === "false") {
+      showCopyBtn = false;
+    }
+  }
+
+  // prompt
+  let showPrompt: (boolean | undefined) = undefined;
+  let prompt = settings.defaultPrompt;
+  const regexResult_promptSimple = REGEX.PROMPT_SIMPLE.exec(firstline);
+  const regexResult_promptComplicate = REGEX.PROMPT_COMPLICATE.exec(firstline);
+  if (regexResult_promptSimple) {
+    showPrompt = true;
+  } else if (regexResult_promptComplicate) {
+    if (regexResult_promptComplicate[1] === "true") {
+      showPrompt = true;
+    } else if (regexResult_promptComplicate[1] === "false") {
+      showPrompt = false;
+    } else {
+      showPrompt = true;
+      prompt = regexResult_promptComplicate[2] || regexResult_promptComplicate[3];
+    }
+  }
+
+  // result
+  let isResult = false;
+  let resultPrompt = settings.defaultResultPrompt;
+  const regexResult_result = REGEX.RESULT.exec(firstline);
+  const regexResultPrompt_result = REGEX.PROMPT_COMPLICATE.exec(firstline);
+  if (regexResult_result) {
+    isResult = true;
+    
+    // override other meta data : only linenos, highlight are available
+    showTitle = false;
+    showLanguage = false;
+    showCopyBtn = false;
+    showPrompt = false;
+
+    if (regexResultPrompt_result) {
+      resultPrompt = regexResultPrompt_result[2] || regexResultPrompt_result[3];
+    }
+  }
+
+  return {
+    showTitle: showTitle,
+    title: title,
+    showLinenos: showLinenos,
+    linenosStart: linenosStart,
+    linenosNum: linenosNum,
+    showHighlight: showHighlight,
+    highlightLines: highlightLines,
+    showLanguage: showLanguage,
+    language: language,
+    showCopyBtn: showCopyBtn,
+    isResult: isResult,
+    resultPrompt: resultPrompt,
+    showPrompt: showPrompt,
+    prompt: prompt
+  };
+}
+
+export async function HKCodeBlockProcessor(
+  el: HTMLElement,
+  context: MarkdownPostProcessorContext,
+  plugin: HKCodeBlockPlugin
+) {
+  const settings = plugin.settings;
+
+  const view = app.workspace.getActiveViewOfType(MarkdownView);
+  if (!view) return;
+
+  const elem_code: (HTMLElement | null) = el.querySelector("pre:not(.frontmatter) > code");
+  if (!elem_code) return;
+
+  const elem_pre: (HTMLElement | null) = elem_code.parentElement;
+  if (!elem_pre) return;
+
+  const elem_div: (HTMLElement | null) = elem_pre.parentElement;
+  if (!elem_div) return;
+
+  const elem_copyBtn: (HTMLElement | null) = elem_div.querySelector(".copy-code-button");
+  if (!elem_copyBtn) return;
+
+  const section_code: (MarkdownSectionInformation | null) = context.getSectionInfo(elem_code);
+  if (!section_code) return;
+
+  // get metadata
+  const { 
+    showTitle,
+    title,
+    showLinenos,
+    linenosStart,
+    linenosNum,
+    showHighlight,
+    highlightLines,
+    showLanguage,
+    language,
+    showCopyBtn,
+    isResult,
+    resultPrompt,
+    showPrompt,
+    prompt
+  } = getMeta(view, elem_code, section_code, settings);
+
+  if (settings.debugMode) {
+    console.log({ 
+      showTitle: showTitle,
+      title: title,
+      showLinenos: showLinenos,
+      linenosStart: linenosStart,
+      linenosNum: linenosNum,
+      showHighlight: showHighlight,
+      highlightLines: highlightLines,
+      showLanguage: showLanguage,
+      language: language,
+      showCopyBtn: showCopyBtn,
+      isResult: isResult,
+      resultPrompt: resultPrompt,
+      showPrompt: showPrompt,
+      prompt: prompt,
+    })
+  }
+
+  // create HTML elements
+  elem_div.classList.add("hk-codeblock");
+  elem_code.classList.add("hk-codeblock-code");
+  elem_copyBtn.remove(); // remove the original copy button as default
+
+  if (settings.useTitleGlobal === "default off, but on when specified" && (showTitle === true)) {
+    elem_div.classList.add("hk-codeblock-show-title");
+
+    const elem_title = document.createElement("div");
+    elem_title.classList.add("hk-codeblock-title");
+    elem_title.innerHTML = title;
+    elem_div.insertBefore(elem_title, elem_pre);
+  }
+
+  if (
+    (settings.useLinenosGlobal === "always on") ||
+    (settings.useLinenosGlobal === "default on, but off when specified" && (showLinenos === undefined || showLinenos === true)) ||
+    (settings.useLinenosGlobal === "default off, but on when specified" && (showLinenos === true))
+  ) {
+    elem_div.classList.add("hk-codeblock-show-linenos");
+
+    const elem_linenos = document.createElement("code");
+    elem_linenos.classList.add("hk-codeblock-linenos");
+    elem_linenos.innerText = Array(linenosNum).fill(0).map((_, idx) => idx + linenosStart).join("\n");
+    elem_pre.insertBefore(elem_linenos, elem_code);
+
+    if (settings.showLinenosSplitter) {
+      elem_linenos.classList.add("show-splitter");
+    }
+  }
+
+  if (settings.useHighlightGlobal === "default off, but on when specified" && (showHighlight === true)) {
+    elem_div.classList.add("hk-codeblock-show-highlight");
+
+    elem_div.style.setProperty("--hk-codeblock-highlight-background-color", settings.highlightColor);
+
+    const elem_highlight = document.createElement("code");
+    elem_highlight.classList.add("hk-codeblock-highlight");
+    elem_highlight.innerHTML = Array(linenosNum).fill(0).map((_, idx) => {
+      const classNames: string[] = [];
+      if (highlightLines.includes(idx + linenosStart)) classNames.push("highlight");
+      return ` `;
+    }).join("\n");
+    elem_pre.insertBefore(elem_highlight, elem_code);
+  }
+
+  if (
+    (settings.useLanguageGlobal === "always on") ||
+    (settings.useLanguageGlobal === "default on, but off when specified" && (showLanguage === undefined || showLanguage === true)) ||
+    (settings.useLanguageGlobal === "default off, but on when specified" && (showLanguage === true))
+  ) {
+    elem_div.classList.add("hk-codeblock-show-language");
+
+    const elem_language = document.createElement("div");
+    elem_language.classList.add("hk-codeblock-language");
+    elem_language.innerText = language;
+    elem_pre.prepend(elem_language);
+  }
+
+  if (
+    (settings.useCopyBtnGlobal === "always on") ||
+    (settings.useCopyBtnGlobal === "default on, but off when specified" && (showCopyBtn === undefined || showCopyBtn === true)) ||
+    (settings.useCopyBtnGlobal === "default off, but on when specified" && (showCopyBtn === true))
+  ) {
+    elem_div.classList.add("hk-codeblock-show-copybtn");
+
+    elem_pre.appendChild(elem_copyBtn);
+  }
+
+  if (
+    (settings.usePromptGlobal === "always on" && settings.promptingLanguages.includes(language)) ||
+    (settings.usePromptGlobal === "default on, but off when specified" && settings.promptingLanguages.includes(language) && (showPrompt === undefined || showPrompt === true)) ||
+    (settings.usePromptGlobal === "default off, but on when specified" && (showPrompt === true))
+  ) {
+    elem_div.classList.add("hk-codeblock-show-prompt");
+
+    // using Prism.js command-line plugin
+    let code_lines = elem_code.innerText.split("\n");
+    if (code_lines[code_lines.length - 1].trim().length == 0) code_lines.pop(); // remove last line if empty
+
+    const no_prompt_line_idxs = code_lines.map((line, idx) => {
+      if (line.trim().length == 0) return (idx + 1); // empty line
+      if (line.startsWith("#")) return (idx + 1); // comment line
+      return -1;
+    }).filter((idx) => idx != -1);
+
+    elem_pre.classList.add("command-line");
+    elem_pre.setAttribute("data-prompt", prompt);
+    elem_pre.setAttribute("data-continuation-str", "\\");
+    elem_pre.setAttribute("data-continuation-prompt", " ".repeat(prompt.length));  // use spaces to align continuation prompt
+    elem_pre.setAttribute("data-output", no_prompt_line_idxs.join(", "));
+  }
+
+  if(settings.useResultGlobal === "enable" && (isResult === true)) {
+    elem_div.classList.add("hk-codeblock-result");
+    elem_code.classList.add("hk-codeblock-result-code");
+
+    elem_div.setAttribute("data-result-prompt", resultPrompt);
+  }
+}
\ No newline at end of file
diff --git a/src/HKCodeBlockSettingTab.ts b/src/HKCodeBlockSettingTab.ts
new file mode 100755
index 0000000..5ac954e
--- /dev/null
+++ b/src/HKCodeBlockSettingTab.ts
@@ -0,0 +1,267 @@
+import { App, PluginSettingTab, Setting } from 'obsidian';
+
+import HKCodeBlockPlugin from './main';
+
+export const fragWithHTML = (text: string) => {
+	return createFragment((frag) => {
+		frag.createDiv().innerHTML = text.split("\n").map((line) => line.trim()).join("
"); + }); +} + +export class HKCodeBlockSettingTab extends PluginSettingTab { + plugin: HKCodeBlockPlugin; + + constructor(app: App, plugin: HKCodeBlockPlugin) { + super(app, plugin); + this.plugin = plugin; + } + + display(): void { + const { containerEl } = this; + containerEl.empty(); + + // title + containerEl.createEl('h2', { text: 'Title' }); + + new Setting(containerEl) + .setName('Use Title') + .setDesc(fragWithHTML(`- default off, but on when specified : the title will only be shown if the title statement is specified + - always off : the title will never be shown`)) + .addDropdown(tc => + tc.addOptions({ + "default off, but on when specified": "default off, but on when specified", + "always off": "always off", + }) + .setValue(this.plugin.settings.useTitleGlobal) + .onChange(async (value: string) => { + this.plugin.settings.useTitleGlobal = value as ("default off, but on when specified" | "always off"); + await this.plugin.saveSettings(); + }) + ); + + // line numbers + containerEl.createEl('h2', { text: 'Line Numbers' }); + + new Setting(containerEl) + .setName('Use Line Numbers') + .setDesc(fragWithHTML(`- always on : line numbers will always be shown + - default on, but off when specified : line numbers will always be shown, but will not be shown if linenos statement is specified as false + - default off, but on when specified : line numbers will only be shown if the linenos statement is specified as true + - always off : line numbers will never be shown`)) + .addDropdown(tc => + tc.addOptions({ + "always on": "always on", + "default on, but off when specified": "default on, but off when specified", + "default off, but on when specified": "default off, but on when specified", + "always off": "always off", + }) + .setValue(this.plugin.settings.useLinenosGlobal) + .onChange(async (value: string) => { + this.plugin.settings.useLinenosGlobal = value as ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off"); + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName('Default Line Number Start') + .setDesc('The default line number start of the code block.') + .addText(tc => + tc.setValue(this.plugin.settings.defaultLinenosStart.toString()) + .onChange(async (value: string) => { + const num = parseInt(value); + if (isNaN(num)) return; + + this.plugin.settings.defaultLinenosStart = num; + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName('Show Line Number Splitter') + .addToggle(tc => + tc.setValue(this.plugin.settings.showLinenosSplitter) + .onChange(async (value: boolean) => { + this.plugin.settings.showLinenosSplitter = value; + await this.plugin.saveSettings(); + }) + ); + + // line highlight + containerEl.createEl('h2', { text: 'Line Highlight' }); + + new Setting(containerEl) + .setName('Use Line Highlight') + .setDesc(fragWithHTML(`- default off, but on when specified : line highlight will only be shown if the line highlight statement is specified + - always off : line highlight will never be shown`)) + .addDropdown(tc => + tc.addOptions({ + "default off, but on when specified": "default off, but on when specified", + "always off": "always off", + }) + .setValue(this.plugin.settings.useHighlightGlobal) + .onChange(async (value: string) => { + this.plugin.settings.useHighlightGlobal = value as ("default off, but on when specified" | "always off"); + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName('Line Highlight Color') + .setDesc('The background color of the highlighted line. Note that the given color will be applied with 0.2 opacity.') + .addText(tc => + tc.setValue(this.plugin.settings.highlightColor) + .onChange(async (value: string) => { + this.plugin.settings.highlightColor = value; + await this.plugin.saveSettings(); + }) + ); + + // language + containerEl.createEl('h2', { text: 'Language Indicator' }); + + new Setting(containerEl) + .setName('Use Language Indicator') + .setDesc(fragWithHTML(`- always on : language indicator will always be shown + - default on, but off when specified : language indicator will always be shown, but will not be shown if the language indicator statement is specified as false + - default off, but on when specified : language indicator will only be shown if the language indicator statement is specified as true + - always off : language indicator will never be shown`)) + .addDropdown(tc => + tc.addOptions({ + "always on": "always on", + "default on, but off when specified": "default on, but off when specified", + "default off, but on when specified": "default off, but on when specified", + "always off": "always off", + }) + .setValue(this.plugin.settings.useLanguageGlobal) + .onChange(async (value: string) => { + this.plugin.settings.useLanguageGlobal = value as ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off"); + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName('Default Language') + .setDesc('The default language name of the code block if the language is not specified.') + .addText(tc => + tc.setValue(this.plugin.settings.defaultLanguage) + .onChange(async (value: string) => { + this.plugin.settings.defaultLanguage = value; + await this.plugin.saveSettings(); + }) + ); + + // copy button + containerEl.createEl('h2', { text: 'Copy Button' }); + + new Setting(containerEl) + .setName('Use Copy Button') + .setDesc(fragWithHTML(`- always on : copy button will always be shown + - default on, but off when specified : copy button will always be shown, but will not be shown if the copy button statement is specified as false + - default off, but on when specified : copy button will only be shown if the copy button statement is specified as true + - always off : copy button will never be shown`)) + .addDropdown(tc => + tc.addOptions({ + "always on": "always on", + "default on, but off when specified": "default on, but off when specified", + "default off, but on when specified": "default off, but on when specified", + "always off": "always off", + }) + .setValue(this.plugin.settings.useCopyBtnGlobal) + .onChange(async (value: string) => { + this.plugin.settings.useCopyBtnGlobal = value as ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off"); + await this.plugin.saveSettings(); + }) + ); + + // prompt + containerEl.createEl('h2', { text: 'Prompt' }); + + new Setting(containerEl) + .setName('Use Prompt') + .setDesc(fragWithHTML(`- always on : prompt will always be shown + - default on, but off when specified : prompt will always be shown, but will not be shown if the prompt statement is specified as false + - default off, but on when specified : prompt will only be shown if the prompt statement is specified as true + - always off : prompt will never be shown + You can also specify the prompt by the statement like \`prompt:"My Prompt"\`. (default: "$")`)) + .addDropdown(tc => + tc.addOptions({ + "always on": "always on", + "default on, but off when specified": "default on, but off when specified", + "default off, but on when specified": "default off, but on when specified", + "always off": "always off", + }) + .setValue(this.plugin.settings.usePromptGlobal) + .onChange(async (value: string) => { + this.plugin.settings.usePromptGlobal = value as ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off"); + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName('Prompting Languages') + .setDesc('The languages that will be prompted by default. You can specify multiple languages by separating them with enters.') + .addTextArea(tc => + tc.setValue(this.plugin.settings.promptingLanguages.join("\n")) + .onChange(async (value: string) => { + const lines = value.split("\n").filter(line => line.trim() !== ""); + this.plugin.settings.promptingLanguages = lines; + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName("Default Prompt") + .setDesc("The default prompt of the bash code block.") + .addText(tc => + tc.setValue(this.plugin.settings.defaultPrompt) + .onChange(async (value: string) => { + this.plugin.settings.defaultPrompt = value; + await this.plugin.saveSettings(); + }) + ); + + // result + containerEl.createEl('h2', { text: 'Result' }); + + new Setting(containerEl) + .setName('Use Result') + .setDesc(fragWithHTML(`- enable : treat the code block starts like \`\`\`\`result\` as the result of the adjacent previous code block + - disable : treat the code block with \`result\` as its language name as a normal code block`)) + .addDropdown(tc => + tc.addOptions({ + "enable": "enable", + "disable": "disable", + }) + .setValue(this.plugin.settings.useResultGlobal) + .onChange(async (value: string) => { + this.plugin.settings.useResultGlobal = value as ("enable" | "disable"); + await this.plugin.saveSettings(); + }) + ); + + new Setting(containerEl) + .setName("Default Result Prompt") + .setDesc("The default prompt of the result code block.") + .addText(tc => + tc.setValue(this.plugin.settings.defaultResultPrompt) + .onChange(async (value: string) => { + this.plugin.settings.defaultResultPrompt = value; + await this.plugin.saveSettings(); + }) + ); + + // for developers + containerEl.createEl('h2', { text: 'Developers' }); + + new Setting(containerEl) + .setName('Debug Mode') + .setDesc('Show logs in the console.') + .addToggle(tc => + tc.setValue(this.plugin.settings.debugMode) + .onChange(async (value: boolean) => { + this.plugin.settings.debugMode = value; + await this.plugin.saveSettings(); + }) + ); + } +} \ No newline at end of file diff --git a/src/HKCodeBlockSettings.ts b/src/HKCodeBlockSettings.ts new file mode 100755 index 0000000..226a8d9 --- /dev/null +++ b/src/HKCodeBlockSettings.ts @@ -0,0 +1,49 @@ +export interface HKCodeBlockSettings { + useTitleGlobal: ("default off, but on when specified" | "always off"); + + useLinenosGlobal: ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off"); + defaultLinenosStart: number; + showLinenosSplitter: boolean; + + useHighlightGlobal: ("default off, but on when specified" | "always off"); + highlightColor: string; + + useLanguageGlobal: ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off"); + defaultLanguage: string; + + useCopyBtnGlobal: ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off"); + + usePromptGlobal: ("always on" | "default on, but off when specified" | "default off, but on when specified" | "always off"); + defaultPrompt: string; + + useResultGlobal: ("enable" | "disable"); + promptingLanguages: string[]; + defaultResultPrompt: string; + + debugMode: boolean; +} + +export const DEFAULT_SETTINGS: HKCodeBlockSettings = { + useTitleGlobal: "default off, but on when specified", + + useLinenosGlobal: "default off, but on when specified", + defaultLinenosStart: 1, + showLinenosSplitter: true, + + useHighlightGlobal: "default off, but on when specified", + highlightColor: "#ff0000", + + useLanguageGlobal: "default on, but off when specified", + defaultLanguage: "plain text", + + useCopyBtnGlobal: "default on, but off when specified", + + usePromptGlobal: "default on, but off when specified", + promptingLanguages: ["bash"], + defaultPrompt: "$", + + useResultGlobal: "enable", + defaultResultPrompt: "Result", + + debugMode: false, +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100755 index 0000000..dc97e5e --- /dev/null +++ b/src/main.ts @@ -0,0 +1,48 @@ +import { Plugin, loadPrism } from 'obsidian'; + +import type { HKCodeBlockSettings } from './HKCodeBlockSettings'; +import { DEFAULT_SETTINGS } from './HKCodeBlockSettings'; +import { HKCodeBlockSettingTab } from './HKCodeBlockSettingTab'; +import { HKCodeBlockProcessor } from './HKCodeBlockProcessor'; + +import { PrismPlugin_CommandLine } from './prism-plugins/prism-command-line'; + +export default class HKCodeBlockPlugin extends Plugin { + settings: HKCodeBlockSettings; + + async onload() { + await this.loadSettings(); + if (this.settings.debugMode) { + console.log("loading HKCodeBlock plugin"); + } + + const Prism = await loadPrism(); + + // activate Prism.js plugins + PrismPlugin_CommandLine(Prism); + + // register settings tab + this.addSettingTab(new HKCodeBlockSettingTab(this.app, this)); + + // register markdown post processor + const processor = this.registerMarkdownPostProcessor((el, ctx) => { + HKCodeBlockProcessor(el, ctx, this); + }); + + processor.sortOrder = 100; // run after the default code block processor + } + + onunload() { + if (this.settings.debugMode) { + console.log("unloading HKCodeBlock plugin"); + } + } + + async loadSettings() { + this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); + } + + async saveSettings() { + await this.saveData(this.settings); + } +} \ No newline at end of file diff --git a/src/prism-plugins/prism-command-line.js b/src/prism-plugins/prism-command-line.js new file mode 100755 index 0000000..3781e14 --- /dev/null +++ b/src/prism-plugins/prism-command-line.js @@ -0,0 +1,243 @@ +export function PrismPlugin_CommandLine(Prism) { + + if (typeof Prism === 'undefined' || typeof document === 'undefined') { + return; + } + + var CLASS_PATTERN = /(?:^|\s)command-line(?:\s|$)/; + var PROMPT_CLASS = 'command-line-prompt'; + + /** @type {(str: string, prefix: string) => boolean} */ + var startsWith = ''.startsWith + ? function (s, p) { return s.startsWith(p); } + : function (s, p) { return s.indexOf(p) === 0; }; + + // Support for IE11 that has no endsWith() + /** @type {(str: string, suffix: string) => boolean} */ + var endsWith = ''.endsWith + ? function (str, suffix) { + return str.endsWith(suffix); + } + : function (str, suffix) { + var len = str.length; + return str.substring(len - suffix.length, len) === suffix; + }; + + /** + * Returns whether the given hook environment has a command line info object. + * + * @param {any} env + * @returns {boolean} + */ + function hasCommandLineInfo(env) { + var vars = env.vars = env.vars || {}; + return 'command-line' in vars; + } + /** + * Returns the command line info object from the given hook environment. + * + * @param {any} env + * @returns {CommandLineInfo} + * + * @typedef CommandLineInfo + * @property {boolean} [complete] + * @property {number} [numberOfLines] + * @property {string[]} [outputLines] + */ + function getCommandLineInfo(env) { + var vars = env.vars = env.vars || {}; + return vars['command-line'] = vars['command-line'] || {}; + } + + + Prism.hooks.add('before-highlight', function (env) { + var commandLine = getCommandLineInfo(env); + + if (commandLine.complete || !env.code) { + commandLine.complete = true; + return; + } + + // Works only for wrapped inside
 (not inline).
+		var pre = env.element.parentElement;
+		if (!pre || !/pre/i.test(pre.nodeName) || // Abort only if neither the 
 nor the  have the class
+			(!CLASS_PATTERN.test(pre.className) && !CLASS_PATTERN.test(env.element.className))) {
+			commandLine.complete = true;
+			return;
+		}
+
+		// The element might be highlighted multiple times, so we just remove the previous prompt
+		var existingPrompt = env.element.querySelector('.' + PROMPT_CLASS);
+		if (existingPrompt) {
+			existingPrompt.remove();
+		}
+
+		var codeLines = env.code.split('\n');
+
+		if(codeLines[codeLines.length - 1].trim().length === 0) { // do not count the last line if it is empty
+			commandLine.numberOfLines = codeLines.length - 1;
+		} else {
+			commandLine.numberOfLines = codeLines.length;
+		}
+		/** @type {string[]} */
+		var outputLines = commandLine.outputLines = [];
+
+		var outputSections = pre.getAttribute('data-output');
+		var outputFilter = pre.getAttribute('data-filter-output');
+		if (outputSections !== null) { // The user specified the output lines. -- cwells
+			outputSections.split(',').forEach(function (section) {
+				var range = section.split('-');
+				var outputStart = parseInt(range[0], 10);
+				var outputEnd = range.length === 2 ? parseInt(range[1], 10) : outputStart;
+
+				if (!isNaN(outputStart) && !isNaN(outputEnd)) {
+					if (outputStart < 1) {
+						outputStart = 1;
+					}
+					if (outputEnd > codeLines.length) {
+						outputEnd = codeLines.length;
+					}
+					// Convert start and end to 0-based to simplify the arrays. -- cwells
+					outputStart--;
+					outputEnd--;
+					// Save the output line in an array and clear it in the code so it's not highlighted. -- cwells
+					for (var j = outputStart; j <= outputEnd; j++) {
+						outputLines[j] = codeLines[j];
+						codeLines[j] = '';
+					}
+				}
+			});
+		} else if (outputFilter) { // Treat lines beginning with this string as output. -- cwells
+			for (var i = 0; i < codeLines.length; i++) {
+				if (startsWith(codeLines[i], outputFilter)) { // This line is output. -- cwells
+					outputLines[i] = codeLines[i].slice(outputFilter.length);
+					codeLines[i] = '';
+				}
+			}
+		}
+
+		var continuationLineIndicies = commandLine.continuationLineIndicies = new Set();
+		var lineContinuationStr = pre.getAttribute('data-continuation-str');
+		var continuationFilter = pre.getAttribute('data-filter-continuation');
+
+		// Identify code lines where the command has continued onto subsequent
+		// lines and thus need a different prompt. Need to do this after the output
+		// lines have been removed to ensure we don't pick up a continuation string
+		// in an output line.
+		for (var j = 0; j < codeLines.length; j++) {
+			var line = codeLines[j];
+			if (!line) {
+				continue;
+			}
+
+			// Record the next line as a continuation if this one ends in a continuation str.
+			if (lineContinuationStr && endsWith(line, lineContinuationStr)) {
+				continuationLineIndicies.add(j + 1);
+			}
+			// Record this line as a continuation if marked with a continuation prefix
+			// (that we will remove).
+			if (j > 0 && continuationFilter && startsWith(line, continuationFilter)) {
+				codeLines[j] = line.slice(continuationFilter.length);
+				continuationLineIndicies.add(j);
+			}
+		}
+
+		env.code = codeLines.join('\n');
+	});
+
+	Prism.hooks.add('before-insert', function (env) {
+		var commandLine = getCommandLineInfo(env);
+
+		if (commandLine.complete) {
+			return;
+		}
+
+		// Reinsert the output lines into the highlighted code. -- cwells
+		var codeLines = env.highlightedCode.split('\n');
+		var outputLines = commandLine.outputLines || [];
+		for (var i = 0, l = codeLines.length; i < l; i++) {
+			// Add spans to allow distinction of input/output text for styling
+			if (outputLines.hasOwnProperty(i)) {
+				// outputLines were removed from codeLines so missed out on escaping
+				// of markup so do it here.
+				codeLines[i] = ''
+					+ Prism.util.encode(outputLines[i]) + '';
+			} else {
+				codeLines[i] = ''
+					+ codeLines[i] + '';
+			}
+		}
+		env.highlightedCode = codeLines.join('\n');
+	});
+
+	Prism.hooks.add('complete', function (env) {
+		if (!hasCommandLineInfo(env)) {
+			// the previous hooks never ran
+			return;
+		}
+
+		var commandLine = getCommandLineInfo(env);
+
+		if (commandLine.complete) {
+			return;
+		}
+
+		var pre = env.element.parentElement;
+		if (CLASS_PATTERN.test(env.element.className)) { // Remove the class "command-line" from the 
+			env.element.className = env.element.className.replace(CLASS_PATTERN, ' ');
+		}
+		if (!CLASS_PATTERN.test(pre.className)) { // Add the class "command-line" to the 
+			pre.className += ' command-line';
+		}
+
+		function getAttribute(key, defaultValue) {
+			return (pre.getAttribute(key) || defaultValue).replace(/"/g, '"');
+		}
+
+		// Create the "rows" that will become the command-line prompts. -- cwells
+		var promptLines = '';
+		var rowCount = commandLine.numberOfLines || 0;
+		var promptText = getAttribute('data-prompt', '');
+		var promptLine;
+		if (promptText !== '') {
+			promptLine = '';
+		} else {
+			var user = getAttribute('data-user', 'user');
+			var host = getAttribute('data-host', 'localhost');
+			promptLine = '';
+		}
+
+		var continuationLineIndicies = commandLine.continuationLineIndicies || new Set();
+		var continuationPromptText = getAttribute('data-continuation-prompt', '>');
+		var continuationPromptLine = '';
+
+		// Assemble all the appropriate prompt/continuation lines
+		for (var j = 0; j < rowCount; j++) {
+			if (continuationLineIndicies.has(j)) {
+				promptLines += continuationPromptLine;
+			} else {
+				promptLines += promptLine;
+			}
+		}
+
+		// Create the wrapper element. -- cwells
+		var prompt = document.createElement('span');
+		prompt.className = PROMPT_CLASS;
+		prompt.innerHTML = promptLines;
+
+		// Remove the prompt from the output lines. -- cwells
+		var outputLines = commandLine.outputLines || [];
+		for (var i = 0, l = outputLines.length; i < l; i++) {
+			if (outputLines.hasOwnProperty(i)) {
+				var node = prompt.children[i];
+				node.removeAttribute('data-user');
+				node.removeAttribute('data-host');
+				node.removeAttribute('data-prompt');
+			}
+		}
+
+		env.element.insertBefore(prompt, env.element.firstChild);
+		commandLine.complete = true;
+	});
+
+}
diff --git a/src/prism-plugins/prism-line-highlight.js b/src/prism-plugins/prism-line-highlight.js
new file mode 100755
index 0000000..b637427
--- /dev/null
+++ b/src/prism-plugins/prism-line-highlight.js
@@ -0,0 +1,346 @@
+export function PrismPlugin_LineHighlight(Prism) {
+
+	if (typeof Prism === 'undefined' || typeof document === 'undefined' || !document.querySelector) {
+		return;
+	}
+
+	var LINE_NUMBERS_CLASS = 'line-numbers';
+	var LINKABLE_LINE_NUMBERS_CLASS = 'linkable-line-numbers';
+	var NEW_LINE_EXP = /\n(?!$)/g;
+
+	/**
+	 * @param {string} selector
+	 * @param {ParentNode} [container]
+	 * @returns {HTMLElement[]}
+	 */
+	function $$(selector, container) {
+		return Array.prototype.slice.call((container || document).querySelectorAll(selector));
+	}
+
+	/**
+	 * Returns whether the given element has the given class.
+	 *
+	 * @param {Element} element
+	 * @param {string} className
+	 * @returns {boolean}
+	 */
+	function hasClass(element, className) {
+		return element.classList.contains(className);
+	}
+
+	/**
+	 * Calls the given function.
+	 *
+	 * @param {() => any} func
+	 * @returns {void}
+	 */
+	function callFunction(func) {
+		func();
+	}
+
+	// Some browsers round the line-height, others don't.
+	// We need to test for it to position the elements properly.
+	var isLineHeightRounded = (function () {
+		var res;
+		return function () {
+			if (typeof res === 'undefined') {
+				var d = document.createElement('div');
+				d.style.fontSize = '13px';
+				d.style.lineHeight = '1.5';
+				d.style.padding = '0';
+				d.style.border = '0';
+				d.innerHTML = ' 
 '; + document.body.appendChild(d); + // Browsers that round the line-height should have offsetHeight === 38 + // The others should have 39. + res = d.offsetHeight === 38; + document.body.removeChild(d); + } + return res; + }; + }()); + + /** + * Returns the top offset of the content box of the given parent and the content box of one of its children. + * + * @param {HTMLElement} parent + * @param {HTMLElement} child + */ + function getContentBoxTopOffset(parent, child) { + var parentStyle = getComputedStyle(parent); + var childStyle = getComputedStyle(child); + + /** + * Returns the numeric value of the given pixel value. + * + * @param {string} px + */ + function pxToNumber(px) { + return +px.substr(0, px.length - 2); + } + + return child.offsetTop + + pxToNumber(childStyle.borderTopWidth) + + pxToNumber(childStyle.paddingTop) + - pxToNumber(parentStyle.paddingTop); + } + + /** + * Returns whether the Line Highlight plugin is active for the given element. + * + * If this function returns `false`, do not call `highlightLines` for the given element. + * + * @param {HTMLElement | null | undefined} pre + * @returns {boolean} + */ + function isActiveFor(pre) { + if (!pre || !/pre/i.test(pre.nodeName)) { + return false; + } + + if (pre.hasAttribute('data-line')) { + return true; + } + + if (pre.id && Prism.util.isActive(pre, LINKABLE_LINE_NUMBERS_CLASS)) { + // Technically, the line numbers plugin is also necessary but this plugin doesn't control the classes of + // the line numbers plugin, so we can't assume that they are present. + return true; + } + + return false; + } + + var scrollIntoView = true; + + Prism.plugins.lineHighlight = { + /** + * Highlights the lines of the given pre. + * + * This function is split into a DOM measuring and mutate phase to improve performance. + * The returned function mutates the DOM when called. + * + * @param {HTMLElement} pre + * @param {string | null} [lines] + * @param {string} [classes=''] + * @returns {() => void} + */ + highlightLines: function highlightLines(pre, lines, classes) { + lines = typeof lines === 'string' ? lines : (pre.getAttribute('data-line') || ''); + + var ranges = lines.replace(/\s+/g, '').split(',').filter(Boolean); + var offset = +pre.getAttribute('data-line-offset') || 0; + + var parseMethod = isLineHeightRounded() ? parseInt : parseFloat; + var lineHeight = parseMethod(getComputedStyle(pre).lineHeight); + var hasLineNumbers = Prism.util.isActive(pre, LINE_NUMBERS_CLASS); + var codeElement = pre.querySelector('code'); + var parentElement = hasLineNumbers ? pre : codeElement || pre; + var mutateActions = /** @type {(() => void)[]} */ ([]); + var lineBreakMatch = codeElement.textContent.match(NEW_LINE_EXP); + var numberOfLines = lineBreakMatch ? lineBreakMatch.length + 1 : 1; + /** + * The top offset between the content box of the element and the content box of the parent element of + * the line highlight element (either `
` or ``).
+			 *
+			 * This offset might not be zero for some themes where the  element has a top margin. Some plugins
+			 * (or users) might also add element above the  element. Because the line highlight is aligned relative
+			 * to the 
 element, we have to take this into account.
+			 *
+			 * This offset will be 0 if the parent element of the line highlight element is the `` element.
+			 */
+			var codePreOffset = !codeElement || parentElement == codeElement ? 0 : getContentBoxTopOffset(pre, codeElement);
+
+			ranges.forEach(function (currentRange) {
+				var range = currentRange.split('-');
+
+				var start = +range[0];
+				var end = +range[1] || start;
+				end = Math.min(numberOfLines + offset, end);
+
+				if (end < start) {
+					return;
+				}
+
+				/** @type {HTMLElement} */
+				var line = pre.querySelector('.line-highlight[data-range="' + currentRange + '"]') || document.createElement('div');
+
+				mutateActions.push(function () {
+					line.setAttribute('aria-hidden', 'true');
+					line.setAttribute('data-range', currentRange);
+					line.className = (classes || '') + ' line-highlight';
+				});
+
+				// if the line-numbers plugin is enabled, then there is no reason for this plugin to display the line numbers
+				if (hasLineNumbers && Prism.plugins.lineNumbers) {
+					var startNode = Prism.plugins.lineNumbers.getLine(pre, start);
+					var endNode = Prism.plugins.lineNumbers.getLine(pre, end);
+
+					if (startNode) {
+						var top = startNode.offsetTop + codePreOffset + 'px';
+						mutateActions.push(function () {
+							line.style.top = top;
+						});
+					}
+
+					if (endNode) {
+						var height = (endNode.offsetTop - startNode.offsetTop) + endNode.offsetHeight + 'px';
+						mutateActions.push(function () {
+							line.style.height = height;
+						});
+					}
+				} else {
+					mutateActions.push(function () {
+						line.setAttribute('data-start', String(start));
+
+						if (end > start) {
+							line.setAttribute('data-end', String(end));
+						}
+
+						line.style.top = (start - offset - 1) * lineHeight + codePreOffset + 'px';
+
+						line.textContent = new Array(end - start + 2).join(' \n');
+					});
+				}
+
+				mutateActions.push(function () {
+					line.style.width = pre.scrollWidth + 'px';
+				});
+
+				mutateActions.push(function () {
+					// allow this to play nicely with the line-numbers plugin
+					// need to attack to pre as when line-numbers is enabled, the code tag is relatively which screws up the positioning
+					parentElement.appendChild(line);
+				});
+			});
+
+			var id = pre.id;
+			if (hasLineNumbers && Prism.util.isActive(pre, LINKABLE_LINE_NUMBERS_CLASS) && id) {
+				// This implements linkable line numbers. Linkable line numbers use Line Highlight to create a link to a
+				// specific line. For this to work, the pre element has to:
+				//  1) have line numbers,
+				//  2) have the `linkable-line-numbers` class or an ascendant that has that class, and
+				//  3) have an id.
+
+				if (!hasClass(pre, LINKABLE_LINE_NUMBERS_CLASS)) {
+					// add class to pre
+					mutateActions.push(function () {
+						pre.classList.add(LINKABLE_LINE_NUMBERS_CLASS);
+					});
+				}
+
+				var start = parseInt(pre.getAttribute('data-start') || '1');
+
+				// iterate all line number spans
+				$$('.line-numbers-rows > span', pre).forEach(function (lineSpan, i) {
+					var lineNumber = i + start;
+					lineSpan.onclick = function () {
+						var hash = id + '.' + lineNumber;
+
+						// this will prevent scrolling since the span is obviously in view
+						scrollIntoView = false;
+						location.hash = hash;
+						setTimeout(function () {
+							scrollIntoView = true;
+						}, 1);
+					};
+				});
+			}
+
+			return function () {
+				mutateActions.forEach(callFunction);
+			};
+		}
+	};
+
+
+	function applyHash() {
+		var hash = location.hash.slice(1);
+
+		// Remove pre-existing temporary lines
+		$$('.temporary.line-highlight').forEach(function (line) {
+			line.parentNode.removeChild(line);
+		});
+
+		var range = (hash.match(/\.([\d,-]+)$/) || [, ''])[1];
+
+		if (!range || document.getElementById(hash)) {
+			return;
+		}
+
+		var id = hash.slice(0, hash.lastIndexOf('.'));
+		var pre = document.getElementById(id);
+
+		if (!pre) {
+			return;
+		}
+
+		if (!pre.hasAttribute('data-line')) {
+			pre.setAttribute('data-line', '');
+		}
+
+		var mutateDom = Prism.plugins.lineHighlight.highlightLines(pre, range, 'temporary ');
+		mutateDom();
+
+		if (scrollIntoView) {
+			document.querySelector('.temporary.line-highlight').scrollIntoView();
+		}
+	}
+
+	var fakeTimer = 0; // Hack to limit the number of times applyHash() runs
+
+	Prism.hooks.add('before-sanity-check', function (env) {
+		var pre = env.element.parentElement;
+		if (!isActiveFor(pre)) {
+			return;
+		}
+
+		/*
+		 * Cleanup for other plugins (e.g. autoloader).
+		 *
+		 * Sometimes  blocks are highlighted multiple times. It is necessary
+		 * to cleanup any left-over tags, because the whitespace inside of the 
+ * tags change the content of the tag. + */ + var num = 0; + $$('.line-highlight', pre).forEach(function (line) { + num += line.textContent.length; + line.parentNode.removeChild(line); + }); + // Remove extra whitespace + if (num && /^(?: \n)+$/.test(env.code.slice(-num))) { + env.code = env.code.slice(0, -num); + } + }); + + Prism.hooks.add('complete', function completeHook(env) { + var pre = env.element.parentElement; + if (!isActiveFor(pre)) { + return; + } + + clearTimeout(fakeTimer); + + var hasLineNumbers = Prism.plugins.lineNumbers; + var isLineNumbersLoaded = env.plugins && env.plugins.lineNumbers; + + if (hasClass(pre, LINE_NUMBERS_CLASS) && hasLineNumbers && !isLineNumbersLoaded) { + Prism.hooks.add('line-numbers', completeHook); + } else { + var mutateDom = Prism.plugins.lineHighlight.highlightLines(pre); + mutateDom(); + fakeTimer = setTimeout(applyHash, 1); + } + }); + + window.addEventListener('hashchange', applyHash); + window.addEventListener('resize', function () { + var actions = $$('pre') + .filter(isActiveFor) + .map(function (pre) { + return Prism.plugins.lineHighlight.highlightLines(pre); + }); + actions.forEach(callFunction); + }); + +} diff --git a/src/prism-plugins/prism-line-numbers.js b/src/prism-plugins/prism-line-numbers.js new file mode 100755 index 0000000..c03c84f --- /dev/null +++ b/src/prism-plugins/prism-line-numbers.js @@ -0,0 +1,252 @@ +export function PrismPlugin_LineNumbers(Prism) { + + if (typeof Prism === 'undefined' || typeof document === 'undefined') { + return; + } + + /** + * Plugin name which is used as a class name for
 which is activating the plugin
+	 *
+	 * @type {string}
+	 */
+	var PLUGIN_NAME = 'line-numbers';
+
+	/**
+	 * Regular expression used for determining line breaks
+	 *
+	 * @type {RegExp}
+	 */
+	var NEW_LINE_EXP = /\n(?!$)/g;
+
+
+	/**
+	 * Global exports
+	 */
+	var config = Prism.plugins.lineNumbers = {
+		/**
+		 * Get node for provided line number
+		 *
+		 * @param {Element} element pre element
+		 * @param {number} number line number
+		 * @returns {Element|undefined}
+		 */
+		getLine: function (element, number) {
+			if (element.tagName !== 'PRE' || !element.classList.contains(PLUGIN_NAME)) {
+				return;
+			}
+
+			var lineNumberRows = element.querySelector('.line-numbers-rows');
+			if (!lineNumberRows) {
+				return;
+			}
+			var lineNumberStart = parseInt(element.getAttribute('data-start'), 10) || 1;
+			var lineNumberEnd = lineNumberStart + (lineNumberRows.children.length - 1);
+
+			if (number < lineNumberStart) {
+				number = lineNumberStart;
+			}
+			if (number > lineNumberEnd) {
+				number = lineNumberEnd;
+			}
+
+			var lineIndex = number - lineNumberStart;
+
+			return lineNumberRows.children[lineIndex];
+		},
+
+		/**
+		 * Resizes the line numbers of the given element.
+		 *
+		 * This function will not add line numbers. It will only resize existing ones.
+		 *
+		 * @param {HTMLElement} element A `
` element with line numbers.
+		 * @returns {void}
+		 */
+		resize: function (element) {
+			resizeElements([element]);
+		},
+
+		/**
+		 * Whether the plugin can assume that the units font sizes and margins are not depended on the size of
+		 * the current viewport.
+		 *
+		 * Setting this to `true` will allow the plugin to do certain optimizations for better performance.
+		 *
+		 * Set this to `false` if you use any of the following CSS units: `vh`, `vw`, `vmin`, `vmax`.
+		 *
+		 * @type {boolean}
+		 */
+		assumeViewportIndependence: true
+	};
+
+	/**
+	 * Resizes the given elements.
+	 *
+	 * @param {HTMLElement[]} elements
+	 */
+	function resizeElements(elements) {
+		elements = elements.filter(function (e) {
+			var codeStyles = getStyles(e);
+			var whiteSpace = codeStyles['white-space'];
+			return whiteSpace === 'pre-wrap' || whiteSpace === 'pre-line';
+		});
+
+		if (elements.length == 0) {
+			return;
+		}
+
+		var infos = elements.map(function (element) {
+			var codeElement = element.querySelector('code');
+			var lineNumbersWrapper = element.querySelector('.line-numbers-rows');
+			if (!codeElement || !lineNumbersWrapper) {
+				return undefined;
+			}
+
+			/** @type {HTMLElement} */
+			var lineNumberSizer = element.querySelector('.line-numbers-sizer');
+			var codeLines = codeElement.textContent.split(NEW_LINE_EXP);
+
+			if (!lineNumberSizer) {
+				lineNumberSizer = document.createElement('span');
+				lineNumberSizer.className = 'line-numbers-sizer';
+
+				codeElement.appendChild(lineNumberSizer);
+			}
+
+			lineNumberSizer.innerHTML = '0';
+			lineNumberSizer.style.display = 'block';
+
+			var oneLinerHeight = lineNumberSizer.getBoundingClientRect().height;
+			lineNumberSizer.innerHTML = '';
+
+			return {
+				element: element,
+				lines: codeLines,
+				lineHeights: [],
+				oneLinerHeight: oneLinerHeight,
+				sizer: lineNumberSizer,
+			};
+		}).filter(Boolean);
+
+		infos.forEach(function (info) {
+			var lineNumberSizer = info.sizer;
+			var lines = info.lines;
+			var lineHeights = info.lineHeights;
+			var oneLinerHeight = info.oneLinerHeight;
+
+			lineHeights[lines.length - 1] = undefined;
+			lines.forEach(function (line, index) {
+				if (line && line.length > 1) {
+					var e = lineNumberSizer.appendChild(document.createElement('span'));
+					e.style.display = 'block';
+					e.textContent = line;
+				} else {
+					lineHeights[index] = oneLinerHeight;
+				}
+			});
+		});
+
+		infos.forEach(function (info) {
+			var lineNumberSizer = info.sizer;
+			var lineHeights = info.lineHeights;
+
+			var childIndex = 0;
+			for (var i = 0; i < lineHeights.length; i++) {
+				if (lineHeights[i] === undefined) {
+					lineHeights[i] = lineNumberSizer.children[childIndex++].getBoundingClientRect().height;
+				}
+			}
+		});
+
+		infos.forEach(function (info) {
+			var lineNumberSizer = info.sizer;
+			var wrapper = info.element.querySelector('.line-numbers-rows');
+
+			lineNumberSizer.style.display = 'none';
+			lineNumberSizer.innerHTML = '';
+
+			info.lineHeights.forEach(function (height, lineNumber) {
+				wrapper.children[lineNumber].style.height = height + 'px';
+			});
+		});
+	}
+
+	/**
+	 * Returns style declarations for the element
+	 *
+	 * @param {Element} element
+	 */
+	function getStyles(element) {
+		if (!element) {
+			return null;
+		}
+
+		return window.getComputedStyle ? getComputedStyle(element) : (element.currentStyle || null);
+	}
+
+	var lastWidth = undefined;
+	window.addEventListener('resize', function () {
+		if (config.assumeViewportIndependence && lastWidth === window.innerWidth) {
+			return;
+		}
+		lastWidth = window.innerWidth;
+
+		resizeElements(Array.prototype.slice.call(document.querySelectorAll('pre.' + PLUGIN_NAME)));
+	});
+
+	Prism.hooks.add('complete', function (env) {
+		if (!env.code) {
+			return;
+		}
+
+		var code = /** @type {Element} */ (env.element);
+		var pre = /** @type {HTMLElement} */ (code.parentNode);
+
+		// works only for  wrapped inside 
 (not inline)
+		if (!pre || !/pre/i.test(pre.nodeName)) {
+			return;
+		}
+
+		// Abort if line numbers already exists
+		if (code.querySelector('.line-numbers-rows')) {
+			return;
+		}
+
+		// only add line numbers if  or one of its ancestors has the `line-numbers` class
+		if (!Prism.util.isActive(code, PLUGIN_NAME)) {
+			return;
+		}
+
+		// Remove the class 'line-numbers' from the 
+		code.classList.remove(PLUGIN_NAME);
+		// Add the class 'line-numbers' to the 
+		pre.classList.add(PLUGIN_NAME);
+
+		var match = env.code.match(NEW_LINE_EXP);
+		var linesNum = match ? match.length + 1 : 1;
+		var lineNumbersWrapper;
+
+		var lines = new Array(linesNum + 1).join('');
+
+		lineNumbersWrapper = document.createElement('span');
+		lineNumbersWrapper.setAttribute('aria-hidden', 'true');
+		lineNumbersWrapper.className = 'line-numbers-rows';
+		lineNumbersWrapper.innerHTML = lines;
+
+		if (pre.hasAttribute('data-start')) {
+			pre.style.counterReset = 'linenumber ' + (parseInt(pre.getAttribute('data-start'), 10) - 1);
+		}
+
+		env.element.appendChild(lineNumbersWrapper);
+
+		resizeElements([pre]);
+
+		Prism.hooks.run('line-numbers', env);
+	});
+
+	Prism.hooks.add('line-numbers', function (env) {
+		env.plugins = env.plugins || {};
+		env.plugins.lineNumbers = true;
+	});
+
+}
diff --git a/src/styles.scss b/src/styles.scss
new file mode 100644
index 0000000..456b263
--- /dev/null
+++ b/src/styles.scss
@@ -0,0 +1,190 @@
+.hk-codeblock {
+  & {
+    // variables
+    --hk-codeblock-margin: 1em;
+    --hk-codeblock-horizontal-padding: 16px;
+    --hk-codeblock-vertical-padding: 8px;
+    --hk-codeblock-background-color: var(--code-background);
+    --hk-codeblock-border-color: var(--divider-color); // applied to title, linenos, and result
+    --hk-codeblock-title-text-color: var(--text-normal);
+    --hk-codeblock-linenos-text-color: var(--code-normal);
+    --hk-codeblock-language-text-color: var(--text-muted); // same with copy button
+    --hk-codeblock-language-text-size: var(--font-ui-smaller); // same with copy button
+    --hk-codeblock-language-text-font: var(--font-interface); // same with copy button
+    --hk-codeblock-prompt-text-color: var(--code-normal);
+    --hk-codeblock-result-text-color: var(--text-normal);
+  }
+
+  position: relative;
+  background-color: var(--hk-codeblock-background-color);
+  margin-bottom: var(--hk-codeblock-margin);
+
+  pre {
+    position: relative;
+    display: flex;
+    flex-direction: row;
+    margin: 0;
+    padding-top: var(--hk-codeblock-vertical-padding);
+    padding-bottom: var(--hk-codeblock-vertical-padding);
+    padding-left: var(--hk-codeblock-horizontal-padding);
+    padding-right: var(--hk-codeblock-horizontal-padding);
+    background-color: var(--hk-codeblock-background-color);
+
+    code.hk-codeblock-code {
+      white-space: pre;
+      overflow-x: auto;
+      padding: 0;
+    }
+  }
+}
+
+/* title */
+.hk-codeblock.hk-codeblock-show-title {
+  .hk-codeblock-title {
+    padding-left: var(--hk-codeblock-horizontal-padding);
+    padding-right: var(--hk-codeblock-horizontal-padding);
+    padding-top: var(--hk-codeblock-vertical-padding);
+    padding-bottom: var(--hk-codeblock-vertical-padding);
+    background-color: var(--hk-codeblock-background-color);
+    border-bottom: 1px solid var(--hk-codeblock-border-color);
+    color: var(--hk-codeblock-title-text-color);
+  }
+
+  .hk-codeblock-title~pre {
+    margin-top: 0;
+  }
+}
+
+/* linenos */
+.hk-codeblock.hk-codeblock-show-linenos {
+  pre {
+    code.hk-codeblock-linenos {
+      flex-shrink: 0;
+      flex-grow: 0;
+      text-align: right;
+      padding-right: 1em;
+      opacity: 0.6;
+      user-select: none;
+      color: var(--hk-codeblock-linenos-text-color);
+
+      &.show-splitter {
+        border-right: 1px solid var(--hk-codeblock-border-color);
+        margin-right: 1em;
+      }
+    }
+  }
+}
+
+/* highlight */
+.hk-codeblock.hk-codeblock-show-highlight {
+  pre {
+    code.hk-codeblock-highlight {
+      display: flex;
+      flex-direction: column;
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      pointer-events: none;
+      user-select: none;
+      padding-top: var(--hk-codeblock-vertical-padding);
+      padding-bottom: var(--hk-codeblock-vertical-padding);
+      opacity: 0.2;
+
+      .line.highlight {
+        background-color: var(--hk-codeblock-highlight-background-color);
+      }
+    }
+  }
+}
+
+/* language */
+.hk-codeblock.hk-codeblock-show-language {
+  pre {
+    .hk-codeblock-language {
+      opacity: 0.4;
+      user-select: none;
+      z-index: 1;
+      margin: 6px;
+      padding: 6px 8px;
+      background-color: transparent;
+      box-shadow: none;
+      color: var(--hk-codeblock-language-text-color);
+      font-size: var(--hk-codeblock-language-text-size);
+      font-family: var(--hk-codeblock-language-text-font);
+      position: absolute;
+      top: 0;
+      right: 0;
+    }
+
+    &:hover .hk-codeblock-language {
+      display: none;
+    }
+  }
+}
+
+/* copy button */
+.hk-codeblock.hk-codeblock-show-copybtn {
+  pre {
+    .copy-code-button {
+      cursor: pointer;
+    }
+  }
+}
+
+/* prompt */
+.hk-codeblock.hk-codeblock-show-prompt {
+  pre {
+    code.hk-codeblock-code {
+      .command-line-prompt {
+        display: block;
+        float: left;
+        font-size: 100%;
+        text-align: right;
+        user-select: none;
+
+        &>span::before {
+          opacity: 0.6;
+          content: ' ';
+          display: block;
+          margin-right: 0.6em;
+          color: var(--hk-codeblock-prompt-text-color);
+        }
+
+        &>span[data-prompt]::before {
+          content: attr(data-prompt);
+        }
+
+        &>span[data-continuation-prompt]::before {
+          content: attr(data-continuation-prompt);
+        }
+      }
+    }
+  }
+}
+
+/* result */
+.hk-codeblock+.hk-codeblock.hk-codeblock-result {
+  margin-top: calc(var(--hk-codeblock-margin) * (-1));
+  border-top: 1px solid var(--hk-codeblock-border-color);
+
+  &::before {
+    content: attr(data-result-prompt);
+    display: block;
+    color: var(--hk-codeblock-result-text-color);
+    opacity: 0.6;
+    font-size: 0.8em;
+    padding-top: var(--hk-codeblock-vertical-padding);
+    padding-left: var(--hk-codeblock-horizontal-padding);
+    padding-right: var(--hk-codeblock-horizontal-padding);
+  }
+
+  pre {
+    margin-top: 0;
+
+    .hk-codeblock-result-code {
+      color: var(--hk-codeblock-result-text-color);
+    }
+  }
+}
\ No newline at end of file
diff --git a/styles.css b/styles.css
deleted file mode 100644
index 71cc60f..0000000
--- a/styles.css
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
-
-This CSS file will be included with your plugin, and
-available in the app when your plugin is enabled.
-
-If your plugin does not need CSS, delete this file.
-
-*/
diff --git a/tsconfig.json b/tsconfig.json
index 2d6fbdf..5ece937 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -10,15 +10,20 @@
     "moduleResolution": "node",
     "importHelpers": true,
     "isolatedModules": true,
-	"strictNullChecks": true,
+    "strictNullChecks": true,
     "lib": [
       "DOM",
       "ES5",
       "ES6",
       "ES7"
-    ]
+    ],
+    "outDir": "./dist",
   },
   "include": [
-    "**/*.ts"
+    "./src/**/*.ts"
+  ],
+  "exclude": [
+    "node_modules",
+    "./dist"
   ]
-}
+}
\ No newline at end of file
diff --git a/version-bump.mjs b/version-bump.mjs
index d409fa0..1c6c502 100644
--- a/version-bump.mjs
+++ b/version-bump.mjs
@@ -1,14 +1,17 @@
 import { readFileSync, writeFileSync } from "fs";
 
+const manifestFilePath = "./dist/manifest.json";
+const versionsFilePath = "./versions.json";
+
 const targetVersion = process.env.npm_package_version;
 
 // read minAppVersion from manifest.json and bump version to target version
-let manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
+let manifest = JSON.parse(readFileSync(manifestFilePath, "utf8"));
 const { minAppVersion } = manifest;
 manifest.version = targetVersion;
-writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
+writeFileSync(manifestFilePath, JSON.stringify(manifest, null, "\t"));
 
 // update versions.json with target version and minAppVersion from manifest.json
-let versions = JSON.parse(readFileSync("versions.json", "utf8"));
+let versions = JSON.parse(readFileSync(versionsFilePath, "utf8"));
 versions[targetVersion] = minAppVersion;
-writeFileSync("versions.json", JSON.stringify(versions, null, "\t"));
+writeFileSync(versionsFilePath, JSON.stringify(versions, null, "\t"));
diff --git a/versions.json b/versions.json
deleted file mode 100644
index 26382a1..0000000
--- a/versions.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-	"1.0.0": "0.15.0"
-}