diff --git a/.github/workflows/publish_doc.yml b/.github/workflows/publish_doc.yml old mode 100644 new mode 100755 index b38e6b1703c..e6c9117e45d --- a/.github/workflows/publish_doc.yml +++ b/.github/workflows/publish_doc.yml @@ -38,19 +38,19 @@ jobs: with: path: ~/.cache/pip key: pip-${{ hashFiles('**/setup.py') }} - - uses: actions/setup-python@v1 + - uses: actions/setup-python@v5 with: - python-version: 3.8 + python-version: '3.10' architecture: "x64" - name: check OS run: cat /etc/os-release - name: install dependencies run: | sudo apt-get update -qq - sudo apt-get install -qq -y cmake python3-dev git pandoc ffmpeg bc + sudo apt-get install -qq -y cmake python3-dev git pandoc ffmpeg bc nodejs npm - name: install espnet env: - ESPNET_PYTHON_VERSION: 3.8 + ESPNET_PYTHON_VERSION: 3.10 TH_VERSION: 2.0.1 CHAINER_VERSION: 6.0.0 USE_CONDA: false @@ -62,4 +62,4 @@ jobs: uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: doc/build + publish_dir: ./dist diff --git a/ci/doc.sh b/ci/doc.sh index 16653b0a485..f8324b6a107 100755 --- a/ci/doc.sh +++ b/ci/doc.sh @@ -1,38 +1,116 @@ #!/usr/bin/env bash +set -euo pipefail + . tools/activate_python.sh +clean_outputs() { + rm -rf dist + rm -rf espnet_bin + rm -rf espnet2_bin + rm -rf utils_py + + rm -rf doc/_gen + rm -rf doc/build + + rm -rf doc/vuepress/src/*.md + rm -rf doc/vuepress/src/notebook + rm -rf doc/vuepress/src/* + rm -rf doc/vuepress/src/.vuepress/.temp + rm -rf doc/vuepress/src/.vuepress/.cache +} + +build_and_convert () { + # $1: path + # $2: output + mkdir -p ./doc/_gen/tools/$2 + for filename in $1; do + bn=$(basename ${filename}) + echo "Converting ${filename} to rst..." + ./doc/usage2rst.sh ${filename} > ./doc/_gen/tools/$2/${bn}.rst + done +} + if [ ! -e tools/kaldi ]; then git clone https://github.com/kaldi-asr/kaldi --depth 1 tools/kaldi fi +# clean previous build +clean_outputs + # build sphinx document under doc/ mkdir -p doc/_gen +mkdir -p doc/_gen/tools +mkdir -p doc/_gen/guide # NOTE allow unbound variable (-u) inside kaldi scripts export LD_LIBRARY_PATH=${LD_LIBRARY_PATH-} set -euo pipefail # generate tools doc -( - cd ./utils - ../doc/argparse2rst.py ./*.py > ../doc/_gen/utils_py.rst -) +mkdir utils_py +./doc/argparse2rst.py \ + --title utils_py \ + --output_dir utils_py \ + ./utils/*.py +mv utils_py ./doc/_gen/tools -./doc/argparse2rst.py ./espnet/bin/*.py > ./doc/_gen/espnet_bin.rst -# FIXME -# ./doc/argparse2rst.py ./espnet2/bin/*.py > ./doc/_gen/espnet2_bin.rst +mkdir espnet_bin +./doc/argparse2rst.py \ + --title espnet_bin \ + --output_dir espnet_bin \ + ./espnet/bin/*.py +mv espnet_bin ./doc/_gen/tools +mkdir espnet2_bin +./doc/argparse2rst.py \ + --title espnet2_bin \ + --output_dir espnet2_bin \ + ./espnet2/bin/*.py +mv espnet2_bin ./doc/_gen/tools -find ./utils/*.sh tools/sentencepiece_commands/spm_* -exec ./doc/usage2rst.sh {} \; | tee ./doc/_gen/utils_sh.rst -find ./espnet2/bin/*.py -exec ./doc/usage2rst.sh {} \; | tee ./doc/_gen/espnet2_bin.rst +build_and_convert "utils/*.sh" utils +build_and_convert "tools/sentencepiece_commands/spm_decode" spm +build_and_convert "tools/sentencepiece_commands/spm_encode" spm +# There seems no help prepared for spm_train command. -./doc/notebook2rst.sh > ./doc/_gen/notebooks.rst +./doc/notebook2rst.sh > ./doc/notebooks.md # generate package doc -./doc/module2rst.py --root espnet espnet2 --dst ./doc --exclude espnet.bin +python ./doc/members2rst.py --root espnet --dst ./doc/_gen/guide --exclude espnet.bin +python ./doc/members2rst.py --root espnet2 --dst ./doc/_gen/guide --exclude espnet2.bin +python ./doc/members2rst.py --root espnetez --dst ./doc/_gen/guide + +# build markdown +cp ./doc/index.rst ./doc/_gen/index.rst +cp ./doc/conf.py ./doc/_gen/ +rm -f ./doc/_gen/tools/espnet2_bin/*_train.rst +sphinx-build -M markdown ./doc/_gen ./doc/build + +# copy markdown files to specific directory. +cp -r ./doc/build/markdown/* ./doc/vuepress/src/ +cp -r ./doc/notebook ./doc/vuepress/src/ +cp ./doc/*.md ./doc/vuepress/src/ +mv ./doc/vuepress/src/README.md ./doc/vuepress/src/document.md +cp -r ./doc/image ./doc/vuepress/src/ + +# Document generation has finished. +# From the following point we modify files for VuePress. +# replace language tags which is not supported by VuePress +# And convert custom tags to < and >, as can be recognized a html tag. +python ./doc/convert_custom_tags_to_html.py ./doc/vuepress/src/guide +python ./doc/convert_custom_tags_to_html.py ./doc/vuepress/src/tools + +# Convert API document to specific html tags to display sphinx style +python ./doc/convert_md_to_homepage.py ./doc/vuepress/src/guide/ +python ./doc/convert_md_to_homepage.py ./doc/vuepress/src/tools/ + +# Create navbar and sidebar. +cd ./doc/vuepress +python create_menu.py --root ./src -# build html -# TODO(karita): add -W to turn warnings into errors -sphinx-build -b html doc doc/build +npm i +# npm run docs:dev +npm run docs:build +mv src/.vuepress/dist ../../ -touch doc/build/.nojekyll +touch ../../dist/.nojekyll diff --git a/doc/README.md b/doc/README.md index a316b2998c4..2b2cf5b397b 100644 --- a/doc/README.md +++ b/doc/README.md @@ -5,11 +5,30 @@ We use [sphinx](https://www.sphinx-doc.org) to generate HTML documentation. ```sh +# Clean conda env for docs $ cd +$ conda create -p ./envs python=3.10 +$ conda activate ./envs + +# Requirements +$ pip install -e ".[all]" $ pip install -e ".[doc]" +$ conda install conda-forge::ffmpeg +$ conda install conda-forge::nodejs==22.6.0 + +# (Optional requirement) To use flake8-docstrings $ pip install -U flake8-docstrings ``` +If you used the above clean conda environment, you have write your own `. tools/activate_python.sh`. +The example will be: +```sh +#!/usr/bin/env bash + +# You might check $CONDA_EXE to find the +. /miniconda/etc/profile.d/conda.sh && conda activate /envs +``` + ## Style check using flake8-docstrings You can check that your docstring style is correct by `ci/test_flake8.sh` using [flake8-docstrings](https://pypi.org/project/flake8-docstrings/). @@ -39,15 +58,13 @@ DO NOT ADD NEW FILES TO THIS BLACK LIST! ## Generate HTML -You can generate local HTML manually using sphinx Makefile - +You can generate and test the webpage using sphinx Makefile. ```sh $ cd $ ./ci/doc.sh +$ npm run docs:dev ``` -open `doc/build/index.html` - ## Deploy When your PR is merged into `master` branch, our [CI](https://github.com/espnet/espnet/blob/master/.github/workflows/doc.yml) will automatically deploy your sphinx html into https://espnet.github.io/espnet/. diff --git a/doc/about_this_doc.md b/doc/about_this_doc.md new file mode 100644 index 00000000000..99052dc4f8a --- /dev/null +++ b/doc/about_this_doc.md @@ -0,0 +1,66 @@ + +# Developer's Guide to the ESPnet Homepage + +This document outlines the process of automatically generating the ESPnet homepage. It provides step-by-step instructions for building the homepage and details the underlying operations during the generation process. + +## Building the Homepage + +1. **Clone the ESPnet Repository**: Begin by cloning the ESPnet repository from GitHub. + +2. **Generate the `activate_python.sh` Script**: + - You can generate this file by running either `setup_anaconda.sh` or `setup_venv.sh`. + - Alternatively, create your own virtual environment and manually write the command to activate it in `activate_python.sh`. + +3. **Run `activate_python.sh`**: Execute this script to activate the Python environment. + +4. **Install the Dependencies**: + Install the necessary dependencies using the following commands: + ``` + espnet[all] + espnet[doc] + k2 + chainer + ``` + +5. **Build the Homepage**: + Run the following script to generate the homepage: + ``` + ./ci/doc.sh + ``` + +## Key Points + +- The homepage is built using VuePress, a static site generator that converts Markdown files into a website. +- The primary function of `ci/doc.sh` is to generate Markdown files for all documentation. + +## Step-by-Step Guide to `ci/doc.sh` + +1. **`build_and_convert` Function**: + This function generates documentation for shell scripts by invoking `./doc/usage2rst.sh` on all scripts in the specified directory (`$1`). The `usage2rst.sh` script executes each script with the `--help` option and saves the output as an RST file in the `$2/.rst` directory. + +2. **Temporary Files Directory**: + All temporary files, including RST files, are stored in the `_gen` directory. + +3. **`./doc/argparse2rst.py` Script**: + This script generates documentation for Python tools located in `espnet/bin`, `espnet2/bin`, and `utils/`. These scripts are executable from the command line, so their documentation is separated from the package information. + +4. **`./doc/notebook2rst.sh` Script**: + This script generates the demo section by pulling the notebook repository and converting Jupyter Notebook (`.ipynb`) files into Markdown. + +5. **`./doc/members2rst.py` Script**: + This script generates RST files for all docstrings. It separates out any docstrings for classes or functions that are not class members and excludes private functions (those starting with `_`). The generated RST files are saved in `./_gen/guide`. + +6. **Sphinx Build Process**: + After copying all necessary files to the `_gen` directory, run `sphinx-build` within `_gen`. Running Sphinx directly in the `doc` directory could cause issues, including potential document corruption. Some files, particularly those ending with `_train` (e.g., `espnet2/bin/asr_train.py`), are excluded from the documentation to avoid errors. + +7. **VuePress Directory Setup**: + Copy the Markdown files from the `doc` directory, along with files generated in steps 4 and 6, into the `vuepress/src` directory. This is where VuePress recognizes the pages for the site. + +8. **Language Support Adjustment**: + VuePress doesn’t support some of the programming languages used in code blocks. To address this, we include a command to replace unsupported language codes with equivalent ones. + +9. **Generate Navigation Files**: + Create the `navbar.yml` and `sidebar.yml` files to define the menus displayed at the top and side of the webpage. For more details, refer to the VuePress-Hope documentation on [navbar configuration](https://theme-hope.vuejs.press/config/theme/layout.html#navbar-config) and [sidebar configuration](https://theme-hope.vuejs.press/config/theme/layout.html#sidebar-config). + +10. **Finalize the Build**: + Install Node.js and the necessary dependencies, then build the homepage. To preview the page, comment out the `docs:build` line and uncomment the `docs:dev` line in the script. diff --git a/doc/argparse2rst.py b/doc/argparse2rst.py index 684673d90a3..310b9c66cd2 100755 --- a/doc/argparse2rst.py +++ b/doc/argparse2rst.py @@ -3,10 +3,17 @@ import logging import pathlib import re +import os +import subprocess import configargparse + +def get_git_revision_hash() -> str: + return subprocess.check_output(['git', 'rev-parse', 'HEAD']).decode('ascii').strip() + + class ModuleInfo: def __init__(self, path): self.path = pathlib.Path(path) @@ -24,6 +31,18 @@ def get_parser(): config_file_parser_class=configargparse.YAMLConfigFileParser, formatter_class=configargparse.ArgumentDefaultsHelpFormatter, ) + parser.add_argument( + "--title", + type=str, + default="Module Reference", + help="title for the generated RST", + ) + parser.add_argument( + "--output_dir", + type=str, + default=".", + help="output directory to save generated RSTs", + ) parser.add_argument( "src", type=str, @@ -33,43 +52,53 @@ def get_parser(): return parser -# parser -args = get_parser().parse_args() - - -modinfo = [] - -for p in args.src: - if "__init__.py" in p: - continue - modinfo.append(ModuleInfo(p)) - - -# print refs -for m in modinfo: - logging.info(f"processing: {m.path.name}") - d = m.module.get_parser().description - assert d is not None - print(f"- :ref:`{m.path.name}`: {d}") - -print() - -# print argparse -for m in modinfo: - cmd = m.path.name - sep = "~" * len(cmd) - print( - f""" - -.. _{cmd}: - +if __name__ == "__main__": + # parser + args = get_parser().parse_args() + + modinfo = [] + for p in args.src: + if "__init__.py" in p: + continue + try: + modinfo.append(ModuleInfo(p)) + except Exception as e: + logging.error(f"Error processing {p}: {str(e)}") + + print(f""" +{args.title} +{"=" * len(args.title)} + +""") + + for m in modinfo: + logging.info(f"processing: {m.path.name}") + d = m.module.get_parser().description + assert d is not None + print(f"- :ref:`{m.path.name}`: {d}") + + print() + + os.makedirs(args.output_dir, exist_ok=True) + + # print argparse to each files + for m in modinfo: + cmd = m.path.name + sourceurl = f"https://github.com/espnet/espnet/blob/" \ + + get_git_revision_hash() + str(m.path.parent / m.path.stem) + ".py" + sep = "~" * len(cmd) + mname = m.name if m.name.startswith("espnet") \ + else ".".join(m.name.split(".")[1:]) + with open(f"{args.output_dir}/{cmd[:-3]}.rst", "w") as writer: # remove .py + writer.write(f""".. _{cmd} {cmd} {sep} +`source <{sourceurl}>`_ + .. argparse:: - :module: {m.name} + :module: {mname} :func: get_parser :prog: {cmd} -""" - ) +""") diff --git a/doc/conf.py b/doc/conf.py index c2f5acd1881..3342d149b4e 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -21,7 +21,7 @@ import sys sys.path.insert(0, os.path.abspath("../espnet/nets")) -sys.path.insert(0, os.path.abspath("../utils")) +sys.path.insert(0, os.path.abspath("../../utils")) # -- General configuration ------------------------------------------------ @@ -41,6 +41,7 @@ "sphinx.ext.todo", "sphinxarg.ext", "sphinx_markdown_tables", + 'myst_parser', ] # Add any paths that contain templates here, relative to this directory. @@ -52,31 +53,12 @@ # source_suffix = '.rst' source_suffix = [".rst", ".md"] -# enable to markdown -from recommonmark.parser import CommonMarkParser - source_parsers = { - ".md": CommonMarkParser, + ".md": 'markdown', } -# AutoStructify setting ref: https://qiita.com/pashango2/items/d1b379b699af85b529ce -from recommonmark.transform import AutoStructify - github_doc_root = "https://github.com/rtfd/recommonmark/tree/master/doc/" - -def setup(app): - app.add_config_value( - "recommonmark_config", - { - "url_resolver": lambda url: github_doc_root + url, - "auto_toc_tree_section": "Contents", - }, - True, - ) - app.add_transform(AutoStructify) - - # The master toctree document. master_doc = "index" diff --git a/doc/convert_custom_tags_to_html.py b/doc/convert_custom_tags_to_html.py new file mode 100644 index 00000000000..7d0496e6746 --- /dev/null +++ b/doc/convert_custom_tags_to_html.py @@ -0,0 +1,245 @@ +import os +import glob +import re +import configargparse + +ALL_HTML_TAGS = [ + "a", + "abbr", + "acronym", + "address", + "applet", + "area", + "article", + "aside", + "audio", + "b", + "base", + "basefont", + "bdi", + "bdo", + "big", + "blockquote", + "body", + "br", + "button", + "canvas", + "caption", + "center", + "cite", + "code", + "col", + "colgroup", + "data", + "datalist", + "dd", + "del", + "details", + "dfn", + "dialog", + "dir", + "div", + "dl", + "dt", + "em", + "embed", + "fieldset", + "figcaption", + "figure", + "font", + "footer", + "form", + "frame", + "frameset", + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "head", + "header", + "hgroup", + "hr", + "html", + "i", + "iframe", + "img", + "input", + "ins", + "kbd", + "label", + "legend", + "li", + "link", + "main", + "map", + "mark", + "menu", + "meta", + "meter", + "nav", + "noframes", + "noscript", + "object", + "ol", + "optgroup", + "option", + "output", + "p", + "param", + "picture", + "pre", + "progress", + "q", + "rp", + "rt", + "ruby", + "s", + "samp", + "script", + "search", + "section", + "select", + "small", + "source", + "span", + "strike", + "strong", + "style", + "sub", + "summary", + "sup", + "svg", + "table", + "tbody", + "td", + "template", + "textarea", + "tfoot", + "th", + "thead", + "time", + "title", + "tr", + "track", + "tt", + "u", + "ul", + "var", + "video", + "wbr", +] + +LANGUAGE_TAG_SET = [ + ("default", "text"), + ("pycon", "python"), + ("cd", "text"), +] + +def get_parser(): + parser = configargparse.ArgumentParser( + description="Convert custom tags to markdown", + config_file_parser_class=configargparse.YAMLConfigFileParser, + formatter_class=configargparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "root", + type=str, + help="source python files that contain get_parser() func", + ) + return parser + + +def replace_custom_tags(content): + # Regex to find tags and their content + tag_pattern = re.compile(r'<(?!!--)([^>]+)>') + def replace_tag(match): + tag_name = match.group(1) + if len(tag_name) > 50: + # heuristics to ignore tags with too long names + # This might occur with image tags, since they have image data + # in base64 format. + return match.group(0) + + if ( + tag_name.split()[0] not in ALL_HTML_TAGS + or ( + len(tag_name.split()) > 1 and "=" not in tag_name + ) + ): + return f"<{tag_name}>" + + end_tag_pattern = re.compile(f'') + end_tag_match = end_tag_pattern.search(content, match.end()) + if not end_tag_match: + return f"<{tag_name}>" + return match.group(0) + return tag_pattern.sub(replace_tag, content) + + +def replace_string_tags(content): + # Regex to find tags and their content + tag_pattern = re.compile(r"['|\"]<(?!\/)(.+?)(?!\/)>['|\"]") + def replace_tag(match): + tag_name = match.group(1) + if len(tag_name) > 50: + # heuristics to ignore tags with too long names + # This might occur with image tags, since they have image data + # in base64 format. + return match.group(0) + if ( + tag_name.split()[0] not in ALL_HTML_TAGS + or ( + len(tag_name.split()) > 1 and "=" not in tag_name + ) + ): + return f"'<{tag_name}>'" + + end_tag_pattern = re.compile(f'') + end_tag_match = end_tag_pattern.search(content, match.end()) + if not end_tag_match: + return f"'<{tag_name}>'" + return match.group(0) + return tag_pattern.sub(replace_tag, content) + + +def replace_language_tags(content): + for (label, lang) in LANGUAGE_TAG_SET: + content = content.replace(f"```{label}", f"```{lang}") + + return content + + +if __name__ == "__main__": + # parser + args = get_parser().parse_args() + + for md in glob.glob(f"{args.root}/*.md", recursive=True): + with open(md, "r") as f: + content = f.read() + + # Replace the "" and "" with "<" and ">", respectively + # if the tag is not in ALL_HTML_TAGS and does not have its end tag + # we need to apply this two functions because + # there are custom tags like: "" + content = replace_language_tags(content) + content = replace_string_tags(content) + content = replace_custom_tags(content) + + with open(md, "w") as f: + f.write(content) + + + for md in glob.glob(f"{args.root}/**/*.md", recursive=True): + with open(md, "r") as f: + content = f.read() + + # Replace the "" and "" with "<" and ">", respectively + # if the tag is not in ALL_HTML_TAGS + content = replace_language_tags(content) + content = replace_string_tags(content) + content = replace_custom_tags(content) + + with open(md, "w") as f: + f.write(content) diff --git a/doc/convert_md_to_homepage.py b/doc/convert_md_to_homepage.py new file mode 100644 index 00000000000..a93abfffd71 --- /dev/null +++ b/doc/convert_md_to_homepage.py @@ -0,0 +1,87 @@ +import markdown +import re +import copy +import configargparse +from glob import glob + + +def get_parser(): + parser = configargparse.ArgumentParser( + description="Convert custom tags to markdown", + config_file_parser_class=configargparse.YAMLConfigFileParser, + formatter_class=configargparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "root", + type=str, + help="source markdown file", + ) + return parser + + +def small_bracket(text): + # forward_core(nnet_output, ys, hlens, ylens) + # -> forward_core(nnet_output, ys, hlens, ylens)" + text = text.replace("<", "<").replace(">", ">") + brackets = re.findall(r'\((.*)\)', text) + if len(brackets) > 0: + text = text.replace( + f"({brackets[0]})", + f"({brackets[0]})" + ) + return text + + +def convert(markdown_text): + # convert "#### Examples" to :::note ::: block + # We assume that this example block will continue to the next header. + example_pattern = r'###\sExamples' + _result = copy.copy(markdown_text) + for match in re.finditer(example_pattern, _result): + _result = _result.replace( + match.group(0), + f"##### Examples" + ) + + # convert ### to div with specific class + h3_pattern = re.compile(r'^###\s+(.+)$', re.MULTILINE) + for match in re.finditer(h3_pattern, _result): + tag_removed = match.group(0).replace("### ", "") + tag_removed = small_bracket(tag_removed) + tag_removed = markdown.markdown(tag_removed) + _result = _result.replace( + match.group(0), + f"
{tag_removed}
\n" + ) + + # convert "#### Note" to :::note ::: block + # We assume that this note block will continue to the next header. + note_pattern = r'####\sNOTE' + for match in re.finditer(note_pattern, _result): + _result = _result.replace( + match.group(0), + f"##### NOTE" + ) + + # Convert "####" to custom-h4 tag. + h4_pattern = re.compile(r'^####\s+(.+)$', re.MULTILINE) + for match in re.finditer(h4_pattern, _result): + tag_removed = match.group(0).replace("#### ", "") + tag_removed = small_bracket(tag_removed) + tag_removed = markdown.markdown(tag_removed) + _result = _result.replace( + match.group(0), + f"
{tag_removed}
\n" + ) + return _result + + +if __name__ == "__main__": + # parser + args = get_parser().parse_args() + + for md in glob(f"{args.root}/**/*.md", recursive=True): + markdown_text = open(md, "r").read() + _result = convert(markdown_text) + with open(md, "w") as f: + f.write(_result) diff --git a/doc/index.md b/doc/index.md new file mode 100644 index 00000000000..970fb93edf3 --- /dev/null +++ b/doc/index.md @@ -0,0 +1,197 @@ +--- +home: true +icon: /assets/image/espnet.png +title: ESPnet +heroImage: /assets/image/espnet_logo1.png +heroImageStyle: + - width: 80% +heroText: "ESPnet: end-to-end speech processing toolkit" +tagline: "ESPnet is an end-to-end speech processing toolkit covering many speech-related tasks." +actions: + - text: Get Started + icon: book + link: ./espnet2_tutorial.md + type: primary + + - text: Demos + icon: lightbulb + link: ./notebook/ + + +highlights: + - header: Easy to install + image: /assets/image/box.svg + bgImage: https://theme-hope-assets.vuejs.press/bg/3-light.svg + bgImageDark: https://theme-hope-assets.vuejs.press/bg/3-dark.svg + highlights: + - title: pip install espnet for easy install. + - title: See this instruction for more details. + + - header: Supports many tasks + description: We provide a complete setup for various speech processing tasks. + image: https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3mOiQTPh_S9XW6m94OQYjucUzUu7L9uEcHP9YsADUGWTcmscynkrLc1Zs8o5rA3G9lSNnEpyHBMCnZzBepYdW8jVofKnLflvOsu-ywIZpQf1Kw5l6tzvhEA1q2cbnFDIzIDlOUOKPOarf/s800/cooking_recipe.png + bgImage: https://theme-hope-assets.vuejs.press/bg/2-light.svg + bgImageDark: https://theme-hope-assets.vuejs.press/bg/2-dark.svg + bgImageStyle: + background-repeat: repeat + background-size: initial + features: + - title: "ASR: Automatic Speech Recognition" + link: https://github.com/espnet/espnet?tab=readme-ov-file#asr-automatic-speech-recognition + + - title: "TTS: Text-to-speech" + link: https://github.com/espnet/espnet?tab=readme-ov-file#tts-text-to-speech + + - title: "SE: Speech enhancement (and separation)" + link: https://github.com/espnet/espnet?tab=readme-ov-file#se-speech-enhancement-and-separation + + - title: "SUM: Speech Summarization" + link: https://github.com/espnet/espnet?tab=readme-ov-file#sum-speech-summarization + + - title: "SVS: Singing Voice Synthesis" + link: https://github.com/espnet/espnet?tab=readme-ov-file#svs-singing-voice-synthesis + + - title: "SSL: Self-supervised Learning" + link: https://github.com/espnet/espnet?tab=readme-ov-file#ssl-self-supervised-learning + + - title: "UASR: Unsupervised ASR " + details: "EURO: ESPnet Unsupervised Recognition - Open-source" + link: https://github.com/espnet/espnet?tab=readme-ov-file#uasr-unsupervised-asr-euro-espnet-unsupervised-recognition---open-source + + - title: "S2T: Speech-to-text with Whisper-style multilingual multitask models" + link: https://github.com/espnet/espnet?tab=readme-ov-file#s2t-speech-to-text-with-whisper-style-multilingual-multitask-models + + - header: More Documents + description: You can find tutorials on ESPnet packages. + bgImage: https://theme-hope-assets.vuejs.press/bg/10-light.svg + bgImageDark: https://theme-hope-assets.vuejs.press/bg/10-dark.svg + bgImageStyle: + background-repeat: repeat + background-size: initial + highlights: + - title: Tutorial + icon: /assets/icon/school_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg + link: ./tutorial.md + + - title: Tutorial (ESPnet1) + icon: /assets/icon/school_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg + link: ./espnet1_tutorial.md + + - title: Training Config + icon: sliders + link: ./espnet2_training_option.md + + - title: Format audio to wav.scp + icon: arrow-rotate-right + link: ./espnet2_format_wav_scp.md + + - title: Task class and data + icon: database + link: ./espnet2_task.md + + - title: Docker + icon: /assets/icon/docker-mark-blue.svg + link: ./docker.md + + - title: Job scheduling system + icon: server + link: ./parallelization.md + + - title: Distributed training + icon: server + link: ./espnet2_distributed.md + + - title: Document Generation + icon: book + link: ./document.md + +footer: Apache License 2.0, Copyright © 2024-present ESPnet community +--- + +## Citations + +``` +@inproceedings{watanabe2018espnet, + author={Shinji Watanabe and Takaaki Hori and Shigeki Karita and Tomoki Hayashi and Jiro Nishitoba and Yuya Unno and Nelson {Enrique Yalta Soplin} and Jahn Heymann and Matthew Wiesner and Nanxin Chen and Adithya Renduchintala and Tsubasa Ochiai}, + title={{ESPnet}: End-to-End Speech Processing Toolkit}, + year={2018}, + booktitle={Proceedings of Interspeech}, + pages={2207--2211}, + doi={10.21437/Interspeech.2018-1456}, + url={http://dx.doi.org/10.21437/Interspeech.2018-1456} +} +@inproceedings{hayashi2020espnet, + title={{Espnet-TTS}: Unified, reproducible, and integratable open source end-to-end text-to-speech toolkit}, + author={Hayashi, Tomoki and Yamamoto, Ryuichi and Inoue, Katsuki and Yoshimura, Takenori and Watanabe, Shinji and Toda, Tomoki and Takeda, Kazuya and Zhang, Yu and Tan, Xu}, + booktitle={Proceedings of IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP)}, + pages={7654--7658}, + year={2020}, + organization={IEEE} +} +@inproceedings{inaguma-etal-2020-espnet, + title = "{ESP}net-{ST}: All-in-One Speech Translation Toolkit", + author = "Inaguma, Hirofumi and + Kiyono, Shun and + Duh, Kevin and + Karita, Shigeki and + Yalta, Nelson and + Hayashi, Tomoki and + Watanabe, Shinji", + booktitle = "Proceedings of the 58th Annual Meeting of the Association for Computational Linguistics: System Demonstrations", + month = jul, + year = "2020", + address = "Online", + publisher = "Association for Computational Linguistics", + url = "https://www.aclweb.org/anthology/2020.acl-demos.34", + pages = "302--311", +} +@article{hayashi2021espnet2, + title={Espnet2-tts: Extending the edge of tts research}, + author={Hayashi, Tomoki and Yamamoto, Ryuichi and Yoshimura, Takenori and Wu, Peter and Shi, Jiatong and Saeki, Takaaki and Ju, Yooncheol and Yasuda, Yusuke and Takamichi, Shinnosuke and Watanabe, Shinji}, + journal={arXiv preprint arXiv:2110.07840}, + year={2021} +} +@inproceedings{li2020espnet, + title={{ESPnet-SE}: End-to-End Speech Enhancement and Separation Toolkit Designed for {ASR} Integration}, + author={Chenda Li and Jing Shi and Wangyou Zhang and Aswin Shanmugam Subramanian and Xuankai Chang and Naoyuki Kamo and Moto Hira and Tomoki Hayashi and Christoph Boeddeker and Zhuo Chen and Shinji Watanabe}, + booktitle={Proceedings of IEEE Spoken Language Technology Workshop (SLT)}, + pages={785--792}, + year={2021}, + organization={IEEE}, +} +@inproceedings{arora2021espnet, + title={{ESPnet-SLU}: Advancing Spoken Language Understanding through ESPnet}, + author={Arora, Siddhant and Dalmia, Siddharth and Denisov, Pavel and Chang, Xuankai and Ueda, Yushi and Peng, Yifan and Zhang, Yuekai and Kumar, Sujay and Ganesan, Karthik and Yan, Brian and others}, + booktitle={ICASSP 2022-2022 IEEE International Conference on Acoustics, Speech and Signal Processing (ICASSP)}, + pages={7167--7171}, + year={2022}, + organization={IEEE} +} +@inproceedings{shi2022muskits, + author={Shi, Jiatong and Guo, Shuai and Qian, Tao and Huo, Nan and Hayashi, Tomoki and Wu, Yuning and Xu, Frank and Chang, Xuankai and Li, Huazhe and Wu, Peter and Watanabe, Shinji and Jin, Qin}, + title={{Muskits}: an End-to-End Music Processing Toolkit for Singing Voice Synthesis}, + year={2022}, + booktitle={Proceedings of Interspeech}, + pages={4277-4281}, + url={https://www.isca-speech.org/archive/pdfs/interspeech_2022/shi22d_interspeech.pdf} +} +@inproceedings{lu22c_interspeech, + author={Yen-Ju Lu and Xuankai Chang and Chenda Li and Wangyou Zhang and Samuele Cornell and Zhaoheng Ni and Yoshiki Masuyama and Brian Yan and Robin Scheibler and Zhong-Qiu Wang and Yu Tsao and Yanmin Qian and Shinji Watanabe}, + title={{ESPnet-SE++: Speech Enhancement for Robust Speech Recognition, Translation, and Understanding}}, + year=2022, + booktitle={Proc. Interspeech 2022}, + pages={5458--5462}, +} +@article{gao2022euro, + title={{EURO}: {ESPnet} Unsupervised ASR Open-source Toolkit}, + author={Gao, Dongji and Shi, Jiatong and Chuang, Shun-Po and Garcia, Leibny Paola and Lee, Hung-yi and Watanabe, Shinji and Khudanpur, Sanjeev}, + journal={arXiv preprint arXiv:2211.17196}, + year={2022} +} +@article{peng2023reproducing, + title={Reproducing Whisper-Style Training Using an Open-Source Toolkit and Publicly Available Data}, + author={Peng, Yifan and Tian, Jinchuan and Yan, Brian and Berrebbi, Dan and Chang, Xuankai and Li, Xinjian and Shi, Jiatong and Arora, Siddhant and Chen, William and Sharma, Roshan and others}, + journal={arXiv preprint arXiv:2309.13876}, + year={2023} +} +``` diff --git a/doc/members2rst.py b/doc/members2rst.py new file mode 100644 index 00000000000..e094a92f203 --- /dev/null +++ b/doc/members2rst.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +from glob import glob +import importlib +import os +import ast +import sys +import subprocess + +import configargparse + + +def get_git_revision_hash() -> str: + return subprocess.check_output(['git', 'rev-parse', 'HEAD']).decode('ascii').strip() + + +GIT_HASH = get_git_revision_hash() + + +def to_module(path_name): + ret = path_name.replace(".py", "").replace("/", ".") + if ret.endswith("."): + return ret[:-1] + return ret + + +def top_level_functions(body): + return (f for f in body + if isinstance(f, ast.FunctionDef) + and not f.name.startswith("_") + ) + + +def top_level_classes(body): + return (f for f in body if isinstance(f, ast.ClassDef)) + + +def parse_ast(filename): + with open(filename, "rt") as file: + return ast.parse(file.read(), filename=filename) + + +def gen_func_rst(func_name, writer, filepath, lineno): + sourceurl = f"https://github.com/espnet/espnet/blob/" \ + + GIT_HASH + filepath + f":L{lineno}" + writer.write(f""".. _{func_name} +{func_name} +{"~" * len(func_name)} + +`source <{sourceurl}>`_ + +.. autofunction:: {func_name} +""") + + +def gen_class_rst(class_name, writer, filepath, lineno): + sourceurl = f"https://github.com/espnet/espnet/blob/" \ + + GIT_HASH + filepath + f":L{lineno}" + writer.write(f""".. _{class_name} +{class_name} +{"~" * len(class_name)} + +`source <{sourceurl}>`_ + +.. autoclass:: {class_name} + :members: + :undoc-members: + :show-inheritance: +""") + + +if __name__ == "__main__": + # parser + parser = configargparse.ArgumentParser( + description="generate RST files from module recursively into /_gen", + config_file_parser_class=configargparse.YAMLConfigFileParser, + formatter_class=configargparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "--root", type=str, help="root module to generate docs" + ) + parser.add_argument("--dst", type=str, help="destination path to generate RSTs") + parser.add_argument("--exclude", nargs="*", default=[], help="exclude module name") + args = parser.parse_args() + print(args) + + + gendir = args.dst + os.makedirs(gendir, exist_ok=True) + os.makedirs(f"{gendir}/{args.root}", exist_ok=True) + + for p in glob(args.root + "/**", recursive=True): + module_name = to_module(p) + if any([ex in module_name for ex in args.exclude]): + continue + if "__init__" in p: + continue + if not p.endswith(".py"): + continue + + submodule_name = module_name.split(".")[1] + os.makedirs(f"{gendir}/{args.root}/{submodule_name}", exist_ok=True) + + if not os.path.exists(f"{gendir}/{args.root}/{submodule_name}/README.rst"): + # 1 get functions + for func in top_level_functions(parse_ast(p).body): + function_name = func.name + print(f"[INFO] generating {func.name} in {module_name}") + # 1.2 generate RST + with open(f"{gendir}/{args.root}/{submodule_name}/{function_name}.rst", "w") as f_rst: + gen_func_rst(f"{module_name}.{function_name}", f_rst, p, func.lineno) + + # 2 get classes + for clz in top_level_classes(parse_ast(p).body): + class_name = clz.name + print(f"[INFO] generating {clz.name} in {module_name}") + # 1.2 generate RST + with open(f"{gendir}/{args.root}/{submodule_name}/{class_name}.rst", "w") as f_rst: + gen_class_rst(f"{module_name}.{class_name}", f_rst, p, clz.lineno) diff --git a/doc/notebook2rst.sh b/doc/notebook2rst.sh index e79fe5c49f8..11967f6cbf0 100755 --- a/doc/notebook2rst.sh +++ b/doc/notebook2rst.sh @@ -8,10 +8,39 @@ if [ ! -d notebook ]; then git clone https://github.com/espnet/notebook --depth 1 fi -echo "\ -.. toctree:: - :maxdepth: 1 - :caption: Notebook: +. ../tools/activate_python.sh + +echo "# Notebook + +Jupyter notebooks for course demos and tutorials. " -find ./notebook -name "*.ipynb" -exec echo " {}" \; +cd notebook +for basedir in */; do + printf '## %s\n' "$basedir" + find ${basedir} \ + -type f \ + -name '*.ipynb' \ + -exec bash -c 'jupyter nbconvert --clear-output "$1"' shell {} \; + find ./${basedir} \ + -type f \ + -name '*.ipynb' \ + -exec bash -c 'jupyter nbconvert --to markdown "$1"' shell {} \; + + while IFS= read -r -d '' md_file; do + filename=$(basename ${md_file}) + echo "* [${filename}](./${md_file:((${#basedir})):100})" + done < <(find ${basedir} -name "*.md" -print0) + + while IFS= read -r -d '' ipynb_file; do + rm ${ipynb_file} + done < <(find ${basedir} -name "*.ipynb" -print0) + + # generate README.md + echo "# ${basedir} Demo" > ${basedir}README.md + while IFS= read -r -d '' md_file; do + filename=$(basename ${md_file}) + echo "* [${filename}](./${md_file:((${#basedir})):100})" >> ${basedir}README.md + done < <(find ${basedir} -name "*.md" -print0) + echo "" +done diff --git a/doc/usage2rst.sh b/doc/usage2rst.sh index 56c47ed0160..c8d99c319e6 100755 --- a/doc/usage2rst.sh +++ b/doc/usage2rst.sh @@ -8,6 +8,7 @@ if [ $1 == "--help" ]; then fi real=$(realpath $1) +githash=$(git rev-parse HEAD) cd ./egs2/wsj/asr1 . path.sh @@ -17,12 +18,15 @@ len=${#cmd} r=$(dirname $real) sep=$(printf '~%.0s' $(seq $len)) usage=$($real --help |& sed "s?${r}/??g" | grep -v -e '--help' | sed "s/^/ /g") +sourceurl="https://github.com/espnet/espnet/blob/${githash}/$1" cat <\`_ + .. code-block:: none ${usage} diff --git a/doc/vuepress/create_menu.py b/doc/vuepress/create_menu.py new file mode 100644 index 00000000000..a689f2a55b0 --- /dev/null +++ b/doc/vuepress/create_menu.py @@ -0,0 +1,125 @@ +import os +import glob +import argparse +import yaml + + +def get_menubar_recursively(directory): + menubars = [] + print(f'Scanning directory: {directory}') + for child in glob.glob(os.path.join(directory, '*')): + if os.path.isdir(child): + children = get_menubar_recursively(child) + if len(children) > 0: + # menubars[0]['children'].append(children[0]['children']) + menubars.append({ + 'text': child.lower().split('/')[-1].upper(), + 'children': get_menubar_recursively(child) + }) + else: + if os.path.splitext(child)[1].lower() == '.ipynb': + menubars.append(f'/{child[len(DOCS):-6]}') # remoce '.ipynb' + elif os.path.splitext(child)[1].lower() == '.md': + menubars.append(f'/{child[len(DOCS):-3]}') # remoce '.ipynb' + return menubars + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument('--root', required=True, + type=str, help='List of directory') + args = parser.parse_args() + + navbars = [] + sidebars = [] + + DOCS = args.root + '/' + + # 1. Create navBar + # 1.1. Create guide + navbars.append({ + 'text': "Guide", + 'icon': "book", + 'prefix': f"guide/", + 'children': [] + }) + + for doc in glob.glob(f"{DOCS}/guide/**/"): + doc_name = doc.split("/")[-2] + navbars[0]['children'].append({ + 'text': doc_name, + 'prefix': f"{doc_name}/", + 'children': [f"README.md"] + sorted([ + f"{submodule.split('/')[-2]}/README.md" + for submodule in glob.glob(f"{doc}/**/") + ]) + }) + + # 1.2. Create Tools + navbars.append({ + 'text': "Tools", + 'icon': "wrench", + 'prefix': f"tools/", + 'children': [] + }) + + for doc in glob.glob(f"{DOCS}/tools/**/"): + doc = doc.split("/")[-2] + navbars[1]['children'].append({ + 'text': doc, + 'prefix': f"{doc}/", + 'children': [f"README.md"] + }) + + # 1.2. Create Notebooks + navbars.append({ + 'text': "Demo", + 'icon': "laptop-code", + 'prefix': f"notebook/", + 'children': [] + }) + + for doc in glob.glob(f"{DOCS}/notebook/**/"): + doc = doc.split("/")[-2] + navbars[2]['children'].append({ + 'text': doc, + 'prefix': f"{doc}/", + 'children': [f"README.md"] + }) + + # 1.2.1. sort + navbars[1]['children'].sort(key=lambda x: x['text'].lower()) + navbars[2]['children'].sort(key=lambda x: x['text'].lower()) + + # 1.3 write navBars.yml + with open('navbars.yml', 'w', encoding='utf-8') as f: + yaml.dump(navbars, f, default_flow_style=False) + + # 2. Create sidebars + # 2.1. Create guide + sidebars.append({ + "text": "Guide", + "icon": "book", + "prefix": "guide/", + "children": "structure", + }) + + # 2.2. Create Tools + sidebars.append({ + "text": "Tools", + "icon": "wrench", + "prefix": "tools/", + "children": "structure", + }) + + # 2.3. Create Notebooks + sidebars.append({ + "text": "Demo", + "icon": "laptop-code", + "prefix": "notebook/", + "children": "structure", + }) + + # 2.3. Write sidebars.yml + with open('sidebars.yml', 'w', encoding='utf-8') as f: + yaml.dump(sidebars, f, default_flow_style=False) diff --git a/doc/vuepress/package-lock.json b/doc/vuepress/package-lock.json new file mode 100644 index 00000000000..8847e70bcee --- /dev/null +++ b/doc/vuepress/package-lock.json @@ -0,0 +1,4775 @@ +{ + "name": "espnet_page", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "espnet_page", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "js-yaml": "^4.1.0" + }, + "devDependencies": { + "@vuepress/bundler-vite": "2.0.0-rc.14", + "vue": "^3.4.31", + "vuepress": "2.0.0-rc.14", + "vuepress-plugin-search-pro": "^2.0.0-rc.51", + "vuepress-theme-hope": "2.0.0-rc.51" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", + "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz", + "integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==", + "dev": true + }, + "node_modules/@lit/reactive-element": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz", + "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==", + "dev": true, + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.2.0" + } + }, + "node_modules/@mdit-vue/plugin-component": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@mdit-vue/plugin-component/-/plugin-component-2.1.3.tgz", + "integrity": "sha512-9AG17beCgpEw/4ldo/M6Y/1Rh4E1bqMmr/rCkWKmCAxy9tJz3lzY7HQJanyHMJufwsb3WL5Lp7Om/aPcQTZ9SA==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1", + "markdown-it": "^14.1.0" + } + }, + "node_modules/@mdit-vue/plugin-frontmatter": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@mdit-vue/plugin-frontmatter/-/plugin-frontmatter-2.1.3.tgz", + "integrity": "sha512-KxsSCUVBEmn6sJcchSTiI5v9bWaoRxe68RBYRDGcSEY1GTnfQ5gQPMIsM48P4q1luLEIWurVGGrRu7u93//LDQ==", + "dev": true, + "dependencies": { + "@mdit-vue/types": "2.1.0", + "@types/markdown-it": "^14.1.1", + "gray-matter": "^4.0.3", + "markdown-it": "^14.1.0" + } + }, + "node_modules/@mdit-vue/plugin-headers": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@mdit-vue/plugin-headers/-/plugin-headers-2.1.3.tgz", + "integrity": "sha512-AcL7a7LHQR3ISINhfjGJNE/bHyM0dcl6MYm1Sr//zF7ZgokPGwD/HhD7TzwmrKA9YNYCcO9P3QmF/RN9XyA6CA==", + "dev": true, + "dependencies": { + "@mdit-vue/shared": "2.1.3", + "@mdit-vue/types": "2.1.0", + "@types/markdown-it": "^14.1.1", + "markdown-it": "^14.1.0" + } + }, + "node_modules/@mdit-vue/plugin-sfc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@mdit-vue/plugin-sfc/-/plugin-sfc-2.1.3.tgz", + "integrity": "sha512-Ezl0dNvQNS639Yl4siXm+cnWtQvlqHrg+u+lnau/OHpj9Xh3LVap/BSQVugKIV37eR13jXXYf3VaAOP1fXPN+w==", + "dev": true, + "dependencies": { + "@mdit-vue/types": "2.1.0", + "@types/markdown-it": "^14.1.1", + "markdown-it": "^14.1.0" + } + }, + "node_modules/@mdit-vue/plugin-title": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@mdit-vue/plugin-title/-/plugin-title-2.1.3.tgz", + "integrity": "sha512-XWVOQoZqczoN97xCDrnQicmXKoqwOjIymIm9HQnRXhHnYKOgJPW1CxSGhkcOGzvDU1v0mD/adojVyyj/s6ggWw==", + "dev": true, + "dependencies": { + "@mdit-vue/shared": "2.1.3", + "@mdit-vue/types": "2.1.0", + "@types/markdown-it": "^14.1.1", + "markdown-it": "^14.1.0" + } + }, + "node_modules/@mdit-vue/plugin-toc": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@mdit-vue/plugin-toc/-/plugin-toc-2.1.3.tgz", + "integrity": "sha512-41Q+iXpLHZt0zJdApVwoVt7WF6za/xUjtjEPf90Z3KLzQO01TXsv48Xp9BsrFHPcPcm8tiZ0+O1/ICJO80V/MQ==", + "dev": true, + "dependencies": { + "@mdit-vue/shared": "2.1.3", + "@mdit-vue/types": "2.1.0", + "@types/markdown-it": "^14.1.1", + "markdown-it": "^14.1.0" + } + }, + "node_modules/@mdit-vue/shared": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@mdit-vue/shared/-/shared-2.1.3.tgz", + "integrity": "sha512-27YI8b0VVZsAlNwaWoaOCWbr4eL8B04HxiYk/y2ktblO/nMcOEOLt4p0RjuobvdyUyjHvGOS09RKhq7qHm1CHQ==", + "dev": true, + "dependencies": { + "@mdit-vue/types": "2.1.0", + "@types/markdown-it": "^14.1.1", + "markdown-it": "^14.1.0" + } + }, + "node_modules/@mdit-vue/types": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@mdit-vue/types/-/types-2.1.0.tgz", + "integrity": "sha512-TMBB/BQWVvwtpBdWD75rkZx4ZphQ6MN0O4QB2Bc0oI5PC2uE57QerhNxdRZ7cvBHE2iY2C+BUNUziCfJbjIRRA==", + "dev": true + }, + "node_modules/@mdit/plugin-alert": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-alert/-/plugin-alert-0.12.0.tgz", + "integrity": "sha512-4OyGK1PZrJbmEF/kS6GKmmG1nlN5h/CyIPZV8lRgnlWLFB37JiEz3EHusPAXAoMtw7VGNFaIcl7OT/I5yyz1JQ==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-align": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-align/-/plugin-align-0.12.0.tgz", + "integrity": "sha512-rvA+xzaVrlsr44s7XD/xadO3lF0QYWCbeSrOS2dhOroNCIOy4RotVP/1tQPr84eqm4oXcxXF0cbjFuwUgE1jYw==", + "dev": true, + "dependencies": { + "@mdit/plugin-container": "0.12.0", + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-attrs": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-attrs/-/plugin-attrs-0.12.0.tgz", + "integrity": "sha512-J0MBwBq958lBtdIcEo02mUIO4ubl2YK+bY799T2SusrLTf3FZsq8+d/OiLTUtovfxaphD7F6yqo8M61AiOpq+w==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-container": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-container/-/plugin-container-0.12.0.tgz", + "integrity": "sha512-61bWK1ek6Rn4o12/BIKTWgGU0miB9ENcXE19H5D4DRhwG5+4+0zp2U6hRLf/mE73+mRYin7iKVzcwwEsqs+u8w==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-demo": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-demo/-/plugin-demo-0.12.0.tgz", + "integrity": "sha512-+KDUOgcvnMtBN/uYWlhIFuWkTJexuxstq8ERy9q7vOiu8Go85qCb27h0RSToKBTmmGy+XqfU2EdJclYPWBupJQ==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-figure": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-figure/-/plugin-figure-0.12.0.tgz", + "integrity": "sha512-3nfcGI+uM0f6AqHZrEr8kSMBI6T2+fKKQXtCbvWQqQ+P3iGgf34Ay2eAtuMDcDGqyfNuR6e8aLoOeY2QWuEynA==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-footnote": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-footnote/-/plugin-footnote-0.12.0.tgz", + "integrity": "sha512-9B+bJdMndCPoA9De9bxRm4/fyz02PHRcttOyuyPJ3G+wCAgIN1c/7CB8ViT1YJuECUjLogJQ/rrgqh7f0LTqLQ==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + } + }, + "node_modules/@mdit/plugin-img-lazyload": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-img-lazyload/-/plugin-img-lazyload-0.12.0.tgz", + "integrity": "sha512-6R42ieXzwkB5BKKZi+ZefqeP/fBG5qo7Sqtl72ewSVqEQ30bgxpk6nkrPI2orRob4tb6z0F/c+R8h6PW5MkTOw==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-img-mark": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-img-mark/-/plugin-img-mark-0.12.0.tgz", + "integrity": "sha512-HkIUwlTg/xPsBi4PG+5dsMnsb7wdiJzELSCEUfdAJTg55nksonHfyV2pFpr87MML4nuZlZK9JHt+Bm2BBDSVSw==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-img-size": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-img-size/-/plugin-img-size-0.12.0.tgz", + "integrity": "sha512-fCcF5gc+ba6gQ5ebrKuI8bK/gFbj8mbeN45FHmBsFDFsfTHa0Xij2v8iok0nP8YEIVj71y8XYojsqCWs6avong==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-include": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-include/-/plugin-include-0.12.0.tgz", + "integrity": "sha512-8pnmp7s1TjbtoBIa/YhYpEivOpeVSyhkQoQrGq1UoaEcTbXqmFwShGkAW3zUYZVFYTl74PgL/UqJnrUojegJQg==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1", + "upath": "^2.0.1" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-katex-slim": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-katex-slim/-/plugin-katex-slim-0.12.0.tgz", + "integrity": "sha512-s2MJGXFZT7u8IUTmy6K1rxxAdYRmGggu0m860siyUrThL112xLN9r3jmXZ83epgi4UA/gLkRDAU5vF6R2JtyjQ==", + "dev": true, + "dependencies": { + "@mdit/plugin-tex": "0.12.0", + "@types/katex": "^0.16.7", + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "katex": "^0.16.9", + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "katex": { + "optional": true + }, + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-mark": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-mark/-/plugin-mark-0.12.0.tgz", + "integrity": "sha512-BDFwbV/tbgUGL8KF2ymYNLEXT2KNBLe8D0rshDrbB4Iko1U2DywACQkmaUbYBJ1VCn7/dff35at9fWrm3QjrwQ==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-mathjax-slim": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-mathjax-slim/-/plugin-mathjax-slim-0.12.0.tgz", + "integrity": "sha512-bLM+JnCTN/3XiyKb64Yhpx014VYLfHBexua4n92cUyoKR9g3waB0loF1WMlg6GdyCTc7OvrUSceNjwWj3YRogg==", + "dev": true, + "dependencies": { + "@mdit/plugin-tex": "0.12.0", + "@types/markdown-it": "^14.1.1", + "upath": "^2.0.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0", + "mathjax-full": "^3.2.2" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + }, + "mathjax-full": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-plantuml": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-plantuml/-/plugin-plantuml-0.12.0.tgz", + "integrity": "sha512-m1pk6PA9+kWUs8kylLqjnQ7Lex68x3c4Ato8zAh+omkhugfWzuQXfFiXRiJ9C7wkdqHoJx/E5XobP3HJnhCpoA==", + "dev": true, + "dependencies": { + "@mdit/plugin-uml": "0.12.0", + "@types/markdown-it": "^14.1.1" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-spoiler": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-spoiler/-/plugin-spoiler-0.12.0.tgz", + "integrity": "sha512-7yu+Gz000O0OxGnGYOoj77Am3WgH4GwzOvwCp7tPLexkJwTve8MyT9In/NEPFaRw8fmgXwthC0gKq4Ubh1+8DA==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-stylize": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-stylize/-/plugin-stylize-0.12.0.tgz", + "integrity": "sha512-5bzZvmjEpGTdwBax9jaDbCBhD1snEx6uTHVUG9HD/L5koKrL86+ox9E5FGeiMiD1dtxeMgL+WqBzV44nRE9ZPg==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-sub": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-sub/-/plugin-sub-0.12.0.tgz", + "integrity": "sha512-27kKkSVkymc+2RNc5XOYkeXip5PgHZPUnHpxUvkpnairLwyHsXb8/gzr9zd5arVkip86rcdy9LIvnF7zO0dNVQ==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-sup": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-sup/-/plugin-sup-0.12.0.tgz", + "integrity": "sha512-3bEDW5/y1UDVU8LVbFsqUvNcMW6orp16uCdRGYCNZ3/IeK7Qj1/9a3wfhScIoI8xRUE6M3JLv41sGBFXLHwi1w==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-tab": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-tab/-/plugin-tab-0.12.0.tgz", + "integrity": "sha512-ZDTEDxHoekcFA5Al+NLizn8Nf0kj6ABkNBAc/VxbQoVQdjZNQtGY2dOPeWW0I96Rao+Aw+IpYRCLFIfb/KtExw==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-tasklist": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-tasklist/-/plugin-tasklist-0.12.0.tgz", + "integrity": "sha512-MPmuLJrqHYR2xI7ST9Xtw/xj+6Xoq7kUvcGuXWdMMNT11DcU1KppkR8QBHov437NFYh6aGyjrHUVeM4T5Ls8yg==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-tex": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-tex/-/plugin-tex-0.12.0.tgz", + "integrity": "sha512-ejeSgSeZvcI5P4hFFQ4q5pHrZBGO2fQWVGm6dZ3BhX4ldoV8LjCIzkcMMXhrhSOVjwHnqmF6xOh9EvI0jzak1w==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": true + } + } + }, + "node_modules/@mdit/plugin-uml": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@mdit/plugin-uml/-/plugin-uml-0.12.0.tgz", + "integrity": "sha512-EfVMmq0CwLJcssxhkvGS2ESenNNEMeK04j702Z9v3am1M9DdEj6zHTrHQd9tA0jNVuFY8ZlmMgDfkkG5k6Rm3Q==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "markdown-it": "^14.1.0" + }, + "peerDependenciesMeta": { + "markdown-it": { + "optional": 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/@rollup/rollup-android-arm-eabi": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", + "integrity": "sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.1.tgz", + "integrity": "sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.1.tgz", + "integrity": "sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.1.tgz", + "integrity": "sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.1.tgz", + "integrity": "sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.1.tgz", + "integrity": "sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.1.tgz", + "integrity": "sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.1.tgz", + "integrity": "sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.1.tgz", + "integrity": "sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.1.tgz", + "integrity": "sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.1.tgz", + "integrity": "sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.1.tgz", + "integrity": "sha512-7O5u/p6oKUFYjRbZkL2FLbwsyoJAjyeXHCU3O4ndvzg2OFO2GinFPSJFGbiwFDaCFc+k7gs9CF243PwdPQFh5g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.1.tgz", + "integrity": "sha512-pDLkYITdYrH/9Cv/Vlj8HppDuLMDUBmgsM0+N+xLtFd18aXgM9Nyqupb/Uw+HeidhfYg2lD6CXvz6CjoVOaKjQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.1.tgz", + "integrity": "sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.1.tgz", + "integrity": "sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.1.tgz", + "integrity": "sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "dev": true + }, + "node_modules/@shikijs/core": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.10.3.tgz", + "integrity": "sha512-D45PMaBaeDHxww+EkcDQtDAtzv00Gcsp72ukBtaLSmqRvh0WgGMq3Al0rl1QQBZfuneO75NXMIzEZGFitThWbg==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/transformers": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.10.3.tgz", + "integrity": "sha512-MNjsyye2WHVdxfZUSr5frS97sLGe6G1T+1P41QjyBFJehZphMcr4aBlRLmq6OSPBslYe9byQPVvt/LJCOfxw8Q==", + "dev": true, + "dependencies": { + "shiki": "1.10.3" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@stackblitz/sdk": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@stackblitz/sdk/-/sdk-1.11.0.tgz", + "integrity": "sha512-DFQGANNkEZRzFk1/rDP6TcFdM82ycHE+zfl9C/M/jXlH68jiqHWHFMQURLELoD8koxvu/eW5uhg94NSAZlYrUQ==", + "dev": true + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dev": true, + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, + "node_modules/@types/hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha512-UP28RddqY8xcU0SCEp9YKutQICXpaAq9N8U2klqF5hegGha7KzTOL8EdhIIV3bOSGBzjEpN9bU/d+nNZBdJYVw==", + "dev": true + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/katex": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", + "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", + "dev": true + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==", + "dev": true, + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/markdown-it-emoji": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/markdown-it-emoji/-/markdown-it-emoji-3.0.1.tgz", + "integrity": "sha512-cz1j8R35XivBqq9mwnsrP2fsz2yicLhB8+PDtuVkKOExwEdsVBNI+ROL3sbhtR5occRZ66vT0QnwFZCqdjf3pA==", + "dev": true, + "dependencies": { + "@types/markdown-it": "^14" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.14.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", + "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true + }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "dev": true + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", + "dev": true + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.5.tgz", + "integrity": "sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==", + "dev": true, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.33.tgz", + "integrity": "sha512-MoIREbkdPQlnGfSKDMgzTqzqx5nmEjIc0ydLVYlTACGBsfvOJ4tHSbZXKVF536n6fB+0eZaGEOqsGThPpdvF5A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.33", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.33.tgz", + "integrity": "sha512-GzB8fxEHKw0gGet5BKlpfXEqoBnzSVWwMnT+dc25wE7pFEfrU/QsvjZMP9rD4iVXHBBoemTct8mN0GJEI6ZX5A==", + "dev": true, + "dependencies": { + "@vue/compiler-core": "3.4.33", + "@vue/shared": "3.4.33" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.33.tgz", + "integrity": "sha512-7rk7Vbkn21xMwIUpHQR4hCVejwE6nvhBOiDgoBcR03qvGqRKA7dCBSsHZhwhYUsmjlbJ7OtD5UFIyhP6BY+c8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.33", + "@vue/compiler-dom": "3.4.33", + "@vue/compiler-ssr": "3.4.33", + "@vue/shared": "3.4.33", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.39", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.33.tgz", + "integrity": "sha512-0WveC9Ai+eT/1b6LCV5IfsufBZ0HP7pSSTdDjcuW302tTEgoBw8rHVHKPbGUtzGReUFCRXbv6zQDDgucnV2WzQ==", + "dev": true, + "dependencies": { + "@vue/compiler-dom": "3.4.33", + "@vue/shared": "3.4.33" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.3.tgz", + "integrity": "sha512-0MiMsFma/HqA6g3KLKn+AGpL1kgKhFWszC9U29NfpWK5LE7bjeXxySWJrOJ77hBz+TBrBQ7o4QJqbPbqbs8rJw==", + "dev": true + }, + "node_modules/@vue/reactivity": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.33.tgz", + "integrity": "sha512-B24QIelahDbyHipBgbUItQblbd4w5HpG3KccL+YkGyo3maXyS253FzcTR3pSz739OTphmzlxP7JxEMWBpewilA==", + "dev": true, + "dependencies": { + "@vue/shared": "3.4.33" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.33.tgz", + "integrity": "sha512-6wavthExzT4iAxpe8q37/rDmf44nyOJGISJPxCi9YsQO+8w9v0gLCFLfH5TzD1V1AYrTAdiF4Y1cgUmP68jP6w==", + "dev": true, + "dependencies": { + "@vue/reactivity": "3.4.33", + "@vue/shared": "3.4.33" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.33.tgz", + "integrity": "sha512-iHsMCUSFJ+4z432Bn9kZzHX+zOXa6+iw36DaVRmKYZpPt9jW9riF32SxNwB124i61kp9+AZtheQ/mKoJLerAaQ==", + "dev": true, + "dependencies": { + "@vue/reactivity": "3.4.33", + "@vue/runtime-core": "3.4.33", + "@vue/shared": "3.4.33", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.33.tgz", + "integrity": "sha512-jTH0d6gQcaYideFP/k0WdEu8PpRS9MF8d0b6SfZzNi+ap972pZ0TNIeTaESwdOtdY0XPVj54XEJ6K0wXxir4fw==", + "dev": true, + "dependencies": { + "@vue/compiler-ssr": "3.4.33", + "@vue/shared": "3.4.33" + }, + "peerDependencies": { + "vue": "3.4.33" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.33.tgz", + "integrity": "sha512-aoRY0jQk3A/cuvdkodTrM4NMfxco8n55eG4H7ML/CRy7OryHfiqvug4xrCBBMbbN+dvXAetDDwZW9DXWWjBntA==", + "dev": true + }, + "node_modules/@vuepress/bundler-vite": { + "version": "2.0.0-rc.14", + "resolved": "https://registry.npmjs.org/@vuepress/bundler-vite/-/bundler-vite-2.0.0-rc.14.tgz", + "integrity": "sha512-kttbowYITMCX3ztz78Qb6bMfXRv/GEpNu+nALksu7j/QJQ0gOzI2is68PatbmzZRWOufVsf1Zf0A8BwolmVcXA==", + "dev": true, + "dependencies": { + "@vitejs/plugin-vue": "^5.0.5", + "@vuepress/client": "2.0.0-rc.14", + "@vuepress/core": "2.0.0-rc.14", + "@vuepress/shared": "2.0.0-rc.14", + "@vuepress/utils": "2.0.0-rc.14", + "autoprefixer": "^10.4.19", + "connect-history-api-fallback": "^2.0.0", + "postcss": "^8.4.38", + "postcss-load-config": "^6.0.1", + "rollup": "^4.18.0", + "vite": "~5.3.1", + "vue": "^3.4.29", + "vue-router": "^4.3.3" + } + }, + "node_modules/@vuepress/cli": { + "version": "2.0.0-rc.14", + "resolved": "https://registry.npmjs.org/@vuepress/cli/-/cli-2.0.0-rc.14.tgz", + "integrity": "sha512-oYJX1nE6/ohF2tzUtpBAFxRr4MF2kdtab3+AQ897esXzrciQnE2LxPQZ8BUOn6Jb3XYW12FXDdkHrr82rN6XnQ==", + "dev": true, + "dependencies": { + "@vuepress/core": "2.0.0-rc.14", + "@vuepress/shared": "2.0.0-rc.14", + "@vuepress/utils": "2.0.0-rc.14", + "cac": "^6.7.14", + "chokidar": "^3.6.0", + "envinfo": "^7.13.0", + "esbuild": "~0.21.5" + }, + "bin": { + "vuepress-cli": "bin/vuepress.js" + } + }, + "node_modules/@vuepress/client": { + "version": "2.0.0-rc.14", + "resolved": "https://registry.npmjs.org/@vuepress/client/-/client-2.0.0-rc.14.tgz", + "integrity": "sha512-ULwxOiWoUi15HWQ6qH60gWjxSXB0797uExCUa4HgHV/8SpIqv4SHFn6jqjo7qCzOxuTqj1RT47JH3oWfUF4XPA==", + "dev": true, + "dependencies": { + "@vue/devtools-api": "^6.6.3", + "@vuepress/shared": "2.0.0-rc.14", + "vue": "^3.4.29", + "vue-router": "^4.3.3" + } + }, + "node_modules/@vuepress/core": { + "version": "2.0.0-rc.14", + "resolved": "https://registry.npmjs.org/@vuepress/core/-/core-2.0.0-rc.14.tgz", + "integrity": "sha512-Ly3fypjXGUgPzjfbXKJeyd59jxJgXkhxhWAGkH/rRyQeV8Nr7Wo1ah3H1MeGhlCRGH1T9Yd3Bz9W7QMoyWFfmg==", + "dev": true, + "dependencies": { + "@vuepress/client": "2.0.0-rc.14", + "@vuepress/markdown": "2.0.0-rc.14", + "@vuepress/shared": "2.0.0-rc.14", + "@vuepress/utils": "2.0.0-rc.14", + "vue": "^3.4.29" + } + }, + "node_modules/@vuepress/helper": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/helper/-/helper-2.0.0-rc.38.tgz", + "integrity": "sha512-IgKQCCbfX4zLkRxLwzNtTMKTZdflAlmBTUEkuD/uJrfFJjGvLShnkw2ONIlwSM6U+SWVHKfW5Ls8pndPvxpI1Q==", + "dev": true, + "dependencies": { + "@vue/shared": "^3.4.31", + "cheerio": "1.0.0-rc.12", + "fflate": "^0.8.2", + "gray-matter": "^4.0.3", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/highlighter-helper": { + "version": "2.0.0-rc.37", + "resolved": "https://registry.npmjs.org/@vuepress/highlighter-helper/-/highlighter-helper-2.0.0-rc.37.tgz", + "integrity": "sha512-l7qxuJJP0+zxDd42UctS0Oc240cCN7BvxfEx6XJfaYmn2Yncrbbk15gS9tUT3jeXB959JGm8uUhxpPP0/4w3kw==", + "dev": true, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/markdown": { + "version": "2.0.0-rc.14", + "resolved": "https://registry.npmjs.org/@vuepress/markdown/-/markdown-2.0.0-rc.14.tgz", + "integrity": "sha512-9xr693gkp71qwEbQLxpo1ybhJ+lA2k5SiuFUgqqrmR2a8CSL3gcmKEGM+y7GMnHvL63U2dYlc9pUOtJ5rG9O0Q==", + "dev": true, + "dependencies": { + "@mdit-vue/plugin-component": "^2.1.3", + "@mdit-vue/plugin-frontmatter": "^2.1.3", + "@mdit-vue/plugin-headers": "^2.1.3", + "@mdit-vue/plugin-sfc": "^2.1.3", + "@mdit-vue/plugin-title": "^2.1.3", + "@mdit-vue/plugin-toc": "^2.1.3", + "@mdit-vue/shared": "^2.1.3", + "@mdit-vue/types": "^2.1.0", + "@types/markdown-it": "^14.1.1", + "@types/markdown-it-emoji": "^3.0.1", + "@vuepress/shared": "2.0.0-rc.14", + "@vuepress/utils": "2.0.0-rc.14", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^9.0.1", + "markdown-it-emoji": "^3.0.0", + "mdurl": "^2.0.0" + } + }, + "node_modules/@vuepress/plugin-active-header-links": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-active-header-links/-/plugin-active-header-links-2.0.0-rc.38.tgz", + "integrity": "sha512-ERleWy3NBW8IWTrk8UgGMfFP1JJMi2SSGqBaQqAjkh2n2B6BSr+sY3U1yw39pnyFwdc+TwML5JomkV/W5pbTTw==", + "dev": true, + "dependencies": { + "@vueuse/core": "^10.11.0", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-back-to-top": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-back-to-top/-/plugin-back-to-top-2.0.0-rc.38.tgz", + "integrity": "sha512-KrEeyv2QX7YZVrvCBohPWdwFXwKFIwyb6HjEKW/2H82+XfBMg1D9b7vqCp/W4EJ1F6ERPYgJLj0sv2AockHZtg==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "@vueuse/core": "^10.11.0", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-blog": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-blog/-/plugin-blog-2.0.0-rc.38.tgz", + "integrity": "sha512-YcwspZIbTxdLNEjkHGAAlaLSfPubHa+j8mdI1NKWjsY1amVnDH2q3/1vIVCaP/YN9a+eHtvTXy6mikNrhnEjgw==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "chokidar": "^3.6.0", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-catalog": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-catalog/-/plugin-catalog-2.0.0-rc.38.tgz", + "integrity": "sha512-XvWlM3D0+zelruCuTknzBlXCcA6fF9zV7UQco/IM1YLqobwNIvJuk9w86UQSw1dh6NVrRVGX3YCz20E3bK8ByQ==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-comment": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-comment/-/plugin-comment-2.0.0-rc.38.tgz", + "integrity": "sha512-V1SqLFv3nJZN2DbMnCa9KMmrYknUwx2/KOqV3FcEXJ2uPZDY2jLnu/yolU6S3YZ6BfJPT15wPPBGlHRLDLnTOg==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "giscus": "^1.5.0", + "vue": "^3.4.31" + }, + "peerDependencies": { + "@waline/client": "^3.1.0", + "artalk": "^2.8.7", + "twikoo": "^1.5.0", + "vuepress": "2.0.0-rc.14" + }, + "peerDependenciesMeta": { + "@waline/client": { + "optional": true + }, + "artalk": { + "optional": true + }, + "twikoo": { + "optional": true + } + } + }, + "node_modules/@vuepress/plugin-copy-code": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-copy-code/-/plugin-copy-code-2.0.0-rc.38.tgz", + "integrity": "sha512-SKO88dEwkCn+2YRNGZJHId8sulas4B8tD8suzSwNyTi+9+T54hrhQpc4cN1GjfbxOPFcINAQsndZFKMX6Wg6tg==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "@vueuse/core": "^10.11.0", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-copyright": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-copyright/-/plugin-copyright-2.0.0-rc.38.tgz", + "integrity": "sha512-ILkUG2yscwajwfa/Ox1QLZJcn76XGRFaRsRm9O/MzkHtZ/qRJ1QZa0ccqpYPKmNWAPw7isPfi95qeAg0nl34KQ==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "@vueuse/core": "^10.11.0", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-git": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-git/-/plugin-git-2.0.0-rc.38.tgz", + "integrity": "sha512-dRJiZ5PVuhhyu+R2BZOlyeqgxVikUUh2Vf6RNVN2DNWv4VHdYybFQuQ+kYDpldYyzoP8932aFRV0d2ocpvxEug==", + "dev": true, + "dependencies": { + "execa": "^9.3.0" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-links-check": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-links-check/-/plugin-links-check-2.0.0-rc.38.tgz", + "integrity": "sha512-UAf7WpfIdMYD14H3N7oXhriOHmWiErWpNGaRGauZvTXPZV3VE8sSylZ7ezsYjepvWstFGqfN0AmBvl46S++AJg==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-notice": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-notice/-/plugin-notice-2.0.0-rc.38.tgz", + "integrity": "sha512-HYS2fTXU8/Nw6S1U3opWMkbGe70I+e/ADyCbcix0Zhz+/5RNoFIuoAT9TmAC2vqO0Bl/LwaLFZItj3frK0m8IQ==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "@vueuse/core": "^10.11.0", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-nprogress": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-nprogress/-/plugin-nprogress-2.0.0-rc.38.tgz", + "integrity": "sha512-KtTvwOA25n8KtXQ1adL3Pa0vf2OdosAxG4UMYGbULe1ScCH9ER86B+cD3vG+pAXLSolNlKmg+VsGjQcO+vF4jQ==", + "dev": true, + "dependencies": { + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-photo-swipe": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-photo-swipe/-/plugin-photo-swipe-2.0.0-rc.38.tgz", + "integrity": "sha512-S1PtFr6UZ7zTp+J6TorOzuXC2lpcQJ/G7iTS24px2swyzELfpBjhf3gdOKl9wjsnqJ/4DdyUkoHUX0dA7piAkw==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "@vueuse/core": "^10.11.0", + "photoswipe": "^5.4.4", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-reading-time": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-reading-time/-/plugin-reading-time-2.0.0-rc.38.tgz", + "integrity": "sha512-ocX2nmvUNbXhuCizTIVZIR2K1pmYA1vA741IH5BPhvD8y5JYc9mZsudJZLPRUgYEi/Yx2o6XMnwqAKrwCqypig==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-rtl": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-rtl/-/plugin-rtl-2.0.0-rc.38.tgz", + "integrity": "sha512-Jfw0iQXRwddi8GiwBB78+Sdonp5VUZGE2md1IUu9xQuMJ4oW6Fgp1duIp2rWEGiiezwz6CqQb2a/ph3s8NYgPw==", + "dev": true, + "dependencies": { + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-sass-palette": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-sass-palette/-/plugin-sass-palette-2.0.0-rc.38.tgz", + "integrity": "sha512-lYVtH02y1bG62sc0r2IiSxNqm+5bQYr75GhEqEnFYh9ZmXLLKdCIw84T/JcK4GLi3MOn5rCPO3o4O6DaPM817g==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "chokidar": "^3.6.0", + "sass": "^1.77.8" + }, + "peerDependencies": { + "sass-loader": "^14.0.0", + "vuepress": "2.0.0-rc.14" + }, + "peerDependenciesMeta": { + "sass-loader": { + "optional": true + } + } + }, + "node_modules/@vuepress/plugin-search": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-search/-/plugin-search-2.0.0-rc.38.tgz", + "integrity": "sha512-5FTyewhnE9me8EzTXVPJYvnDyo90gw0shkXDfqmImqygk3LFcpKSxJE7imSIPjFBl+Vl9zop+EK2YJF/l4KvlQ==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "chokidar": "^3.6.0", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-seo": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-seo/-/plugin-seo-2.0.0-rc.38.tgz", + "integrity": "sha512-H/f2AtEYohFy0QJv/mbwmdDj0NgY5mpbKY1GtPW+LBn5fymWJ37TZ+gz+/+Htq4BdEbWQmcIj2XteTxdzeyAvQ==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-shiki": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-shiki/-/plugin-shiki-2.0.0-rc.38.tgz", + "integrity": "sha512-e+4OiDxry48bGskgvpxItsNxLOjAckMjASNcH9xGaXeUH3LiwTaCDIBbb89GeIh1LJ4Xnjw1HMlkpomgQmrI8A==", + "dev": true, + "dependencies": { + "@shikijs/transformers": "^1.10.3", + "@vuepress/helper": "2.0.0-rc.38", + "@vuepress/highlighter-helper": "2.0.0-rc.37", + "nanoid": "^5.0.7", + "shiki": "^1.10.3" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-shiki/node_modules/nanoid": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/@vuepress/plugin-sitemap": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-sitemap/-/plugin-sitemap-2.0.0-rc.38.tgz", + "integrity": "sha512-R5arITfgVxvdpsapUG48vWR0/loy70MGYC97XU5m9BbNh/Wd7y+QXn6OOAXTAT4U4Vl6c18zMeq3kVyrhj0dKQ==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "sitemap": "^8.0.0" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-theme-data": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-theme-data/-/plugin-theme-data-2.0.0-rc.38.tgz", + "integrity": "sha512-YeqhtIzBbdB9OORY2M/N+c8O0HqqfEj/6H8waGXfBxHnb/M+kTJ2PnmCjiqrjiTG1JuhuZOpxIjG/rio2VV3+A==", + "dev": true, + "dependencies": { + "@vue/devtools-api": "^6.6.3", + "vue": "^3.4.31" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/plugin-watermark": { + "version": "2.0.0-rc.38", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-watermark/-/plugin-watermark-2.0.0-rc.38.tgz", + "integrity": "sha512-5lFQ2Cr5PXS57IzGOC0X4h/4XPmC9FSyEweeR3cGMhLqJ1CST0TplUzRftVNsqoXibH/2/UKBQch01tQxzrCAg==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "vue": "^3.4.31", + "watermark-js-plus": "^1.5.2" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/@vuepress/shared": { + "version": "2.0.0-rc.14", + "resolved": "https://registry.npmjs.org/@vuepress/shared/-/shared-2.0.0-rc.14.tgz", + "integrity": "sha512-VDDnPpz4x1Q07richcVRGbc4qc2RG/6bKoEYSImofTFzvdmHer538ouv8kD2SNU10UrSOpxxUiphnhlhNIe03A==", + "dev": true, + "dependencies": { + "@mdit-vue/types": "^2.1.0" + } + }, + "node_modules/@vuepress/utils": { + "version": "2.0.0-rc.14", + "resolved": "https://registry.npmjs.org/@vuepress/utils/-/utils-2.0.0-rc.14.tgz", + "integrity": "sha512-1h/5qcKBeIhIg6SZM2IoZVOaIdFSeQ1CdEWadqQWy1uwupEeVrU3QPkjFyn0vUt0O/EuuVqQcLLC8OuS/wldNw==", + "dev": true, + "dependencies": { + "@types/debug": "^4.1.12", + "@types/fs-extra": "^11.0.4", + "@types/hash-sum": "^1.0.2", + "@vuepress/shared": "2.0.0-rc.14", + "debug": "^4.3.5", + "fs-extra": "^11.2.0", + "globby": "^14.0.1", + "hash-sum": "^2.0.0", + "ora": "^8.0.1", + "picocolors": "^1.0.1", + "upath": "^2.0.1" + } + }, + "node_modules/@vueuse/core": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.0.tgz", + "integrity": "sha512-x3sD4Mkm7PJ+pcq3HX8PLPBadXCAlSDR/waK87dz0gQE+qJnaaFhc/dZVfJz+IUYzTMVGum2QlR7ImiJQN4s6g==", + "dev": true, + "dependencies": { + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "10.11.0", + "@vueuse/shared": "10.11.0", + "vue-demi": ">=0.14.8" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.8", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", + "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", + "dev": true, + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.0.tgz", + "integrity": "sha512-kQX7l6l8dVWNqlqyN3ePW3KmjCQO3ZMgXuBMddIu83CmucrsBfXlH+JoviYyRBws/yLTQO8g3Pbw+bdIoVm4oQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.0.tgz", + "integrity": "sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==", + "dev": true, + "dependencies": { + "vue-demi": ">=0.14.8" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.8", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", + "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", + "dev": true, + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "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, + "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/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "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==" + }, + "node_modules/autoprefixer": { + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/balloon-css": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/balloon-css/-/balloon-css-1.2.0.tgz", + "integrity": "sha512-urXwkHgwp6GsXVF+it01485Z2Cj4pnW02ICnM0TemOlkKmCNnDLmyy+ZZiRXBpwldUXO+aRNr7Hdia4CBvXJ5A==", + "dev": true + }, + "node_modules/bcrypt-ts": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-ts/-/bcrypt-ts-5.0.2.tgz", + "integrity": "sha512-gDwQ5784AkkfhHACh3jGcg1hUubyZyeq9AtVd5gXkcyHGVOC+mORjRIHSj+fHfqwY5vxwyBLXQpcfk8MpK0ROg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001642", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", + "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "dev": true, + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "dev": true, + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/cliui/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/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, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "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 + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/create-codepen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/create-codepen/-/create-codepen-2.0.0.tgz", + "integrity": "sha512-ehJ0Zw5RSV2G4+/azUb7vEZWRSA/K9cW7HDock1Y9ViDexkgSJUZJRcObdw/YAWeXKjreEQV9l/igNSsJ1yw5A==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "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, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "node_modules/dayjs": { + "version": "1.11.12", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.12.tgz", + "integrity": "sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", + "dev": true + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.830", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.830.tgz", + "integrity": "sha512-TrPKKH20HeN0J1LHzsYLs2qwXrp8TF4nHdu4sq61ozGbzMpWhI7iIOPYPPkxeq1azMT9PZ8enPFcftbs/Npcjg==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true + }, + "node_modules/encode-utf8": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/envinfo": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", + "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/execa": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.3.0.tgz", + "integrity": "sha512-l6JFbqnHEadBoVAVpN5dl2yCyfX28WoBAGaoQcNmLLSedOxTxcn2Qa83s8I/PA5i56vWru2OHOtrwF7Om2vqlg==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "cross-spawn": "^7.0.3", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^7.0.0", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^5.2.0", + "pretty-ms": "^9.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.5.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "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/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true + }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "dev": true, + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/giscus": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/giscus/-/giscus-1.5.0.tgz", + "integrity": "sha512-t3LL0qbSO3JXq3uyQeKpF5CegstGfKX/0gI6eDe1cmnI7D56R7j52yLdzw4pdKrg3VnufwCgCM3FDz7G1Qr6lg==", + "dev": true, + "dependencies": { + "lit": "^3.1.2" + } + }, + "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/globby": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.2.tgz", + "integrity": "sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==", + "dev": true, + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", + "ignore": "^5.2.4", + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/human-signals": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-7.0.0.tgz", + "integrity": "sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", + "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", + "dev": 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-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "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-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "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==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lit": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/lit/-/lit-3.1.4.tgz", + "integrity": "sha512-q6qKnKXHy2g1kjBaNfcoLlgbI3+aSOZ9Q4tiGa9bGYXq5RBXxkVTqTIVmP2VWMp29L4GyvCFm8ZQ2o56eUAMyA==", + "dev": true, + "dependencies": { + "@lit/reactive-element": "^2.0.4", + "lit-element": "^4.0.4", + "lit-html": "^3.1.2" + } + }, + "node_modules/lit-element": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.6.tgz", + "integrity": "sha512-U4sdJ3CSQip7sLGZ/uJskO5hGiqtlpxndsLr6mt3IQIjheg93UKYeGQjWMRql1s/cXNOaRrCzC2FQwjIwSUqkg==", + "dev": true, + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.2.0", + "@lit/reactive-element": "^2.0.4", + "lit-html": "^3.1.2" + } + }, + "node_modules/lit-html": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.1.4.tgz", + "integrity": "sha512-yKKO2uVv7zYFHlWMfZmqc+4hkmSbFp8jgjdZY9vvR9jr4J8fH6FUMXhr+ljfELgmjpvlF7Z1SJ5n5/Jeqtc9YA==", + "dev": true, + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "dev": true, + "dependencies": { + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-anchor": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-9.0.1.tgz", + "integrity": "sha512-cBt7aAzmkfX8X7FqAe8EBryiKmToXgMQEEMqkXzWCm0toDtfDYIGboKeTKd8cpNJArJtutrf+977wFJTsvNGmQ==", + "dev": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/markdown-it-emoji": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-3.0.0.tgz", + "integrity": "sha512-+rUD93bXHubA4arpEZO3q80so0qgoFJEKRkRbjKX8RTdca89v2kfyF+xR3i2sQTwql9tpPZPOQN5B+PunspXRg==", + "dev": true + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true + }, + "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.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.17.tgz", + "integrity": "sha512-Ww6ZlOiEQfPfXM45v17oabk77Z7mg5bOt7AjDyzy7RjK9OrLrLC8dyZQoAPEOtFX9SaNf1Tdvr5gRJWdTJj7GA==", + "dev": 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/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz", + "integrity": "sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==", + "dev": true, + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "dev": true, + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-type": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/photoswipe": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/photoswipe/-/photoswipe-5.4.4.tgz", + "integrity": "sha512-WNFHoKrkZNnvFFhbHL93WDkW3ifwVOXSW3w1UuZZelSmgXpIGiZSNlZJq37rR8YejqME2rHs9EhH9ZvlvFH2NA==", + "dev": true, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true + }, + "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/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/postcss": { + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/pretty-ms": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.0.0.tgz", + "integrity": "sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==", + "dev": true, + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qrcode": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", + "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", + "dev": true, + "dependencies": { + "dijkstrajs": "^1.0.1", + "encode-utf8": "^1.0.3", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "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/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/rollup": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.1.tgz", + "integrity": "sha512-Elx2UT8lzxxOXMpy5HWQGZqkrQOtrVDDa/bm9l10+U4rQnVzbL/LgZ4NOM1MPIDyHk69W4InuYDF5dzRh4Kw1A==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.1", + "@rollup/rollup-android-arm64": "4.18.1", + "@rollup/rollup-darwin-arm64": "4.18.1", + "@rollup/rollup-darwin-x64": "4.18.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.1", + "@rollup/rollup-linux-arm-musleabihf": "4.18.1", + "@rollup/rollup-linux-arm64-gnu": "4.18.1", + "@rollup/rollup-linux-arm64-musl": "4.18.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.1", + "@rollup/rollup-linux-riscv64-gnu": "4.18.1", + "@rollup/rollup-linux-s390x-gnu": "4.18.1", + "@rollup/rollup-linux-x64-gnu": "4.18.1", + "@rollup/rollup-linux-x64-musl": "4.18.1", + "@rollup/rollup-win32-arm64-msvc": "4.18.1", + "@rollup/rollup-win32-ia32-msvc": "4.18.1", + "@rollup/rollup-win32-x64-msvc": "4.18.1", + "fsevents": "~2.3.2" + } + }, + "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.77.8", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", + "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==", + "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": ">=14.0.0" + } + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "dev": true + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "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, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/shiki": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.3.tgz", + "integrity": "sha512-eneCLncGuvPdTutJuLyUGS8QNPAVFO5Trvld2wgEq1e002mwctAhJKeMGWtWVXOIEzmlcLRqcgPSorR6AVzOmQ==", + "dev": true, + "dependencies": { + "@shikijs/core": "1.10.3", + "@types/hast": "^3.0.4" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sitemap": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-8.0.0.tgz", + "integrity": "sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A==", + "dev": true, + "dependencies": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" + }, + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=14.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "dev": true + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slimsearch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/slimsearch/-/slimsearch-2.1.1.tgz", + "integrity": "sha512-l1utJWal8F/RIheYk88DE2+enI12nIrn5SHt4ih/CNAH81PzkTv2GVBODlLynDJb7xan5hjd8XTL5f0L4cxLQA==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dev": true, + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/upath": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", + "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.4.tgz", + "integrity": "sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.39", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.33.tgz", + "integrity": "sha512-VdMCWQOummbhctl4QFMcW6eNtXHsFyDlX60O/tsSQuCcuDOnJ1qPOhhVla65Niece7xq/P2zyZReIO5mP+LGTQ==", + "dev": true, + "dependencies": { + "@vue/compiler-dom": "3.4.33", + "@vue/compiler-sfc": "3.4.33", + "@vue/runtime-dom": "3.4.33", + "@vue/server-renderer": "3.4.33", + "@vue/shared": "3.4.33" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.4.0.tgz", + "integrity": "sha512-HB+t2p611aIZraV2aPSRNXf0Z/oLZFrlygJm+sZbdJaW6lcFqEDQwnzUBXn+DApw+/QzDU/I9TeWx9izEjTmsA==", + "dev": true, + "dependencies": { + "@vue/devtools-api": "^6.5.1" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vuepress": { + "version": "2.0.0-rc.14", + "resolved": "https://registry.npmjs.org/vuepress/-/vuepress-2.0.0-rc.14.tgz", + "integrity": "sha512-t902FYKFF2MavNQjm/I4gN8etl6iX4PETutu4c1Pt7qQjXF6Hp2eurZaW32O5/TaYWsbVG757FwKodRLj9GDng==", + "dev": true, + "dependencies": { + "@vuepress/cli": "2.0.0-rc.14", + "@vuepress/client": "2.0.0-rc.14", + "@vuepress/core": "2.0.0-rc.14", + "@vuepress/markdown": "2.0.0-rc.14", + "@vuepress/shared": "2.0.0-rc.14", + "@vuepress/utils": "2.0.0-rc.14", + "vue": "^3.4.29" + }, + "bin": { + "vuepress": "bin/vuepress.js", + "vuepress-vite": "bin/vuepress-vite.js", + "vuepress-webpack": "bin/vuepress-webpack.js" + }, + "engines": { + "node": ">=18.16.0" + }, + "peerDependencies": { + "@vuepress/bundler-vite": "2.0.0-rc.14", + "@vuepress/bundler-webpack": "2.0.0-rc.14", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "@vuepress/bundler-vite": { + "optional": true + }, + "@vuepress/bundler-webpack": { + "optional": true + } + } + }, + "node_modules/vuepress-plugin-components": { + "version": "2.0.0-rc.51", + "resolved": "https://registry.npmjs.org/vuepress-plugin-components/-/vuepress-plugin-components-2.0.0-rc.51.tgz", + "integrity": "sha512-oPlym6g6hAqX9PzV40jrCqrST5XNz2QLYUP+OtvT6iStJkmyjirVOJ/0eVLXRo8lVfqntcBEKebZ5dhz5qYB9w==", + "dev": true, + "dependencies": { + "@stackblitz/sdk": "^1.11.0", + "@vuepress/helper": "2.0.0-rc.38", + "@vuepress/plugin-sass-palette": "2.0.0-rc.38", + "@vueuse/core": "^10.11.0", + "balloon-css": "^1.2.0", + "create-codepen": "^2.0.0", + "qrcode": "^1.5.3", + "vue": "^3.4.31", + "vuepress-shared": "2.0.0-rc.51" + }, + "engines": { + "node": ">=18.19.0", + "npm": ">=8", + "pnpm": ">=7", + "yarn": ">=2" + }, + "peerDependencies": { + "artplayer": "^5.0.0", + "dashjs": "4.7.4", + "hls.js": "^1.4.12", + "mpegts.js": "^1.7.3", + "sass-loader": "^14.0.0", + "vidstack": "^1.11.21", + "vuepress": "2.0.0-rc.14" + }, + "peerDependenciesMeta": { + "artplayer": { + "optional": true + }, + "dashjs": { + "optional": true + }, + "hls.js": { + "optional": true + }, + "mpegts.js": { + "optional": true + }, + "sass-loader": { + "optional": true + }, + "vidstack": { + "optional": true + } + } + }, + "node_modules/vuepress-plugin-md-enhance": { + "version": "2.0.0-rc.51", + "resolved": "https://registry.npmjs.org/vuepress-plugin-md-enhance/-/vuepress-plugin-md-enhance-2.0.0-rc.51.tgz", + "integrity": "sha512-m8J9DUleFvwfNujgRgRlkwddPTCyumtlPtOXgRpnnTn1uiXVtJoq4PwFMY7PiNMoNr0Q/6a6fuDjEJfNgG/l1w==", + "dev": true, + "dependencies": { + "@mdit/plugin-alert": "^0.12.0", + "@mdit/plugin-align": "^0.12.0", + "@mdit/plugin-attrs": "^0.12.0", + "@mdit/plugin-container": "^0.12.0", + "@mdit/plugin-demo": "^0.12.0", + "@mdit/plugin-figure": "^0.12.0", + "@mdit/plugin-footnote": "^0.12.0", + "@mdit/plugin-img-lazyload": "^0.12.0", + "@mdit/plugin-img-mark": "^0.12.0", + "@mdit/plugin-img-size": "^0.12.0", + "@mdit/plugin-include": "^0.12.0", + "@mdit/plugin-katex-slim": "^0.12.0", + "@mdit/plugin-mark": "^0.12.0", + "@mdit/plugin-mathjax-slim": "^0.12.0", + "@mdit/plugin-plantuml": "^0.12.0", + "@mdit/plugin-spoiler": "^0.12.0", + "@mdit/plugin-stylize": "^0.12.0", + "@mdit/plugin-sub": "^0.12.0", + "@mdit/plugin-sup": "^0.12.0", + "@mdit/plugin-tab": "^0.12.0", + "@mdit/plugin-tasklist": "^0.12.0", + "@mdit/plugin-tex": "^0.12.0", + "@mdit/plugin-uml": "^0.12.0", + "@types/markdown-it": "^14.1.1", + "@vuepress/helper": "2.0.0-rc.38", + "@vuepress/plugin-sass-palette": "2.0.0-rc.38", + "@vueuse/core": "^10.11.0", + "balloon-css": "^1.2.0", + "js-yaml": "^4.1.0", + "vue": "^3.4.31", + "vuepress-shared": "2.0.0-rc.51" + }, + "engines": { + "node": ">=18.19.0", + "npm": ">=8", + "pnpm": ">=7", + "yarn": ">=2" + }, + "peerDependencies": { + "@types/reveal.js": "^5.0.0", + "@vue/repl": "^4.1.1", + "chart.js": "^4.0.0", + "echarts": "^5.0.0", + "flowchart.ts": "^2.0.0 || ^3.0.0", + "katex": "^0.16.0", + "kotlin-playground": "^1.23.0", + "markmap-lib": "^0.17.0", + "markmap-toolbar": "^0.17.0", + "markmap-view": "^0.17.0", + "mathjax-full": "^3.2.2", + "mermaid": "^10.8.0", + "reveal.js": "^5.0.0", + "sandpack-vue3": "^3.0.0", + "sass-loader": "^14.0.0", + "vuepress": "2.0.0-rc.14" + }, + "peerDependenciesMeta": { + "@types/reveal.js": { + "optional": true + }, + "@vue/repl": { + "optional": true + }, + "chart.js": { + "optional": true + }, + "echarts": { + "optional": true + }, + "flowchart.ts": { + "optional": true + }, + "katex": { + "optional": true + }, + "kotlin-playground": { + "optional": true + }, + "markmap-lib": { + "optional": true + }, + "markmap-toolbar": { + "optional": true + }, + "markmap-view": { + "optional": true + }, + "mathjax-full": { + "optional": true + }, + "mermaid": { + "optional": true + }, + "reveal.js": { + "optional": true + }, + "sandpack-vue3": { + "optional": true + }, + "sass-loader": { + "optional": true + } + } + }, + "node_modules/vuepress-plugin-search-pro": { + "version": "2.0.0-rc.51", + "resolved": "https://registry.npmjs.org/vuepress-plugin-search-pro/-/vuepress-plugin-search-pro-2.0.0-rc.51.tgz", + "integrity": "sha512-k4w1CyX3ZSQA9oxH2bwYL25R+qg6Lfvt8mYz88zwTY1a8i9Un8ngkxwQagmwD8cebyQ/YzTRoQfLwBRO9WU6tw==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "@vuepress/plugin-sass-palette": "2.0.0-rc.38", + "@vueuse/core": "^10.11.0", + "cheerio": "1.0.0-rc.12", + "chokidar": "^3.6.0", + "slimsearch": "^2.1.1", + "vue": "^3.4.31", + "vuepress-shared": "2.0.0-rc.51" + }, + "engines": { + "node": ">=18.19.0", + "npm": ">=8", + "pnpm": ">=7", + "yarn": ">=2" + }, + "peerDependencies": { + "sass-loader": "^14.0.0", + "vuepress": "2.0.0-rc.14" + }, + "peerDependenciesMeta": { + "sass-loader": { + "optional": true + } + } + }, + "node_modules/vuepress-shared": { + "version": "2.0.0-rc.51", + "resolved": "https://registry.npmjs.org/vuepress-shared/-/vuepress-shared-2.0.0-rc.51.tgz", + "integrity": "sha512-9E/7nV1qe9A2gydeYClkmPH6McXOrI26rdFXybrMEbBHUhzmqsBN7GaM3YxNE6qSqGzpEBOOuurBllJFKwd66A==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "@vueuse/core": "^10.11.0", + "cheerio": "1.0.0-rc.12", + "dayjs": "^1.11.11", + "execa": "^9.3.0", + "fflate": "^0.8.2", + "gray-matter": "^4.0.3", + "semver": "^7.6.2", + "vue": "^3.4.31" + }, + "engines": { + "node": ">=18.19.0", + "npm": ">=8", + "pnpm": ">=7", + "yarn": ">=2" + }, + "peerDependencies": { + "vuepress": "2.0.0-rc.14" + } + }, + "node_modules/vuepress-theme-hope": { + "version": "2.0.0-rc.51", + "resolved": "https://registry.npmjs.org/vuepress-theme-hope/-/vuepress-theme-hope-2.0.0-rc.51.tgz", + "integrity": "sha512-Q7AIm8pp0mWtWWiJmLSpWo7yY6a8e4JJx5V0sktD8dDsiscBUB4ct3jimJQWe7X6QJx9uOFEVaulHAtSm3I4lw==", + "dev": true, + "dependencies": { + "@vuepress/helper": "2.0.0-rc.38", + "@vuepress/plugin-active-header-links": "2.0.0-rc.38", + "@vuepress/plugin-back-to-top": "2.0.0-rc.38", + "@vuepress/plugin-blog": "2.0.0-rc.38", + "@vuepress/plugin-catalog": "2.0.0-rc.38", + "@vuepress/plugin-comment": "2.0.0-rc.38", + "@vuepress/plugin-copy-code": "2.0.0-rc.38", + "@vuepress/plugin-copyright": "2.0.0-rc.38", + "@vuepress/plugin-git": "2.0.0-rc.38", + "@vuepress/plugin-links-check": "2.0.0-rc.38", + "@vuepress/plugin-notice": "2.0.0-rc.38", + "@vuepress/plugin-nprogress": "2.0.0-rc.38", + "@vuepress/plugin-photo-swipe": "2.0.0-rc.38", + "@vuepress/plugin-reading-time": "2.0.0-rc.38", + "@vuepress/plugin-rtl": "2.0.0-rc.38", + "@vuepress/plugin-sass-palette": "2.0.0-rc.38", + "@vuepress/plugin-seo": "2.0.0-rc.38", + "@vuepress/plugin-shiki": "2.0.0-rc.38", + "@vuepress/plugin-sitemap": "2.0.0-rc.38", + "@vuepress/plugin-theme-data": "2.0.0-rc.38", + "@vuepress/plugin-watermark": "2.0.0-rc.38", + "@vueuse/core": "^10.11.0", + "balloon-css": "^1.2.0", + "bcrypt-ts": "^5.0.2", + "cheerio": "1.0.0-rc.12", + "chokidar": "^3.6.0", + "gray-matter": "^4.0.3", + "vue": "^3.4.31", + "vuepress-plugin-components": "2.0.0-rc.51", + "vuepress-plugin-md-enhance": "2.0.0-rc.51", + "vuepress-shared": "2.0.0-rc.51" + }, + "engines": { + "node": ">=18.19.0", + "npm": ">=8", + "pnpm": ">=7", + "yarn": ">=2" + }, + "peerDependencies": { + "@vuepress/plugin-docsearch": "2.0.0-rc.38", + "@vuepress/plugin-feed": "2.0.0-rc.38", + "@vuepress/plugin-prismjs": "2.0.0-rc.37", + "@vuepress/plugin-pwa": "2.0.0-rc.38", + "@vuepress/plugin-redirect": "2.0.0-rc.38", + "@vuepress/plugin-search": "2.0.0-rc.38", + "nodejs-jieba": "^0.1.2", + "sass-loader": "^14.0.0", + "vuepress": "2.0.0-rc.14", + "vuepress-plugin-search-pro": "2.0.0-rc.51" + }, + "peerDependenciesMeta": { + "@vuepress/plugin-docsearch": { + "optional": true + }, + "@vuepress/plugin-feed": { + "optional": true + }, + "@vuepress/plugin-prismjs": { + "optional": true + }, + "@vuepress/plugin-pwa": { + "optional": true + }, + "@vuepress/plugin-redirect": { + "optional": true + }, + "@vuepress/plugin-search": { + "optional": true + }, + "nodejs-jieba": { + "optional": true + }, + "sass-loader": { + "optional": true + }, + "vuepress-plugin-search-pro": { + "optional": true + } + } + }, + "node_modules/watermark-js-plus": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/watermark-js-plus/-/watermark-js-plus-1.5.2.tgz", + "integrity": "sha512-iqgSeAfwnCKNpClmyjl7rhj0SEbt8j+MqZc6C3YKY5xjMdxlRMIOcnYdBYBiznzILVyJ6YbwxD5OMajK1D+uCA==", + "dev": true, + "engines": { + "node": ">=16.0.0" + } + }, + "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, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/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, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/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, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yoctocolors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", + "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/doc/vuepress/package.json b/doc/vuepress/package.json new file mode 100644 index 00000000000..8644b4837ce --- /dev/null +++ b/doc/vuepress/package.json @@ -0,0 +1,23 @@ +{ + "name": "espnet_page", + "description": "Home page for ESPnet", + "version": "1.0.0", + "license": "MIT", + "type": "module", + "scripts": { + "docs:build": "vuepress-vite build src", + "docs:clean-dev": "vuepress-vite dev src --clean-cache", + "docs:dev": "vuepress-vite dev src", + "docs:update-package": "npx vp-update" + }, + "devDependencies": { + "@vuepress/bundler-vite": "2.0.0-rc.14", + "vue": "^3.4.31", + "vuepress": "2.0.0-rc.14", + "vuepress-plugin-search-pro": "^2.0.0-rc.51", + "vuepress-theme-hope": "2.0.0-rc.51" + }, + "dependencies": { + "js-yaml": "^4.1.0" + } +} diff --git a/doc/vuepress/src/.vuepress/config.ts b/doc/vuepress/src/.vuepress/config.ts new file mode 100644 index 00000000000..b0f0b195eee --- /dev/null +++ b/doc/vuepress/src/.vuepress/config.ts @@ -0,0 +1,32 @@ +import { defineUserConfig } from "vuepress"; +import { viteBundler } from "@vuepress/bundler-vite"; + +import theme from "./theme.js"; + +export default defineUserConfig({ + base: "/espnet/", + + lang: "en-US", + description: "A documentation for ESPnet", + + bundler: viteBundler({ + viteOptions: { + build: { + sourcemap: false, + rollupOptions: { + output: { + manualChunks() { + return 'vendor'; + }, + }, + }, + }, + }, + vuePluginOptions: {}, + }), + + theme, + + // Enable it with pwa + // shouldPrefetch: false, +}); diff --git a/doc/vuepress/src/.vuepress/head.ts b/doc/vuepress/src/.vuepress/head.ts new file mode 100644 index 00000000000..c9ce42e5555 --- /dev/null +++ b/doc/vuepress/src/.vuepress/head.ts @@ -0,0 +1,10 @@ +import type { HeadConfig } from 'vuepress/core' + +export const head: HeadConfig[] = [ + ['link', { rel: 'manifest', href: '/manifest.webmanifest' }], + ['meta', { name: 'application-name', content: 'Example' }], + ['meta', { name: 'apple-mobile-web-app-title', content: 'Example' }], + ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }], + ['meta', { name: 'msapplication-TileColor', content: '#3eaf7c' }], + ['meta', { name: 'theme-color', content: '#3eaf7c' }], +] diff --git a/doc/vuepress/src/.vuepress/navbar.ts b/doc/vuepress/src/.vuepress/navbar.ts new file mode 100644 index 00000000000..680e355bd6e --- /dev/null +++ b/doc/vuepress/src/.vuepress/navbar.ts @@ -0,0 +1,7 @@ +import { navbar } from "vuepress-theme-hope"; +import { load } from 'js-yaml' +import { readFileSync } from 'fs' + +const navbarContents = load(readFileSync('navbars.yml', 'utf-8')) + +export default navbar(navbarContents); diff --git a/doc/vuepress/src/.vuepress/public/assets/icon/school_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg b/doc/vuepress/src/.vuepress/public/assets/icon/school_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg new file mode 100644 index 00000000000..e35807efcd6 --- /dev/null +++ b/doc/vuepress/src/.vuepress/public/assets/icon/school_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg @@ -0,0 +1 @@ + diff --git a/doc/vuepress/src/.vuepress/public/assets/icon/speech_to_text_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg b/doc/vuepress/src/.vuepress/public/assets/icon/speech_to_text_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg new file mode 100644 index 00000000000..76d2603596e --- /dev/null +++ b/doc/vuepress/src/.vuepress/public/assets/icon/speech_to_text_24dp_5F6368_FILL0_wght400_GRAD0_opsz24.svg @@ -0,0 +1 @@ + diff --git a/doc/vuepress/src/.vuepress/public/assets/image/box.svg b/doc/vuepress/src/.vuepress/public/assets/image/box.svg new file mode 100644 index 00000000000..618eddab415 --- /dev/null +++ b/doc/vuepress/src/.vuepress/public/assets/image/box.svg @@ -0,0 +1 @@ + diff --git a/doc/vuepress/src/.vuepress/public/assets/image/environment_structure.png b/doc/vuepress/src/.vuepress/public/assets/image/environment_structure.png new file mode 100644 index 00000000000..3ce82bbdb55 Binary files /dev/null and b/doc/vuepress/src/.vuepress/public/assets/image/environment_structure.png differ diff --git a/doc/vuepress/src/.vuepress/public/assets/image/espnet.png b/doc/vuepress/src/.vuepress/public/assets/image/espnet.png new file mode 100644 index 00000000000..bd3a30a6602 Binary files /dev/null and b/doc/vuepress/src/.vuepress/public/assets/image/espnet.png differ diff --git a/doc/vuepress/src/.vuepress/public/assets/image/espnet_logo1.png b/doc/vuepress/src/.vuepress/public/assets/image/espnet_logo1.png new file mode 100644 index 00000000000..d2a6709dccc Binary files /dev/null and b/doc/vuepress/src/.vuepress/public/assets/image/espnet_logo1.png differ diff --git a/doc/vuepress/src/.vuepress/public/assets/image/github-dark.svg b/doc/vuepress/src/.vuepress/public/assets/image/github-dark.svg new file mode 100644 index 00000000000..98d74c33f3f --- /dev/null +++ b/doc/vuepress/src/.vuepress/public/assets/image/github-dark.svg @@ -0,0 +1 @@ + diff --git a/doc/vuepress/src/.vuepress/public/assets/image/github-light.svg b/doc/vuepress/src/.vuepress/public/assets/image/github-light.svg new file mode 100644 index 00000000000..c679c236fd2 --- /dev/null +++ b/doc/vuepress/src/.vuepress/public/assets/image/github-light.svg @@ -0,0 +1 @@ + diff --git a/doc/vuepress/src/.vuepress/sidebar.ts b/doc/vuepress/src/.vuepress/sidebar.ts new file mode 100644 index 00000000000..644874414eb --- /dev/null +++ b/doc/vuepress/src/.vuepress/sidebar.ts @@ -0,0 +1,9 @@ +import { sidebar } from "vuepress-theme-hope"; +import { load } from 'js-yaml' +import { readFileSync } from 'fs' + +const sidebarContent = load(readFileSync('sidebars.yml', 'utf-8')) + +export default sidebar({ + "/": sidebarContent, +}); diff --git a/doc/vuepress/src/.vuepress/styles/config.scss b/doc/vuepress/src/.vuepress/styles/config.scss new file mode 100644 index 00000000000..f91061d7ba2 --- /dev/null +++ b/doc/vuepress/src/.vuepress/styles/config.scss @@ -0,0 +1,3 @@ +// you can change config here +$colors: #c0392b, #d35400, #f39c12, #27ae60, #16a085, #2980b9, #8e44ad, #2c3e50, + #7f8c8d !default; diff --git a/doc/vuepress/src/.vuepress/styles/index.scss b/doc/vuepress/src/.vuepress/styles/index.scss new file mode 100644 index 00000000000..5e51c52ea74 --- /dev/null +++ b/doc/vuepress/src/.vuepress/styles/index.scss @@ -0,0 +1,43 @@ +// place your custom styles here +body { + color: #1f1e33; +} +// place your custom styles here +.custom-h3 { + padding: 0.5em !important; + margin: 0 !important; + color: #1f1e33; + background: #f4feff; + border-left: solid 5px #58a0ff; + + em { + font-size: 90%; + line-height: normal; + color: #2980b9; + } + + p { + margin: 0; + } +} + +.custom-h4 { + margin: 0.5em 0 !important; + padding: 0.3em !important; + border: none; + border-left-width: medium; + border-left-style: none; + border-left-color: currentcolor; + border-left: 3px solid #ccc; + background: #f0f0f0; + color: #1f1e33; + + p { + margin: 0; + } +} + +.small-bracket { + font-size: 90%; + opacity: 90%; +} diff --git a/doc/vuepress/src/.vuepress/styles/palette.scss b/doc/vuepress/src/.vuepress/styles/palette.scss new file mode 100644 index 00000000000..574b51c001f --- /dev/null +++ b/doc/vuepress/src/.vuepress/styles/palette.scss @@ -0,0 +1,3 @@ +// you can change colors here +$theme-color: #096dd9; +$tip-bg-color: #F4FFF5; diff --git a/doc/vuepress/src/.vuepress/theme.ts b/doc/vuepress/src/.vuepress/theme.ts new file mode 100644 index 00000000000..b8db7b12920 --- /dev/null +++ b/doc/vuepress/src/.vuepress/theme.ts @@ -0,0 +1,113 @@ +import { hopeTheme } from "vuepress-theme-hope"; +import { searchProPlugin } from "vuepress-plugin-search-pro"; + +import navbar from "./navbar.js" +import sidebar from "./sidebar.js" + +export default hopeTheme({ + + iconAssets: "fontawesome-with-brands", + + logo: "/assets/image/espnet_logo1.png", + + favicon: "/assets/image/espnet.png", + + repo: "espnet/espnet", + + docsDir: "src", + + // navbar + navbar, + + // sidebar + sidebar, + + footer: "Copyright © 2024 ESPnet Community. All rights reserved.", + + displayFooter: true, + + toc: false, + + plugins: { + + // All features are enabled for demo, only preserve features you need here + mdEnhance: { + align: true, + attrs: true, + codetabs: true, + component: true, + demo: true, + figure: true, + hint: true, + imgLazyload: true, + imgSize: true, + include: true, + mark: true, + plantuml: true, + spoiler: true, + stylize: [ + { + matcher: "Recommended", + replacer: ({ tag }) => { + if (tag === "em") + return { + tag: "Badge", + attrs: { type: "tip" }, + content: "Recommended", + }; + }, + }, + ], + sub: true, + sup: true, + tabs: true, + tasklist: true, + vPre: true, + + // install chart.js before enabling it + // chart: true, + + // insert component easily + + // install echarts before enabling it + // echarts: true, + + // install flowchart.ts before enabling it + // flowchart: true, + + // gfm requires mathjax-full to provide tex support + // gfm: true, + + // install katex before enabling it + // katex: true, + + // install mathjax-full before enabling it + // mathjax: true, + + // install mermaid before enabling it + // mermaid: true, + + // playground: { + // presets: ["ts", "vue"], + // }, + + // install reveal.js before enabling it + // revealJs: { + // plugins: ["highlight", "math", "search", "notes", "zoom"], + // }, + + // install @vue/repl before enabling it + // vuePlayground: true, + + // install sandpack-vue3 before enabling it + // sandpack: true, + }, + + searchPro: searchProPlugin({ + placeholder: "Search", + indexContent: false, + autoSuggestions: false, + }), + + }, +}); diff --git a/doc/vuepress/tsconfig.json b/doc/vuepress/tsconfig.json new file mode 100644 index 00000000000..e7496b008d1 --- /dev/null +++ b/doc/vuepress/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "NodeNext", + "moduleResolution": "NodeNext", + "target": "ES2022" + }, + "include": [ + "src/.vuepress/**/*.ts", + "src/.vuepress/**/*.vue" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/egs2/TEMPLATE/asr1/utils/divide_lang.sh b/egs2/TEMPLATE/asr1/utils/divide_lang.sh new file mode 120000 index 00000000000..770a679fe18 --- /dev/null +++ b/egs2/TEMPLATE/asr1/utils/divide_lang.sh @@ -0,0 +1 @@ +../../../../utils/divide_lang.sh \ No newline at end of file diff --git a/egs2/TEMPLATE/asr1/utils/free-gpu.sh b/egs2/TEMPLATE/asr1/utils/free-gpu.sh new file mode 120000 index 00000000000..06d1890dc22 --- /dev/null +++ b/egs2/TEMPLATE/asr1/utils/free-gpu.sh @@ -0,0 +1 @@ +../../../../utils/free-gpu.sh \ No newline at end of file diff --git a/espnet/vc/__init__.py b/espnet/vc/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/espnet/vc/pytorch_backend/__init__.py b/espnet/vc/pytorch_backend/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/espnet2/asr/state_spaces/utils.py b/espnet2/asr/state_spaces/utils.py index 7234cf07888..029816e5302 100644 --- a/espnet2/asr/state_spaces/utils.py +++ b/espnet2/asr/state_spaces/utils.py @@ -19,7 +19,7 @@ def is_dict(x): def to_dict(x, recursive=True): """Convert Sequence or Mapping object to dict. - lists get converted to {0: x[0], 1: x[1], ...} + lists get converted to {0: x[0], 1: x[1]} """ if is_list(x): x = {i: v for i, v in enumerate(x)} diff --git a/espnetez/config.py b/espnetez/config.py index 88136165f16..e2859c4c738 100644 --- a/espnetez/config.py +++ b/espnetez/config.py @@ -4,6 +4,35 @@ def convert_none_to_None(dic): + """ + Recursively convert string representations of 'none' in a dictionary to None. + + This function traverses a dictionary and replaces any occurrences of the string + "none" with the actual Python None type. If a value in the dictionary is another + dictionary, this function is called recursively to ensure all nested dictionaries + are processed. + + Args: + dic (dict): A dictionary potentially containing the string "none" as a value. + + Returns: + dict: The input dictionary with all instances of the string "none" replaced + by None. + + Examples: + >>> sample_dict = {'key1': 'none', 'key2': {'subkey1': 'none', + 'subkey2': 'value'}} + >>> convert_none_to_None(sample_dict) + {'key1': None, 'key2': {'subkey1': None, 'subkey2': 'value'}} + + >>> nested_dict = {'level1': {'level2': {'level3': 'none'}}} + >>> convert_none_to_None(nested_dict) + {'level1': {'level2': {'level3': None}}} + + Note: + This function modifies the input dictionary in place, but it also returns + the modified dictionary for convenience. + """ for k, v in dic.items(): if isinstance(v, dict): dic[k] = convert_none_to_None(dic[k]) @@ -14,6 +43,38 @@ def convert_none_to_None(dic): def from_yaml(task, path): + """ + Load configuration from a YAML file and merge it with the default configuration. + + This function reads a YAML configuration file from the specified path and merges + its contents with the default configuration for the specified task. If there are any + keys in the YAML file that have the string value "none", they are converted to + `None` type. The resulting configuration dictionary is returned. + + Args: + task (str): The name of the task for which the configuration is being loaded. + path (str): The file path to the YAML configuration file. + + Returns: + dict: A dictionary containing the merged configuration settings. + + Raises: + FileNotFoundError: If the specified YAML file does not exist. + yaml.YAMLError: If the YAML file is not formatted correctly. + + Examples: + >>> config = from_yaml('speech_recognition', 'config.yaml') + >>> print(config) + {'learning_rate': 0.001, 'batch_size': 32, 'preprocessor_conf': None} + + >>> config = from_yaml('text_to_speech', 'path/to/config.yaml') + >>> print(config['model_type']) + 'tacotron2' + + Note: + Ensure that the task name provided corresponds to a valid task class + in the `espnetez.task` module to avoid runtime errors. + """ task_class = get_ez_task(task) with open(path, "r") as f: config = yaml.load(f, Loader=yaml.Loader) @@ -28,6 +89,50 @@ def from_yaml(task, path): def update_finetune_config(task, pretrain_config, path): + """ + Update the fine-tuning configuration with values from a specified YAML file. + + This function loads the fine-tuning configuration from a YAML file and + updates the provided pre-training configuration dictionary. It prioritizes + values from the fine-tuning configuration, while ensuring that any + distributed-related settings are reset to their defaults. Additionally, + it integrates default configurations from the specified task. + + Args: + task (str): The name of the task for which the configuration is being updated. + pretrain_config (dict): The existing pre-training configuration dictionary + to be updated. + path (str): The file path to the YAML file containing the fine-tuning + configuration. + + Returns: + dict: The updated pre-training configuration dictionary after merging with the + fine-tuning configuration and defaults from the specified task. + + Examples: + >>> pretrain_cfg = { + ... "learning_rate": 0.001, + ... "batch_size": 32, + ... "dist_backend": "nccl" + ... } + >>> updated_cfg = update_finetune_config("asr", pretrain_cfg, + "finetune_config.yaml") + >>> print(updated_cfg) + { + "learning_rate": 0.0001, # updated from finetune_config.yaml + "batch_size": 32, + "dist_backend": "nccl", + "other_config": "default_value" # from task defaults + } + + Raises: + FileNotFoundError: If the specified YAML file does not exist. + yaml.YAMLError: If the YAML file is improperly formatted. + + Note: + The function assumes that the task class provides a method + `get_default_config()` which returns the default configuration as a dictionary. + """ with open(path, "r") as f: finetune_config = yaml.load(f, Loader=yaml.Loader) default_config = get_ez_task(task).get_default_config() diff --git a/espnetez/data/dump.py b/espnetez/data/dump.py index 5314a1373d8..90b22440a9b 100644 --- a/espnetez/data/dump.py +++ b/espnetez/data/dump.py @@ -9,13 +9,41 @@ def join_dumps( dump_prefix: List[str], output_dir: Union[str, Path], ): - """Create a joined dump file from a list of dump paths. + """ + Create a joined dump file from a list of dump paths. + + This function takes multiple dump paths and prefixes, reads the corresponding + dump files, and creates a new dump file in the specified output directory. + Each line from the original dump files is prefixed with the corresponding + prefix from the `dump_prefix` list. Args: - dump_paths (List[str]): List of paths for the dump directory. - dump_prefix (List[str]): List of prefixes for the dump files. - output_dir (Union[str, Path]): Output directory of the joined dump file. + dump_paths (List[str]): A list of paths for the dump directories. + Each path should contain the dump files to be joined. + dump_prefix (List[str]): A list of prefixes for the dump files. + Each prefix will be added to the beginning of the + corresponding lines in the joined output file. + output_dir (Union[str, Path]): The output directory where the joined dump + file will be saved. If the directory does + not exist, it will be created. + + Raises: + ValueError: If any of the expected dump files do not exist in the specified + dump paths. + + Examples: + >>> join_dumps( + ... dump_paths=["/path/to/dump1", "/path/to/dump2"], + ... dump_prefix=["dataset1", "dataset2"], + ... output_dir="/path/to/output" + ... ) + This will read dump files from "/path/to/dump1" and "/path/to/dump2", + prefix the lines with "dataset1-" and "dataset2-", and write the joined + content to "/path/to/output". + Note: + It is assumed that all dump directories contain the same set of dump file + names. If the dump files have different names, a ValueError will be raised. """ dump_file_names = [ os.path.basename(g) for g in glob.glob(os.path.join(dump_paths[0], "*")) @@ -45,14 +73,70 @@ def create_dump_file( dataset: Union[Dict[str, Dict], List[Dict]], data_inputs: Dict[str, Dict], ): - """Create a dump file for a dataset. + """ + Create a dump file for a dataset. + + This function generates a dump file in the specified directory containing + the specified data from the dataset. The dump file will include information + related to the input variables as specified in the `data_inputs` argument. Args: - dump_dir (str): Output folder of the dump files. - dataset (Union[Dict[str, Dict], List[Dict]]): Dictionary of dataset. - data_inputs (Dict[str, List[str, str]]): - data information for each input variables. + dump_dir (Union[str, Path]): + The output directory where the dump files will be saved. + If the directory does not exist, it will be created. + + dataset (Union[Dict[str, Dict], List[Dict]]): + The dataset from which to create the dump file. It can either be + a dictionary where each key represents a data entry or a list of + dictionaries representing multiple entries. + + data_inputs (Dict[str, Dict]): + A dictionary containing data information for each input variable. + Each key should correspond to a variable name, and the value should + be a list where the first element is the desired output file name + for that variable. + + Raises: + ValueError: + If `dataset` is neither a dictionary nor a list, or if any + expected data entry is missing. + + Examples: + Creating a dump file from a dictionary dataset: + + >>> dump_dir = "output/dump" + >>> dataset = { + ... 0: {"feature1": "value1", "feature2": "value2"}, + ... 1: {"feature1": "value3", "feature2": "value4"}, + ... } + >>> data_inputs = { + ... "feature1": ["feature1_dump.txt"], + ... "feature2": ["feature2_dump.txt"], + ... } + >>> create_dump_file(dump_dir, dataset, data_inputs) + + This will create two files: `feature1_dump.txt` and `feature2_dump.txt` + in the `output/dump` directory, each containing the corresponding data. + + Creating a dump file from a list dataset: + + >>> dump_dir = "output/dump" + >>> dataset = [ + ... {"feature1": "value1", "feature2": "value2"}, + ... {"feature1": "value3", "feature2": "value4"}, + ... ] + >>> data_inputs = { + ... "feature1": ["feature1_dump.txt"], + ... "feature2": ["feature2_dump.txt"], + ... } + >>> create_dump_file(dump_dir, dataset, data_inputs) + + Similar to the previous example, this will create the same dump files + in the specified output directory. + Note: + Ensure that the output directory has the necessary write permissions + to avoid any I/O errors during file creation. """ if not os.path.exists(dump_dir): os.makedirs(dump_dir) diff --git a/espnetez/dataloader.py b/espnetez/dataloader.py index db78d92d7ea..745112e3d87 100644 --- a/espnetez/dataloader.py +++ b/espnetez/dataloader.py @@ -4,8 +4,76 @@ class Dataloader(AbsIterFactory): + """ + DataLoader class for building data iterators. + + This class extends the `AbsIterFactory` and provides a method to create + a PyTorch DataLoader. It accepts keyword arguments that can be passed + directly to the DataLoader constructor. + + Attributes: + kwargs (dict): A dictionary of keyword arguments for the DataLoader. + + Args: + **kwargs: Arbitrary keyword arguments that are passed to the + `torch.utils.data.DataLoader` constructor. Common arguments include: + - dataset: The dataset from which to load the data. + - batch_size: Number of samples per batch. + - shuffle: Whether to shuffle the data at every epoch. + - num_workers: Number of subprocesses to use for data loading. + - collate_fn: A function to merge a list of samples to form a + mini-batch. + + Examples: + >>> from torchvision import datasets, transforms + >>> transform = transforms.Compose([transforms.ToTensor()]) + >>> dataset = datasets.MNIST(root='./data', train=True, + ... transform=transform, download=True) + >>> dataloader = Dataloader(dataset=dataset, batch_size=32, + ... shuffle=True) + >>> train_loader = dataloader.build_iter(epoch=1) + + Note: + The `build_iter` method does not utilize the `epoch` and `shuffle` + parameters in its current implementation. They are included for + potential future use, such as enabling shuffling based on epoch + number. + """ + def __init__(self, **kwargs): self.kwargs = kwargs def build_iter(self, epoch: int, shuffle: bool = None) -> DataLoader: + """ + Constructs a PyTorch DataLoader instance. + + This method initializes and returns a DataLoader using the + parameters provided during the instantiation of the Dataloader + class. It can be customized with various options to suit the + needs of the data loading process. + + Args: + epoch (int): The current epoch number. This can be used + to implement epoch-based behaviors, such as shuffling + the dataset. + shuffle (bool, optional): A flag indicating whether to + shuffle the dataset. If set to True, the data will be + shuffled before each epoch. Defaults to None, which + means the value set in kwargs will be used. + + Returns: + DataLoader: A PyTorch DataLoader instance configured with + the provided arguments. + + Examples: + >>> dataloader = Dataloader(batch_size=32, dataset=my_dataset) + >>> train_loader = dataloader.build_iter(epoch=1, shuffle=True) + >>> for data in train_loader: + ... # Process data + ... pass + + Note: + Ensure that the dataset provided in kwargs is compatible + with the DataLoader's expected format. + """ return DataLoader(**self.kwargs) diff --git a/espnetez/dataset.py b/espnetez/dataset.py index d31b92c67c4..0bb92cb2f0e 100644 --- a/espnetez/dataset.py +++ b/espnetez/dataset.py @@ -4,14 +4,136 @@ class ESPnetEZDataset(AbsDataset): + """ + A dataset class for handling ESPnet data with easy access to data information. + + This class extends the AbsDataset class and provides functionalities to + manage a dataset and its associated metadata. It allows users to retrieve + dataset items using unique identifiers and check for available names in + the dataset. + + Attributes: + dataset (Union[list, Tuple]): The dataset containing the actual data entries. + data_info (Dict[str, callable]): A dictionary mapping attribute names to + functions that extract those attributes from the dataset. + + Args: + dataset (Union[list, Tuple]): The dataset from which data will be extracted. + data_info (Dict[str, callable]): A dictionary where keys are attribute names + and values are functions that process the dataset entries. + + Methods: + has_name(name): Checks if the given name exists in the data_info dictionary. + names() -> Tuple[str, ...]: Returns a tuple of all names in the data_info. + __getitem__(uid: Union[str, int]) -> Tuple[str, Dict]: Retrieves the data + entry corresponding to the provided unique identifier. + __len__() -> int: Returns the total number of entries in the dataset. + + Examples: + >>> dataset = [ + ("audio1.wav", "transcription1"), + ("audio2.wav", "transcription2") + ] + >>> data_info = { + ... "audio": lambda x: x[0], + ... "transcription": lambda x: x[1] + ... } + >>> ez_dataset = ESPnetEZDataset(dataset, data_info) + >>> ez_dataset.has_name("audio") + True + >>> ez_dataset.names() + ('audio', 'transcription') + >>> ez_dataset[0] + ('0', {'audio': 'audio1.wav', 'transcription': 'transcription1'}) + >>> len(ez_dataset) + 2 + + Note: + The dataset and data_info must be provided in a compatible format to ensure + proper functionality of the methods. + """ + def __init__(self, dataset, data_info): self.dataset = dataset self.data_info = data_info def has_name(self, name) -> bool: + """ + Check if the specified name exists in the dataset's data information. + + This method searches the `data_info` attribute of the dataset to determine + if the given `name` is present as a key. It is useful for validating + whether certain attributes or features are available in the dataset. + + Args: + name (str): The name to search for in the dataset's data information. + + Returns: + bool: True if the name exists in the data information; False otherwise. + + Examples: + >>> dataset = ESPnetEZDataset(dataset=[...], + data_info={'feature1': ..., 'feature2': ...}) + >>> dataset.has_name('feature1') + True + >>> dataset.has_name('feature3') + False + + Note: + The method performs a simple membership check using the `in` operator, + which is efficient for dictionaries. + """ return name in self.data_info def names(self) -> Tuple[str, ...]: + """ + A dataset class for ESPnet that handles data retrieval and management. + + This class extends the abstract dataset class to provide functionalities + specific to the ESPnet framework. It manages a dataset and its associated + metadata, allowing for efficient data access and manipulation. + + Attributes: + dataset (Union[list, tuple]): The underlying dataset that contains the data. + data_info (Dict[str, callable]): A dictionary mapping names to functions + that process each data entry in the dataset. + + Args: + dataset (Union[list, tuple]): The dataset to be wrapped. + data_info (Dict[str, callable]): A dictionary where keys are the names of + the data attributes and values are functions that extract or transform + the data from the dataset. + + Methods: + has_name(name: str) -> bool: + Checks if a given name exists in the data_info. + + names() -> Tuple[str, ...]: + Returns a tuple of all the names available in the data_info. + + __getitem__(uid: Union[str, int]) -> Tuple[str, Dict]: + Retrieves the data entry corresponding to the provided identifier. + + __len__() -> int: + Returns the number of entries in the dataset. + + Examples: + >>> dataset = ESPnetEZDataset(dataset=[...], + data_info={'feature': lambda x: x.feature, 'label': lambda x: x.label}) + >>> dataset.has_name('feature') + True + >>> dataset.names() + ('feature', 'label') + >>> entry = dataset[0] + >>> print(entry) + ('0', {'feature': ..., 'label': ...}) + >>> len(dataset) + 100 + + Note: + The functions provided in the data_info should be callable and should + accept a single argument corresponding to an entry from the dataset. + """ return tuple(self.data_info.keys()) def __getitem__(self, uid: Union[str, int]) -> Tuple[str, Dict]: diff --git a/espnetez/preprocess/sentencepiece.py b/espnetez/preprocess/sentencepiece.py index e74522256e8..0e784e72291 100644 --- a/espnetez/preprocess/sentencepiece.py +++ b/espnetez/preprocess/sentencepiece.py @@ -12,12 +12,44 @@ def prepare_sentences( remove_characters: str = "", ): """ - Create train.txt file for sentencepiece training from the given dump file. + Create a training text file for SentencePiece model training from the + provided dump text files. + + This function consolidates multiple text files into a single `train.txt` + file, which is formatted for use in SentencePiece training. It also + provides an option to remove specified characters from the text before + writing to the output file. Args: - dump_text_paths (Union[str, Path]): Dump text file path. - output_path (Union[str, Path]): Output directory for train.txt file. - remove_characters (str): Characters to be removed from the text. + dump_text_paths (Union[str, Path]): + A single dump text file path or a list of paths to the dump + text files that will be processed. + output_path (Union[str, Path]): + The directory where the `train.txt` file will be saved. + If the directory does not exist, it will be created. + remove_characters (str, optional): + A string containing characters to be removed from the text. + Defaults to an empty string, meaning no characters will be + removed. + + Raises: + FileNotFoundError: If any of the dump text files do not exist. + IOError: If there is an error reading from the dump text files + or writing to the output path. + + Examples: + >>> prepare_sentences("data/dump.txt", "output", remove_characters=",.!") + This will create an `output/train.txt` file from `data/dump.txt`, + removing commas, periods, and exclamation marks from the text. + + >>> prepare_sentences(["data/dump1.txt", "data/dump2.txt"], "output") + This will create an `output/train.txt` file by concatenating + `data/dump1.txt` and `data/dump2.txt` without removing any characters. + + Note: + Ensure that the input dump text files are properly formatted, as + the function expects each line to have a space-separated format + where the text to be processed is after the first space. """ # Please join the dump set before running this function. if not os.path.exists(output_path): @@ -48,17 +80,49 @@ def train_sentencepiece( model_type: str = "bpe", user_defined_symbols: list = [], ): - """Main function to train sentencepiece model. + """ + Main function to train a SentencePiece model. + + This function trains a SentencePiece model using the provided training + data and saves the resulting model and vocabulary files to the specified + output directory. The model can be customized through various parameters + such as vocabulary size, character coverage, and model type. Args: - dump_text_path (Union[str, Path]): Path to the train.txt file. - output_path (Union[str, Path]): Output directory to store - sentencepiece model and vocaburary list. - vocab_size (int, optional): Vocaburary size. Defaults to 5000. - character_coverage (float, optional): Character coverage. - Defaults to 0.9995. - model_type (str, optional): Model type of sentencepiece. Defaults to "bpe". - user_defined_symbols (list, optional): User defined symbols. + dump_text_path (Union[str, Path]): Path to the `train.txt` file + containing the training data for the SentencePiece model. + output_path (Union[str, Path]): Output directory where the trained + SentencePiece model and vocabulary list will be stored. + vocab_size (int, optional): The size of the vocabulary to be generated + by the SentencePiece model. Defaults to 5000. + character_coverage (float, optional): The character coverage rate + for the model, which indicates the percentage of characters in + the training data that should be covered. Defaults to 0.9995. + model_type (str, optional): The type of model to be trained. + Options include 'bpe' (Byte Pair Encoding), 'unigram', + 'char', and 'word'. Defaults to "bpe". + user_defined_symbols (list, optional): A list of user-defined symbols + that should be included in the model. Defaults to an empty list. + + Raises: + FileNotFoundError: If the specified `dump_text_path` does not exist. + Exception: If the training of the SentencePiece model fails for any + reason. + + Examples: + >>> train_sentencepiece( + ... dump_text_path='path/to/train.txt', + ... output_path='path/to/output', + ... vocab_size=8000, + ... character_coverage=0.995, + ... model_type='unigram', + ... user_defined_symbols=['', ''] + ... ) + + Note: + Ensure that the `train.txt` file has been prepared using the + `prepare_sentences` function before calling this function. + The output directory will be created if it does not already exist. """ # Please prepare sentences before running this function. spm.SentencePieceTrainer.Train( diff --git a/espnetez/preprocess/tokenizer.py b/espnetez/preprocess/tokenizer.py index 32093497df7..47376404c4b 100644 --- a/espnetez/preprocess/tokenizer.py +++ b/espnetez/preprocess/tokenizer.py @@ -11,6 +11,43 @@ def tokenize( sos_eos="", **kwargs, ): + """ + Tokenizes the input text and saves the output to a specified file. + + This function utilizes the ESPnet tokenizer to process a given input text file, + tokenize its contents, and save the results to an output file. Additionally, + it can optionally write a vocabulary file and allows for the inclusion of + special symbols such as blank tokens, out-of-vocabulary tokens, and start/end + of sentence tokens. + + Args: + input (str): Path to the input text file to be tokenized. + output (str): Path to the output file where the tokenized text will be saved. + write_vocabulary (bool, optional): Whether to write the vocabulary to a file. + Defaults to True. + blank (str, optional): Symbol to represent blank tokens. Defaults to "". + oov (str, optional): Symbol to represent out-of-vocabulary tokens. + Defaults to "". + sos_eos (str, optional): Symbol to represent start and end of sentence tokens. + Defaults to "". + **kwargs: Additional keyword arguments to customize the tokenizer behavior. + + Returns: + None: The function does not return any value but writes the tokenized + output to the specified file. + + Raises: + FileNotFoundError: If the input file does not exist. + ValueError: If the provided arguments are invalid. + + Examples: + # Basic usage + tokenize('input.txt', 'output.txt') + + # Customizing the tokenizer with additional symbols + tokenize('input.txt', 'output.txt', write_vocabulary=False, + blank="", oov="", sos_eos="") + """ parser = get_parser() kws = ["--input", input, "--output", output] kws += [ diff --git a/espnetez/task.py b/espnetez/task.py index 00447b8630b..f80acab4c14 100644 --- a/espnetez/task.py +++ b/espnetez/task.py @@ -66,6 +66,44 @@ def get_ez_task(task_name: str, use_custom_dataset: bool = False) -> AbsTask: + """ + Retrieve a customized task class for the ESPnet-EZ framework. + + This function returns a task class based on the specified task name. + If the `use_custom_dataset` flag is set to True, a version of the task + class that supports custom datasets will be returned. The returned class + inherits from the appropriate base task class and may be extended with + additional functionality. + + Args: + task_name (str): The name of the task to retrieve. This must be one of + the keys defined in the `TASK_CLASSES` dictionary, such as 'asr', + 'mt', 'tts', etc. + use_custom_dataset (bool, optional): A flag indicating whether to use + a version of the task class that supports custom datasets. Defaults + to False. + + Returns: + AbsTask: An instance of the task class corresponding to the provided + `task_name`. If `use_custom_dataset` is True, the returned class will + be capable of handling custom datasets. + + Raises: + KeyError: If `task_name` is not found in the `TASK_CLASSES` dictionary. + + Examples: + >>> asr_task = get_ez_task("asr") + >>> custom_asr_task = get_ez_task("asr", use_custom_dataset=True) + + >>> mt_task = get_ez_task("mt") + >>> custom_mt_task = get_ez_task("mt", use_custom_dataset=True) + + Note: + The task classes are designed to be used within the ESPnet-EZ framework, + which allows for flexibility in handling various speech and language tasks. + Ensure that the required dependencies for the specific task are properly + installed and configured. + """ task_class = TASK_CLASSES[task_name] if use_custom_dataset: @@ -85,6 +123,39 @@ def build_model(cls, args=None): def get_ez_task_with_dataset(task_name: str) -> AbsTask: + """ + Create an ESPnet-EZ task class with a custom dataset for a given task. + + This function returns a task class that inherits from the specified + task class in the ESPnet framework, enabling the use of custom datasets + for training and validation. The created task class includes methods + for building models and iterators specifically tailored for handling + datasets. + + Args: + task_name (str): The name of the task for which the class is being created. + This should correspond to one of the predefined task classes + in the ESPnet framework, such as 'asr', 'tts', etc. + + Returns: + AbsTask: A subclass of AbsTask that supports custom datasets for the + specified task. + + Examples: + >>> from espnetez.task import get_ez_task_with_dataset + >>> custom_asr_task = get_ez_task_with_dataset("asr") + >>> custom_asr_task.train_dataset = my_custom_train_dataset + >>> custom_asr_task.valid_dataset = my_custom_valid_dataset + >>> model = custom_asr_task.build_model(args) + >>> iterator = custom_asr_task.build_iter_factory(args, distributed_option, + mode='train') + + Note: + Ensure that the specified task name is valid and that the corresponding + task class is available in the TASK_CLASSES dictionary. The created + task class will need to have its `train_dataset` and `valid_dataset` + attributes set to the appropriate dataset instances before training. + """ task_class = TASK_CLASSES[task_name] class ESPnetEZDataTask(task_class): diff --git a/espnetez/trainer.py b/espnetez/trainer.py index 6e433ed7451..2f74a8855b3 100644 --- a/espnetez/trainer.py +++ b/espnetez/trainer.py @@ -13,6 +13,53 @@ def check_argument( train_dataloader, valid_dataloader, ): + """ + Validate the arguments for training and validation data sources. + + This function checks the consistency of the input arguments used for + specifying training and validation data sources. It ensures that + the user adheres to the rules of specifying either dump directories, + datasets, or dataloaders, but not a mix of them. The function will + raise a ValueError if the conditions are not met. + + Args: + train_dump_dir (str or None): The directory containing training + dump files. Should be None if using datasets or dataloaders. + valid_dump_dir (str or None): The directory containing validation + dump files. Should be None if using datasets or dataloaders. + train_dataset (Dataset or None): The training dataset. Should be + None if using dump files or dataloaders. + valid_dataset (Dataset or None): The validation dataset. Should be + None if using dump files or dataloaders. + train_dataloader (DataLoader or None): The training dataloader. + Should be None if using dump files or datasets. + valid_dataloader (DataLoader or None): The validation dataloader. + Should be None if using dump files or datasets. + + Returns: + bool: Returns True if all checks pass. + + Raises: + ValueError: If any of the argument conditions are violated. + + Examples: + # Example of valid usage with dump files + check_argument('/path/to/train_dump', '/path/to/valid_dump', None, None, None, + None) + + # Example of valid usage with datasets + check_argument(None, None, train_dataset, valid_dataset, None, None) + + # Example of invalid usage - mix of dump files and datasets + check_argument('/path/to/train_dump', None, train_dataset, None, None, None) + # Raises ValueError: If you try to use dump file, dataset or dataloader should + be None. + + Note: + Ensure to specify at least one of the arguments: dump directories, + datasets, or dataloaders. The function enforces exclusive use of + each data source type. + """ # if we have dump files, dataset/dataloader should be None, # else if we have dataset, dumpfile/dataloader should be None, # else if we have dataloader, dumpfile/dataset should be None. @@ -69,7 +116,57 @@ def check_argument( class Trainer: - """Generic trainer class for ESPnet training!""" + """ + Generic trainer class for ESPnet training. + + This class is responsible for managing the training process of ESPnet models. + It handles the configuration, dataset preparation, and the training loop. + The Trainer class supports multiple input methods including dump directories, + custom datasets, and dataloaders. It ensures that the provided arguments are + consistent and valid before starting the training process. + + Attributes: + train_config (Namespace): Configuration for training, can be a dictionary or + Namespace object. + task_class (Task): Task class instantiated from the provided task identifier. + stats_dir (str): Directory where statistics for training and validation will be + stored. + output_dir (str): Directory where model outputs will be saved. + + Args: + task (str): The task identifier used to retrieve the corresponding task class. + train_config (Union[dict, Namespace]): Configuration for training. + output_dir (str): Directory for saving model outputs. + stats_dir (str): Directory for storing training statistics. + data_info (dict, optional): Information about the dataset paths and types. + train_dump_dir (str, optional): Directory containing training dump files. + valid_dump_dir (str, optional): Directory containing validation dump files. + train_dataset (Dataset, optional): Custom training dataset. + valid_dataset (Dataset, optional): Custom validation dataset. + train_dataloader (DataLoader, optional): DataLoader for training data. + valid_dataloader (DataLoader, optional): DataLoader for validation data. + build_model_fn (callable, optional): Function to build the model. + **kwargs: Additional keyword arguments for configuring the training. + + Raises: + ValueError: If any of the argument validation checks fail. + + Examples: + >>> trainer = Trainer( + ... task='asr', + ... train_config={'batch_size': 32, 'learning_rate': 0.001}, + ... output_dir='./output', + ... stats_dir='./stats', + ... train_dump_dir='./train_dump', + ... valid_dump_dir='./valid_dump' + ... ) + >>> trainer.collect_stats() # Collect statistics from the dataset + >>> trainer.train() # Start the training process + + Note: + Ensure that either dump directories, datasets, or dataloaders are specified + as input parameters, but not a combination of them in conflicting ways. + """ def __init__( self, @@ -143,6 +240,24 @@ def __init__( self.task_class.build_model_fn = build_model_fn def train(self): + """ + Train the model using the specified training configuration. + + This method orchestrates the training process by first ensuring that + the necessary shape files are available. It checks for the presence + of shape files in the specified statistics directory, and if they + are found, it proceeds to invoke the main training routine of the + task class. + + Raises: + AssertionError: If no shape files are found in the statistics + directory for either training or validation. + + Examples: + >>> trainer = Trainer(task='my_task', train_config=my_train_config, + ... output_dir='output/', stats_dir='stats/') + >>> trainer.train() # Starts the training process + """ # after collect_stats, define shape files self.train_config.train_shape_file = glob.glob( os.path.join(self.stats_dir, "train", "*shape") @@ -161,6 +276,36 @@ def train(self): self.task_class.main(self.train_config) def collect_stats(self): + """ + Collects statistics for training and validation datasets. + + This method initializes the process of gathering statistical data + from the training and validation datasets. It creates the necessary + directories to store the statistics if they do not already exist + and sets the configuration parameters for collecting statistics. + The statistics are used to define the shape files required for + training. + + The method will call the `main` function of the `task_class` + with the updated configuration, which includes the output directory + set to the statistics directory. + + Raises: + OSError: If the directory for storing statistics cannot be created. + + Examples: + >>> trainer = Trainer(task='example_task', train_config=some_config, + ... output_dir='/path/to/output', + ... stats_dir='/path/to/stats') + >>> trainer.collect_stats() + + Note: + This method must be called before training to ensure that + the shape files are defined properly. After running this method, + the `train_shape_file` and `valid_shape_file` attributes + of `train_config` will be populated based on the collected + statistics. + """ if not os.path.exists(self.stats_dir): os.makedirs(self.stats_dir) diff --git a/setup.py b/setup.py index 0f152e467eb..e5e2405c4d2 100644 --- a/setup.py +++ b/setup.py @@ -107,13 +107,15 @@ ], "doc": [ "Jinja2<3.1", - "Sphinx==2.1.2", + "sphinx<9.0.0", "sphinx-rtd-theme>=0.2.4", "sphinx-argparse>=0.2.5", "commonmark==0.8.1", - "recommonmark>=0.4.0", + "myst-parser", "nbsphinx>=0.4.2", "sphinx-markdown-tables>=0.0.12", + "jupyterlab<5", + "sphinx-markdown-builder", ], } requirements["all"].extend(requirements["train"] + requirements["recipe"]) diff --git a/utils/divide_lang.sh b/utils/divide_lang.sh index b1fd3c22349..fcb8a56d8bc 100755 --- a/utils/divide_lang.sh +++ b/utils/divide_lang.sh @@ -5,10 +5,10 @@ . ./path.sh -if [ "$#" -ne 2 ]; then +if [ "$1" = "--help" ] ; then echo "Usage: $0 " echo "e.g.: $0 dev" - exit 1 + exit 0 fi set=$1 diff --git a/utils/free-gpu.sh b/utils/free-gpu.sh index 6db1969dfe9..1d6fba28d5d 100755 --- a/utils/free-gpu.sh +++ b/utils/free-gpu.sh @@ -1,10 +1,12 @@ #!/usr/bin/env bash # Author: Gaurav Kumar - -# Usage: e.g. -# % free-gpu.sh -n 2 -# 1,2 +if [ "$1" = "--help" ] ; then + echo "Usage: $0 -n " + echo "e.g.: $0 -n 2" + echo "1, 2" + exit 0 +fi # Allow requests for multiple GPUs # (Optional) defaults to 1