@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.
Files changed (489) hide show
  1. package/README.md +36 -8
  2. package/dist/crowdin-rustdoc-css.css +3 -0
  3. package/dist/crowdin-rustdoc-css.css.map +1 -0
  4. package/dist/crowdin-rustdoc-css.js +0 -0
  5. package/dist/crowdin.js +1 -1
  6. package/dist/crowdin.js.map +1 -1
  7. package/dist/format-number.js +1 -1
  8. package/dist/format-number.js.map +1 -1
  9. package/dist/language-icons/AL.svg +1 -0
  10. package/dist/language-icons/ANTLR.svg +1 -0
  11. package/dist/language-icons/API Blueprint.svg +1 -0
  12. package/dist/language-icons/APL.svg +1 -0
  13. package/dist/language-icons/ASP.NET.svg +1 -0
  14. package/dist/language-icons/ATS.svg +1 -0
  15. package/dist/language-icons/ActionScript.svg +1 -0
  16. package/dist/language-icons/Ada.svg +1 -0
  17. package/dist/language-icons/ApacheConf.svg +1 -0
  18. package/dist/language-icons/Apex.svg +1 -0
  19. package/dist/language-icons/AppleScript.svg +1 -0
  20. package/dist/language-icons/Assembly.svg +1 -0
  21. package/dist/language-icons/Astro.svg +1 -0
  22. package/dist/language-icons/AutoHotkey.svg +1 -0
  23. package/dist/language-icons/AutoIt.svg +1 -0
  24. package/dist/language-icons/Avro IDL.svg +1 -0
  25. package/dist/language-icons/Awk.svg +1 -0
  26. package/dist/language-icons/Ballerina.svg +1 -0
  27. package/dist/language-icons/Batchfile.svg +1 -0
  28. package/dist/language-icons/Befunge.svg +1 -0
  29. package/dist/language-icons/Bicep.svg +1 -0
  30. package/dist/language-icons/Blade.svg +1 -0
  31. package/dist/language-icons/BlitzBasic.svg +1 -0
  32. package/dist/language-icons/Browserslist.svg +1 -0
  33. package/dist/language-icons/C#.svg +1 -0
  34. package/dist/language-icons/C++.svg +1 -0
  35. package/dist/language-icons/C.svg +1 -0
  36. package/dist/language-icons/CMake.svg +1 -0
  37. package/dist/language-icons/COBOL.svg +1 -0
  38. package/dist/language-icons/CSS.svg +1 -0
  39. package/dist/language-icons/Cabal Config.svg +1 -0
  40. package/dist/language-icons/Carbon.svg +63 -0
  41. package/dist/language-icons/Ceylon.svg +1 -0
  42. package/dist/language-icons/Clojure.svg +1 -0
  43. package/dist/language-icons/Cloud Firestore Security Rules.svg +1 -0
  44. package/dist/language-icons/CodeQL.svg +1 -0
  45. package/dist/language-icons/CoffeeScript.svg +1 -0
  46. package/dist/language-icons/ColdFusion CFC.svg +1 -0
  47. package/dist/language-icons/ColdFusion.svg +1 -0
  48. package/dist/language-icons/Crystal.svg +1 -0
  49. package/dist/language-icons/Cuda.svg +1 -0
  50. package/dist/language-icons/Cython.svg +1 -0
  51. package/dist/language-icons/D.svg +1 -0
  52. package/dist/language-icons/Darcs Patch.svg +1 -0
  53. package/dist/language-icons/Dart.svg +1 -0
  54. package/dist/language-icons/Diff.svg +1 -0
  55. package/dist/language-icons/Dockerfile.svg +1 -0
  56. package/dist/language-icons/Dylan.svg +1 -0
  57. package/dist/language-icons/EJS.svg +1 -0
  58. package/dist/language-icons/EditorConfig.svg +1 -0
  59. package/dist/language-icons/Elixir.svg +1 -0
  60. package/dist/language-icons/Elm.svg +1 -0
  61. package/dist/language-icons/Emacs Lisp.svg +1 -0
  62. package/dist/language-icons/EmberScript.svg +1 -0
  63. package/dist/language-icons/Erlang.svg +1 -0
  64. package/dist/language-icons/F#.svg +1 -0
  65. package/dist/language-icons/Fortran.svg +1 -0
  66. package/dist/language-icons/FreeMarker.svg +1 -0
  67. package/dist/language-icons/G-code.svg +1 -0
  68. package/dist/language-icons/GLSL.svg +1 -0
  69. package/dist/language-icons/Game Maker Language.svg +1 -0
  70. package/dist/language-icons/Gherkin.svg +1 -0
  71. package/dist/language-icons/Git Attributes.svg +1 -0
  72. package/dist/language-icons/Git Config.svg +1 -0
  73. package/dist/language-icons/Glyph.svg +1 -0
  74. package/dist/language-icons/Gnuplot.svg +1 -0
  75. package/dist/language-icons/Go Checksums.svg +1 -0
  76. package/dist/language-icons/Go Module.svg +1 -0
  77. package/dist/language-icons/Go.svg +1 -0
  78. package/dist/language-icons/Gradle.svg +1 -0
  79. package/dist/language-icons/GraphQL.svg +1 -0
  80. package/dist/language-icons/Graphviz (DOT).svg +1 -0
  81. package/dist/language-icons/Groovy.svg +1 -0
  82. package/dist/language-icons/HLSL.svg +1 -0
  83. package/dist/language-icons/HTML+EEX.svg +1 -0
  84. package/dist/language-icons/HTML+ERB.svg +1 -0
  85. package/dist/language-icons/HTML+Razor.svg +1 -0
  86. package/dist/language-icons/HTML.svg +1 -0
  87. package/dist/language-icons/HTTP.svg +1 -0
  88. package/dist/language-icons/Haml.svg +1 -0
  89. package/dist/language-icons/Handlebars.svg +1 -0
  90. package/dist/language-icons/Harbour.svg +1 -0
  91. package/dist/language-icons/Haskell.svg +1 -0
  92. package/dist/language-icons/Haxe.svg +1 -0
  93. package/dist/language-icons/Hy.svg +1 -0
  94. package/dist/language-icons/INI.svg +1 -0
  95. package/dist/language-icons/Idris.svg +1 -0
  96. package/dist/language-icons/Inno Setup.svg +1 -0
  97. package/dist/language-icons/Io.svg +1 -0
  98. package/dist/language-icons/JSON.svg +1 -0
  99. package/dist/language-icons/JSON5.svg +1 -0
  100. package/dist/language-icons/JSONLD.svg +1 -0
  101. package/dist/language-icons/Janet.svg +1 -0
  102. package/dist/language-icons/Jasmin.svg +1 -0
  103. package/dist/language-icons/Java.svg +1 -0
  104. package/dist/language-icons/JavaScript+ERB.svg +1 -0
  105. package/dist/language-icons/JavaScript.svg +1 -0
  106. package/dist/language-icons/Jest Snapshot.svg +1 -0
  107. package/dist/language-icons/Jinja.svg +1 -0
  108. package/dist/language-icons/Jsonnet.svg +1 -0
  109. package/dist/language-icons/Julia.svg +1 -0
  110. package/dist/language-icons/Jupyter Notebook.svg +1 -0
  111. package/dist/language-icons/Kotlin.svg +1 -0
  112. package/dist/language-icons/Kusto.svg +1 -0
  113. package/dist/language-icons/LICENSE +395 -0
  114. package/dist/language-icons/LOLCODE.svg +1 -0
  115. package/dist/language-icons/LSL.svg +1 -0
  116. package/dist/language-icons/Less.svg +1 -0
  117. package/dist/language-icons/Lex.svg +1 -0
  118. package/dist/language-icons/Liquid.svg +1 -0
  119. package/dist/language-icons/LiveScript.svg +1 -0
  120. package/dist/language-icons/Lua.svg +1 -0
  121. package/dist/language-icons/MATLAB.svg +1 -0
  122. package/dist/language-icons/MAXScript.svg +1 -0
  123. package/dist/language-icons/Makefile.svg +1 -0
  124. package/dist/language-icons/Markdown.svg +1 -0
  125. package/dist/language-icons/Marko.svg +1 -0
  126. package/dist/language-icons/Mathematica.svg +1 -0
  127. package/dist/language-icons/Maven POM.svg +1 -0
  128. package/dist/language-icons/Meson.svg +1 -0
  129. package/dist/language-icons/Microsoft Visual Studio Solution.svg +1 -0
  130. package/dist/language-icons/Mustache.svg +1 -0
  131. package/dist/language-icons/NPM Config.svg +1 -0
  132. package/dist/language-icons/NSIS.svg +1 -0
  133. package/dist/language-icons/Nearley.svg +1 -0
  134. package/dist/language-icons/NetLinx+ERB.svg +1 -0
  135. package/dist/language-icons/Nginx.svg +1 -0
  136. package/dist/language-icons/Nim.svg +1 -0
  137. package/dist/language-icons/Ninja.svg +1 -0
  138. package/dist/language-icons/Nix.svg +1 -0
  139. package/dist/language-icons/NumPy.svg +1 -0
  140. package/dist/language-icons/Nunjucks.svg +1 -0
  141. package/dist/language-icons/OCaml.svg +1 -0
  142. package/dist/language-icons/Objective-C++.svg +1 -0
  143. package/dist/language-icons/Objective-C.svg +1 -0
  144. package/dist/language-icons/OpenCL.svg +1 -0
  145. package/dist/language-icons/OpenSCAD.svg +1 -0
  146. package/dist/language-icons/Org.svg +1 -0
  147. package/dist/language-icons/PHP.svg +1 -0
  148. package/dist/language-icons/PLSQL.svg +1 -0
  149. package/dist/language-icons/Pascal.svg +52 -0
  150. package/dist/language-icons/Perl.svg +1 -0
  151. package/dist/language-icons/PlantUML.svg +1 -0
  152. package/dist/language-icons/Pony.svg +1 -0
  153. package/dist/language-icons/PostCSS.svg +1 -0
  154. package/dist/language-icons/PostScript.svg +1 -0
  155. package/dist/language-icons/PowerShell.svg +1 -0
  156. package/dist/language-icons/Prisma.svg +1 -0
  157. package/dist/language-icons/Processing.svg +1 -0
  158. package/dist/language-icons/Procfile.svg +1 -0
  159. package/dist/language-icons/Prolog.svg +1 -0
  160. package/dist/language-icons/Protocol Buffer.svg +1 -0
  161. package/dist/language-icons/Pug.svg +1 -0
  162. package/dist/language-icons/Puppet.svg +1 -0
  163. package/dist/language-icons/PureScript.svg +1 -0
  164. package/dist/language-icons/Python.svg +1 -0
  165. package/dist/language-icons/Q#.svg +1 -0
  166. package/dist/language-icons/QML.svg +1 -0
  167. package/dist/language-icons/QMake.svg +1 -0
  168. package/dist/language-icons/R.svg +1 -0
  169. package/dist/language-icons/RAML.svg +1 -0
  170. package/dist/language-icons/README.md +8 -0
  171. package/dist/language-icons/REXX.svg +1 -0
  172. package/dist/language-icons/RMarkdown.svg +1 -0
  173. package/dist/language-icons/Racket.svg +1 -0
  174. package/dist/language-icons/Raku.svg +1 -0
  175. package/dist/language-icons/ReScript.svg +1 -0
  176. package/dist/language-icons/Reason.svg +1 -0
  177. package/dist/language-icons/Red.svg +1 -0
  178. package/dist/language-icons/Riot.svg +1 -0
  179. package/dist/language-icons/RobotFramework.svg +1 -0
  180. package/dist/language-icons/Ruby.svg +1 -0
  181. package/dist/language-icons/Rust.svg +1 -0
  182. package/dist/language-icons/SAS.svg +1 -0
  183. package/dist/language-icons/SCSS.svg +1 -0
  184. package/dist/language-icons/SPARQL.svg +1 -0
  185. package/dist/language-icons/SQF.svg +1 -0
  186. package/dist/language-icons/SQL.svg +1 -0
  187. package/dist/language-icons/SVG.svg +1 -0
  188. package/dist/language-icons/SWIG.svg +1 -0
  189. package/dist/language-icons/SaltStack.svg +1 -0
  190. package/dist/language-icons/Sass.svg +1 -0
  191. package/dist/language-icons/Scala.svg +1 -0
  192. package/dist/language-icons/Scilab.svg +1 -0
  193. package/dist/language-icons/ShaderLab.svg +1 -0
  194. package/dist/language-icons/Shell.svg +1 -0
  195. package/dist/language-icons/Slice.svg +1 -0
  196. package/dist/language-icons/Slim.svg +1 -0
  197. package/dist/language-icons/Smarty.svg +1 -0
  198. package/dist/language-icons/Solidity.svg +1 -0
  199. package/dist/language-icons/Squirrel.svg +1 -0
  200. package/dist/language-icons/Stan.svg +1 -0
  201. package/dist/language-icons/Stata.svg +1 -0
  202. package/dist/language-icons/Stylus.svg +1 -0
  203. package/dist/language-icons/SugarSS.svg +1 -0
  204. package/dist/language-icons/Svelte.svg +1 -0
  205. package/dist/language-icons/Swift.svg +1 -0
  206. package/dist/language-icons/SystemVerilog.svg +1 -0
  207. package/dist/language-icons/TOML.svg +1 -0
  208. package/dist/language-icons/Tcl.svg +1 -0
  209. package/dist/language-icons/TeX.svg +1 -0
  210. package/dist/language-icons/Text.svg +1 -0
  211. package/dist/language-icons/Textile.svg +1 -0
  212. package/dist/language-icons/Twig.svg +1 -0
  213. package/dist/language-icons/TypeScript.svg +1 -0
  214. package/dist/language-icons/V.svg +1 -0
  215. package/dist/language-icons/VBA.svg +1 -0
  216. package/dist/language-icons/VBScript.svg +1 -0
  217. package/dist/language-icons/VHDL.svg +1 -0
  218. package/dist/language-icons/Vala.svg +1 -0
  219. package/dist/language-icons/Velocity Template Language.svg +1 -0
  220. package/dist/language-icons/Verilog.svg +1 -0
  221. package/dist/language-icons/Vim script.svg +1 -0
  222. package/dist/language-icons/Volt.svg +1 -0
  223. package/dist/language-icons/Vue.svg +1 -0
  224. package/dist/language-icons/WebAssembly.svg +1 -0
  225. package/dist/language-icons/Wikitext.svg +1 -0
  226. package/dist/language-icons/Windows Registry Entries.svg +1 -0
  227. package/dist/language-icons/XML.svg +1 -0
  228. package/dist/language-icons/XQuery.svg +1 -0
  229. package/dist/language-icons/XSLT.svg +1 -0
  230. package/dist/language-icons/YAML.svg +1 -0
  231. package/dist/language-icons/YANG.svg +1 -0
  232. package/dist/language-icons/Yacc.svg +1 -0
  233. package/dist/language-icons/Zig.svg +1 -0
  234. package/dist/language-icons/kvlang.svg +1 -0
  235. package/dist/language-icons/q.svg +1 -0
  236. package/dist/language-icons/reStructuredText.svg +1 -0
  237. package/dist/language-icons/robots.txt.svg +1 -0
  238. package/dist/language-icons/url.svg +1 -0
  239. package/dist/levenshtein-distance.js +1 -1
  240. package/dist/levenshtein-distance.js.map +1 -1
  241. package/dist/load-script.js +1 -1
  242. package/dist/load-script.js.map +1 -1
  243. package/dist/ranking-sorter.js +1 -1
  244. package/dist/ranking-sorter.js.map +1 -1
  245. package/dist/sleep.js +1 -1
  246. package/dist/sleep.js.map +1 -1
  247. package/package.json +33 -25
  248. package/src/css/crowdin-rustdoc.scss +30 -0
  249. package/src/js/crowdin-rustdoc-css.js +1 -0
  250. package/src/js/crowdin.js +116 -20
  251. package/src/js/format-number.js +2 -2
  252. package/src/js/levenshtein-distance.js +2 -2
  253. package/src/js/load-script.js +2 -2
  254. package/src/js/ranking-sorter.js +8 -11
  255. package/src/js/sleep.js +2 -2
  256. package/src/language-icons/AL.svg +1 -0
  257. package/src/language-icons/ANTLR.svg +1 -0
  258. package/src/language-icons/API Blueprint.svg +1 -0
  259. package/src/language-icons/APL.svg +1 -0
  260. package/src/language-icons/ASP.NET.svg +1 -0
  261. package/src/language-icons/ATS.svg +1 -0
  262. package/src/language-icons/ActionScript.svg +1 -0
  263. package/src/language-icons/Ada.svg +1 -0
  264. package/src/language-icons/ApacheConf.svg +1 -0
  265. package/src/language-icons/Apex.svg +1 -0
  266. package/src/language-icons/AppleScript.svg +1 -0
  267. package/src/language-icons/Assembly.svg +1 -0
  268. package/src/language-icons/Astro.svg +1 -0
  269. package/src/language-icons/AutoHotkey.svg +1 -0
  270. package/src/language-icons/AutoIt.svg +1 -0
  271. package/src/language-icons/Avro IDL.svg +1 -0
  272. package/src/language-icons/Awk.svg +1 -0
  273. package/src/language-icons/Ballerina.svg +1 -0
  274. package/src/language-icons/Batchfile.svg +1 -0
  275. package/src/language-icons/Befunge.svg +1 -0
  276. package/src/language-icons/Bicep.svg +1 -0
  277. package/src/language-icons/Blade.svg +1 -0
  278. package/src/language-icons/BlitzBasic.svg +1 -0
  279. package/src/language-icons/Browserslist.svg +1 -0
  280. package/src/language-icons/C#.svg +1 -0
  281. package/src/language-icons/C++.svg +1 -0
  282. package/src/language-icons/C.svg +1 -0
  283. package/src/language-icons/CMake.svg +1 -0
  284. package/src/language-icons/COBOL.svg +1 -0
  285. package/src/language-icons/CSS.svg +1 -0
  286. package/src/language-icons/Cabal Config.svg +1 -0
  287. package/src/language-icons/Carbon.svg +63 -0
  288. package/src/language-icons/Ceylon.svg +1 -0
  289. package/src/language-icons/Clojure.svg +1 -0
  290. package/src/language-icons/Cloud Firestore Security Rules.svg +1 -0
  291. package/src/language-icons/CodeQL.svg +1 -0
  292. package/src/language-icons/CoffeeScript.svg +1 -0
  293. package/src/language-icons/ColdFusion CFC.svg +1 -0
  294. package/src/language-icons/ColdFusion.svg +1 -0
  295. package/src/language-icons/Crystal.svg +1 -0
  296. package/src/language-icons/Cuda.svg +1 -0
  297. package/src/language-icons/Cython.svg +1 -0
  298. package/src/language-icons/D.svg +1 -0
  299. package/src/language-icons/Darcs Patch.svg +1 -0
  300. package/src/language-icons/Dart.svg +1 -0
  301. package/src/language-icons/Diff.svg +1 -0
  302. package/src/language-icons/Dockerfile.svg +1 -0
  303. package/src/language-icons/Dylan.svg +1 -0
  304. package/src/language-icons/EJS.svg +1 -0
  305. package/src/language-icons/EditorConfig.svg +1 -0
  306. package/src/language-icons/Elixir.svg +1 -0
  307. package/src/language-icons/Elm.svg +1 -0
  308. package/src/language-icons/Emacs Lisp.svg +1 -0
  309. package/src/language-icons/EmberScript.svg +1 -0
  310. package/src/language-icons/Erlang.svg +1 -0
  311. package/src/language-icons/F#.svg +1 -0
  312. package/src/language-icons/Fortran.svg +1 -0
  313. package/src/language-icons/FreeMarker.svg +1 -0
  314. package/src/language-icons/G-code.svg +1 -0
  315. package/src/language-icons/GLSL.svg +1 -0
  316. package/src/language-icons/Game Maker Language.svg +1 -0
  317. package/src/language-icons/Gherkin.svg +1 -0
  318. package/src/language-icons/Git Attributes.svg +1 -0
  319. package/src/language-icons/Git Config.svg +1 -0
  320. package/src/language-icons/Glyph.svg +1 -0
  321. package/src/language-icons/Gnuplot.svg +1 -0
  322. package/src/language-icons/Go Checksums.svg +1 -0
  323. package/src/language-icons/Go Module.svg +1 -0
  324. package/src/language-icons/Go.svg +1 -0
  325. package/src/language-icons/Gradle.svg +1 -0
  326. package/src/language-icons/GraphQL.svg +1 -0
  327. package/src/language-icons/Graphviz (DOT).svg +1 -0
  328. package/src/language-icons/Groovy.svg +1 -0
  329. package/src/language-icons/HLSL.svg +1 -0
  330. package/src/language-icons/HTML+EEX.svg +1 -0
  331. package/src/language-icons/HTML+ERB.svg +1 -0
  332. package/src/language-icons/HTML+Razor.svg +1 -0
  333. package/src/language-icons/HTML.svg +1 -0
  334. package/src/language-icons/HTTP.svg +1 -0
  335. package/src/language-icons/Haml.svg +1 -0
  336. package/src/language-icons/Handlebars.svg +1 -0
  337. package/src/language-icons/Harbour.svg +1 -0
  338. package/src/language-icons/Haskell.svg +1 -0
  339. package/src/language-icons/Haxe.svg +1 -0
  340. package/src/language-icons/Hy.svg +1 -0
  341. package/src/language-icons/INI.svg +1 -0
  342. package/src/language-icons/Idris.svg +1 -0
  343. package/src/language-icons/Inno Setup.svg +1 -0
  344. package/src/language-icons/Io.svg +1 -0
  345. package/src/language-icons/JSON.svg +1 -0
  346. package/src/language-icons/JSON5.svg +1 -0
  347. package/src/language-icons/JSONLD.svg +1 -0
  348. package/src/language-icons/Janet.svg +1 -0
  349. package/src/language-icons/Jasmin.svg +1 -0
  350. package/src/language-icons/Java.svg +1 -0
  351. package/src/language-icons/JavaScript+ERB.svg +1 -0
  352. package/src/language-icons/JavaScript.svg +1 -0
  353. package/src/language-icons/Jest Snapshot.svg +1 -0
  354. package/src/language-icons/Jinja.svg +1 -0
  355. package/src/language-icons/Jsonnet.svg +1 -0
  356. package/src/language-icons/Julia.svg +1 -0
  357. package/src/language-icons/Jupyter Notebook.svg +1 -0
  358. package/src/language-icons/Kotlin.svg +1 -0
  359. package/src/language-icons/Kusto.svg +1 -0
  360. package/src/language-icons/LICENSE +395 -0
  361. package/src/language-icons/LOLCODE.svg +1 -0
  362. package/src/language-icons/LSL.svg +1 -0
  363. package/src/language-icons/Less.svg +1 -0
  364. package/src/language-icons/Lex.svg +1 -0
  365. package/src/language-icons/Liquid.svg +1 -0
  366. package/src/language-icons/LiveScript.svg +1 -0
  367. package/src/language-icons/Lua.svg +1 -0
  368. package/src/language-icons/MATLAB.svg +1 -0
  369. package/src/language-icons/MAXScript.svg +1 -0
  370. package/src/language-icons/Makefile.svg +1 -0
  371. package/src/language-icons/Markdown.svg +1 -0
  372. package/src/language-icons/Marko.svg +1 -0
  373. package/src/language-icons/Mathematica.svg +1 -0
  374. package/src/language-icons/Maven POM.svg +1 -0
  375. package/src/language-icons/Meson.svg +1 -0
  376. package/src/language-icons/Microsoft Visual Studio Solution.svg +1 -0
  377. package/src/language-icons/Mustache.svg +1 -0
  378. package/src/language-icons/NPM Config.svg +1 -0
  379. package/src/language-icons/NSIS.svg +1 -0
  380. package/src/language-icons/Nearley.svg +1 -0
  381. package/src/language-icons/NetLinx+ERB.svg +1 -0
  382. package/src/language-icons/Nginx.svg +1 -0
  383. package/src/language-icons/Nim.svg +1 -0
  384. package/src/language-icons/Ninja.svg +1 -0
  385. package/src/language-icons/Nix.svg +1 -0
  386. package/src/language-icons/NumPy.svg +1 -0
  387. package/src/language-icons/Nunjucks.svg +1 -0
  388. package/src/language-icons/OCaml.svg +1 -0
  389. package/src/language-icons/Objective-C++.svg +1 -0
  390. package/src/language-icons/Objective-C.svg +1 -0
  391. package/src/language-icons/OpenCL.svg +1 -0
  392. package/src/language-icons/OpenSCAD.svg +1 -0
  393. package/src/language-icons/Org.svg +1 -0
  394. package/src/language-icons/PHP.svg +1 -0
  395. package/src/language-icons/PLSQL.svg +1 -0
  396. package/src/language-icons/Pascal.svg +52 -0
  397. package/src/language-icons/Perl.svg +1 -0
  398. package/src/language-icons/PlantUML.svg +1 -0
  399. package/src/language-icons/Pony.svg +1 -0
  400. package/src/language-icons/PostCSS.svg +1 -0
  401. package/src/language-icons/PostScript.svg +1 -0
  402. package/src/language-icons/PowerShell.svg +1 -0
  403. package/src/language-icons/Prisma.svg +1 -0
  404. package/src/language-icons/Processing.svg +1 -0
  405. package/src/language-icons/Procfile.svg +1 -0
  406. package/src/language-icons/Prolog.svg +1 -0
  407. package/src/language-icons/Protocol Buffer.svg +1 -0
  408. package/src/language-icons/Pug.svg +1 -0
  409. package/src/language-icons/Puppet.svg +1 -0
  410. package/src/language-icons/PureScript.svg +1 -0
  411. package/src/language-icons/Python.svg +1 -0
  412. package/src/language-icons/Q#.svg +1 -0
  413. package/src/language-icons/QML.svg +1 -0
  414. package/src/language-icons/QMake.svg +1 -0
  415. package/src/language-icons/R.svg +1 -0
  416. package/src/language-icons/RAML.svg +1 -0
  417. package/src/language-icons/README.md +8 -0
  418. package/src/language-icons/REXX.svg +1 -0
  419. package/src/language-icons/RMarkdown.svg +1 -0
  420. package/src/language-icons/Racket.svg +1 -0
  421. package/src/language-icons/Raku.svg +1 -0
  422. package/src/language-icons/ReScript.svg +1 -0
  423. package/src/language-icons/Reason.svg +1 -0
  424. package/src/language-icons/Red.svg +1 -0
  425. package/src/language-icons/Riot.svg +1 -0
  426. package/src/language-icons/RobotFramework.svg +1 -0
  427. package/src/language-icons/Ruby.svg +1 -0
  428. package/src/language-icons/Rust.svg +1 -0
  429. package/src/language-icons/SAS.svg +1 -0
  430. package/src/language-icons/SCSS.svg +1 -0
  431. package/src/language-icons/SPARQL.svg +1 -0
  432. package/src/language-icons/SQF.svg +1 -0
  433. package/src/language-icons/SQL.svg +1 -0
  434. package/src/language-icons/SVG.svg +1 -0
  435. package/src/language-icons/SWIG.svg +1 -0
  436. package/src/language-icons/SaltStack.svg +1 -0
  437. package/src/language-icons/Sass.svg +1 -0
  438. package/src/language-icons/Scala.svg +1 -0
  439. package/src/language-icons/Scilab.svg +1 -0
  440. package/src/language-icons/ShaderLab.svg +1 -0
  441. package/src/language-icons/Shell.svg +1 -0
  442. package/src/language-icons/Slice.svg +1 -0
  443. package/src/language-icons/Slim.svg +1 -0
  444. package/src/language-icons/Smarty.svg +1 -0
  445. package/src/language-icons/Solidity.svg +1 -0
  446. package/src/language-icons/Squirrel.svg +1 -0
  447. package/src/language-icons/Stan.svg +1 -0
  448. package/src/language-icons/Stata.svg +1 -0
  449. package/src/language-icons/Stylus.svg +1 -0
  450. package/src/language-icons/SugarSS.svg +1 -0
  451. package/src/language-icons/Svelte.svg +1 -0
  452. package/src/language-icons/Swift.svg +1 -0
  453. package/src/language-icons/SystemVerilog.svg +1 -0
  454. package/src/language-icons/TOML.svg +1 -0
  455. package/src/language-icons/Tcl.svg +1 -0
  456. package/src/language-icons/TeX.svg +1 -0
  457. package/src/language-icons/Text.svg +1 -0
  458. package/src/language-icons/Textile.svg +1 -0
  459. package/src/language-icons/Twig.svg +1 -0
  460. package/src/language-icons/TypeScript.svg +1 -0
  461. package/src/language-icons/V.svg +1 -0
  462. package/src/language-icons/VBA.svg +1 -0
  463. package/src/language-icons/VBScript.svg +1 -0
  464. package/src/language-icons/VHDL.svg +1 -0
  465. package/src/language-icons/Vala.svg +1 -0
  466. package/src/language-icons/Velocity Template Language.svg +1 -0
  467. package/src/language-icons/Verilog.svg +1 -0
  468. package/src/language-icons/Vim script.svg +1 -0
  469. package/src/language-icons/Volt.svg +1 -0
  470. package/src/language-icons/Vue.svg +1 -0
  471. package/src/language-icons/WebAssembly.svg +1 -0
  472. package/src/language-icons/Wikitext.svg +1 -0
  473. package/src/language-icons/Windows Registry Entries.svg +1 -0
  474. package/src/language-icons/XML.svg +1 -0
  475. package/src/language-icons/XQuery.svg +1 -0
  476. package/src/language-icons/XSLT.svg +1 -0
  477. package/src/language-icons/YAML.svg +1 -0
  478. package/src/language-icons/YANG.svg +1 -0
  479. package/src/language-icons/Yacc.svg +1 -0
  480. package/src/language-icons/Zig.svg +1 -0
  481. package/src/language-icons/kvlang.svg +1 -0
  482. package/src/language-icons/q.svg +1 -0
  483. package/src/language-icons/reStructuredText.svg +1 -0
  484. package/src/language-icons/robots.txt.svg +1 -0
  485. package/src/language-icons/url.svg +1 -0
  486. package/tests/crowdin.test.js +247 -6
  487. package/tests/global-exposure.test.js +31 -0
  488. package/tests/load-script.test.js +22 -0
  489. package/tests/sleep.test.js +2 -2
@@ -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
- global.document.body.innerHTML = `
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
- global.window.proxyTranslator = {
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 global.window.proxyTranslator;
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(window.proxyTranslator.init).toHaveBeenCalledWith(
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(window.proxyTranslator.init).toHaveBeenCalledWith(
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
  });
@@ -16,7 +16,7 @@ describe('sleep function', () => {
16
16
  })
17
17
 
18
18
  beforeEach(() => {
19
- jest.spyOn(global, 'setTimeout');
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
- let delay_value = delay[0];
29
+ const delay_value = delay;
30
30
  const sleepPromise = sleep(delay_value);
31
31
  jest.advanceTimersByTime(delay_value);
32
32
  await sleepPromise;