From 3b89a4eaabe237733b7a196a07ff438a27f45565 Mon Sep 17 00:00:00 2001 From: Cell <1024@lruihao.cn> Date: Wed, 24 Apr 2024 17:39:17 +0800 Subject: [PATCH] :sparkles: Feat: refactor FixItDecryptor and add confirm btn Resolved #437 --- .../_partials/_single/_fixit-decryptor.scss | 26 ++- assets/js/fixit-decryptor.js | 191 ++++++++++-------- assets/js/theme.js | 68 +++++-- i18n/de.toml | 1 + i18n/en.toml | 1 + i18n/es.toml | 1 + i18n/fr.toml | 1 + i18n/hi.toml | 1 + i18n/it.toml | 1 + i18n/pl.toml | 1 + i18n/pt-BR.toml | 1 + i18n/ro.toml | 1 + i18n/ru.toml | 1 + i18n/sr.toml | 1 + i18n/vi.toml | 1 + i18n/zh-CN.toml | 1 + i18n/zh-TW.toml | 1 + layouts/partials/single/fixit-decryptor.html | 5 +- layouts/shortcodes/fixit-encryptor.html | 3 + 19 files changed, 195 insertions(+), 112 deletions(-) diff --git a/assets/css/_partials/_single/_fixit-decryptor.scss b/assets/css/_partials/_single/_fixit-decryptor.scss index ed37c9ecc..9882a170d 100644 --- a/assets/css/_partials/_single/_fixit-decryptor.scss +++ b/assets/css/_partials/_single/_fixit-decryptor.scss @@ -3,12 +3,8 @@ text-align: center; margin-top: 3rem; - .fixit-encryptor-shortcode & { - margin-top: 1rem; - } - - #fixit-decryptor-input, .fixit-decryptor-input, + .fixit-decryptor-btn, .fixit-encryptor-btn { display: inline-block; box-sizing: border-box; @@ -40,9 +36,8 @@ } } - #fixit-decryptor-input, .fixit-decryptor-input { - width: clamp(50%, 400px, 100%); + width: calc(clamp(50%, 450px, 100%) - 100px); height: 3rem; padding-left: 1rem; padding-right: 1rem; @@ -53,10 +48,11 @@ } } + .fixit-decryptor-btn, .fixit-encryptor-btn { cursor: pointer; @include transition(all 0.1s ease-out); - padding: 0.6rem 1rem; + padding: 0.8rem 1rem; background-color: $header-background-color; @@ -66,6 +62,20 @@ } } +// fixit-encryptor shortcodes +fixit-encryptor { + .fixit-decryptor-container { + margin-top: 1rem; + } + &.decrypted > .fixit-decryptor-container { + .fixit-decryptor-loading, + .fixit-decryptor-input, + .fixit-decryptor-btn { + display: none; + } + } +} + .encrypted-hidden { display: none !important; } diff --git a/assets/js/fixit-decryptor.js b/assets/js/fixit-decryptor.js index 51f2d25e0..aa9d4653f 100644 --- a/assets/js/fixit-decryptor.js +++ b/assets/js/fixit-decryptor.js @@ -12,86 +12,125 @@ FixItDecryptor = function (options = {}) { this.options = options || {}; this.options.duration = this.options.duration || 24 * 60 * 60; // default cache one day this.decryptedEventSet = new Set(); + this.partialDecryptedEventSet = new Set(); this.resetEventSet = new Set(); this.$el = document.querySelector('.fixit-decryptor-container'); /** * decrypt content - * @param {String} base64EncodeContent encrypted content + * @param {Element} $content content element + * @param {String} salt salt string + * @param {Boolean} [isAll=true] whether to decrypt all content */ - var _decryptContent = (base64EncodeContent) => { + var _decryptContent = ($content, salt, isAll=true) => { try { - this.$el.querySelector('.fixit-decryptor-loading').classList.add('d-none'); - this.$el.querySelector('#fixit-decryptor-input').classList.add('d-none'); - this.$el.querySelector('.fixit-encryptor-btn').classList.remove('d-none'); - document.querySelector('#content').insertAdjacentHTML( + if (isAll) { + // decrypt all content + this.$el.querySelector('.fixit-decryptor-loading').classList.add('d-none'); + this.$el.querySelector('.fixit-decryptor-input').classList.add('d-none'); + this.$el.querySelector('.fixit-decryptor-btn').classList.add('d-none'); + this.$el.querySelector('.fixit-encryptor-btn').classList.remove('d-none'); + } else { + // decrypt shortcode content + $content.parentElement.classList.add('decrypted'); + } + $content.insertAdjacentHTML( 'afterbegin', - CryptoJS.enc.Base64.parse(base64EncodeContent).toString(CryptoJS.enc.Utf8) + CryptoJS.enc.Base64 + .parse($content.getAttribute('data-content').replace(salt, '')) + .toString(CryptoJS.enc.Utf8) ); } catch (err) { return console.error(err); } // decrypted hook - console.log(this.decryptedEventSet) - for (const event of this.decryptedEventSet) { - event(); - } + const eventSet = isAll ? this.decryptedEventSet : this.partialDecryptedEventSet; + for (const event of eventSet) { + event($content); + } }; + /** + * validate password + * @param {Element} $decryptor decryptor element + * @param {Element} $content content element + * @param {Function} callback callback function after password validation + * @returns + */ + var _validatePassword = ($decryptor, $content, callback) => { + const password = $content.getAttribute('data-password'); + const inputEl = $decryptor.querySelector('.fixit-decryptor-input'); + const input = inputEl.value.trim(); + const inputMd5 = CryptoJS.MD5(input).toString(); + const inputSha256 = CryptoJS.SHA256(input).toString(); + const saltLen = input.length % 2 ? input.length : input.length + 1; + + inputEl.value = ''; + inputEl.blur(); + if (!input) { + alert('Please enter the correct password!'); + return console.warn('Please enter the correct password!'); + } + if (inputMd5 !== password) { + alert(`Password error: ${input} not the correct password!`); + return console.warn(`Password error: ${input} not the correct password!`); + } + callback(inputMd5, inputSha256.slice(saltLen)); + } + /** * initialize FixIt decryptor */ _proto.init = () => { this.addEventListener('decrypted', this.options?.decrypted); + this.addEventListener('partial-decrypted', this.options?.partialDecrypted); this.addEventListener('reset', this.options?.reset); this.validateCache(); - const _decryptor = this; - this.$el.querySelector('#fixit-decryptor-input')?.addEventListener('keydown', function (e) { - if (e.key === 'Enter') { - e.preventDefault(); - const $content = document.querySelector('#content'); - const password = $content.getAttribute('data-password'); - const input = this.value.trim(); - const saltLen = input.length % 2 ? input.length : input.length + 1; - const inputMd5 = CryptoJS.MD5(input).toString(); - const inputSha256 = CryptoJS.SHA256(input).toString(); - - this.value = ''; - this.blur(); - if (!input) { - alert('Please enter the correct password!'); - return console.warn('Please enter the correct password!'); - } - if (inputMd5 !== password) { - alert(`Password error: ${input} not the correct password!`); - return console.warn(`Password error: ${input} not the correct password!`); - } + const decryptorHandler = () => { + const $content = document.querySelector('#content'); + _validatePassword(this.$el, $content, (password, salt) => { // cache decryption statistics window.localStorage?.setItem( `fixit-decryptor/#${location.pathname}`, JSON.stringify({ - expiration: Math.ceil(Date.now() / 1000) + _decryptor.options.duration, - md5: inputMd5, - sha256: inputSha256.slice(saltLen) + expiration: Math.ceil(Date.now() / 1000) + this.options.duration, + password, + salt, }) ); - _decryptContent($content.getAttribute('data-content').replace(inputSha256.slice(saltLen), '')); + _decryptContent($content, salt); + }); + }; + + // bind decryptor input enter keydown event + this.$el.querySelector('#fixit-decryptor-input')?.addEventListener('keydown', (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + decryptorHandler(); } }); + + // bind decryptor button click event + this.$el.querySelector('.fixit-decryptor-btn')?.addEventListener('click', (e) => { + e.preventDefault(); + decryptorHandler(); + }); - this.$el.querySelector('.fixit-encryptor-btn')?.addEventListener('click', function (e) { + // bind encryptor button click event + this.$el.querySelector('.fixit-encryptor-btn')?.addEventListener('click', (e) => { e.preventDefault(); - this.classList.add('d-none') - _decryptor.$el.querySelector('#fixit-decryptor-input').classList.remove('d-none'); + e.target.classList.add('d-none') + this.$el.querySelector('.fixit-decryptor-input').classList.remove('d-none'); + this.$el.querySelector('.fixit-decryptor-btn').classList.remove('d-none'); document.querySelector('#content').innerHTML = ''; document.querySelector('#content').insertAdjacentElement( 'afterbegin', - _decryptor.$el + this.$el ); window.localStorage?.removeItem(`fixit-decryptor/#${location.pathname}`); // reset hook - for (const event of _decryptor.resetEventSet) { + for (const event of this.resetEventSet) { event(); } }); @@ -101,50 +140,31 @@ FixItDecryptor = function (options = {}) { * initialize fixit-encryptor shortcodes */ _proto.initShortcodes = () => { - // TODO TODO shortcode decrypted event - // this.addEventListener('decrypted', this.options?.decrypted); - const _decryptor = this; - const $shortcodes = document.querySelectorAll('fixit-encryptor:not(.decrypted)'); + customElements.get('fixit-encryptor') || customElements.define('fixit-encryptor', class extends HTMLElement {}); + const $shortcodes = document.querySelectorAll('fixit-encryptor:not(:has(.decrypted))'); $shortcodes.forEach($shortcode => { + const decryptorHandler = () => { + const $decryptor = $shortcode.querySelector('.fixit-decryptor-container'); + const $content = $shortcode.querySelector('[data-password][data-content]'); + _validatePassword($decryptor, $content, (password, salt) => { + _decryptContent($content, salt, false); + }); + }; + + // bind decryptor input enter keydown event $shortcode.querySelector('.fixit-decryptor-input')?.addEventListener('keydown', function (e) { if (e.key === 'Enter') { e.preventDefault(); - const $decryptor = this.parentElement.parentElement; - const $content = $decryptor.nextElementSibling; - const password = $content.getAttribute('data-password'); - const input = this.value.trim(); - const saltLen = input.length % 2 ? input.length : input.length + 1; - const inputMd5 = CryptoJS.MD5(input).toString(); - const inputSha256 = CryptoJS.SHA256(input).toString(); - - this.value = ''; - this.blur(); - if (!input) { - alert('Please enter the correct password!'); - return console.warn('Please enter the correct password!'); - } - if (inputMd5 !== password) { - alert(`Password error: ${input} not the correct password!`); - return console.warn(`Password error: ${input} not the correct password!`); - } - try { - const base64EncodeContent = $content.getAttribute('data-content').replace(inputSha256.slice(saltLen), ''); - $decryptor.querySelector('.fixit-decryptor-input').classList.add('d-none'); - $content.insertAdjacentHTML( - 'afterbegin', - CryptoJS.enc.Base64.parse(base64EncodeContent).toString(CryptoJS.enc.Utf8) - ); - $decryptor.parentElement.classList.add('decrypted'); - } catch (err) { - return console.error(err); - } - // TODO shortcode decrypted hook - // for (const event of _decryptor.decryptedEventSet) { - // event(); - // } + decryptorHandler(); } }); + + // bind decryptor button click event + $shortcode.querySelector('.fixit-decryptor-btn')?.addEventListener('click', function (e) { + e.preventDefault(); + decryptorHandler(); + }); }); }; @@ -159,17 +179,18 @@ FixItDecryptor = function (options = {}) { if (!cachedStat) { this.$el.querySelector('.fixit-decryptor-loading').classList.add('d-none'); - this.$el.querySelector('#fixit-decryptor-input').classList.remove('d-none'); + this.$el.querySelector('.fixit-decryptor-input').classList.remove('d-none'); + this.$el.querySelector('.fixit-decryptor-btn').classList.remove('d-none'); return this; } - if (cachedStat?.md5 !== password || Number(cachedStat?.expiration) < Math.ceil(Date.now() / 1000)) { + if (cachedStat?.password !== password || Number(cachedStat?.expiration) < Math.ceil(Date.now() / 1000)) { this.$el.querySelector('.fixit-decryptor-loading').classList.add('d-none'); - this.$el.querySelector('#fixit-decryptor-input').classList.remove('d-none'); + this.$el.querySelector('.fixit-decryptor-input').classList.remove('d-none'); window.localStorage?.removeItem(`fixit-decryptor/#${location.pathname}`); console.warn('The password has expired, please re-enter!'); return this; } - _decryptContent($content.getAttribute('data-content').replace(cachedStat.sha256, '')); + _decryptContent($content, cachedStat.salt); return this; }; @@ -187,6 +208,9 @@ FixItDecryptor = function (options = {}) { case 'decrypted': this.decryptedEventSet.add(listener); break; + case 'partial-decrypted': + this.partialDecryptedEventSet.add(listener); + break; case 'reset': this.resetEventSet.add(listener); break; @@ -211,6 +235,9 @@ FixItDecryptor = function (options = {}) { case 'decrypted': this.decryptedEventSet.delete(listener); break; + case 'partial-decrypted': + this.partialDecryptedEventSet.delete(listener); + break; case 'reset': this.resetEventSet.delete(listener); break; diff --git a/assets/js/theme.js b/assets/js/theme.js index 9fb19ba14..c87246e22 100644 --- a/assets/js/theme.js +++ b/assets/js/theme.js @@ -48,8 +48,8 @@ class FixIt { }); } - initTwemoji() { - this.config.twemoji && twemoji.parse(document.body); + initTwemoji(target = document.body) { + this.config.twemoji && twemoji.parse(target); } initMenu() { @@ -93,7 +93,7 @@ class FixIt { this.isDark = !this.isDark; window.localStorage?.setItem('theme', this.isDark ? 'dark' : 'light'); for (let event of this.switchThemeEventSet) { - event(); + event(this.isDark); } }, false); }); @@ -333,8 +333,8 @@ class FixIt { } } - initDetails() { - this.util.forEach(document.getElementsByClassName('details'), ($details) => { + initDetails(target = document) { + this.util.forEach(target.getElementsByClassName('details'), ($details) => { const $summary = $details.querySelector('.details-summary'); $summary.addEventListener('click', () => { $details.classList.toggle('open'); @@ -344,7 +344,8 @@ class FixIt { initLightGallery() { if (this.config.lightgallery) { - lightGallery(document.getElementById('content'), { + this.lg && this.lg.destroy(true); + this.lg = lightGallery(document.getElementById('content'), { plugins: [lgThumbnail, lgZoom], selector: '.lightgallery', speed: 400, @@ -376,7 +377,7 @@ class FixIt { $preChroma.parentElement.replaceChild($chroma, $preChroma); $td.appendChild($preChroma); }); - this.util.forEach(document.querySelectorAll('.highlight > .chroma'), ($chroma) => { + this.util.forEach(document.querySelectorAll('.highlight > .chroma:not(:has(.code-header))'), ($chroma) => { const $codeElements = $chroma.querySelectorAll('pre.chroma > code'); if ($codeElements.length) { const $code = $codeElements[$codeElements.length - 1]; @@ -455,8 +456,8 @@ class FixIt { }); } - initTable() { - this.util.forEach(document.querySelectorAll('.content table'), ($table) => { + initTable(target = document) { + this.util.forEach(target.querySelectorAll('.content table'), ($table) => { const $wrapper = document.createElement('div'); $wrapper.className = 'table-wrapper'; $table.parentElement.replaceChild($wrapper, $table); @@ -548,9 +549,9 @@ class FixIt { }, false); } - initMath() { + initMath(target = document.body) { if (this.config.math) { - renderMathInElement(document.body, this.config.math); + renderMathInElement(target, this.config.math); } } @@ -561,11 +562,13 @@ class FixIt { const themes = window.mermaid.themes ?? ['default', 'dark']; window.mermaid.initialize({ securityLevel: 'loose', - startOnLoad: true, + startOnLoad: false, theme: this.isDark ? themes[1] : themes[0], }); - this.switchThemeEventSet.add(() => { + window.mermaid.run() + this.switchThemeEventSet.add((isDark) => { // Mermaid does not provide a method for switching yet. When switching themes, refresh the page. + // TODO save the original mermaid pre and reload the mermaid render window.location.reload(); }); this.beforeprintEventSet.add(() => { @@ -579,6 +582,7 @@ class FixIt { } echarts.registerTheme('light', this.config.echarts.lightTheme); echarts.registerTheme('dark', this.config.echarts.darkTheme); + // BUG 主题切换的时候有问题 this._echartsOnSwitchTheme = this._echartsOnSwitchTheme || (() => { this._echartsArr = this._echartsArr || []; for (let i = 0; i < this._echartsArr.length; i++) { @@ -606,10 +610,13 @@ class FixIt { initMapbox() { if (this.config.mapbox) { - mapboxgl.accessToken = this.config.mapbox.accessToken; - mapboxgl.setRTLTextPlugin(this.config.mapbox.RTLTextPlugin); - this._mapboxArr = this._mapboxArr || []; - this.util.forEach(document.getElementsByClassName('mapbox'), ($mapbox) => { + if (!mapboxgl.accessToken) { + mapboxgl.accessToken = this.config.mapbox.accessToken; + mapboxgl.setRTLTextPlugin(this.config.mapbox.RTLTextPlugin); + this._mapboxArr = this._mapboxArr || []; + } + // BUG 切换主题时有问题 + this.util.forEach(document.querySelectorAll('.mapbox:empty'), ($mapbox) => { const { lng, lat, zoom, lightStyle, darkStyle, marked, navigation, geolocate, scale, fullscreen } = JSON.parse($mapbox.dataset.options); const mapbox = new mapboxgl.Map({ container: $mapbox, @@ -658,7 +665,7 @@ class FixIt { } } - initTypeit() { + initTypeit(target = document) { if (this.config.typeit) { const typeitConfig = this.config.typeit; const speed = typeitConfig.speed || 100; @@ -667,7 +674,7 @@ class FixIt { const loop = typeitConfig.loop ?? false; // divide them into different groups according to the data-group attribute value of the element // results in an object like {group1: [ele1, ele2], group2: [ele3, ele4]} - const typeitElements = document.querySelectorAll('.typeit') + const typeitElements = target.querySelectorAll('.typeit') const groupMap = Array.from(typeitElements).reduce((acc, ele) => { const group = ele.dataset.group || ele.id || Math.random().toString(36).substring(2); acc[group] = acc[group] || []; @@ -953,12 +960,28 @@ class FixIt { this.initEcharts(); this.initTypeit(); this.initMapbox(); + this.initToc(); + this.initTocListener(); + this.initPangu(); this.util.forEach(document.querySelectorAll('.encrypted-hidden'), ($element) => { $element.classList.replace('encrypted-hidden', 'decrypted-shown'); }); - this.initToc(); - this.initTocListener(); + }, + partialDecrypted: ($content) => { + this.initTwemoji($content); + this.initDetails($content); + this.initLightGallery(); + this.initHighlight(); + this.initTable($content); + this.initMath($content); + // TODO this.initEcharts(); + this.initTypeit($content); + this.initMapbox(); this.initPangu(); + window.mermaid.run && window.mermaid.run(); + this.util.forEach($content.querySelectorAll('.encrypted-hidden'), ($element) => { + $element.classList.replace('encrypted-hidden', 'decrypted-shown'); + }); }, reset: () => { this.util.forEach(document.querySelectorAll('.decrypted-shown'), ($element) => { @@ -970,6 +993,9 @@ class FixIt { this.decryptor.addEventListener('decrypted', () => { this.decryptor.initShortcodes(); }) + this.decryptor.addEventListener('partial-decrypted', () => { + this.decryptor.initShortcodes(); + }) this.decryptor.initShortcodes(); } this.config.encryption?.all && this.decryptor.init(); diff --git a/i18n/de.toml b/i18n/de.toml index 3e559e528..a7772a12f 100644 --- a/i18n/de.toml +++ b/i18n/de.toml @@ -129,6 +129,7 @@ expirationReminder = "Dieser Artikel wurde zuletzt auf {{ .Date }} aktualisiert, encryptedAbstract = "" encryptedMessage = "" password = "Passwort" +enterBtn = "" encryptyAgain = "" relatedContent = "Ähnliche Inhalte" diff --git a/i18n/en.toml b/i18n/en.toml index 209f15c09..94c7341b9 100644 --- a/i18n/en.toml +++ b/i18n/en.toml @@ -128,6 +128,7 @@ expirationReminder = "This article was last updated on {{ .Date }}, the content encryptedAbstract = "This article has been encrypted, so its raw content is invisible!" encryptedMessage = "Please enter the password" password = "Password" +enterBtn = "Enter" encryptyAgain = "Encrypt again" relatedContent = "Related Content" diff --git a/i18n/es.toml b/i18n/es.toml index effdf4072..ed39c8dd2 100644 --- a/i18n/es.toml +++ b/i18n/es.toml @@ -129,6 +129,7 @@ expirationReminder = "Este artículo se actualizó por última vez el {{ .Date } encryptedAbstract = "" encryptedMessage = "" password = "Contraseña" +enterBtn = "" encryptyAgain = "" relatedContent = "Contenido relacionado" diff --git a/i18n/fr.toml b/i18n/fr.toml index 34e6d5a05..18b8cafe7 100644 --- a/i18n/fr.toml +++ b/i18n/fr.toml @@ -128,6 +128,7 @@ expirationReminder = "Cet article a été mis à jour pour la dernière fois le encryptedAbstract = "Cet article a été chiffré, son contenu n'est donc pas lisible!" encryptedMessage = "Entrer le mot de passe" password = "Mot de passe" +enterBtn = "Entrer" encryptyAgain = "Chiffrer à nouveau" relatedContent = "Contenu lié" diff --git a/i18n/hi.toml b/i18n/hi.toml index 49bde0e28..1d9595276 100644 --- a/i18n/hi.toml +++ b/i18n/hi.toml @@ -129,6 +129,7 @@ expirationReminder = "यह लेख अंतिम बार {{ .Date }} प encryptedAbstract = "यह लेख एन्क्रिप्ट किया गया है, इसलिए इसकी मूल सामग्री अदृश्य है!" encryptedMessage = "कृपया पासवर्ड दर्ज करें" password = "पासवर्ड" +enterBtn = "दर्ज करें" encryptyAgain = "फिर से एन्क्रिप्ट करें" relatedContent = "संबंधित सामग्री" diff --git a/i18n/it.toml b/i18n/it.toml index 21bb4f270..4e983a262 100644 --- a/i18n/it.toml +++ b/i18n/it.toml @@ -129,6 +129,7 @@ expirationReminder = "Questo articolo è stato aggiornato l'ultima volta il {{ . encryptedAbstract = "" encryptedMessage = "" password = "Password" +enterBtn = "" encryptyAgain = "" relatedContent = "Contenuti correlati" diff --git a/i18n/pl.toml b/i18n/pl.toml index 0a8209ff6..26642b7c6 100644 --- a/i18n/pl.toml +++ b/i18n/pl.toml @@ -129,6 +129,7 @@ expirationReminder = "Ten artykuł był ostatnio aktualizowany {{ .Date }}, jego encryptedAbstract = "" encryptedMessage = "" password = "Hasło" +enterBtn = "" encryptyAgain = "" relatedContent = "Powiązane treści" diff --git a/i18n/pt-BR.toml b/i18n/pt-BR.toml index 10b88c5bc..e4cf70a9a 100644 --- a/i18n/pt-BR.toml +++ b/i18n/pt-BR.toml @@ -129,6 +129,7 @@ expirationReminder = "Este artigo foi atualizado pela última vez em {{ .Date }} encryptedAbstract = "" encryptedMessage = "" password = "Contrasinha" +enterBtn = "" encryptyAgain = "" relatedContent = "Conteúdo relacionado" diff --git a/i18n/ro.toml b/i18n/ro.toml index 8f2dc1d58..152b1f477 100644 --- a/i18n/ro.toml +++ b/i18n/ro.toml @@ -129,6 +129,7 @@ expirationReminder = "Acest articol a fost actualizat ultima dată pe {{ .Date } encryptedAbstract = "" encryptedMessage = "" password = "Parolă" +enterBtn = "" encryptyAgain = "" relatedContent = "Conținut înrudit" diff --git a/i18n/ru.toml b/i18n/ru.toml index 85a514e63..2610bdb07 100644 --- a/i18n/ru.toml +++ b/i18n/ru.toml @@ -129,6 +129,7 @@ expirationReminder = "Эта статья последний раз обновл encryptedAbstract = "" encryptedMessage = "" password = "арготизм" +enterBtn = "" encryptyAgain = "" relatedContent = "Связанный контент" diff --git a/i18n/sr.toml b/i18n/sr.toml index 3da42f632..6b7ce2e61 100644 --- a/i18n/sr.toml +++ b/i18n/sr.toml @@ -129,6 +129,7 @@ expirationReminder = "Овај чланак је последњи пут ажу encryptedAbstract = "" encryptedMessage = "" password = "Паролица" +enterBtn = "" encryptyAgain = "" relatedContent = "Повезани садржај" diff --git a/i18n/vi.toml b/i18n/vi.toml index 948f5bdb5..2e2062ab1 100644 --- a/i18n/vi.toml +++ b/i18n/vi.toml @@ -128,6 +128,7 @@ expirationReminder = "Bài viết này được cập nhật lần cuối vào { encryptedAbstract = "" encryptedMessage = "" password = "Mật khẩu" +enterBtn = "" encryptyAgain = "" relatedContent = "Nội dung liên quan" diff --git a/i18n/zh-CN.toml b/i18n/zh-CN.toml index b1ed49fe9..93bc346ef 100644 --- a/i18n/zh-CN.toml +++ b/i18n/zh-CN.toml @@ -126,6 +126,7 @@ expirationReminder = "本文最后更新于 {{ .Date }},文中内容可能已 encryptedAbstract = "本文已加密,因此其原始内容不可见!" encryptedMessage = "请输入密码" password = "密码" +enterBtn = "进入" encryptyAgain = "重新加密" relatedContent = "相关内容" diff --git a/i18n/zh-TW.toml b/i18n/zh-TW.toml index 643b23c05..020f3e953 100644 --- a/i18n/zh-TW.toml +++ b/i18n/zh-TW.toml @@ -126,6 +126,7 @@ expirationReminder = "本文最後更新於 {{ .Date }},文中內容可能已 encryptedAbstract = "本文已加密,囙此其原始內容不可見!" encryptedMessage = "請輸入密碼" password = "密碼" +enterBtn = "進入" encryptyAgain = "重新加密" relatedContent = "相關內容" diff --git a/layouts/partials/single/fixit-decryptor.html b/layouts/partials/single/fixit-decryptor.html index 1f107450f..a73119c56 100644 --- a/layouts/partials/single/fixit-decryptor.html +++ b/layouts/partials/single/fixit-decryptor.html @@ -6,8 +6,11 @@