From 4495843d9fe1eded45057b4e12d5eee6c0e790c1 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Sun, 23 Mar 2025 16:15:06 -0400 Subject: [PATCH 1/3] docs: add jsdoc and rtd build --- .flake8 | 6 ++ .github/workflows/ci.yml | 20 ++++ .github/workflows/update-docs.yml | 96 +++++++++++++++++++ .gitignore | 2 + .readthedocs.yaml | 32 +++++++ docs/static/avatar.png | Bin 0 -> 11532 bytes docs/static/favicon.ico | Bin 0 -> 114227 bytes docs/static/logo.png | Bin 0 -> 24458 bytes examples/doxygen/Doxyfile | 73 ++++++++++++++ examples/doxygen/header.html | 96 +++++++++++++++++++ examples/doxygen/package.json | 12 +++ examples/doxygen/sample.md | 33 +++++++ examples/jekyll/Gemfile | 5 + examples/jekyll/_config.yml | 51 ++++++++++ examples/jekyll/assets/js/crowdin-init.js | 1 + examples/jekyll/assets/js/discord-init.js | 1 + examples/jekyll/favicon.ico | Bin 0 -> 114227 bytes examples/jekyll/index.md | 10 ++ examples/jekyll/shared-web-jekyll.gemspec | 20 ++++ examples/sphinx/.rstcheck.cfg | 8 ++ examples/sphinx/Makefile | 20 ++++ examples/sphinx/make.bat | 35 +++++++ examples/sphinx/requirements.txt | 3 + examples/sphinx/source/_static/js/crowdin.js | 1 + examples/sphinx/source/conf.py | 94 ++++++++++++++++++ examples/sphinx/source/index.rst | 29 ++++++ jsdoc.json | 68 +++++++++++++ package.json | 3 + src/css/crowdin-bootstrap.scss | 20 ++++ src/css/crowdin-clean-jsdoc.scss | 36 +++++++ src/css/crowdin-doxygen.scss | 20 ++++ src/css/crowdin-furo.scss | 20 ++++ src/js/crowdin-bootstrap-css.js | 1 + src/js/crowdin-clean-jsdoc-css.js | 1 + src/js/crowdin-doxygen-css.js | 1 + src/js/crowdin-furo-css.js | 1 + src/js/crowdin.js | 45 ++++----- src/js/discord.js | 8 ++ src/js/format-number.js | 8 +- src/js/levenshtein-distance.js | 6 ++ src/js/load-script.js | 4 +- src/js/ranking-sorter.js | 6 +- src/js/sleep.js | 4 +- tests/crowdin.test.js | 18 +--- webpack.config.js | 4 + 45 files changed, 868 insertions(+), 54 deletions(-) create mode 100644 .flake8 create mode 100644 .github/workflows/update-docs.yml create mode 100644 .readthedocs.yaml create mode 100644 docs/static/avatar.png create mode 100644 docs/static/favicon.ico create mode 100644 docs/static/logo.png create mode 100644 examples/doxygen/Doxyfile create mode 100644 examples/doxygen/header.html create mode 100644 examples/doxygen/package.json create mode 100644 examples/doxygen/sample.md create mode 100644 examples/jekyll/Gemfile create mode 100644 examples/jekyll/_config.yml create mode 100644 examples/jekyll/assets/js/crowdin-init.js create mode 100644 examples/jekyll/assets/js/discord-init.js create mode 100644 examples/jekyll/favicon.ico create mode 100644 examples/jekyll/index.md create mode 100644 examples/jekyll/shared-web-jekyll.gemspec create mode 100644 examples/sphinx/.rstcheck.cfg create mode 100644 examples/sphinx/Makefile create mode 100644 examples/sphinx/make.bat create mode 100644 examples/sphinx/requirements.txt create mode 100644 examples/sphinx/source/_static/js/crowdin.js create mode 100644 examples/sphinx/source/conf.py create mode 100644 examples/sphinx/source/index.rst create mode 100644 jsdoc.json create mode 100644 src/css/crowdin-bootstrap.scss create mode 100644 src/css/crowdin-clean-jsdoc.scss create mode 100644 src/css/crowdin-doxygen.scss create mode 100644 src/css/crowdin-furo.scss create mode 100644 src/js/crowdin-bootstrap-css.js create mode 100644 src/js/crowdin-clean-jsdoc-css.js create mode 100644 src/js/crowdin-doxygen-css.js create mode 100644 src/js/crowdin-furo-css.js diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..2ea7395 --- /dev/null +++ b/.flake8 @@ -0,0 +1,6 @@ +[flake8] +filename = + *.py +max-line-length = 120 +extend-exclude = + venv/ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a2b762..68b0a60 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,6 +94,26 @@ jobs: token: ${{ secrets.CODECOV_TOKEN }} verbose: true + release: + if: ${{ needs.setup_release.outputs.publish_release == 'true' }} + needs: + - setup_release + - build + runs-on: ubuntu-latest + steps: + - name: Create Release + id: action + uses: LizardByte/create-release-action@v2025.102.13208 + with: + allowUpdates: false + artifacts: '' + body: ${{ needs.setup_release.outputs.release_body }} + generateReleaseNotes: ${{ needs.setup_release.outputs.release_generate_release_notes }} + name: ${{ needs.setup_release.outputs.release_tag }} + prerelease: true + tag: ${{ needs.setup_release.outputs.release_tag }} + token: ${{ secrets.GH_BOT_TOKEN }} + publish-gpr: if: ${{ needs.setup_release.outputs.publish_release == 'true' }} needs: diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml new file mode 100644 index 0000000..ba84de8 --- /dev/null +++ b/.github/workflows/update-docs.yml @@ -0,0 +1,96 @@ +--- +# This action is centrally managed in https://github.com//.github/ +# Don't make changes to this file in this repo as they will be overwritten with changes made to the same file in +# the above-mentioned repo. + +# Use the `rtd` repository label to identify repositories that should trigger have this workflow. +# If the project slug is not the repository name, add a repository variable named `READTHEDOCS_SLUG` with the value of +# the ReadTheDocs project slug. + +# Update readthedocs on release events. + +name: Update docs + +on: + release: + types: [created, edited, deleted] + +concurrency: + group: "${{ github.workflow }}-${{ github.event.release.tag_name }}" + cancel-in-progress: true + +jobs: + update-docs: + env: + RTD_SLUG: ${{ vars.READTHEDOCS_SLUG }} + RTD_TOKEN: ${{ secrets.READTHEDOCS_TOKEN }} + TAG: ${{ github.event.release.tag_name }} + if: >- + !github.event.release.draft + runs-on: ubuntu-latest + steps: + - name: Get RTD_SLUG + run: | + # if the RTD_SLUG is not set, use the repository name in lowercase + if [ -z "${RTD_SLUG}" ]; then + RTD_SLUG=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]') + fi + echo "RTD_SLUG=${RTD_SLUG}" >> $GITHUB_ENV + + - name: Deactivate deleted release + if: >- + github.event_name == 'release' && + github.event.action == 'deleted' + run: | + json_body=$(jq -n \ + --arg active "false" \ + --arg hidden "false" \ + --arg privacy_level "public" \ + '{active: $active, hidden: $hidden, privacy_level: $privacy_level}') + + curl \ + -X PATCH \ + -H "Authorization: Token ${RTD_TOKEN}" \ + https://readthedocs.org/api/v3/projects/${RTD_SLUG}/versions/${TAG}/ \ + -H "Content-Type: application/json" \ + -d "$json_body" + + - name: Check if edited release is latest GitHub release + id: check + if: >- + github.event_name == 'release' && + github.event.action == 'edited' + uses: actions/github-script@v7 + with: + script: | + const latestRelease = await github.rest.repos.getLatestRelease({ + owner: context.repo.owner, + repo: context.repo.repo + }); + + core.setOutput('isLatestRelease', latestRelease.data.tag_name === context.payload.release.tag_name); + + - name: Update RTD project + # changing the default branch in readthedocs makes "latest" point to that branch/tag + # we can also update other properties like description, etc. + if: >- + steps.check.outputs.isLatestRelease == 'true' + run: | + json_body=$(jq -n \ + --arg default_branch "${TAG}" \ + --arg description "${{ github.event.repository.description }}" \ + '{default_branch: $default_branch}') + + # change the default branch to the latest release + curl \ + -X PATCH \ + -H "Authorization: Token ${RTD_TOKEN}" \ + -H "Content-Type: application/json" \ + https://readthedocs.org/api/v3/projects/${RTD_SLUG}/ \ + -d "$json_body" + + # trigger a build for the latest version + curl \ + -X POST \ + -H "Authorization: Token ${RTD_TOKEN}" \ + https://readthedocs.org/api/v3/projects/${RTD_SLUG}/versions/latest/builds/ diff --git a/.gitignore b/.gitignore index a00257a..42f2718 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,7 @@ junit.xml coverage/ # Ignore build artifacts +_readthedocs/ +build/ dist/ lizardbyte-shared-web*.tgz diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..1986b20 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,32 @@ +--- +version: 2 +build: + os: "ubuntu-24.04" + tools: + nodejs: "22" + python: "3.13" + ruby: "3.3" + commands: + - 'echo "output directory: ${READTHEDOCS_OUTPUT}html"' + # shared-web build + - npm install + - npm run build + - npm pack + - mkdir -p ${READTHEDOCS_OUTPUT}html/dist + - cp -r dist/* ${READTHEDOCS_OUTPUT}html/dist + # jsdoc build + - npm run generate-docs + # jekyll example build + - 'echo "baseurl: projects/shared-web/$READTHEDOCS_VERSION"/jekyll >> ./examples/jekyll/_config.yml' + - cd examples/jekyll && gem install bundle + - cd examples/jekyll && bundle install + - cd examples/jekyll && jekyll build --verbose --destination ${READTHEDOCS_OUTPUT}html/jekyll + # doxygen example build + - cd examples/doxygen && npm install + - cd examples/doxygen && npm run build + # sphinx example build + - python -m pip install -r examples/sphinx/requirements.txt --no-cache-dir + - cd examples/sphinx && make html BUILDDIR=${READTHEDOCS_OUTPUT}html/sphinx + - cd examples/sphinx && rstcheck -r . + # debug output + - cd ${READTHEDOCS_OUTPUT}html && ls -la -R diff --git a/docs/static/avatar.png b/docs/static/avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..e131ef4e924b73d65924300e13c97457c8afcb5b GIT binary patch literal 11532 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 z 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 literal 0 HcmV?d00001 diff --git a/examples/doxygen/Doxyfile b/examples/doxygen/Doxyfile new file mode 100644 index 0000000..ff35112 --- /dev/null +++ b/examples/doxygen/Doxyfile @@ -0,0 +1,73 @@ +DOXYFILE_ENCODING = UTF-8 + +# project metadata +DOCSET_BUNDLE_ID = dev.lizardbyte.shared-web.doxygen +DOCSET_PUBLISHER_ID = dev.lizardbyte.shared-web.doxygen +DOCSET_PUBLISHER_NAME = LizardByte +PROJECT_BRIEF = "Example use of @lizardbyte/shared-web in doxygen html." +PROJECT_ICON = $(READTHEDOCS_OUTPUT)html/favicon.ico +PROJECT_LOGO = $(READTHEDOCS_OUTPUT)html/logo.png +PROJECT_NAME = shared-web Doxygen sample + +# doxygen-awesome-css +HTML_COLORSTYLE = LIGHT # required with Doxygen >= 1.9.5 +HTML_COLORSTYLE_HUE = 209 +HTML_COLORSTYLE_SAT = 255 +HTML_COLORSTYLE_GAMMA = 113 +HTML_COPY_CLIPBOARD = NO # required for Doxygen >= 1.10.0 +HTML_EXTRA_FILES = ./node_modules/@jothepro/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js +HTML_EXTRA_FILES += ./node_modules/@jothepro/doxygen-awesome-css/doxygen-awesome-fragment-copy-button.js +HTML_EXTRA_FILES += ./node_modules/@jothepro/doxygen-awesome-css/doxygen-awesome-paragraph-link.js +HTML_EXTRA_FILES += ./node_modules/@jothepro/doxygen-awesome-css/doxygen-awesome-interactive-toc.js +HTML_EXTRA_FILES += ./node_modules/@jothepro/doxygen-awesome-css/doxygen-awesome-tabs.js +HTML_EXTRA_STYLESHEET = ./node_modules/@jothepro/doxygen-awesome-css/doxygen-awesome.css +HTML_HEADER = header.html + +# @lizardbyte/shared-web +HTML_EXTRA_FILES += ./node_modules/@lizardbyte/shared-web/dist/crowdin.js +HTML_EXTRA_STYLESHEET += ./node_modules/@lizardbyte/shared-web/dist/crowdin-doxygen-css.css + +# general settings +CASE_SENSE_NAMES = YES +CREATE_SUBDIRS = NO +DISABLE_INDEX = NO +DOCBOOK_OUTPUT = docbook +DOT_GRAPH_MAX_NODES = 50 +DOT_IMAGE_FORMAT = svg +EXTRACT_ALL = NO +FULL_SIDEBAR = NO +GENERATE_HTML = YES +GENERATE_LATEX = NO +GENERATE_TREEVIEW = YES +GENERATE_XML = NO +HAVE_DOT = NO +HTML_OUTPUT = html +INTERACTIVE_SVG = YES +LATEX_OUTPUT = latex +MACRO_EXPANSION = YES +MAN_OUTPUT = man +MARKDOWN_ID_STYLE = GITHUB +MARKDOWN_SUPPORT = YES +# If DOXYCONFIG_THREADS is not set in the environment, both DOT_NUM_THREADS and +# NUM_PROC_THREADS will be set to blank. A blank value for either is equivalent +# to the value of 0, i.e., multithreading will be used. +DOT_NUM_THREADS = $(DOXYCONFIG_THREADS) +NUM_PROC_THREADS = $(DOXYCONFIG_THREADS) +PROJECT_NUMBER = $(READTHEDOCS_VERSION) +OUTPUT_DIRECTORY = $(READTHEDOCS_OUTPUT)html/doxygen +RECURSIVE = YES +RTF_OUTPUT = rtf +SORT_BRIEF_DOCS = YES +STRIP_FROM_INC_PATH = ../ +STRIP_FROM_PATH = ../ +WARN_AS_ERROR = FAIL_ON_WARNINGS +WARN_IF_DOC_ERROR = YES +WARN_IF_INCOMPLETE_DOC = YES +WARN_IF_UNDOC_ENUM_VAL = YES +WARN_IF_UNDOCUMENTED = YES +WARN_NO_PARAMDOC = YES +WARNINGS = YES +XML_OUTPUT = xml + +USE_MDFILE_AS_MAINPAGE = sample.md +INPUT = sample.md diff --git a/examples/doxygen/header.html b/examples/doxygen/header.html new file mode 100644 index 0000000..c17326e --- /dev/null +++ b/examples/doxygen/header.html @@ -0,0 +1,96 @@ + + + + + + + + +$projectname: $title +$title + + + + + + + + + +$treeview +$search +$mathjax +$darkmode + +$extrastylesheet + + + + + + + + + + + + + + + + + +
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
$projectname $projectnumber +
+
$projectbrief
+
+
$projectbrief
+
$searchbox
$searchbox
+
+ + diff --git a/examples/doxygen/package.json b/examples/doxygen/package.json new file mode 100644 index 0000000..59df4d9 --- /dev/null +++ b/examples/doxygen/package.json @@ -0,0 +1,12 @@ +{ + "name": "shared-web-doxygen-example", + "version": "0.0.0", + "description": "Example use of @lizardbyte/shared-web in doxygen html.", + "devDependencies": { + "@jothepro/doxygen-awesome-css": "github:jothepro/doxygen-awesome-css#v2.3.4", + "@lizardbyte/shared-web": "file:../../lizardbyte-shared-web-0.0.0.tgz" + }, + "scripts": { + "build": "doxygen Doxyfile" + } +} diff --git a/examples/doxygen/sample.md b/examples/doxygen/sample.md new file mode 100644 index 0000000..5bfbb69 --- /dev/null +++ b/examples/doxygen/sample.md @@ -0,0 +1,33 @@ +# shared-web Doxygen sample + +This is a sample project for Doxygen with doxygen-awesome-css theme. This project allows you to visualize how the +widgets appear in Doxygen documentation. + +This will be automatically enabled in our [doxyconfig](https://github.com/LizardByte/doxyconfig) repo. + +## Widgets + +You can include widgets in your Doxygen documentation by adding the following to your +Doxyfile (or Doxygen configuration file). You may need to adjust the paths depending on your project structure. + +### CrowdIn + +Doxyfile: +```doxygen +HTML_EXTRA_FILES += ../node_modules/@lizardbyte/shared-web/dist/crowdin.js +HTML_EXTRA_STYLESHEET += ../node_modules/@lizardbyte/shared-web/dist/crowdin-doxygen-css.css +``` + +header.html: +```html + + + +``` + +
+ + [TOC] +
diff --git a/examples/jekyll/Gemfile b/examples/jekyll/Gemfile new file mode 100644 index 0000000..be173b2 --- /dev/null +++ b/examples/jekyll/Gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gemspec diff --git a/examples/jekyll/_config.yml b/examples/jekyll/_config.yml new file mode 100644 index 0000000..b7017ec --- /dev/null +++ b/examples/jekyll/_config.yml @@ -0,0 +1,51 @@ +--- +# See https://github.com/daattali/beautiful-jekyll/blob/master/_config.yml for documented options + +remote_theme: ReenigneArcher/beautiful-jekyll@c303cbc58172bba5b1295cff2e6930bdad98a997 +title: shared-web Jekyll sample +author: LizardByte +avatar: "../avatar.png" +round-avatar: true +title-on-all-pages: true +post_search: false +edit_page_button: true +navbar-var-length: true +keywords: "shared-web, LizardByte, Jekyll, example" +footer-col: "#242526" +footer-hover-col: "#28a9e6" +footer-link-col: "#dfdfdf" +footer-text-col: "#a8aaa8" +hover-col: "#28a9e6" +link-col: "#28a9e6" +navbar-border-col: "#393a3b" +navbar-col: "#151515" +navbar-text-col: "#e4e6eb" +page-col: "#303436" +text-col: "#e4e4e4" +mobile-theme-col: "#05FF3B" +site-css: + - "../dist/crowdin-bootstrap-css.css" +site-js: + - "../dist/crowdin.js" + - "../dist/discord.js" + - "/assets/js/crowdin-init.js" + - "/assets/js/discord-init.js" + +# Advanced settings +timezone: "America/New_York" +markdown: kramdown +highlighter: rouge +permalink: /:year-:month-:day-:title/ +paginate: 5 +kramdown: + input: GFM + +# Exclude these files from production site +exclude: + - Gemfile + - Gemfile.lock + +plugins: + - jekyll-paginate + - jekyll-remote-theme + - jekyll-sitemap diff --git a/examples/jekyll/assets/js/crowdin-init.js b/examples/jekyll/assets/js/crowdin-init.js new file mode 100644 index 0000000..9ae9050 --- /dev/null +++ b/examples/jekyll/assets/js/crowdin-init.js @@ -0,0 +1 @@ +window.initCrowdIn('LizardByte-docs', null); diff --git a/examples/jekyll/assets/js/discord-init.js b/examples/jekyll/assets/js/discord-init.js new file mode 100644 index 0000000..e9e9585 --- /dev/null +++ b/examples/jekyll/assets/js/discord-init.js @@ -0,0 +1 @@ +window.initDiscord(); diff --git a/examples/jekyll/favicon.ico b/examples/jekyll/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..79620bf5b76dbc9bd4c49dd68c0e9fecac911f2f GIT binary patch literal 114227 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 z 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 xL|2M6lu}g4yyB}K= 3.9.3" + spec.add_runtime_dependency "jekyll-paginate", "~> 1.1" + spec.add_runtime_dependency "jekyll-sitemap", "~> 1.4" + spec.add_runtime_dependency "kramdown-parser-gfm", "~> 1.1" + spec.add_runtime_dependency "kramdown", "~> 2.3" + spec.add_runtime_dependency "webrick", "~> 1.8" + + spec.add_development_dependency "jekyll-remote-theme", "~> 0.4" +end diff --git a/examples/sphinx/.rstcheck.cfg b/examples/sphinx/.rstcheck.cfg new file mode 100644 index 0000000..fb16fa6 --- /dev/null +++ b/examples/sphinx/.rstcheck.cfg @@ -0,0 +1,8 @@ +# configuration file for rstcheck, an rst linting tool +# https://rstcheck.readthedocs.io/en/latest/usage/config + +[rstcheck] +ignore_directives = + include, + mdinclude, + todo, diff --git a/examples/sphinx/Makefile b/examples/sphinx/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/examples/sphinx/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/examples/sphinx/make.bat b/examples/sphinx/make.bat new file mode 100644 index 0000000..dc1312a --- /dev/null +++ b/examples/sphinx/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/examples/sphinx/requirements.txt b/examples/sphinx/requirements.txt new file mode 100644 index 0000000..1cc61d5 --- /dev/null +++ b/examples/sphinx/requirements.txt @@ -0,0 +1,3 @@ +furo==2024.8.6 +rstcheck[sphinx]==6.2.4 +Sphinx==8.2.3 diff --git a/examples/sphinx/source/_static/js/crowdin.js b/examples/sphinx/source/_static/js/crowdin.js new file mode 100644 index 0000000..c801b66 --- /dev/null +++ b/examples/sphinx/source/_static/js/crowdin.js @@ -0,0 +1 @@ +window.initCrowdIn('LizardByte-docs', 'sphinx') diff --git a/examples/sphinx/source/conf.py b/examples/sphinx/source/conf.py new file mode 100644 index 0000000..5aeaf0d --- /dev/null +++ b/examples/sphinx/source/conf.py @@ -0,0 +1,94 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# standard imports +from datetime import datetime +import os + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. + +script_dir = os.path.dirname(os.path.abspath(__file__)) # the directory of this file +source_dir = os.path.dirname(script_dir) # the source folder directory +root_dir = os.path.dirname(os.path.dirname(source_dir)) # the root folder directory + +# -- Project information ----------------------------------------------------- +project = 'shared-web Sphinx sample' +project_copyright = f'{datetime.now().year}, {project}' +author = 'ReenigneArcher' + +# The full version, including alpha/beta/rc tags +version = os.getenv('READTHEDOCS_VERSION', 'latest') + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autosectionlabel', + 'sphinx.ext.todo', # enable to-do sections + 'sphinx.ext.viewcode', # add links to view source code +] + +# Add any paths that contain templates here, relative to this directory. +# templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + +# Extensions to include. +source_suffix = { + '.rst': 'restructuredtext', +} + + +# -- Options for HTML output ------------------------------------------------- + +# images +html_favicon = os.path.join(root_dir, 'docs', 'static', 'favicon.ico') +html_logo = os.path.join(root_dir, 'docs', 'static', 'logo.png') + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# These paths are either relative to html_static_path +# or fully qualified paths (eg. https://...) +html_css_files = [ + # use jsdelivr for an easy way to include the css + # 'https://cdn.jsdelivr.net/npm/@lizardbyte/shared-web@latest/dist/crowdin-furo-css.css', + '../../../dist/crowdin-furo-css.css', # crowdin style from the readthedocs build +] +html_js_files = [ + # use jsdelivr for an easy way to include the script + # 'https://cdn.jsdelivr.net/npm/@lizardbyte/shared-web@latest/dist/crowdin.js', + '../../../dist/crowdin.js', # crowdin language selector from the readthedocs build + 'js/crowdin.js', # initialize crowdin language selector +] + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'furo' + +html_theme_options = { + "top_of_page_button": "edit", + "source_edit_link": "https://github.com/lizardbyte/shared-web/blob/master/examples/sphinx/source/{filename}", +} + +# extension config options +autosectionlabel_prefix_document = True # Make sure the target is unique +todo_include_todos = True + +# disable epub mimetype warnings +# https://github.com/readthedocs/readthedocs.org/blob/eadf6ac6dc6abc760a91e1cb147cc3c5f37d1ea8/docs/conf.py#L235-L236 +suppress_warnings = ["epub.unknown_project_files"] diff --git a/examples/sphinx/source/index.rst b/examples/sphinx/source/index.rst new file mode 100644 index 0000000..8e47d94 --- /dev/null +++ b/examples/sphinx/source/index.rst @@ -0,0 +1,29 @@ +shared-web Sphinx sample +======================== + +This is a sample project for Sphinx with Furo theme. This project allows you to visualize how the +widgets appear in Sphinx documentation. + +Widgets +------- + +CrowdIn +~~~~~~~ + +Add the following to the Sphinx configuration file to enable the CrowdIn language selector: + +.. code-block:: python + + html_css_files = [ + 'https://cdn.jsdelivr.net/npm/@lizardbyte/shared-web@latest/dist/crowdin-furo-css.css', + ] + html_js_files = [ + 'https://cdn.jsdelivr.net/npm/@lizardbyte/shared-web@latest/dist/crowdin.js', + 'js/crowdin.js', # initialize crowdin language selector + ] + +Then create a file named ``js/crowdin.js`` located in the ``html_static_path`` directory, with the following content: + +.. code-block:: javascript + + window.initCrowdIn('LizardByte-docs', 'sphinx') diff --git a/jsdoc.json b/jsdoc.json new file mode 100644 index 0000000..06e5364 --- /dev/null +++ b/jsdoc.json @@ -0,0 +1,68 @@ +{ + "source": { + "include": ["src", "README.md"], + "includePattern": ".js$", + "excludePattern": "(node_modules/|docs/build)" + }, + "plugins": ["plugins/markdown"], + "opts": { + "encoding": "utf8", + "readme": "./README.md", + "destination": "./_readthedocs/html", + "recurse": true, + "verbose": true, + "template": "node_modules/clean-jsdoc-theme", + "theme_opts": { + "add_scripts": "window.initCrowdIn('LizardByte-docs', null);", + "default_theme": "fallback-dark", + "favicon": "favicon.ico", + "include_css": ["./dist/crowdin-clean-jsdoc-css.css"], + "include_js": ["./dist/crowdin.js"], + "menu": [ + { + "title": "Jekyll Sample", + "link": "jekyll", + "target": "_blank", + "class": "", + "id": "jekyll-sample" + }, + { + "title": "Doxygen Sample", + "link": "doxygen/html", + "target": "_blank", + "class": "", + "id": "doxygen-sample" + }, + { + "title": "Sphinx Sample", + "link": "sphinx/html", + "target": "_blank", + "class": "", + "id": "sphinx-sample" + }, + { + "title": "❤ Donate", + "link": "https://app.lizardbyte.dev", + "target": "_blank", + "class": "", + "id": "donate" + } + ] + } + }, + "markdown": { + "hardwrap": false, + "idInHeadings": true + }, + "templates": { + "cleverLinks": true, + "monospaceLinks": false, + "default": { + "staticFiles": { + "include": [ + "./docs/static" + ] + } + } + } +} diff --git a/package.json b/package.json index 33d3da4..a51ef7a 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "@eslint/js": "9.22.0", "@jest/globals": "29.7.0", "babel-loader": "10.0.0", + "clean-jsdoc-theme": "4.3.0", "cross-env": "7.0.3", "css-loader": "7.1.2", "eslint": "9.22.0", @@ -38,6 +39,7 @@ "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", "jest-junit": "16.0.0", + "jsdoc": "4.0.4", "mini-css-extract-plugin": "2.9.2", "node-fetch": "3.3.2", "npm-run-all": "4.1.5", @@ -58,6 +60,7 @@ }, "scripts": { "build": "cross-env NODE_ENV=production webpack", + "generate-docs": "jsdoc --configure jsdoc.json --verbose", "start": "webpack serve", "test": "npm-run-all test:unit test:report test:lint", "test:unit": "jest --coverage", diff --git a/src/css/crowdin-bootstrap.scss b/src/css/crowdin-bootstrap.scss new file mode 100644 index 0000000..a2f1cc5 --- /dev/null +++ b/src/css/crowdin-bootstrap.scss @@ -0,0 +1,20 @@ +#crowdin-language-picker .cr-picker-button, +#crowdin-language-picker .cr-picker-submenu { + background-color: var(--navbar-col) !important; + border: 1px solid var(--navbar-border-col) !important; + color: var(--navbar-text-col) !important; +} + +#crowdin-language-picker .cr-picker-button:hover, +#crowdin-language-picker .cr-picker-submenu > a:hover { + background-color: var(--navbar-text-col) !important; + color: var(--navbar-col) !important; +} + +#crowdin-language-picker .cr-picker-submenu > a { + color: var(--navbar-text-col) !important; +} + +#crowdin-language-picker .cr-picker-submenu > a.cr-selected { + color: var(--navbar-border-col) !important; +} diff --git a/src/css/crowdin-clean-jsdoc.scss b/src/css/crowdin-clean-jsdoc.scss new file mode 100644 index 0000000..c7056b7 --- /dev/null +++ b/src/css/crowdin-clean-jsdoc.scss @@ -0,0 +1,36 @@ +:root { + --crowdin-primary-color: #f7f7f7; + --crowdin-secondary-color: #565656; + --crowdin-primary-text-color: #111111; + --crowdin-secondary-text-color: #c5c5c9; +} + +@media (prefers-color-scheme: dark) { + body[data-theme="dark"] { + --crowdin-primary-color: #222222; + --crowdin-secondary-color: #717171; + --crowdin-primary-text-color: #ffffff; + --crowdin-secondary-text-color: #8b949e; + } +} + +#crowdin-language-picker .cr-picker-button, +#crowdin-language-picker .cr-picker-submenu { + background-color: var(--crowdin-primary-color) !important; + border: 1px solid var(--crowdin-secondary-color) !important; + color: var(--crowdin-primary-text-color) !important; +} + +#crowdin-language-picker .cr-picker-button:hover, +#crowdin-language-picker .cr-picker-submenu > a:hover { + background-color: var(--crowdin-primary-text-color) !important; + color: var(--crowdin-primary-color) !important; +} + +#crowdin-language-picker .cr-picker-submenu > a { + color: var(--crowdin-primary-text-color) !important; +} + +#crowdin-language-picker .cr-picker-submenu > a.cr-selected { + color: var(--crowdin-secondary-text-color) !important; +} diff --git a/src/css/crowdin-doxygen.scss b/src/css/crowdin-doxygen.scss new file mode 100644 index 0000000..7670c09 --- /dev/null +++ b/src/css/crowdin-doxygen.scss @@ -0,0 +1,20 @@ +#crowdin-language-picker .cr-picker-button, +#crowdin-language-picker .cr-picker-submenu { + background-color: var(--page-background-color) !important; + border: 1px solid var(--page-secondary-foreground-color) !important; + color: var(--page-foreground-color) !important; +} + +#crowdin-language-picker .cr-picker-button:hover, +#crowdin-language-picker .cr-picker-submenu > a:hover { + background-color: var(--page-foreground-color) !important; + color: var(--page-background-color) !important; +} + +#crowdin-language-picker .cr-picker-submenu > a { + color: var(--page-foreground-color) !important; +} + +#crowdin-language-picker .cr-picker-submenu > a.cr-selected { + color: var(--page-secondary-foreground-color) !important; +} diff --git a/src/css/crowdin-furo.scss b/src/css/crowdin-furo.scss new file mode 100644 index 0000000..eda4616 --- /dev/null +++ b/src/css/crowdin-furo.scss @@ -0,0 +1,20 @@ +#crowdin-language-picker .cr-picker-button, +#crowdin-language-picker .cr-picker-submenu { + background-color: var(--color-code-background) !important; + border: 1px solid var(--color-foreground-border) !important; + color: var(--color-code-foreground) !important; +} + +#crowdin-language-picker .cr-picker-button:hover, +#crowdin-language-picker .cr-picker-submenu > a:hover { + background-color: var(--color-code-foreground) !important; + color: var(--color-code-background) !important; +} + +#crowdin-language-picker .cr-picker-submenu > a { + color: var(--color-code-foreground) !important; +} + +#crowdin-language-picker .cr-picker-submenu > a.cr-selected { + color: var(--color-background-item) !important; +} diff --git a/src/js/crowdin-bootstrap-css.js b/src/js/crowdin-bootstrap-css.js new file mode 100644 index 0000000..ca2d617 --- /dev/null +++ b/src/js/crowdin-bootstrap-css.js @@ -0,0 +1 @@ +import "../css/crowdin-bootstrap.scss"; diff --git a/src/js/crowdin-clean-jsdoc-css.js b/src/js/crowdin-clean-jsdoc-css.js new file mode 100644 index 0000000..7a8f5e2 --- /dev/null +++ b/src/js/crowdin-clean-jsdoc-css.js @@ -0,0 +1 @@ +import "../css/crowdin-clean-jsdoc.scss"; diff --git a/src/js/crowdin-doxygen-css.js b/src/js/crowdin-doxygen-css.js new file mode 100644 index 0000000..735e3ed --- /dev/null +++ b/src/js/crowdin-doxygen-css.js @@ -0,0 +1 @@ +import "../css/crowdin-doxygen.scss"; diff --git a/src/js/crowdin-furo-css.js b/src/js/crowdin-furo-css.js new file mode 100644 index 0000000..2b53616 --- /dev/null +++ b/src/js/crowdin-furo-css.js @@ -0,0 +1 @@ +import "../css/crowdin-furo.scss"; diff --git a/src/js/crowdin.js b/src/js/crowdin.js index d330d0f..dbbc7ae 100644 --- a/src/js/crowdin.js +++ b/src/js/crowdin.js @@ -2,17 +2,17 @@ const loadScript = require('./load-script'); /** * Initializes Crowdin translation widget based on project and UI platform. - * @param {string} project - Project name ('LizardByte' or 'LizardByte-docs') - * @param {string|null} platform - UI platform ('bootstrap', 'sphinx', or null) + * @param {string} project - Project name ('LizardByte' or 'LizardByte-docs'). + * @param {string|null} platform - UI platform ('sphinx', or null). */ -function initCrowdIn(project = 'LizardByte', platform = 'bootstrap') { +function initCrowdIn(project = 'LizardByte', platform = null) { // Input validation if (!['LizardByte', 'LizardByte-docs'].includes(project)) { console.error('Invalid project. Must be "LizardByte" or "LizardByte-docs"'); return; } - if (!['bootstrap', 'sphinx', null].includes(platform)) { - console.error('Invalid UI. Must be "bootstrap", "sphinx", or null'); + if (!['sphinx', null].includes(platform)) { + console.error('Invalid UI. Must be "sphinx", or null'); return; } @@ -79,30 +79,23 @@ function initCrowdIn(project = 'LizardByte', platform = 'bootstrap') { if (platform === null) { return; } - setTimeout(() => { - const container = document.getElementById('crowdin-language-picker'); - const button = document.getElementsByClassName('cr-picker-button')[0]; - const menu = document.getElementsByClassName('cr-picker-submenu')[0]; - const selected = document.getElementsByClassName('cr-selected')[0]; - if (platform === 'bootstrap') { - button.classList.add('border-white', 'btn', 'btn-outline-light', 'bg-dark', 'text-white', 'rounded-0'); - menu.classList.add('border-white', 'bg-dark', 'text-white', 'rounded-0'); - selected.classList.add('text-white'); - } else if (platform === 'sphinx') { - container.classList.remove('cr-position-bottom-left') - container.style.width = button.offsetWidth + 10 + 'px'; - container.style.position = 'relative'; - container.style.left = '10px'; - container.style.bottom = '10px'; + const container = document.getElementById('crowdin-language-picker'); + const button = document.getElementsByClassName('cr-picker-button')[0]; - // get rst versions - const sidebar = document.getElementsByClassName('sidebar-sticky')[0]; + if (platform === 'sphinx') { + container.classList.remove('cr-position-bottom-left') + container.style.width = button.offsetWidth + 10 + 'px'; + container.style.position = 'relative'; + container.style.left = '10px'; + container.style.bottom = '10px'; - // move button to related pages - sidebar.appendChild(container); - } - }, 500); // Short delay to ensure elements are available + // get rst versions + const sidebar = document.getElementsByClassName('sidebar-sticky')[0]; + + // move button to related pages + sidebar.appendChild(container); + } }); } diff --git a/src/js/discord.js b/src/js/discord.js index 43907ea..ef25380 100644 --- a/src/js/discord.js +++ b/src/js/discord.js @@ -5,11 +5,19 @@ const loadScript = require('./load-script'); const { fetchRandomQuote } = require('./random-quote'); +/** + * Notify the user with a random quote. + * @param {Object} quote - The quote object. + * @param {Crate} crate - The Crate object. + */ function randomQuote(quote, crate) { let the_quote = quote['quote_safe'] || quote['quote']; crate.notify(the_quote); } +/** + * Initialize the Discord widget. + */ function initDiscord() { loadScript('https://cdn.jsdelivr.net/npm/@widgetbot/crate@3', function() { let widgetbot = new Crate({ diff --git a/src/js/format-number.js b/src/js/format-number.js index f31a1ed..3dcf21c 100644 --- a/src/js/format-number.js +++ b/src/js/format-number.js @@ -1,8 +1,8 @@ /** - * Format a number to a human-readable string - * @param num The number to format - * @param decimalPlaces The number of decimal places to include in the formatted string - * @returns {string} + * Format a number to a human-readable string. + * @param {number} num The number to format. + * @param {number} decimalPlaces The number of decimal places to include in the formatted string. + * @returns {string} The formatted number as a string with suffix (k, M, etc.). */ function formatNumber(num, decimalPlaces = 1) { if (num >= 1000000) { diff --git a/src/js/levenshtein-distance.js b/src/js/levenshtein-distance.js index d7ea625..9c367fb 100644 --- a/src/js/levenshtein-distance.js +++ b/src/js/levenshtein-distance.js @@ -1,3 +1,9 @@ +/** + * Calculate the levenshtein distance between two strings. + * @param {string} a - The first string to compare. + * @param {string} b - The second string to compare. + * @returns {number|*} - The percentage of the levenshtein distance. + */ function levenshteinDistance(a, b) { if (a.length === 0) return b.length; if (b.length === 0) return a.length; diff --git a/src/js/load-script.js b/src/js/load-script.js index 26fe180..dddfcf4 100644 --- a/src/js/load-script.js +++ b/src/js/load-script.js @@ -1,7 +1,7 @@ /** * Load a script asynchronously, and add it to the DOM. Optionally, call a callback when the script has loaded. - * @param url The URL of the script to load. - * @param callback An optional callback to call when the script has loaded. + * @param {string} url The URL of the script to load. + * @param {Function} callback An optional callback to call when the script has loaded. */ function loadScript(url, callback) { const script = document.createElement('script'); diff --git a/src/js/ranking-sorter.js b/src/js/ranking-sorter.js index 9725f94..0960e8b 100644 --- a/src/js/ranking-sorter.js +++ b/src/js/ranking-sorter.js @@ -1,8 +1,8 @@ /** * Sorts an array of objects by two keys in descending order. - * @param firstKey The primary key to sort by. - * @param secondKey The secondary key to sort by, in case the first key is equal. - * @returns {(function(*, *): (number))|*} The sorting function. + * @param {string} firstKey The primary key to sort by. + * @param {string} secondKey The secondary key to sort by, in case the first key is equal. + * @returns {Function} The sorting function that returns a number. */ function rankingSorter(firstKey, secondKey) { return function(a, b) { diff --git a/src/js/sleep.js b/src/js/sleep.js index c7fedca..77d4ccb 100644 --- a/src/js/sleep.js +++ b/src/js/sleep.js @@ -1,7 +1,7 @@ /** * Sleep for a given amount of time. - * @param ms The time to sleep in milliseconds - * @returns {Promise} A promise that resolves after the given time + * @param {number} ms The time to sleep in milliseconds. + * @returns {Promise} A promise that resolves after the given time. */ function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); diff --git a/tests/crowdin.test.js b/tests/crowdin.test.js index fb47b7f..b61c44d 100644 --- a/tests/crowdin.test.js +++ b/tests/crowdin.test.js @@ -56,7 +56,7 @@ describe('initCrowdIn', () => { it('should validate platform parameter', () => { initCrowdIn('LizardByte', 'invalidPlatform'); - expect(console.error).toHaveBeenCalledWith('Invalid UI. Must be "bootstrap", "sphinx", or null'); + expect(console.error).toHaveBeenCalledWith('Invalid UI. Must be "sphinx", or null'); }); it('should initialize proxyTranslator with LizardByte settings', () => { @@ -100,22 +100,6 @@ describe('initCrowdIn', () => { expect(button.classList.contains('btn')).toBe(false); }); - it('should apply bootstrap styling', () => { - initCrowdIn('LizardByte', 'bootstrap'); - - // Simulate script loading and UI styling timeout - jest.runAllTimers(); - - const button = document.getElementsByClassName('cr-picker-button')[0]; - const menu = document.getElementsByClassName('cr-picker-submenu')[0]; - const selected = document.getElementsByClassName('cr-selected')[0]; - - expect(button.classList.contains('btn')).toBe(true); - expect(button.classList.contains('btn-outline-light')).toBe(true); - expect(menu.classList.contains('bg-dark')).toBe(true); - expect(selected.classList.contains('text-white')).toBe(true); - }); - it('should apply sphinx styling', () => { initCrowdIn('LizardByte', 'sphinx'); diff --git a/webpack.config.js b/webpack.config.js index a64acc5..e063322 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -7,6 +7,10 @@ let production = process.env.NODE_ENV === 'production'; let config = { entry: { 'crowdin': './src/js/crowdin', + 'crowdin-bootstrap-css': './src/js/crowdin-bootstrap-css', + 'crowdin-clean-jsdoc-css': './src/js/crowdin-clean-jsdoc-css', + 'crowdin-doxygen-css': './src/js/crowdin-doxygen-css', + 'crowdin-furo-css': './src/js/crowdin-furo-css', 'discord': './src/js/discord', 'format-number': './src/js/format-number', 'levenshtein-distance': './src/js/levenshtein-distance', From 33c8e46a663bc915bbed40e433806f24a517ce0b Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 25 Mar 2025 19:13:03 -0400 Subject: [PATCH 2/3] docs(examples): use `npm run build` for all examples --- .readthedocs.yaml | 11 +++++------ examples/doxygen/package.json | 2 +- examples/jekyll/package.json | 17 +++++++++++++++++ examples/sphinx/package.json | 13 +++++++++++++ 4 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 examples/jekyll/package.json create mode 100644 examples/sphinx/package.json diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 1986b20..da79057 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -18,15 +18,14 @@ build: - npm run generate-docs # jekyll example build - 'echo "baseurl: projects/shared-web/$READTHEDOCS_VERSION"/jekyll >> ./examples/jekyll/_config.yml' - - cd examples/jekyll && gem install bundle - - cd examples/jekyll && bundle install - - cd examples/jekyll && jekyll build --verbose --destination ${READTHEDOCS_OUTPUT}html/jekyll + - cd examples/jekyll && npm install + - cd examples/jekyll && npm run build # doxygen example build - cd examples/doxygen && npm install - cd examples/doxygen && npm run build # sphinx example build - - python -m pip install -r examples/sphinx/requirements.txt --no-cache-dir - - cd examples/sphinx && make html BUILDDIR=${READTHEDOCS_OUTPUT}html/sphinx - - cd examples/sphinx && rstcheck -r . + - cd examples/sphinx && npm install + - cd examples/sphinx && npm run build + - cd examples/sphinx && npm run lint # debug output - cd ${READTHEDOCS_OUTPUT}html && ls -la -R diff --git a/examples/doxygen/package.json b/examples/doxygen/package.json index 59df4d9..0786d88 100644 --- a/examples/doxygen/package.json +++ b/examples/doxygen/package.json @@ -2,7 +2,7 @@ "name": "shared-web-doxygen-example", "version": "0.0.0", "description": "Example use of @lizardbyte/shared-web in doxygen html.", - "devDependencies": { + "dependencies": { "@jothepro/doxygen-awesome-css": "github:jothepro/doxygen-awesome-css#v2.3.4", "@lizardbyte/shared-web": "file:../../lizardbyte-shared-web-0.0.0.tgz" }, diff --git a/examples/jekyll/package.json b/examples/jekyll/package.json new file mode 100644 index 0000000..6342269 --- /dev/null +++ b/examples/jekyll/package.json @@ -0,0 +1,17 @@ +{ + "name": "shared-web-jekyll-example", + "version": "0.0.0", + "description": "Example use of @lizardbyte/shared-web in Jekyll.", + "dependencies": { + "@lizardbyte/shared-web": "file:../../lizardbyte-shared-web-0.0.0.tgz" + }, + "devDependencies": { + "npm-run-all": "4.1.5" + }, + "scripts": { + "postinstall": "npm-run-all postinstall:*", + "postinstall:bundler": "echo 'Installing bundler...' && gem install bundler", + "postinstall:bundle": "echo 'Installing Jekyll dependencies...' && bundle install", + "build": "jekyll build --verbose --destination ${READTHEDOCS_OUTPUT:-build/}html/jekyll" + } +} diff --git a/examples/sphinx/package.json b/examples/sphinx/package.json new file mode 100644 index 0000000..7822586 --- /dev/null +++ b/examples/sphinx/package.json @@ -0,0 +1,13 @@ +{ + "name": "shared-web-sphinx-example", + "version": "0.0.0", + "description": "Example use of @lizardbyte/shared-web in Sphinx.", + "dependencies": { + "@lizardbyte/shared-web": "file:../../lizardbyte-shared-web-0.0.0.tgz" + }, + "scripts": { + "postinstall": "echo 'Installing Python dependencies...' && python -m pip install -r requirements.txt --no-cache-dir", + "build": "python -m sphinx -b html source ${READTHEDOCS_OUTPUT:-build/}html/sphinx/html", + "lint": "python -m rstcheck -r ." + } +} From 4aec8181eec3473ac46d7e6bac2cc4a8b94f8361 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Tue, 25 Mar 2025 20:50:53 -0400 Subject: [PATCH 3/3] docs(examples): simplify doxygen config --- examples/doxygen/Doxyfile | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/examples/doxygen/Doxyfile b/examples/doxygen/Doxyfile index ff35112..75ad772 100644 --- a/examples/doxygen/Doxyfile +++ b/examples/doxygen/Doxyfile @@ -31,10 +31,6 @@ HTML_EXTRA_STYLESHEET += ./node_modules/@lizardbyte/shared-web/dist/crowdin-doxy CASE_SENSE_NAMES = YES CREATE_SUBDIRS = NO DISABLE_INDEX = NO -DOCBOOK_OUTPUT = docbook -DOT_GRAPH_MAX_NODES = 50 -DOT_IMAGE_FORMAT = svg -EXTRACT_ALL = NO FULL_SIDEBAR = NO GENERATE_HTML = YES GENERATE_LATEX = NO @@ -42,24 +38,11 @@ GENERATE_TREEVIEW = YES GENERATE_XML = NO HAVE_DOT = NO HTML_OUTPUT = html -INTERACTIVE_SVG = YES -LATEX_OUTPUT = latex -MACRO_EXPANSION = YES -MAN_OUTPUT = man MARKDOWN_ID_STYLE = GITHUB MARKDOWN_SUPPORT = YES -# If DOXYCONFIG_THREADS is not set in the environment, both DOT_NUM_THREADS and -# NUM_PROC_THREADS will be set to blank. A blank value for either is equivalent -# to the value of 0, i.e., multithreading will be used. -DOT_NUM_THREADS = $(DOXYCONFIG_THREADS) -NUM_PROC_THREADS = $(DOXYCONFIG_THREADS) PROJECT_NUMBER = $(READTHEDOCS_VERSION) OUTPUT_DIRECTORY = $(READTHEDOCS_OUTPUT)html/doxygen RECURSIVE = YES -RTF_OUTPUT = rtf -SORT_BRIEF_DOCS = YES -STRIP_FROM_INC_PATH = ../ -STRIP_FROM_PATH = ../ WARN_AS_ERROR = FAIL_ON_WARNINGS WARN_IF_DOC_ERROR = YES WARN_IF_INCOMPLETE_DOC = YES @@ -67,7 +50,6 @@ WARN_IF_UNDOC_ENUM_VAL = YES WARN_IF_UNDOCUMENTED = YES WARN_NO_PARAMDOC = YES WARNINGS = YES -XML_OUTPUT = xml USE_MDFILE_AS_MAINPAGE = sample.md INPUT = sample.md