@lizardbyte/shared-web 2025.321.1458 → 2025.323.15856
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/dist/crowdin.js +1 -1
- package/dist/crowdin.js.map +1 -1
- package/package.json +1 -1
- package/src/js/crowdin.js +105 -44
- package/tests/crowdin.test.js +132 -0
package/dist/crowdin.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(()=>{var e={
|
|
1
|
+
(()=>{var e={714:(e,t,o)=>{var n=o(836);function s(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"LizardByte",t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"bootstrap";["LizardByte","LizardByte-docs"].includes(e)?["bootstrap","sphinx",null].includes(t)?n("https://proxy-translator.app.crowdin.net/assets/proxy-translator.js",(function(){var o={LizardByte:{baseUrl:"https://app.lizardbyte.dev",valuesParams:"U2FsdGVkX193b3LJT2/HWNIVSb3D61klmnbJ+dvGjoY2XSu35S3gL3FRLBfiXVk4nRsFlfzaC0R7JrklvnS7Xqz5im/VrO+sGzo3LbebxNIMp8LZe28udpnJcA2I2u8B",filePath:"/app.lizardbyte.dev.json",distribution:"0913bb75b61f0b26247ffa91bw4"},"LizardByte-docs":{baseUrl:"https://docs.lizardbyte.dev",valuesParams:"U2FsdGVkX19eQczbrFgaLYbrEBP8is5CVpC2YSnXxH/sRjWqaBtQOsLZJbSRMepcn3D2sofzZxALb2pvT3MLmM+WG5EpWSF7CzzYsAOJ+k/FpMUJ1PZ1FQmmlKCIWyD7",filePath:"/docs.lizardbyte.dev.json",distribution:"fb3b3d5c18de9bc717d96b91bw4"}},n={bg:{code:"bg",name:"Bulgarian",twoLettersCode:"bg"},de:{code:"de",name:"German",twoLettersCode:"de"},en:{code:"en",name:"English",twoLettersCode:"en"},"en-GB":{code:"en-GB",name:"English, United Kingdom",twoLettersCode:"en"},"en-US":{code:"en-US",name:"English, United States",twoLettersCode:"en"},"es-ES":{code:"es-ES",name:"Spanish",twoLettersCode:"es"},fr:{code:"fr",name:"French",twoLettersCode:"fr"},it:{code:"it",name:"Italian",twoLettersCode:"it"},ja:{code:"ja",name:"Japanese",twoLettersCode:"ja"},ko:{code:"ko",name:"Korean",twoLettersCode:"ko"},pl:{code:"pl",name:"Polish",twoLettersCode:"pl"},"pt-BR":{code:"pt-BR",name:"Portuguese, Brazilian",twoLettersCode:"pt"},"pt-PT":{code:"pt-PT",name:"Portuguese",twoLettersCode:"pt"},ru:{code:"ru",name:"Russian",twoLettersCode:"ru"},"sv-SE":{code:"sv-SE",name:"Swedish",twoLettersCode:"sv"},tr:{code:"tr",name:"Turkish",twoLettersCode:"tr"},uk:{code:"uk",name:"Ukrainian",twoLettersCode:"uk"},"zh-CN":{code:"zh-CN",name:"Chinese Simplified",twoLettersCode:"zh"},"zh-TW":{code:"zh-TW",name:"Chinese Traditional",twoLettersCode:"zh"}};n=Object.fromEntries(Object.entries(n).sort((function(e,t){return e[1].name.localeCompare(t[1].name)}))),window.proxyTranslator.init({baseUrl:o[e].baseUrl,appUrl:"https://proxy-translator.app.crowdin.net",valuesParams:o[e].valuesParams,distributionBaseUrl:"https://distributions.crowdin.net",filePath:o[e].filePath,distribution:o[e].distribution,distributionSeparateFiles:void 0,languagesData:n,defaultLanguage:"en",defaultLanguageTitle:"English",languageDetectType:"default",poweredBy:!1,position:"bottom-left",submenuPosition:"top-left"}),null!==t&&setTimeout((function(){var e=document.getElementById("crowdin-language-picker"),o=document.getElementsByClassName("cr-picker-button")[0],n=document.getElementsByClassName("cr-picker-submenu")[0],s=document.getElementsByClassName("cr-selected")[0];"bootstrap"===t?(o.classList.add("border-white","btn","btn-outline-light","bg-dark","text-white","rounded-0"),n.classList.add("border-white","bg-dark","text-white","rounded-0"),s.classList.add("text-white")):"sphinx"===t&&(e.classList.remove("cr-position-bottom-left"),e.style.width=o.offsetWidth+10+"px",e.style.position="relative",e.style.left="10px",e.style.bottom="10px",document.getElementsByClassName("sidebar-sticky")[0].appendChild(e))}),500)})):console.error('Invalid UI. Must be "bootstrap", "sphinx", or null'):console.error('Invalid project. Must be "LizardByte" or "LizardByte-docs"')}"undefined"!=typeof window&&(window.initDiscord=s),e.exports=s},836:e=>{function t(e,t){var o=document.createElement("script");o.src=e,o.async=!0,o.onload=function(){t&&t(null,o)},o.onerror=function(){t&&t(new Error("Failed to load script: ".concat(e)))},document.head.appendChild(o)}"undefined"!=typeof window&&(window.loadScript=t),e.exports=t}},t={};!function o(n){var s=t[n];if(void 0!==s)return s.exports;var r=t[n]={exports:{}};return e[n](r,r.exports,o),r.exports}(714)})();
|
|
2
2
|
//# sourceMappingURL=crowdin.js.map
|
package/dist/crowdin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crowdin.js","mappings":"qBAKA,SAASA,EAAWC,EAAKC,GACrB,IAAMC,EAASC,SAASC,cAAc,UACtCF,EAAOG,IAAML,EACbE,EAAOI,OAAQ,EAEfJ,EAAOK,OAAS,WACRN,GAAUA,EAAS,KAAMC,EACjC,EAEAA,EAAOM,QAAU,WACTP,GAAUA,EAAS,IAAIQ,MAAM,0BAADC,OAA2BV,IAC/D,EAEAG,SAASQ,KAAKC,YAAYV,EAC9B,CAGsB,oBAAXW,SACPA,OAAOd,WAAaA,GAGxBe,EAAOC,QAAUhB,C,GCzBbiB,EAA2B,CAAC,GAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqBE,IAAjBD,EACH,OAAOA,EAAaJ,QAGrB,IAAID,EAASE,EAAyBE,GAAY,CAGjDH,QAAS,CAAC,GAOX,OAHAM,EAAoBH,GAAUJ,EAAQA,EAAOC,QAASE,GAG/CH,EAAOC,OACf,ECtBmBO,CAAQ,IAE3BvB,CAAW,uEAAuE,WAC9Ec,OAAOU,gBAAgBC,KAAK,CACxBC,QAAS,6BACTC,OAAQ,2CACRC,aAAc,mIACdC,oBAAqB,oCACrBC,SAAU,2BACVC,aAAc,8BACdC,cAAe,CACX,GAAM,CAAC,KAAO,KAAK,KAAO,SAAS,eAAiB,MACpD,QAAS,CAAC,KAAO,QAAQ,KAAO,UAAU,eAAiB,MAC3D,GAAM,CAAC,KAAO,KAAK,KAAO,SAAS,eAAiB,MACpD,GAAM,CAAC,KAAO,KAAK,KAAO,UAAU,eAAiB,MACrD,GAAK,CAAC,KAAO,KAAK,KAAO,WAAW,eAAiB,MACrD,QAAQ,CAAC,KAAO,QAAQ,KAAO,aAAa,eAAiB,MAC7D,GAAM,CAAC,KAAO,KAAK,KAAO,UAAU,eAAiB,MACrD,QAAQ,CAAC,KAAO,QAAQ,KAAO,UAAU,eAAiB,MAC1D,GAAK,CAAC,KAAO,KAAK,KAAO,UAAU,eAAiB,MACpD,QAAQ,CAAC,KAAO,QAAQ,KAAO,qBAAqB,eAAiB,MACrE,GAAM,CAAC,KAAO,KAAK,KAAO,UAAU,eAAiB,MACrD,QAAS,CAAC,KAAO,QAAQ,KAAO,yBAAyB,eAAiB,MAC1E,QAAS,CAAC,KAAO,QAAQ,KAAO,0BAA0B,eAAiB,OAE/EC,gBAAiB,KACjBC,qBAAsB,UACtBC,mBAAoB,UACpBC,WAAW,EACXC,SAAU,cACVC,gBAAiB,aAIrB,IAAIC,EAASnC,SAASoC,uBAAuB,oBAAoB,GACjED,EAAOE,UAAUC,IAAI,gBACrBH,EAAOE,UAAUC,IAAI,OACrBH,EAAOE,UAAUC,IAAI,qBACrBH,EAAOE,UAAUC,IAAI,WACrBH,EAAOE,UAAUC,IAAI,cACrBH,EAAOE,UAAUC,IAAI,aAGrB,IAAIC,EAAOvC,SAASoC,uBAAuB,qBAAqB,GAChEG,EAAKF,UAAUC,IAAI,gBACnBC,EAAKF,UAAUC,IAAI,WACnBC,EAAKF,UAAUC,IAAI,cACnBC,EAAKF,UAAUC,IAAI,aAGJtC,SAASoC,uBAAuB,eAAe,GACrDC,UAAUC,IAAI,aAC3B,G","sources":["webpack://@lizardbyte/shared-web/./src/js/load-script.js","webpack://@lizardbyte/shared-web/webpack/bootstrap","webpack://@lizardbyte/shared-web/./src/js/crowdin.js"],"sourcesContent":["/**\n * Load a script asynchronously, and add it to the DOM. Optionally, call a callback when the script has loaded.\n * @param url The URL of the script to load.\n * @param callback An optional callback to call when the script has loaded.\n */\nfunction loadScript(url, callback) {\n const script = document.createElement('script');\n script.src = url;\n script.async = true;\n\n script.onload = () => {\n if (callback) callback(null, script);\n };\n\n script.onerror = () => {\n if (callback) callback(new Error(`Failed to load script: ${url}`));\n };\n\n document.head.appendChild(script);\n}\n\n// Expose to the global scope\nif (typeof window !== 'undefined') {\n window.loadScript = loadScript;\n}\n\nmodule.exports = loadScript;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","const loadScript = require('./load-script');\n\nloadScript('https://proxy-translator.app.crowdin.net/assets/proxy-translator.js', function() {\n window.proxyTranslator.init({\n baseUrl: \"https://app.lizardbyte.dev\",\n appUrl: \"https://proxy-translator.app.crowdin.net\",\n valuesParams: \"U2FsdGVkX19ClOT7gAzJBnfQPMcvqkPxFWxyPrnN7UEMztYDAOA+/W4kvMqRz2gDLv2/K3hTEtwbcq5imv5k5MUAykz0uklBcdH49kqeo1AhYpNKXdwXZNYBPXmNUm5F\",\n distributionBaseUrl: \"https://distributions.crowdin.net\",\n filePath: \"/app.lizardbyte.dev.json\",\n distribution: \"0913bb75b61f0b26247ffa91bw4\",\n languagesData: {\n \"fr\": {\"code\":\"fr\",\"name\":\"French\",\"twoLettersCode\":\"fr\"},\n \"es-ES\": {\"code\":\"es-ES\",\"name\":\"Spanish\",\"twoLettersCode\":\"es\"},\n \"de\": {\"code\":\"de\",\"name\":\"German\",\"twoLettersCode\":\"de\"},\n \"it\": {\"code\":\"it\",\"name\":\"Italian\",\"twoLettersCode\":\"it\"},\n \"ja\":{\"code\":\"ja\",\"name\":\"Japanese\",\"twoLettersCode\":\"ja\"},\n \"pt-PT\":{\"code\":\"pt-PT\",\"name\":\"Portuguese\",\"twoLettersCode\":\"pt\"},\n \"ru\": {\"code\":\"ru\",\"name\":\"Russian\",\"twoLettersCode\":\"ru\"},\n \"sv-SE\":{\"code\":\"sv-SE\",\"name\":\"Swedish\",\"twoLettersCode\":\"sv\"},\n \"tr\":{\"code\":\"tr\",\"name\":\"Turkish\",\"twoLettersCode\":\"tr\"},\n \"zh-CN\":{\"code\":\"zh-CN\",\"name\":\"Chinese Simplified\",\"twoLettersCode\":\"zh\"},\n \"en\": {\"code\":\"en\",\"name\":\"English\",\"twoLettersCode\":\"en\"},\n \"en-US\": {\"code\":\"en-US\",\"name\":\"English, United States\",\"twoLettersCode\":\"en\"},\n \"en-GB\": {\"code\":\"en-GB\",\"name\":\"English, United Kingdom\",\"twoLettersCode\":\"en\"}\n },\n defaultLanguage: \"en\",\n defaultLanguageTitle: \"English\",\n languageDetectType: \"default\",\n poweredBy: false,\n position: \"bottom-left\",\n submenuPosition: \"top-left\",\n });\n\n // change styling of language selector button\n let button = document.getElementsByClassName('cr-picker-button')[0]\n button.classList.add('border-white')\n button.classList.add('btn')\n button.classList.add('btn-outline-light')\n button.classList.add('bg-dark')\n button.classList.add('text-white')\n button.classList.add('rounded-0')\n\n // change styling of language selector menu\n let menu = document.getElementsByClassName('cr-picker-submenu')[0]\n menu.classList.add('border-white')\n menu.classList.add('bg-dark')\n menu.classList.add('text-white')\n menu.classList.add('rounded-0')\n\n // change styling of selected language in menu\n let selected = document.getElementsByClassName('cr-selected')[0]\n selected.classList.add('text-white')\n});\n"],"names":["loadScript","url","callback","script","document","createElement","src","async","onload","onerror","Error","concat","head","appendChild","window","module","exports","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","require","proxyTranslator","init","baseUrl","appUrl","valuesParams","distributionBaseUrl","filePath","distribution","languagesData","defaultLanguage","defaultLanguageTitle","languageDetectType","poweredBy","position","submenuPosition","button","getElementsByClassName","classList","add","menu"],"sourceRoot":""}
|
|
1
|
+
{"version":3,"file":"crowdin.js","mappings":"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","sources":["webpack://@lizardbyte/shared-web/./src/js/crowdin.js","webpack://@lizardbyte/shared-web/./src/js/load-script.js","webpack://@lizardbyte/shared-web/webpack/bootstrap","webpack://@lizardbyte/shared-web/webpack/startup"],"sourcesContent":["const loadScript = require('./load-script');\n\n/**\n * Initializes Crowdin translation widget based on project and UI platform.\n * @param {string} project - Project name ('LizardByte' or 'LizardByte-docs')\n * @param {string|null} platform - UI platform ('bootstrap', 'sphinx', or null)\n */\nfunction initCrowdIn(project = 'LizardByte', platform = 'bootstrap') {\n // Input validation\n if (!['LizardByte', 'LizardByte-docs'].includes(project)) {\n console.error('Invalid project. Must be \"LizardByte\" or \"LizardByte-docs\"');\n return;\n }\n if (!['bootstrap', 'sphinx', null].includes(platform)) {\n console.error('Invalid UI. Must be \"bootstrap\", \"sphinx\", or null');\n return;\n }\n\n loadScript('https://proxy-translator.app.crowdin.net/assets/proxy-translator.js', function() {\n // Configure base settings based on project\n const projectSettings = {\n 'LizardByte': {\n baseUrl: \"https://app.lizardbyte.dev\",\n valuesParams: \"U2FsdGVkX193b3LJT2/HWNIVSb3D61klmnbJ+dvGjoY2XSu35S3gL3FRLBfiXVk4nRsFlfzaC0R7JrklvnS7Xqz5im/VrO+sGzo3LbebxNIMp8LZe28udpnJcA2I2u8B\",\n filePath: \"/app.lizardbyte.dev.json\",\n distribution: \"0913bb75b61f0b26247ffa91bw4\",\n },\n 'LizardByte-docs': {\n baseUrl: \"https://docs.lizardbyte.dev\",\n valuesParams: \"U2FsdGVkX19eQczbrFgaLYbrEBP8is5CVpC2YSnXxH/sRjWqaBtQOsLZJbSRMepcn3D2sofzZxALb2pvT3MLmM+WG5EpWSF7CzzYsAOJ+k/FpMUJ1PZ1FQmmlKCIWyD7\",\n filePath: \"/docs.lizardbyte.dev.json\",\n distribution: \"fb3b3d5c18de9bc717d96b91bw4\",\n }\n };\n\n let languagesData = {\n \"bg\":{\"code\":\"bg\",\"name\":\"Bulgarian\",\"twoLettersCode\":\"bg\"},\n \"de\":{\"code\":\"de\",\"name\":\"German\",\"twoLettersCode\":\"de\"},\n \"en\":{\"code\":\"en\",\"name\":\"English\",\"twoLettersCode\":\"en\"},\n \"en-GB\":{\"code\":\"en-GB\",\"name\":\"English, United Kingdom\",\"twoLettersCode\":\"en\"},\n \"en-US\":{\"code\":\"en-US\",\"name\":\"English, United States\",\"twoLettersCode\":\"en\"},\n \"es-ES\":{\"code\":\"es-ES\",\"name\":\"Spanish\",\"twoLettersCode\":\"es\"},\n \"fr\":{\"code\":\"fr\",\"name\":\"French\",\"twoLettersCode\":\"fr\"},\n \"it\":{\"code\":\"it\",\"name\":\"Italian\",\"twoLettersCode\":\"it\"},\n \"ja\":{\"code\":\"ja\",\"name\":\"Japanese\",\"twoLettersCode\":\"ja\"},\n \"ko\":{\"code\":\"ko\",\"name\":\"Korean\",\"twoLettersCode\":\"ko\"},\n \"pl\":{\"code\":\"pl\",\"name\":\"Polish\",\"twoLettersCode\":\"pl\"},\n \"pt-BR\":{\"code\":\"pt-BR\",\"name\":\"Portuguese, Brazilian\",\"twoLettersCode\":\"pt\"},\n \"pt-PT\":{\"code\":\"pt-PT\",\"name\":\"Portuguese\",\"twoLettersCode\":\"pt\"},\n \"ru\":{\"code\":\"ru\",\"name\":\"Russian\",\"twoLettersCode\":\"ru\"},\n \"sv-SE\":{\"code\":\"sv-SE\",\"name\":\"Swedish\",\"twoLettersCode\":\"sv\"},\n \"tr\":{\"code\":\"tr\",\"name\":\"Turkish\",\"twoLettersCode\":\"tr\"},\n \"uk\":{\"code\":\"uk\",\"name\":\"Ukrainian\",\"twoLettersCode\":\"uk\"},\n \"zh-CN\":{\"code\":\"zh-CN\",\"name\":\"Chinese Simplified\",\"twoLettersCode\":\"zh\"},\n \"zh-TW\":{\"code\":\"zh-TW\",\"name\":\"Chinese Traditional\",\"twoLettersCode\":\"zh\"},\n };\n // sort languages by name\n languagesData = Object.fromEntries(Object.entries(languagesData).sort((a, b) => a[1].name.localeCompare(b[1].name)));\n\n // Initialize Crowdin translator\n window.proxyTranslator.init({\n baseUrl: projectSettings[project].baseUrl,\n appUrl: \"https://proxy-translator.app.crowdin.net\",\n valuesParams: projectSettings[project].valuesParams,\n distributionBaseUrl: \"https://distributions.crowdin.net\",\n filePath: projectSettings[project].filePath,\n distribution: projectSettings[project].distribution,\n distributionSeparateFiles: undefined,\n languagesData: languagesData,\n defaultLanguage: \"en\",\n defaultLanguageTitle: \"English\",\n languageDetectType: \"default\",\n poweredBy: false,\n position: \"bottom-left\",\n submenuPosition: \"top-left\",\n });\n\n // Apply styling based on UI framework\n if (platform === null) {\n return;\n }\n setTimeout(() => {\n const container = document.getElementById('crowdin-language-picker');\n const button = document.getElementsByClassName('cr-picker-button')[0];\n const menu = document.getElementsByClassName('cr-picker-submenu')[0];\n const selected = document.getElementsByClassName('cr-selected')[0];\n\n if (platform === 'bootstrap') {\n button.classList.add('border-white', 'btn', 'btn-outline-light', 'bg-dark', 'text-white', 'rounded-0');\n menu.classList.add('border-white', 'bg-dark', 'text-white', 'rounded-0');\n selected.classList.add('text-white');\n } else if (platform === 'sphinx') {\n container.classList.remove('cr-position-bottom-left')\n container.style.width = button.offsetWidth + 10 + 'px';\n container.style.position = 'relative';\n container.style.left = '10px';\n container.style.bottom = '10px';\n\n // get rst versions\n const sidebar = document.getElementsByClassName('sidebar-sticky')[0];\n\n // move button to related pages\n sidebar.appendChild(container);\n }\n }, 500); // Short delay to ensure elements are available\n });\n}\n\n// Expose to the global scope\nif (typeof window !== 'undefined') {\n window.initDiscord = initCrowdIn;\n}\n\nmodule.exports = initCrowdIn;\n","/**\n * Load a script asynchronously, and add it to the DOM. Optionally, call a callback when the script has loaded.\n * @param url The URL of the script to load.\n * @param callback An optional callback to call when the script has loaded.\n */\nfunction loadScript(url, callback) {\n const script = document.createElement('script');\n script.src = url;\n script.async = true;\n\n script.onload = () => {\n if (callback) callback(null, script);\n };\n\n script.onerror = () => {\n if (callback) callback(new Error(`Failed to load script: ${url}`));\n };\n\n document.head.appendChild(script);\n}\n\n// Expose to the global scope\nif (typeof window !== 'undefined') {\n window.loadScript = loadScript;\n}\n\nmodule.exports = loadScript;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(714);\n"],"names":["loadScript","require","initCrowdIn","project","arguments","length","undefined","platform","includes","projectSettings","baseUrl","valuesParams","filePath","distribution","languagesData","Object","fromEntries","entries","sort","a","b","name","localeCompare","window","proxyTranslator","init","appUrl","distributionBaseUrl","distributionSeparateFiles","defaultLanguage","defaultLanguageTitle","languageDetectType","poweredBy","position","submenuPosition","setTimeout","container","document","getElementById","button","getElementsByClassName","menu","selected","classList","add","remove","style","width","offsetWidth","left","bottom","appendChild","console","error","initDiscord","module","exports","url","callback","script","createElement","src","async","onload","onerror","Error","concat","head","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","__webpack_modules__"],"sourceRoot":""}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"type": "git",
|
|
5
5
|
"url": "git+https://github.com/LizardByte/shared-web.git"
|
|
6
6
|
},
|
|
7
|
-
"version": "2025.
|
|
7
|
+
"version": "2025.323.15856",
|
|
8
8
|
"description": "Shared web assets for LizardByte projects",
|
|
9
9
|
"license": "AGPL-3.0-only",
|
|
10
10
|
"funding": "https://app.lizardbyte.dev",
|
package/src/js/crowdin.js
CHANGED
|
@@ -1,53 +1,114 @@
|
|
|
1
1
|
const loadScript = require('./load-script');
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Initializes Crowdin translation widget based on project and UI platform.
|
|
5
|
+
* @param {string} project - Project name ('LizardByte' or 'LizardByte-docs')
|
|
6
|
+
* @param {string|null} platform - UI platform ('bootstrap', 'sphinx', or null)
|
|
7
|
+
*/
|
|
8
|
+
function initCrowdIn(project = 'LizardByte', platform = 'bootstrap') {
|
|
9
|
+
// Input validation
|
|
10
|
+
if (!['LizardByte', 'LizardByte-docs'].includes(project)) {
|
|
11
|
+
console.error('Invalid project. Must be "LizardByte" or "LizardByte-docs"');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (!['bootstrap', 'sphinx', null].includes(platform)) {
|
|
15
|
+
console.error('Invalid UI. Must be "bootstrap", "sphinx", or null');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
loadScript('https://proxy-translator.app.crowdin.net/assets/proxy-translator.js', function() {
|
|
20
|
+
// Configure base settings based on project
|
|
21
|
+
const projectSettings = {
|
|
22
|
+
'LizardByte': {
|
|
23
|
+
baseUrl: "https://app.lizardbyte.dev",
|
|
24
|
+
valuesParams: "U2FsdGVkX193b3LJT2/HWNIVSb3D61klmnbJ+dvGjoY2XSu35S3gL3FRLBfiXVk4nRsFlfzaC0R7JrklvnS7Xqz5im/VrO+sGzo3LbebxNIMp8LZe28udpnJcA2I2u8B",
|
|
25
|
+
filePath: "/app.lizardbyte.dev.json",
|
|
26
|
+
distribution: "0913bb75b61f0b26247ffa91bw4",
|
|
27
|
+
},
|
|
28
|
+
'LizardByte-docs': {
|
|
29
|
+
baseUrl: "https://docs.lizardbyte.dev",
|
|
30
|
+
valuesParams: "U2FsdGVkX19eQczbrFgaLYbrEBP8is5CVpC2YSnXxH/sRjWqaBtQOsLZJbSRMepcn3D2sofzZxALb2pvT3MLmM+WG5EpWSF7CzzYsAOJ+k/FpMUJ1PZ1FQmmlKCIWyD7",
|
|
31
|
+
filePath: "/docs.lizardbyte.dev.json",
|
|
32
|
+
distribution: "fb3b3d5c18de9bc717d96b91bw4",
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
let languagesData = {
|
|
37
|
+
"bg":{"code":"bg","name":"Bulgarian","twoLettersCode":"bg"},
|
|
38
|
+
"de":{"code":"de","name":"German","twoLettersCode":"de"},
|
|
39
|
+
"en":{"code":"en","name":"English","twoLettersCode":"en"},
|
|
40
|
+
"en-GB":{"code":"en-GB","name":"English, United Kingdom","twoLettersCode":"en"},
|
|
41
|
+
"en-US":{"code":"en-US","name":"English, United States","twoLettersCode":"en"},
|
|
42
|
+
"es-ES":{"code":"es-ES","name":"Spanish","twoLettersCode":"es"},
|
|
43
|
+
"fr":{"code":"fr","name":"French","twoLettersCode":"fr"},
|
|
44
|
+
"it":{"code":"it","name":"Italian","twoLettersCode":"it"},
|
|
16
45
|
"ja":{"code":"ja","name":"Japanese","twoLettersCode":"ja"},
|
|
46
|
+
"ko":{"code":"ko","name":"Korean","twoLettersCode":"ko"},
|
|
47
|
+
"pl":{"code":"pl","name":"Polish","twoLettersCode":"pl"},
|
|
48
|
+
"pt-BR":{"code":"pt-BR","name":"Portuguese, Brazilian","twoLettersCode":"pt"},
|
|
17
49
|
"pt-PT":{"code":"pt-PT","name":"Portuguese","twoLettersCode":"pt"},
|
|
18
|
-
"ru":
|
|
50
|
+
"ru":{"code":"ru","name":"Russian","twoLettersCode":"ru"},
|
|
19
51
|
"sv-SE":{"code":"sv-SE","name":"Swedish","twoLettersCode":"sv"},
|
|
20
52
|
"tr":{"code":"tr","name":"Turkish","twoLettersCode":"tr"},
|
|
53
|
+
"uk":{"code":"uk","name":"Ukrainian","twoLettersCode":"uk"},
|
|
21
54
|
"zh-CN":{"code":"zh-CN","name":"Chinese Simplified","twoLettersCode":"zh"},
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
55
|
+
"zh-TW":{"code":"zh-TW","name":"Chinese Traditional","twoLettersCode":"zh"},
|
|
56
|
+
};
|
|
57
|
+
// sort languages by name
|
|
58
|
+
languagesData = Object.fromEntries(Object.entries(languagesData).sort((a, b) => a[1].name.localeCompare(b[1].name)));
|
|
59
|
+
|
|
60
|
+
// Initialize Crowdin translator
|
|
61
|
+
window.proxyTranslator.init({
|
|
62
|
+
baseUrl: projectSettings[project].baseUrl,
|
|
63
|
+
appUrl: "https://proxy-translator.app.crowdin.net",
|
|
64
|
+
valuesParams: projectSettings[project].valuesParams,
|
|
65
|
+
distributionBaseUrl: "https://distributions.crowdin.net",
|
|
66
|
+
filePath: projectSettings[project].filePath,
|
|
67
|
+
distribution: projectSettings[project].distribution,
|
|
68
|
+
distributionSeparateFiles: undefined,
|
|
69
|
+
languagesData: languagesData,
|
|
70
|
+
defaultLanguage: "en",
|
|
71
|
+
defaultLanguageTitle: "English",
|
|
72
|
+
languageDetectType: "default",
|
|
73
|
+
poweredBy: false,
|
|
74
|
+
position: "bottom-left",
|
|
75
|
+
submenuPosition: "top-left",
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Apply styling based on UI framework
|
|
79
|
+
if (platform === null) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
const container = document.getElementById('crowdin-language-picker');
|
|
84
|
+
const button = document.getElementsByClassName('cr-picker-button')[0];
|
|
85
|
+
const menu = document.getElementsByClassName('cr-picker-submenu')[0];
|
|
86
|
+
const selected = document.getElementsByClassName('cr-selected')[0];
|
|
87
|
+
|
|
88
|
+
if (platform === 'bootstrap') {
|
|
89
|
+
button.classList.add('border-white', 'btn', 'btn-outline-light', 'bg-dark', 'text-white', 'rounded-0');
|
|
90
|
+
menu.classList.add('border-white', 'bg-dark', 'text-white', 'rounded-0');
|
|
91
|
+
selected.classList.add('text-white');
|
|
92
|
+
} else if (platform === 'sphinx') {
|
|
93
|
+
container.classList.remove('cr-position-bottom-left')
|
|
94
|
+
container.style.width = button.offsetWidth + 10 + 'px';
|
|
95
|
+
container.style.position = 'relative';
|
|
96
|
+
container.style.left = '10px';
|
|
97
|
+
container.style.bottom = '10px';
|
|
98
|
+
|
|
99
|
+
// get rst versions
|
|
100
|
+
const sidebar = document.getElementsByClassName('sidebar-sticky')[0];
|
|
101
|
+
|
|
102
|
+
// move button to related pages
|
|
103
|
+
sidebar.appendChild(container);
|
|
104
|
+
}
|
|
105
|
+
}, 500); // Short delay to ensure elements are available
|
|
32
106
|
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Expose to the global scope
|
|
110
|
+
if (typeof window !== 'undefined') {
|
|
111
|
+
window.initDiscord = initCrowdIn;
|
|
112
|
+
}
|
|
33
113
|
|
|
34
|
-
|
|
35
|
-
let button = document.getElementsByClassName('cr-picker-button')[0]
|
|
36
|
-
button.classList.add('border-white')
|
|
37
|
-
button.classList.add('btn')
|
|
38
|
-
button.classList.add('btn-outline-light')
|
|
39
|
-
button.classList.add('bg-dark')
|
|
40
|
-
button.classList.add('text-white')
|
|
41
|
-
button.classList.add('rounded-0')
|
|
42
|
-
|
|
43
|
-
// change styling of language selector menu
|
|
44
|
-
let menu = document.getElementsByClassName('cr-picker-submenu')[0]
|
|
45
|
-
menu.classList.add('border-white')
|
|
46
|
-
menu.classList.add('bg-dark')
|
|
47
|
-
menu.classList.add('text-white')
|
|
48
|
-
menu.classList.add('rounded-0')
|
|
49
|
-
|
|
50
|
-
// change styling of selected language in menu
|
|
51
|
-
let selected = document.getElementsByClassName('cr-selected')[0]
|
|
52
|
-
selected.classList.add('text-white')
|
|
53
|
-
});
|
|
114
|
+
module.exports = initCrowdIn;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
describe,
|
|
3
|
+
expect,
|
|
4
|
+
it,
|
|
5
|
+
jest,
|
|
6
|
+
beforeEach,
|
|
7
|
+
afterEach
|
|
8
|
+
} from '@jest/globals';
|
|
9
|
+
|
|
10
|
+
// We need to mock the module BEFORE importing the module that uses it
|
|
11
|
+
jest.mock('../src/js/load-script', () => {
|
|
12
|
+
return function(url, callback) {
|
|
13
|
+
if (callback) setTimeout(callback, 0);
|
|
14
|
+
return true;
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const initCrowdIn = require('../src/js/crowdin');
|
|
19
|
+
|
|
20
|
+
describe('initCrowdIn', () => {
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
// Mock DOM elements
|
|
23
|
+
global.document.body.innerHTML = `
|
|
24
|
+
<div id="crowdin-language-picker">
|
|
25
|
+
<div class="cr-picker-button"></div>
|
|
26
|
+
<div class="cr-picker-submenu"></div>
|
|
27
|
+
<div class="cr-selected"></div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<!-- Sphinx sidebar -->
|
|
31
|
+
<div class="sidebar-sticky"></div>
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
// Mock console.error
|
|
35
|
+
jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
36
|
+
|
|
37
|
+
// Mock window.proxyTranslator
|
|
38
|
+
global.window.proxyTranslator = {
|
|
39
|
+
init: jest.fn()
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Use fake timers to control setTimeout
|
|
43
|
+
jest.useFakeTimers();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
afterEach(() => {
|
|
47
|
+
jest.clearAllMocks();
|
|
48
|
+
jest.useRealTimers();
|
|
49
|
+
delete global.window.proxyTranslator;
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should validate project parameter', () => {
|
|
53
|
+
initCrowdIn('InvalidProject');
|
|
54
|
+
expect(console.error).toHaveBeenCalledWith('Invalid project. Must be "LizardByte" or "LizardByte-docs"');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should validate platform parameter', () => {
|
|
58
|
+
initCrowdIn('LizardByte', 'invalidPlatform');
|
|
59
|
+
expect(console.error).toHaveBeenCalledWith('Invalid UI. Must be "bootstrap", "sphinx", or null');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should initialize proxyTranslator with LizardByte settings', () => {
|
|
63
|
+
initCrowdIn();
|
|
64
|
+
|
|
65
|
+
// Simulate script loading
|
|
66
|
+
jest.runAllTimers();
|
|
67
|
+
|
|
68
|
+
expect(window.proxyTranslator.init).toHaveBeenCalledWith(
|
|
69
|
+
expect.objectContaining({
|
|
70
|
+
baseUrl: "https://app.lizardbyte.dev",
|
|
71
|
+
distribution: "0913bb75b61f0b26247ffa91bw4",
|
|
72
|
+
defaultLanguage: "en"
|
|
73
|
+
})
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should initialize proxyTranslator with LizardByte-docs settings', () => {
|
|
78
|
+
initCrowdIn('LizardByte-docs');
|
|
79
|
+
|
|
80
|
+
// Simulate script loading
|
|
81
|
+
jest.runAllTimers();
|
|
82
|
+
|
|
83
|
+
expect(window.proxyTranslator.init).toHaveBeenCalledWith(
|
|
84
|
+
expect.objectContaining({
|
|
85
|
+
baseUrl: "https://docs.lizardbyte.dev",
|
|
86
|
+
distribution: "fb3b3d5c18de9bc717d96b91bw4",
|
|
87
|
+
defaultLanguage: "en"
|
|
88
|
+
})
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('should not apply styling when platform is null', () => {
|
|
93
|
+
initCrowdIn('LizardByte', null);
|
|
94
|
+
|
|
95
|
+
// Simulate script loading and run the setTimeout from UI styling
|
|
96
|
+
jest.runAllTimers();
|
|
97
|
+
|
|
98
|
+
// Verify that no styling was applied
|
|
99
|
+
const button = document.getElementsByClassName('cr-picker-button')[0];
|
|
100
|
+
expect(button.classList.contains('btn')).toBe(false);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('should apply bootstrap styling', () => {
|
|
104
|
+
initCrowdIn('LizardByte', 'bootstrap');
|
|
105
|
+
|
|
106
|
+
// Simulate script loading and UI styling timeout
|
|
107
|
+
jest.runAllTimers();
|
|
108
|
+
|
|
109
|
+
const button = document.getElementsByClassName('cr-picker-button')[0];
|
|
110
|
+
const menu = document.getElementsByClassName('cr-picker-submenu')[0];
|
|
111
|
+
const selected = document.getElementsByClassName('cr-selected')[0];
|
|
112
|
+
|
|
113
|
+
expect(button.classList.contains('btn')).toBe(true);
|
|
114
|
+
expect(button.classList.contains('btn-outline-light')).toBe(true);
|
|
115
|
+
expect(menu.classList.contains('bg-dark')).toBe(true);
|
|
116
|
+
expect(selected.classList.contains('text-white')).toBe(true);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should apply sphinx styling', () => {
|
|
120
|
+
initCrowdIn('LizardByte', 'sphinx');
|
|
121
|
+
|
|
122
|
+
// Simulate script loading and UI styling timeout
|
|
123
|
+
jest.runAllTimers();
|
|
124
|
+
|
|
125
|
+
const container = document.getElementById('crowdin-language-picker');
|
|
126
|
+
const sidebar = document.getElementsByClassName('sidebar-sticky')[0];
|
|
127
|
+
|
|
128
|
+
expect(container.classList.contains('cr-position-bottom-left')).toBe(false);
|
|
129
|
+
expect(container.style.position).toBe('relative');
|
|
130
|
+
expect(sidebar.contains(container)).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
});
|