@lizardbyte/shared-web 2026.219.33142 → 2026.726.204939
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -8
- package/dist/crowdin-rustdoc-css.css +3 -0
- package/dist/crowdin-rustdoc-css.css.map +1 -0
- package/dist/crowdin-rustdoc-css.js +0 -0
- package/dist/crowdin.js +1 -1
- package/dist/crowdin.js.map +1 -1
- package/dist/format-number.js +1 -1
- package/dist/format-number.js.map +1 -1
- package/dist/language-icons/AL.svg +1 -0
- package/dist/language-icons/ANTLR.svg +1 -0
- package/dist/language-icons/API Blueprint.svg +1 -0
- package/dist/language-icons/APL.svg +1 -0
- package/dist/language-icons/ASP.NET.svg +1 -0
- package/dist/language-icons/ATS.svg +1 -0
- package/dist/language-icons/ActionScript.svg +1 -0
- package/dist/language-icons/Ada.svg +1 -0
- package/dist/language-icons/ApacheConf.svg +1 -0
- package/dist/language-icons/Apex.svg +1 -0
- package/dist/language-icons/AppleScript.svg +1 -0
- package/dist/language-icons/Assembly.svg +1 -0
- package/dist/language-icons/Astro.svg +1 -0
- package/dist/language-icons/AutoHotkey.svg +1 -0
- package/dist/language-icons/AutoIt.svg +1 -0
- package/dist/language-icons/Avro IDL.svg +1 -0
- package/dist/language-icons/Awk.svg +1 -0
- package/dist/language-icons/Ballerina.svg +1 -0
- package/dist/language-icons/Batchfile.svg +1 -0
- package/dist/language-icons/Befunge.svg +1 -0
- package/dist/language-icons/Bicep.svg +1 -0
- package/dist/language-icons/Blade.svg +1 -0
- package/dist/language-icons/BlitzBasic.svg +1 -0
- package/dist/language-icons/Browserslist.svg +1 -0
- package/dist/language-icons/C#.svg +1 -0
- package/dist/language-icons/C++.svg +1 -0
- package/dist/language-icons/C.svg +1 -0
- package/dist/language-icons/CMake.svg +1 -0
- package/dist/language-icons/COBOL.svg +1 -0
- package/dist/language-icons/CSS.svg +1 -0
- package/dist/language-icons/Cabal Config.svg +1 -0
- package/dist/language-icons/Carbon.svg +63 -0
- package/dist/language-icons/Ceylon.svg +1 -0
- package/dist/language-icons/Clojure.svg +1 -0
- package/dist/language-icons/Cloud Firestore Security Rules.svg +1 -0
- package/dist/language-icons/CodeQL.svg +1 -0
- package/dist/language-icons/CoffeeScript.svg +1 -0
- package/dist/language-icons/ColdFusion CFC.svg +1 -0
- package/dist/language-icons/ColdFusion.svg +1 -0
- package/dist/language-icons/Crystal.svg +1 -0
- package/dist/language-icons/Cuda.svg +1 -0
- package/dist/language-icons/Cython.svg +1 -0
- package/dist/language-icons/D.svg +1 -0
- package/dist/language-icons/Darcs Patch.svg +1 -0
- package/dist/language-icons/Dart.svg +1 -0
- package/dist/language-icons/Diff.svg +1 -0
- package/dist/language-icons/Dockerfile.svg +1 -0
- package/dist/language-icons/Dylan.svg +1 -0
- package/dist/language-icons/EJS.svg +1 -0
- package/dist/language-icons/EditorConfig.svg +1 -0
- package/dist/language-icons/Elixir.svg +1 -0
- package/dist/language-icons/Elm.svg +1 -0
- package/dist/language-icons/Emacs Lisp.svg +1 -0
- package/dist/language-icons/EmberScript.svg +1 -0
- package/dist/language-icons/Erlang.svg +1 -0
- package/dist/language-icons/F#.svg +1 -0
- package/dist/language-icons/Fortran.svg +1 -0
- package/dist/language-icons/FreeMarker.svg +1 -0
- package/dist/language-icons/G-code.svg +1 -0
- package/dist/language-icons/GLSL.svg +1 -0
- package/dist/language-icons/Game Maker Language.svg +1 -0
- package/dist/language-icons/Gherkin.svg +1 -0
- package/dist/language-icons/Git Attributes.svg +1 -0
- package/dist/language-icons/Git Config.svg +1 -0
- package/dist/language-icons/Glyph.svg +1 -0
- package/dist/language-icons/Gnuplot.svg +1 -0
- package/dist/language-icons/Go Checksums.svg +1 -0
- package/dist/language-icons/Go Module.svg +1 -0
- package/dist/language-icons/Go.svg +1 -0
- package/dist/language-icons/Gradle.svg +1 -0
- package/dist/language-icons/GraphQL.svg +1 -0
- package/dist/language-icons/Graphviz (DOT).svg +1 -0
- package/dist/language-icons/Groovy.svg +1 -0
- package/dist/language-icons/HLSL.svg +1 -0
- package/dist/language-icons/HTML+EEX.svg +1 -0
- package/dist/language-icons/HTML+ERB.svg +1 -0
- package/dist/language-icons/HTML+Razor.svg +1 -0
- package/dist/language-icons/HTML.svg +1 -0
- package/dist/language-icons/HTTP.svg +1 -0
- package/dist/language-icons/Haml.svg +1 -0
- package/dist/language-icons/Handlebars.svg +1 -0
- package/dist/language-icons/Harbour.svg +1 -0
- package/dist/language-icons/Haskell.svg +1 -0
- package/dist/language-icons/Haxe.svg +1 -0
- package/dist/language-icons/Hy.svg +1 -0
- package/dist/language-icons/INI.svg +1 -0
- package/dist/language-icons/Idris.svg +1 -0
- package/dist/language-icons/Inno Setup.svg +1 -0
- package/dist/language-icons/Io.svg +1 -0
- package/dist/language-icons/JSON.svg +1 -0
- package/dist/language-icons/JSON5.svg +1 -0
- package/dist/language-icons/JSONLD.svg +1 -0
- package/dist/language-icons/Janet.svg +1 -0
- package/dist/language-icons/Jasmin.svg +1 -0
- package/dist/language-icons/Java.svg +1 -0
- package/dist/language-icons/JavaScript+ERB.svg +1 -0
- package/dist/language-icons/JavaScript.svg +1 -0
- package/dist/language-icons/Jest Snapshot.svg +1 -0
- package/dist/language-icons/Jinja.svg +1 -0
- package/dist/language-icons/Jsonnet.svg +1 -0
- package/dist/language-icons/Julia.svg +1 -0
- package/dist/language-icons/Jupyter Notebook.svg +1 -0
- package/dist/language-icons/Kotlin.svg +1 -0
- package/dist/language-icons/Kusto.svg +1 -0
- package/dist/language-icons/LICENSE +395 -0
- package/dist/language-icons/LOLCODE.svg +1 -0
- package/dist/language-icons/LSL.svg +1 -0
- package/dist/language-icons/Less.svg +1 -0
- package/dist/language-icons/Lex.svg +1 -0
- package/dist/language-icons/Liquid.svg +1 -0
- package/dist/language-icons/LiveScript.svg +1 -0
- package/dist/language-icons/Lua.svg +1 -0
- package/dist/language-icons/MATLAB.svg +1 -0
- package/dist/language-icons/MAXScript.svg +1 -0
- package/dist/language-icons/Makefile.svg +1 -0
- package/dist/language-icons/Markdown.svg +1 -0
- package/dist/language-icons/Marko.svg +1 -0
- package/dist/language-icons/Mathematica.svg +1 -0
- package/dist/language-icons/Maven POM.svg +1 -0
- package/dist/language-icons/Meson.svg +1 -0
- package/dist/language-icons/Microsoft Visual Studio Solution.svg +1 -0
- package/dist/language-icons/Mustache.svg +1 -0
- package/dist/language-icons/NPM Config.svg +1 -0
- package/dist/language-icons/NSIS.svg +1 -0
- package/dist/language-icons/Nearley.svg +1 -0
- package/dist/language-icons/NetLinx+ERB.svg +1 -0
- package/dist/language-icons/Nginx.svg +1 -0
- package/dist/language-icons/Nim.svg +1 -0
- package/dist/language-icons/Ninja.svg +1 -0
- package/dist/language-icons/Nix.svg +1 -0
- package/dist/language-icons/NumPy.svg +1 -0
- package/dist/language-icons/Nunjucks.svg +1 -0
- package/dist/language-icons/OCaml.svg +1 -0
- package/dist/language-icons/Objective-C++.svg +1 -0
- package/dist/language-icons/Objective-C.svg +1 -0
- package/dist/language-icons/OpenCL.svg +1 -0
- package/dist/language-icons/OpenSCAD.svg +1 -0
- package/dist/language-icons/Org.svg +1 -0
- package/dist/language-icons/PHP.svg +1 -0
- package/dist/language-icons/PLSQL.svg +1 -0
- package/dist/language-icons/Pascal.svg +52 -0
- package/dist/language-icons/Perl.svg +1 -0
- package/dist/language-icons/PlantUML.svg +1 -0
- package/dist/language-icons/Pony.svg +1 -0
- package/dist/language-icons/PostCSS.svg +1 -0
- package/dist/language-icons/PostScript.svg +1 -0
- package/dist/language-icons/PowerShell.svg +1 -0
- package/dist/language-icons/Prisma.svg +1 -0
- package/dist/language-icons/Processing.svg +1 -0
- package/dist/language-icons/Procfile.svg +1 -0
- package/dist/language-icons/Prolog.svg +1 -0
- package/dist/language-icons/Protocol Buffer.svg +1 -0
- package/dist/language-icons/Pug.svg +1 -0
- package/dist/language-icons/Puppet.svg +1 -0
- package/dist/language-icons/PureScript.svg +1 -0
- package/dist/language-icons/Python.svg +1 -0
- package/dist/language-icons/Q#.svg +1 -0
- package/dist/language-icons/QML.svg +1 -0
- package/dist/language-icons/QMake.svg +1 -0
- package/dist/language-icons/R.svg +1 -0
- package/dist/language-icons/RAML.svg +1 -0
- package/dist/language-icons/README.md +8 -0
- package/dist/language-icons/REXX.svg +1 -0
- package/dist/language-icons/RMarkdown.svg +1 -0
- package/dist/language-icons/Racket.svg +1 -0
- package/dist/language-icons/Raku.svg +1 -0
- package/dist/language-icons/ReScript.svg +1 -0
- package/dist/language-icons/Reason.svg +1 -0
- package/dist/language-icons/Red.svg +1 -0
- package/dist/language-icons/Riot.svg +1 -0
- package/dist/language-icons/RobotFramework.svg +1 -0
- package/dist/language-icons/Ruby.svg +1 -0
- package/dist/language-icons/Rust.svg +1 -0
- package/dist/language-icons/SAS.svg +1 -0
- package/dist/language-icons/SCSS.svg +1 -0
- package/dist/language-icons/SPARQL.svg +1 -0
- package/dist/language-icons/SQF.svg +1 -0
- package/dist/language-icons/SQL.svg +1 -0
- package/dist/language-icons/SVG.svg +1 -0
- package/dist/language-icons/SWIG.svg +1 -0
- package/dist/language-icons/SaltStack.svg +1 -0
- package/dist/language-icons/Sass.svg +1 -0
- package/dist/language-icons/Scala.svg +1 -0
- package/dist/language-icons/Scilab.svg +1 -0
- package/dist/language-icons/ShaderLab.svg +1 -0
- package/dist/language-icons/Shell.svg +1 -0
- package/dist/language-icons/Slice.svg +1 -0
- package/dist/language-icons/Slim.svg +1 -0
- package/dist/language-icons/Smarty.svg +1 -0
- package/dist/language-icons/Solidity.svg +1 -0
- package/dist/language-icons/Squirrel.svg +1 -0
- package/dist/language-icons/Stan.svg +1 -0
- package/dist/language-icons/Stata.svg +1 -0
- package/dist/language-icons/Stylus.svg +1 -0
- package/dist/language-icons/SugarSS.svg +1 -0
- package/dist/language-icons/Svelte.svg +1 -0
- package/dist/language-icons/Swift.svg +1 -0
- package/dist/language-icons/SystemVerilog.svg +1 -0
- package/dist/language-icons/TOML.svg +1 -0
- package/dist/language-icons/Tcl.svg +1 -0
- package/dist/language-icons/TeX.svg +1 -0
- package/dist/language-icons/Text.svg +1 -0
- package/dist/language-icons/Textile.svg +1 -0
- package/dist/language-icons/Twig.svg +1 -0
- package/dist/language-icons/TypeScript.svg +1 -0
- package/dist/language-icons/V.svg +1 -0
- package/dist/language-icons/VBA.svg +1 -0
- package/dist/language-icons/VBScript.svg +1 -0
- package/dist/language-icons/VHDL.svg +1 -0
- package/dist/language-icons/Vala.svg +1 -0
- package/dist/language-icons/Velocity Template Language.svg +1 -0
- package/dist/language-icons/Verilog.svg +1 -0
- package/dist/language-icons/Vim script.svg +1 -0
- package/dist/language-icons/Volt.svg +1 -0
- package/dist/language-icons/Vue.svg +1 -0
- package/dist/language-icons/WebAssembly.svg +1 -0
- package/dist/language-icons/Wikitext.svg +1 -0
- package/dist/language-icons/Windows Registry Entries.svg +1 -0
- package/dist/language-icons/XML.svg +1 -0
- package/dist/language-icons/XQuery.svg +1 -0
- package/dist/language-icons/XSLT.svg +1 -0
- package/dist/language-icons/YAML.svg +1 -0
- package/dist/language-icons/YANG.svg +1 -0
- package/dist/language-icons/Yacc.svg +1 -0
- package/dist/language-icons/Zig.svg +1 -0
- package/dist/language-icons/kvlang.svg +1 -0
- package/dist/language-icons/q.svg +1 -0
- package/dist/language-icons/reStructuredText.svg +1 -0
- package/dist/language-icons/robots.txt.svg +1 -0
- package/dist/language-icons/url.svg +1 -0
- package/dist/levenshtein-distance.js +1 -1
- package/dist/levenshtein-distance.js.map +1 -1
- package/dist/load-script.js +1 -1
- package/dist/load-script.js.map +1 -1
- package/dist/ranking-sorter.js +1 -1
- package/dist/ranking-sorter.js.map +1 -1
- package/dist/sleep.js +1 -1
- package/dist/sleep.js.map +1 -1
- package/package.json +33 -25
- package/src/css/crowdin-rustdoc.scss +30 -0
- package/src/js/crowdin-rustdoc-css.js +1 -0
- package/src/js/crowdin.js +116 -20
- package/src/js/format-number.js +2 -2
- package/src/js/levenshtein-distance.js +2 -2
- package/src/js/load-script.js +2 -2
- package/src/js/ranking-sorter.js +8 -11
- package/src/js/sleep.js +2 -2
- package/src/language-icons/AL.svg +1 -0
- package/src/language-icons/ANTLR.svg +1 -0
- package/src/language-icons/API Blueprint.svg +1 -0
- package/src/language-icons/APL.svg +1 -0
- package/src/language-icons/ASP.NET.svg +1 -0
- package/src/language-icons/ATS.svg +1 -0
- package/src/language-icons/ActionScript.svg +1 -0
- package/src/language-icons/Ada.svg +1 -0
- package/src/language-icons/ApacheConf.svg +1 -0
- package/src/language-icons/Apex.svg +1 -0
- package/src/language-icons/AppleScript.svg +1 -0
- package/src/language-icons/Assembly.svg +1 -0
- package/src/language-icons/Astro.svg +1 -0
- package/src/language-icons/AutoHotkey.svg +1 -0
- package/src/language-icons/AutoIt.svg +1 -0
- package/src/language-icons/Avro IDL.svg +1 -0
- package/src/language-icons/Awk.svg +1 -0
- package/src/language-icons/Ballerina.svg +1 -0
- package/src/language-icons/Batchfile.svg +1 -0
- package/src/language-icons/Befunge.svg +1 -0
- package/src/language-icons/Bicep.svg +1 -0
- package/src/language-icons/Blade.svg +1 -0
- package/src/language-icons/BlitzBasic.svg +1 -0
- package/src/language-icons/Browserslist.svg +1 -0
- package/src/language-icons/C#.svg +1 -0
- package/src/language-icons/C++.svg +1 -0
- package/src/language-icons/C.svg +1 -0
- package/src/language-icons/CMake.svg +1 -0
- package/src/language-icons/COBOL.svg +1 -0
- package/src/language-icons/CSS.svg +1 -0
- package/src/language-icons/Cabal Config.svg +1 -0
- package/src/language-icons/Carbon.svg +63 -0
- package/src/language-icons/Ceylon.svg +1 -0
- package/src/language-icons/Clojure.svg +1 -0
- package/src/language-icons/Cloud Firestore Security Rules.svg +1 -0
- package/src/language-icons/CodeQL.svg +1 -0
- package/src/language-icons/CoffeeScript.svg +1 -0
- package/src/language-icons/ColdFusion CFC.svg +1 -0
- package/src/language-icons/ColdFusion.svg +1 -0
- package/src/language-icons/Crystal.svg +1 -0
- package/src/language-icons/Cuda.svg +1 -0
- package/src/language-icons/Cython.svg +1 -0
- package/src/language-icons/D.svg +1 -0
- package/src/language-icons/Darcs Patch.svg +1 -0
- package/src/language-icons/Dart.svg +1 -0
- package/src/language-icons/Diff.svg +1 -0
- package/src/language-icons/Dockerfile.svg +1 -0
- package/src/language-icons/Dylan.svg +1 -0
- package/src/language-icons/EJS.svg +1 -0
- package/src/language-icons/EditorConfig.svg +1 -0
- package/src/language-icons/Elixir.svg +1 -0
- package/src/language-icons/Elm.svg +1 -0
- package/src/language-icons/Emacs Lisp.svg +1 -0
- package/src/language-icons/EmberScript.svg +1 -0
- package/src/language-icons/Erlang.svg +1 -0
- package/src/language-icons/F#.svg +1 -0
- package/src/language-icons/Fortran.svg +1 -0
- package/src/language-icons/FreeMarker.svg +1 -0
- package/src/language-icons/G-code.svg +1 -0
- package/src/language-icons/GLSL.svg +1 -0
- package/src/language-icons/Game Maker Language.svg +1 -0
- package/src/language-icons/Gherkin.svg +1 -0
- package/src/language-icons/Git Attributes.svg +1 -0
- package/src/language-icons/Git Config.svg +1 -0
- package/src/language-icons/Glyph.svg +1 -0
- package/src/language-icons/Gnuplot.svg +1 -0
- package/src/language-icons/Go Checksums.svg +1 -0
- package/src/language-icons/Go Module.svg +1 -0
- package/src/language-icons/Go.svg +1 -0
- package/src/language-icons/Gradle.svg +1 -0
- package/src/language-icons/GraphQL.svg +1 -0
- package/src/language-icons/Graphviz (DOT).svg +1 -0
- package/src/language-icons/Groovy.svg +1 -0
- package/src/language-icons/HLSL.svg +1 -0
- package/src/language-icons/HTML+EEX.svg +1 -0
- package/src/language-icons/HTML+ERB.svg +1 -0
- package/src/language-icons/HTML+Razor.svg +1 -0
- package/src/language-icons/HTML.svg +1 -0
- package/src/language-icons/HTTP.svg +1 -0
- package/src/language-icons/Haml.svg +1 -0
- package/src/language-icons/Handlebars.svg +1 -0
- package/src/language-icons/Harbour.svg +1 -0
- package/src/language-icons/Haskell.svg +1 -0
- package/src/language-icons/Haxe.svg +1 -0
- package/src/language-icons/Hy.svg +1 -0
- package/src/language-icons/INI.svg +1 -0
- package/src/language-icons/Idris.svg +1 -0
- package/src/language-icons/Inno Setup.svg +1 -0
- package/src/language-icons/Io.svg +1 -0
- package/src/language-icons/JSON.svg +1 -0
- package/src/language-icons/JSON5.svg +1 -0
- package/src/language-icons/JSONLD.svg +1 -0
- package/src/language-icons/Janet.svg +1 -0
- package/src/language-icons/Jasmin.svg +1 -0
- package/src/language-icons/Java.svg +1 -0
- package/src/language-icons/JavaScript+ERB.svg +1 -0
- package/src/language-icons/JavaScript.svg +1 -0
- package/src/language-icons/Jest Snapshot.svg +1 -0
- package/src/language-icons/Jinja.svg +1 -0
- package/src/language-icons/Jsonnet.svg +1 -0
- package/src/language-icons/Julia.svg +1 -0
- package/src/language-icons/Jupyter Notebook.svg +1 -0
- package/src/language-icons/Kotlin.svg +1 -0
- package/src/language-icons/Kusto.svg +1 -0
- package/src/language-icons/LICENSE +395 -0
- package/src/language-icons/LOLCODE.svg +1 -0
- package/src/language-icons/LSL.svg +1 -0
- package/src/language-icons/Less.svg +1 -0
- package/src/language-icons/Lex.svg +1 -0
- package/src/language-icons/Liquid.svg +1 -0
- package/src/language-icons/LiveScript.svg +1 -0
- package/src/language-icons/Lua.svg +1 -0
- package/src/language-icons/MATLAB.svg +1 -0
- package/src/language-icons/MAXScript.svg +1 -0
- package/src/language-icons/Makefile.svg +1 -0
- package/src/language-icons/Markdown.svg +1 -0
- package/src/language-icons/Marko.svg +1 -0
- package/src/language-icons/Mathematica.svg +1 -0
- package/src/language-icons/Maven POM.svg +1 -0
- package/src/language-icons/Meson.svg +1 -0
- package/src/language-icons/Microsoft Visual Studio Solution.svg +1 -0
- package/src/language-icons/Mustache.svg +1 -0
- package/src/language-icons/NPM Config.svg +1 -0
- package/src/language-icons/NSIS.svg +1 -0
- package/src/language-icons/Nearley.svg +1 -0
- package/src/language-icons/NetLinx+ERB.svg +1 -0
- package/src/language-icons/Nginx.svg +1 -0
- package/src/language-icons/Nim.svg +1 -0
- package/src/language-icons/Ninja.svg +1 -0
- package/src/language-icons/Nix.svg +1 -0
- package/src/language-icons/NumPy.svg +1 -0
- package/src/language-icons/Nunjucks.svg +1 -0
- package/src/language-icons/OCaml.svg +1 -0
- package/src/language-icons/Objective-C++.svg +1 -0
- package/src/language-icons/Objective-C.svg +1 -0
- package/src/language-icons/OpenCL.svg +1 -0
- package/src/language-icons/OpenSCAD.svg +1 -0
- package/src/language-icons/Org.svg +1 -0
- package/src/language-icons/PHP.svg +1 -0
- package/src/language-icons/PLSQL.svg +1 -0
- package/src/language-icons/Pascal.svg +52 -0
- package/src/language-icons/Perl.svg +1 -0
- package/src/language-icons/PlantUML.svg +1 -0
- package/src/language-icons/Pony.svg +1 -0
- package/src/language-icons/PostCSS.svg +1 -0
- package/src/language-icons/PostScript.svg +1 -0
- package/src/language-icons/PowerShell.svg +1 -0
- package/src/language-icons/Prisma.svg +1 -0
- package/src/language-icons/Processing.svg +1 -0
- package/src/language-icons/Procfile.svg +1 -0
- package/src/language-icons/Prolog.svg +1 -0
- package/src/language-icons/Protocol Buffer.svg +1 -0
- package/src/language-icons/Pug.svg +1 -0
- package/src/language-icons/Puppet.svg +1 -0
- package/src/language-icons/PureScript.svg +1 -0
- package/src/language-icons/Python.svg +1 -0
- package/src/language-icons/Q#.svg +1 -0
- package/src/language-icons/QML.svg +1 -0
- package/src/language-icons/QMake.svg +1 -0
- package/src/language-icons/R.svg +1 -0
- package/src/language-icons/RAML.svg +1 -0
- package/src/language-icons/README.md +8 -0
- package/src/language-icons/REXX.svg +1 -0
- package/src/language-icons/RMarkdown.svg +1 -0
- package/src/language-icons/Racket.svg +1 -0
- package/src/language-icons/Raku.svg +1 -0
- package/src/language-icons/ReScript.svg +1 -0
- package/src/language-icons/Reason.svg +1 -0
- package/src/language-icons/Red.svg +1 -0
- package/src/language-icons/Riot.svg +1 -0
- package/src/language-icons/RobotFramework.svg +1 -0
- package/src/language-icons/Ruby.svg +1 -0
- package/src/language-icons/Rust.svg +1 -0
- package/src/language-icons/SAS.svg +1 -0
- package/src/language-icons/SCSS.svg +1 -0
- package/src/language-icons/SPARQL.svg +1 -0
- package/src/language-icons/SQF.svg +1 -0
- package/src/language-icons/SQL.svg +1 -0
- package/src/language-icons/SVG.svg +1 -0
- package/src/language-icons/SWIG.svg +1 -0
- package/src/language-icons/SaltStack.svg +1 -0
- package/src/language-icons/Sass.svg +1 -0
- package/src/language-icons/Scala.svg +1 -0
- package/src/language-icons/Scilab.svg +1 -0
- package/src/language-icons/ShaderLab.svg +1 -0
- package/src/language-icons/Shell.svg +1 -0
- package/src/language-icons/Slice.svg +1 -0
- package/src/language-icons/Slim.svg +1 -0
- package/src/language-icons/Smarty.svg +1 -0
- package/src/language-icons/Solidity.svg +1 -0
- package/src/language-icons/Squirrel.svg +1 -0
- package/src/language-icons/Stan.svg +1 -0
- package/src/language-icons/Stata.svg +1 -0
- package/src/language-icons/Stylus.svg +1 -0
- package/src/language-icons/SugarSS.svg +1 -0
- package/src/language-icons/Svelte.svg +1 -0
- package/src/language-icons/Swift.svg +1 -0
- package/src/language-icons/SystemVerilog.svg +1 -0
- package/src/language-icons/TOML.svg +1 -0
- package/src/language-icons/Tcl.svg +1 -0
- package/src/language-icons/TeX.svg +1 -0
- package/src/language-icons/Text.svg +1 -0
- package/src/language-icons/Textile.svg +1 -0
- package/src/language-icons/Twig.svg +1 -0
- package/src/language-icons/TypeScript.svg +1 -0
- package/src/language-icons/V.svg +1 -0
- package/src/language-icons/VBA.svg +1 -0
- package/src/language-icons/VBScript.svg +1 -0
- package/src/language-icons/VHDL.svg +1 -0
- package/src/language-icons/Vala.svg +1 -0
- package/src/language-icons/Velocity Template Language.svg +1 -0
- package/src/language-icons/Verilog.svg +1 -0
- package/src/language-icons/Vim script.svg +1 -0
- package/src/language-icons/Volt.svg +1 -0
- package/src/language-icons/Vue.svg +1 -0
- package/src/language-icons/WebAssembly.svg +1 -0
- package/src/language-icons/Wikitext.svg +1 -0
- package/src/language-icons/Windows Registry Entries.svg +1 -0
- package/src/language-icons/XML.svg +1 -0
- package/src/language-icons/XQuery.svg +1 -0
- package/src/language-icons/XSLT.svg +1 -0
- package/src/language-icons/YAML.svg +1 -0
- package/src/language-icons/YANG.svg +1 -0
- package/src/language-icons/Yacc.svg +1 -0
- package/src/language-icons/Zig.svg +1 -0
- package/src/language-icons/kvlang.svg +1 -0
- package/src/language-icons/q.svg +1 -0
- package/src/language-icons/reStructuredText.svg +1 -0
- package/src/language-icons/robots.txt.svg +1 -0
- package/src/language-icons/url.svg +1 -0
- package/tests/crowdin.test.js +247 -6
- package/tests/global-exposure.test.js +31 -0
- package/tests/load-script.test.js +22 -0
- package/tests/sleep.test.js +2 -2
package/tests/crowdin.test.js
CHANGED
|
@@ -17,10 +17,41 @@ jest.mock('../src/js/load-script', () => {
|
|
|
17
17
|
|
|
18
18
|
const initCrowdIn = require('../src/js/crowdin');
|
|
19
19
|
|
|
20
|
+
const delayedPickerMarkup = `
|
|
21
|
+
<div id="crowdin-language-picker" class="cr-position-bottom-left">
|
|
22
|
+
<div class="cr-picker-button"></div>
|
|
23
|
+
<div class="cr-picker-submenu"></div>
|
|
24
|
+
</div>
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
function expectDelayedStyling(options) {
|
|
28
|
+
globalThis.document.body.innerHTML = options.initialMarkup;
|
|
29
|
+
|
|
30
|
+
initCrowdIn('LizardByte', options.platform);
|
|
31
|
+
|
|
32
|
+
expect(() => {
|
|
33
|
+
jest.advanceTimersByTime(0);
|
|
34
|
+
}).not.toThrow();
|
|
35
|
+
|
|
36
|
+
globalThis.document.body.insertAdjacentHTML('beforeend', delayedPickerMarkup);
|
|
37
|
+
|
|
38
|
+
jest.advanceTimersByTime(50);
|
|
39
|
+
|
|
40
|
+
const container = document.getElementById('crowdin-language-picker');
|
|
41
|
+
const sidebar = document.getElementsByClassName(options.sidebarClass)[0];
|
|
42
|
+
|
|
43
|
+
expect(container.classList.contains('cr-position-bottom-left')).toBe(false);
|
|
44
|
+
expect(container.style.position).toBe(options.position);
|
|
45
|
+
if (options.pickerClass !== null) {
|
|
46
|
+
expect(container.classList.contains(options.pickerClass)).toBe(true);
|
|
47
|
+
}
|
|
48
|
+
expect(sidebar.contains(container)).toBe(true);
|
|
49
|
+
}
|
|
50
|
+
|
|
20
51
|
describe('initCrowdIn', () => {
|
|
21
52
|
beforeEach(() => {
|
|
22
53
|
// Mock DOM elements
|
|
23
|
-
|
|
54
|
+
globalThis.document.body.innerHTML = `
|
|
24
55
|
<div id="crowdin-language-picker">
|
|
25
56
|
<div class="cr-picker-button"></div>
|
|
26
57
|
<div class="cr-picker-submenu"></div>
|
|
@@ -29,24 +60,33 @@ describe('initCrowdIn', () => {
|
|
|
29
60
|
|
|
30
61
|
<!-- Sphinx sidebar -->
|
|
31
62
|
<div class="sidebar-sticky"></div>
|
|
63
|
+
|
|
64
|
+
<!-- rustdoc sidebar -->
|
|
65
|
+
<nav class="sidebar">
|
|
66
|
+
<div class="sidebar-elems"></div>
|
|
67
|
+
</nav>
|
|
32
68
|
`;
|
|
33
69
|
|
|
34
70
|
// Mock console.error
|
|
35
71
|
jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
36
72
|
|
|
37
73
|
// Mock window.proxyTranslator
|
|
38
|
-
|
|
74
|
+
globalThis.window.proxyTranslator = {
|
|
39
75
|
init: jest.fn()
|
|
40
76
|
};
|
|
41
77
|
|
|
42
78
|
// Use fake timers to control setTimeout
|
|
43
79
|
jest.useFakeTimers();
|
|
80
|
+
|
|
81
|
+
// Reset fetch interceptor flag so each test starts clean
|
|
82
|
+
delete globalThis._crowdinMirrorInstalled;
|
|
44
83
|
});
|
|
45
84
|
|
|
46
85
|
afterEach(() => {
|
|
47
86
|
jest.clearAllMocks();
|
|
48
87
|
jest.useRealTimers();
|
|
49
|
-
delete
|
|
88
|
+
delete globalThis.window.proxyTranslator;
|
|
89
|
+
delete globalThis._crowdinMirrorInstalled;
|
|
50
90
|
});
|
|
51
91
|
|
|
52
92
|
it('should validate project parameter', () => {
|
|
@@ -56,7 +96,7 @@ describe('initCrowdIn', () => {
|
|
|
56
96
|
|
|
57
97
|
it('should validate platform parameter', () => {
|
|
58
98
|
initCrowdIn('LizardByte', 'invalidPlatform');
|
|
59
|
-
expect(console.error).toHaveBeenCalledWith('Invalid UI. Must be "sphinx", or null');
|
|
99
|
+
expect(console.error).toHaveBeenCalledWith('Invalid UI. Must be "sphinx", "rustdoc", or null');
|
|
60
100
|
});
|
|
61
101
|
|
|
62
102
|
it('should initialize proxyTranslator with LizardByte settings', () => {
|
|
@@ -65,7 +105,7 @@ describe('initCrowdIn', () => {
|
|
|
65
105
|
// Simulate script loading
|
|
66
106
|
jest.runAllTimers();
|
|
67
107
|
|
|
68
|
-
expect(
|
|
108
|
+
expect(globalThis.proxyTranslator.init).toHaveBeenCalledWith(
|
|
69
109
|
expect.objectContaining({
|
|
70
110
|
baseUrl: "http://localhost",
|
|
71
111
|
distribution: "458f881791aebba1d4dde491bw4",
|
|
@@ -80,7 +120,7 @@ describe('initCrowdIn', () => {
|
|
|
80
120
|
// Simulate script loading
|
|
81
121
|
jest.runAllTimers();
|
|
82
122
|
|
|
83
|
-
expect(
|
|
123
|
+
expect(globalThis.proxyTranslator.init).toHaveBeenCalledWith(
|
|
84
124
|
expect.objectContaining({
|
|
85
125
|
baseUrl: "http://localhost",
|
|
86
126
|
distribution: "d6c830ba4b41106fefe5d391bw4",
|
|
@@ -113,4 +153,205 @@ describe('initCrowdIn', () => {
|
|
|
113
153
|
expect(container.style.position).toBe('relative');
|
|
114
154
|
expect(sidebar.contains(container)).toBe(true);
|
|
115
155
|
});
|
|
156
|
+
|
|
157
|
+
it('should apply rustdoc styling', () => {
|
|
158
|
+
initCrowdIn('LizardByte', 'rustdoc');
|
|
159
|
+
|
|
160
|
+
// Simulate script loading and UI styling timeout
|
|
161
|
+
jest.runAllTimers();
|
|
162
|
+
|
|
163
|
+
const container = document.getElementById('crowdin-language-picker');
|
|
164
|
+
const sidebar = document.getElementsByClassName('sidebar-elems')[0];
|
|
165
|
+
|
|
166
|
+
expect(container.classList.contains('cr-position-bottom-left')).toBe(false);
|
|
167
|
+
expect(container.classList.contains('rustdoc-crowdin-picker')).toBe(true);
|
|
168
|
+
expect(container.style.position).toBe('static');
|
|
169
|
+
expect(sidebar.contains(container)).toBe(true);
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should wait for sphinx language picker before applying styling', () => {
|
|
173
|
+
expectDelayedStyling({
|
|
174
|
+
initialMarkup: '<div class="sidebar-sticky"></div>',
|
|
175
|
+
pickerClass: null,
|
|
176
|
+
platform: 'sphinx',
|
|
177
|
+
position: 'relative',
|
|
178
|
+
sidebarClass: 'sidebar-sticky',
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('should wait for rustdoc language picker before applying styling', () => {
|
|
183
|
+
expectDelayedStyling({
|
|
184
|
+
initialMarkup: '<nav class="sidebar"><div class="sidebar-elems"></div></nav>',
|
|
185
|
+
pickerClass: 'rustdoc-crowdin-picker',
|
|
186
|
+
platform: 'rustdoc',
|
|
187
|
+
position: 'static',
|
|
188
|
+
sidebarClass: 'sidebar-elems',
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('should move rustdoc language picker to sidebar when sidebar-elems is unavailable', () => {
|
|
193
|
+
globalThis.document.body.innerHTML = `
|
|
194
|
+
<nav class="sidebar"></nav>
|
|
195
|
+
<div id="crowdin-language-picker" class="cr-position-bottom-left">
|
|
196
|
+
<div class="cr-picker-button"></div>
|
|
197
|
+
<div class="cr-picker-submenu"></div>
|
|
198
|
+
</div>
|
|
199
|
+
`;
|
|
200
|
+
|
|
201
|
+
initCrowdIn('LizardByte', 'rustdoc');
|
|
202
|
+
jest.runAllTimers();
|
|
203
|
+
|
|
204
|
+
const container = document.getElementById('crowdin-language-picker');
|
|
205
|
+
const sidebar = document.getElementsByClassName('sidebar')[0];
|
|
206
|
+
|
|
207
|
+
expect(container.classList.contains('rustdoc-crowdin-picker')).toBe(true);
|
|
208
|
+
expect(sidebar.contains(container)).toBe(true);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should stop retrying platform styling after the retry limit', () => {
|
|
212
|
+
globalThis.document.body.innerHTML = `
|
|
213
|
+
<nav class="sidebar">
|
|
214
|
+
<div class="sidebar-elems"></div>
|
|
215
|
+
</nav>
|
|
216
|
+
`;
|
|
217
|
+
|
|
218
|
+
initCrowdIn('LizardByte', 'rustdoc');
|
|
219
|
+
|
|
220
|
+
jest.advanceTimersByTime(0);
|
|
221
|
+
jest.advanceTimersByTime(5000);
|
|
222
|
+
|
|
223
|
+
expect(jest.getTimerCount()).toBe(0);
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
describe('Crowdin fetch interceptor', () => {
|
|
228
|
+
const CROWDIN_CDN = 'https://distributions.crowdin.net';
|
|
229
|
+
const MIRROR = 'https://cdn.jsdelivr.net/gh/LizardByte/i18n@dist';
|
|
230
|
+
|
|
231
|
+
beforeEach(() => {
|
|
232
|
+
// Reset interceptor state so each test gets a fresh install
|
|
233
|
+
delete globalThis._crowdinMirrorInstalled;
|
|
234
|
+
|
|
235
|
+
// Install a controllable mock fetch
|
|
236
|
+
globalThis.fetch = jest.fn().mockResolvedValue({ ok: true });
|
|
237
|
+
|
|
238
|
+
// Minimal DOM + proxyTranslator stub so initCrowdIn callback doesn't crash
|
|
239
|
+
globalThis.window.proxyTranslator = { init: jest.fn() };
|
|
240
|
+
globalThis.document.body.innerHTML = '';
|
|
241
|
+
|
|
242
|
+
jest.useFakeTimers();
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
afterEach(() => {
|
|
246
|
+
jest.clearAllMocks();
|
|
247
|
+
jest.useRealTimers();
|
|
248
|
+
delete globalThis._crowdinMirrorInstalled;
|
|
249
|
+
delete globalThis.window.proxyTranslator;
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('should redirect Crowdin CDN fetch calls to the GitHub Pages mirror', async () => {
|
|
253
|
+
// Save mock before initCrowdIn wraps globalThis.fetch
|
|
254
|
+
const mockFetch = globalThis.fetch;
|
|
255
|
+
|
|
256
|
+
initCrowdIn();
|
|
257
|
+
jest.runAllTimers();
|
|
258
|
+
|
|
259
|
+
const testUrl = `${CROWDIN_CDN}/458f881791aebba1d4dde491bw4/manifest.json`;
|
|
260
|
+
await globalThis.fetch(testUrl);
|
|
261
|
+
|
|
262
|
+
// The wrapper should have called the underlying mock with the mirrored URL.
|
|
263
|
+
// The interceptor uses URL parsing, so the path is taken from parsed.pathname.
|
|
264
|
+
expect(mockFetch).toHaveBeenCalled();
|
|
265
|
+
const calledUrl = mockFetch.mock.calls[0][0];
|
|
266
|
+
expect(calledUrl).toBe(`${MIRROR}/458f881791aebba1d4dde491bw4/manifest.json`);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it('should preserve query string when redirecting', async () => {
|
|
270
|
+
const mockFetch = globalThis.fetch;
|
|
271
|
+
|
|
272
|
+
initCrowdIn();
|
|
273
|
+
jest.runAllTimers();
|
|
274
|
+
|
|
275
|
+
const testUrl = `${CROWDIN_CDN}/458f881791aebba1d4dde491bw4/languages.json?timestamp=1234`;
|
|
276
|
+
await globalThis.fetch(testUrl);
|
|
277
|
+
|
|
278
|
+
const calledUrl = mockFetch.mock.calls[0][0];
|
|
279
|
+
expect(calledUrl).toBe(`${MIRROR}/458f881791aebba1d4dde491bw4/languages.json?timestamp=1234`);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
it('should not redirect non-Crowdin fetch calls', async () => {
|
|
283
|
+
const mockFetch = globalThis.fetch;
|
|
284
|
+
|
|
285
|
+
initCrowdIn();
|
|
286
|
+
jest.runAllTimers();
|
|
287
|
+
|
|
288
|
+
const externalUrl = 'https://example.com/data.json';
|
|
289
|
+
await globalThis.fetch(externalUrl);
|
|
290
|
+
|
|
291
|
+
const calledUrl = mockFetch.mock.calls[0][0];
|
|
292
|
+
expect(calledUrl).toBe(externalUrl);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
it('should not redirect a lookalike hostname (incomplete-URL-sanitisation guard)', async () => {
|
|
296
|
+
// A URL whose hostname merely starts with the CDN hostname must NOT be
|
|
297
|
+
// redirected – this is the exact bypass that CodeQL flags when using
|
|
298
|
+
// startsWith() instead of exact hostname comparison.
|
|
299
|
+
const mockFetch = globalThis.fetch;
|
|
300
|
+
|
|
301
|
+
initCrowdIn();
|
|
302
|
+
jest.runAllTimers();
|
|
303
|
+
|
|
304
|
+
const lookalike = 'https://distributions.crowdin.net.evil.com/steal';
|
|
305
|
+
await globalThis.fetch(lookalike);
|
|
306
|
+
|
|
307
|
+
const calledUrl = mockFetch.mock.calls[0][0];
|
|
308
|
+
expect(calledUrl).toBe(lookalike);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
it('should install the interceptor only once (idempotent)', () => {
|
|
312
|
+
initCrowdIn();
|
|
313
|
+
const fetchAfterFirst = globalThis.fetch;
|
|
314
|
+
jest.runAllTimers();
|
|
315
|
+
|
|
316
|
+
// Calling initCrowdIn again must NOT wrap fetch a second time
|
|
317
|
+
initCrowdIn();
|
|
318
|
+
jest.runAllTimers();
|
|
319
|
+
|
|
320
|
+
expect(globalThis.fetch).toBe(fetchAfterFirst);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it('should continue when fetch is unavailable', () => {
|
|
324
|
+
delete globalThis.fetch;
|
|
325
|
+
|
|
326
|
+
initCrowdIn();
|
|
327
|
+
jest.runAllTimers();
|
|
328
|
+
|
|
329
|
+
expect(globalThis.proxyTranslator.init).toHaveBeenCalled();
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('should pass non-string fetch inputs through unchanged', async () => {
|
|
333
|
+
const mockFetch = globalThis.fetch;
|
|
334
|
+
const requestLike = new URL('https://example.com/data.json');
|
|
335
|
+
|
|
336
|
+
initCrowdIn();
|
|
337
|
+
jest.runAllTimers();
|
|
338
|
+
|
|
339
|
+
await globalThis.fetch(requestLike);
|
|
340
|
+
|
|
341
|
+
const calledUrl = mockFetch.mock.calls[0][0];
|
|
342
|
+
expect(calledUrl).toBe(requestLike);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('should pass invalid URL strings through unchanged', async () => {
|
|
346
|
+
const mockFetch = globalThis.fetch;
|
|
347
|
+
const invalidUrl = 'not a valid absolute URL';
|
|
348
|
+
|
|
349
|
+
initCrowdIn();
|
|
350
|
+
jest.runAllTimers();
|
|
351
|
+
|
|
352
|
+
await globalThis.fetch(invalidUrl);
|
|
353
|
+
|
|
354
|
+
const calledUrl = mockFetch.mock.calls[0][0];
|
|
355
|
+
expect(calledUrl).toBe(invalidUrl);
|
|
356
|
+
});
|
|
116
357
|
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @jest-environment node
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
describe,
|
|
7
|
+
expect,
|
|
8
|
+
it,
|
|
9
|
+
jest,
|
|
10
|
+
} from '@jest/globals';
|
|
11
|
+
|
|
12
|
+
const exposedModules = [
|
|
13
|
+
['formatNumber', '../src/js/format-number'],
|
|
14
|
+
['initCrowdIn', '../src/js/crowdin'],
|
|
15
|
+
['levenshteinDistance', '../src/js/levenshtein-distance'],
|
|
16
|
+
['loadScript', '../src/js/load-script'],
|
|
17
|
+
['rankingSorter', '../src/js/ranking-sorter'],
|
|
18
|
+
['sleep', '../src/js/sleep'],
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
describe('global browser exposure', () => {
|
|
22
|
+
it.each(exposedModules)('should not expose %s when window is unavailable', (globalName, modulePath) => {
|
|
23
|
+
jest.resetModules();
|
|
24
|
+
|
|
25
|
+
const moduleExport = require(modulePath);
|
|
26
|
+
|
|
27
|
+
expect(globalThis.window).toBeUndefined();
|
|
28
|
+
expect(moduleExport).toBeDefined();
|
|
29
|
+
expect(globalThis[globalName]).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -45,4 +45,26 @@ describe('loadScript', () => {
|
|
|
45
45
|
expect(script).toBeInstanceOf(HTMLScriptElement);
|
|
46
46
|
expect(script.src).toBe(url);
|
|
47
47
|
});
|
|
48
|
+
|
|
49
|
+
it('should handle load without a callback', () => {
|
|
50
|
+
const url = 'https://example.com/test-script.js';
|
|
51
|
+
loadScript(url);
|
|
52
|
+
|
|
53
|
+
const script = document.head.querySelector('script');
|
|
54
|
+
|
|
55
|
+
expect(() => {
|
|
56
|
+
script.onload();
|
|
57
|
+
}).not.toThrow();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should handle failure without a callback', () => {
|
|
61
|
+
const url = 'https://example.com/test-script.js';
|
|
62
|
+
loadScript(url);
|
|
63
|
+
|
|
64
|
+
const script = document.head.querySelector('script');
|
|
65
|
+
|
|
66
|
+
expect(() => {
|
|
67
|
+
script.onerror();
|
|
68
|
+
}).not.toThrow();
|
|
69
|
+
});
|
|
48
70
|
});
|
package/tests/sleep.test.js
CHANGED
|
@@ -16,7 +16,7 @@ describe('sleep function', () => {
|
|
|
16
16
|
})
|
|
17
17
|
|
|
18
18
|
beforeEach(() => {
|
|
19
|
-
jest.spyOn(
|
|
19
|
+
jest.spyOn(globalThis, 'setTimeout');
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
test.each([
|
|
@@ -26,7 +26,7 @@ describe('sleep function', () => {
|
|
|
26
26
|
[2000], // 2 seconds
|
|
27
27
|
[60000], // 60 seconds
|
|
28
28
|
])('resolves after %i milliseconds', async (delay) => {
|
|
29
|
-
|
|
29
|
+
const delay_value = delay;
|
|
30
30
|
const sleepPromise = sleep(delay_value);
|
|
31
31
|
jest.advanceTimersByTime(delay_value);
|
|
32
32
|
await sleepPromise;
|