Merge branch 'feature/encryption' (#123)

This commit is contained in:
Cell
2022-05-27 23:47:31 +08:00
40 changed files with 2233 additions and 56 deletions
+1
View File
@@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
> Add hugo new features support.
> Snapshot:
- :tada: Feat: add content encryption of pages ([#123](https://github.com/Lruihao/FixIt/issues/123))
- :sparkles: Feat: add total word count feature in section and remove from footer ([#124](https://github.com/Lruihao/FixIt/issues/124))
- :sparkles: Feat: enhance auto toc feature ([#104](https://github.com/Lruihao/FixIt/issues/104) [#136](https://github.com/Lruihao/FixIt/issues/136))
- :sparkles: Feat(SEO): add options to make output baidu_urls.txt file ([#138](https://github.com/Lruihao/FixIt/issues/138))
+1
View File
@@ -248,6 +248,7 @@ Thanks to the authors of following resources included in the theme:
* [Twikoo](https://twikoo.js.org/)
* [github-corners](https://github.com/tholman/github-corners)
* [giscus](https://giscus.app/)
* [crypto-js](https://github.com/brix/crypto-js)
## Author
+1
View File
@@ -247,6 +247,7 @@ FixIt 主题中用到了以下项目,感谢它们的作者:
* [Twikoo](https://twikoo.js.org/)
* [github-corners](https://github.com/tholman/github-corners)
* [giscus](https://giscus.app/zh-CN)
* [crypto-js](https://github.com/brix/crypto-js)
## 作者
+3 -1
View File
@@ -18,7 +18,9 @@
text-align: center !important;
}
.d-none,
.d-none {
display: none !important;
}
.d-none-desktop {
display: none;
}
+1
View File
@@ -1,4 +1,5 @@
@import '../_partial/_single/toc';
@import '../_partial/_single/fixit-decryptor';
.single {
.single-title {
@@ -0,0 +1,52 @@
.fixit-decryptor-container {
font-family: $global-font-family;
text-align: center;
margin-top: 3rem;
#fixit-decryptor-input,
.fixit-encryptor-btn {
display: inline-block;
box-sizing: border-box;
outline: none;
color: $global-font-color;
background-color: $global-background-color;
border: 1px solid darken($global-border-color, 15%);
border-radius: $global-border-radius;
transition: 0.1s;
box-shadow: 0px 0px 5px 0px darken($global-border-color, 15%);
&:active,
&:focus,
&:hover {
color: darken($global-link-hover-color, 6%);
border-color: $global-link-hover-color;
box-shadow: 0px 0px 5px 0px lighten($global-link-hover-color, 20%);
[theme='dark'] & {
color: lighten($global-link-hover-color-dark, 6%);
border-color: $global-link-hover-color-dark;
box-shadow: 0px 0px 5px 0px darken($global-link-hover-color-dark, 20%);
}
}
[theme='dark'] & {
color: $global-font-color-dark;
border-color: lighten($global-border-color-dark, 15%);
background-color: $global-background-color-dark;
box-shadow: 0px 0px 5px 0px lighten($global-border-color-dark, 15%);
}
}
#fixit-decryptor-input {
width: clamp(50%, 400px, 100%);
height: 3rem;
padding-left: 1rem;
padding-right: 1rem;
}
.fixit-encryptor-btn {
cursor: pointer;
transition: 0.1s;
padding: 0.6rem 1rem;
}
}
+9
View File
@@ -1,3 +1,7 @@
# Tip: remove sourceMappingURL of local libraries to avoid source map 404 error.
# See https://github.com/Lruihao/FixIt/issues/67
# TODO https://unpkg.com/ cdn support
prefix:
libFiles: https://cdn.jsdelivr.net/npm/
# simple-icons@6.3.0 https://github.com/simple-icons/simple-icons
@@ -20,6 +24,11 @@ libFiles:
# cookieconsent@3.1.1 https://github.com/osano/cookieconsent
cookieconsentCSS: cookieconsent@3.1.1/build/cookieconsent.min.css
cookieconsentJS: cookieconsent@3.1.1/build/cookieconsent.min.js
# crypto-js@4.1.1 https://github.com/brix/crypto-js
cryptoCoreJS: crypto-js@4.1.1/core.js
cryptoEncBase64JS: crypto-js@4.1.1/enc-base64.js
cryptoMd5JS: crypto-js@4.1.1/md5.js
cryptoSha256JS: crypto-js@4.1.1/sha256.js
# echarts@5.2.2 https://github.com/apache/echarts
echartsJS: echarts@5.3.2/dist/echarts.min.js
echartsMacaronsJS: echarts@5.3.2/theme/macarons.min.js
+163
View File
@@ -0,0 +1,163 @@
/**
* FixIt decryptor for encrypted pages
* @param {Object} options
* @param {Function} [options.decrypted] handler after decrypting
* @param {Function} [options.reset] handler after encrypting again
* @param {Number} [options.duration=86400] number of seconds to cache decryption statistics. unit: s
* @author @Lruihao https://lruihao.cn
* @since v0.2.15
*/
FixItDecryptor = function (options = {}) {
var _proto = FixItDecryptor.prototype;
this.options = options || {};
this.options.duration = this.options.duration || 24 * 60 * 60; // default cache one day
this.decryptedEventSet = new Set();
this.resetEventSet = new Set();
this.$el = document.querySelector('.fixit-decryptor-container');
/**
* decrypt content
* @param {String} base64EncodeContent encrypted content
*/
var _decryptContent = (base64EncodeContent) => {
try {
this.$el.querySelector('#fixit-decryptor-input').classList.add('d-none');
this.$el.querySelector('.fixit-encryptor-btn').classList.remove('d-none');
document.querySelector('#content').insertAdjacentHTML(
'afterbegin',
CryptoJS.enc.Base64.parse(base64EncodeContent).toString(CryptoJS.enc.Utf8)
);
} catch (err) {
return console.error(err);
}
// decrypted hook
for (const event of this.decryptedEventSet) {
event();
}
};
/**
* initialize FixIt decryptor
*/
_proto.init = () => {
this.addEventListener('decrypted', this.options?.decrypted);
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 = '';
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!`);
}
// 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)
})
);
_decryptContent($content.getAttribute('data-content').replace(inputSha256.slice(saltLen), ''));
}
});
this.$el.querySelector('.fixit-encryptor-btn')?.addEventListener('click', function (e) {
e.preventDefault();
this.classList.add('d-none')
_decryptor.$el.querySelector('#fixit-decryptor-input').classList.remove('d-none');
document.querySelector('#content').innerHTML = '';
document.querySelector('#content').insertAdjacentElement(
'afterbegin',
_decryptor.$el
);
window.localStorage.removeItem(`fixit-decryptor/#${location.pathname}`);
// reset hook
for (const event of _decryptor.resetEventSet) {
event();
}
});
};
/**
* validate the cached decryption statistics in localStorage
*/
_proto.validateCache = () => {
const $content = document.querySelector('#content');
const password = $content.getAttribute('data-password');
const cachedStat = JSON.parse(window.localStorage.getItem(`fixit-decryptor/#${location.pathname}`));
if (!cachedStat) {
return this.$el.querySelector('#fixit-decryptor-input').classList.remove('d-none');
}
if (cachedStat?.md5 !== password || Number(cachedStat?.expiration) < Math.ceil(Date.now() / 1000)) {
this.$el.querySelector('#fixit-decryptor-input').classList.remove('d-none');
window.localStorage.removeItem(`fixit-decryptor/#${location.pathname}`);
return console.warn('The password has expired, please re-enter!');
}
_decryptContent($content.getAttribute('data-content').replace(cachedStat.sha256, ''));
};
/**
* add event listener for FixIt Decryptor
* @param {String} event
* @param {Function} listener event handler
* @returns {FixItDecryptor}
*/
_proto.addEventListener = (event, listener) => {
if (typeof listener !== 'function') {
return this;
}
switch (event) {
case 'decrypted':
this.decryptedEventSet.add(listener);
break;
case 'reset':
this.resetEventSet.add(listener);
break;
default:
console.warn(`Event ${event} not found in FixIt Decryptor!`);
break;
}
return this;
};
/**
* remove event listener for FixIt Decryptor
* @param {String} event
* @param {Function} listener event handler
* @returns {FixItDecryptor}
*/
_proto.removeEventListener = (event, listener) => {
if (typeof listener !== 'function') {
return this;
}
switch (event) {
case 'decrypted':
this.decryptedEventSet.delete(listener);
break;
case 'reset':
this.resetEventSet.delete(listener);
break;
default:
console.warn(`Event ${event} not found in FixIt Decryptor!`);
break;
}
return this;
};
};
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -5,6 +5,7 @@ artalk@2.2.12 https://github.com/ArtalkJS/Artalk
autocomplete.js@0.38.1 https://github.com/algolia/autocomplete.js
cell-watermark@1.0.3 https://github.com/Lruihao/watermark
cookieconsent@3.1.1 https://github.com/osano/cookieconsent
crypto-js@4.1.1 https://github.com/brix/crypto-js
echarts@5.3.2 https://github.com/apache/echarts
fontawesome-free@6.1.1 https://github.com/FortAwesome/Font-Awesome
gitalk@1.7.2 https://github.com/gitalk/gitalk
+807
View File
@@ -0,0 +1,807 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory();
}
else if (typeof define === "function" && define.amd) {
// AMD
define([], factory);
}
else {
// Global (browser)
root.CryptoJS = factory();
}
}(this, function () {
/*globals window, global, require*/
/**
* CryptoJS core components.
*/
var CryptoJS = CryptoJS || (function (Math, undefined) {
var crypto;
// Native crypto from window (Browser)
if (typeof window !== 'undefined' && window.crypto) {
crypto = window.crypto;
}
// Native crypto in web worker (Browser)
if (typeof self !== 'undefined' && self.crypto) {
crypto = self.crypto;
}
// Native crypto from worker
if (typeof globalThis !== 'undefined' && globalThis.crypto) {
crypto = globalThis.crypto;
}
// Native (experimental IE 11) crypto from window (Browser)
if (!crypto && typeof window !== 'undefined' && window.msCrypto) {
crypto = window.msCrypto;
}
// Native crypto from global (NodeJS)
if (!crypto && typeof global !== 'undefined' && global.crypto) {
crypto = global.crypto;
}
// Native crypto import via require (NodeJS)
if (!crypto && typeof require === 'function') {
try {
crypto = require('crypto');
} catch (err) {}
}
/*
* Cryptographically secure pseudorandom number generator
*
* As Math.random() is cryptographically not safe to use
*/
var cryptoSecureRandomInt = function () {
if (crypto) {
// Use getRandomValues method (Browser)
if (typeof crypto.getRandomValues === 'function') {
try {
return crypto.getRandomValues(new Uint32Array(1))[0];
} catch (err) {}
}
// Use randomBytes method (NodeJS)
if (typeof crypto.randomBytes === 'function') {
try {
return crypto.randomBytes(4).readInt32LE();
} catch (err) {}
}
}
throw new Error('Native crypto module could not be used to get secure random number.');
};
/*
* Local polyfill of Object.create
*/
var create = Object.create || (function () {
function F() {}
return function (obj) {
var subtype;
F.prototype = obj;
subtype = new F();
F.prototype = null;
return subtype;
};
}());
/**
* CryptoJS namespace.
*/
var C = {};
/**
* Library namespace.
*/
var C_lib = C.lib = {};
/**
* Base object for prototypal inheritance.
*/
var Base = C_lib.Base = (function () {
return {
/**
* Creates a new object that inherits from this object.
*
* @param {Object} overrides Properties to copy into the new object.
*
* @return {Object} The new object.
*
* @static
*
* @example
*
* var MyType = CryptoJS.lib.Base.extend({
* field: 'value',
*
* method: function () {
* }
* });
*/
extend: function (overrides) {
// Spawn
var subtype = create(this);
// Augment
if (overrides) {
subtype.mixIn(overrides);
}
// Create default initializer
if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {
subtype.init = function () {
subtype.$super.init.apply(this, arguments);
};
}
// Initializer's prototype is the subtype object
subtype.init.prototype = subtype;
// Reference supertype
subtype.$super = this;
return subtype;
},
/**
* Extends this object and runs the init method.
* Arguments to create() will be passed to init().
*
* @return {Object} The new object.
*
* @static
*
* @example
*
* var instance = MyType.create();
*/
create: function () {
var instance = this.extend();
instance.init.apply(instance, arguments);
return instance;
},
/**
* Initializes a newly created object.
* Override this method to add some logic when your objects are created.
*
* @example
*
* var MyType = CryptoJS.lib.Base.extend({
* init: function () {
* // ...
* }
* });
*/
init: function () {
},
/**
* Copies properties into this object.
*
* @param {Object} properties The properties to mix in.
*
* @example
*
* MyType.mixIn({
* field: 'value'
* });
*/
mixIn: function (properties) {
for (var propertyName in properties) {
if (properties.hasOwnProperty(propertyName)) {
this[propertyName] = properties[propertyName];
}
}
// IE won't copy toString using the loop above
if (properties.hasOwnProperty('toString')) {
this.toString = properties.toString;
}
},
/**
* Creates a copy of this object.
*
* @return {Object} The clone.
*
* @example
*
* var clone = instance.clone();
*/
clone: function () {
return this.init.prototype.extend(this);
}
};
}());
/**
* An array of 32-bit words.
*
* @property {Array} words The array of 32-bit words.
* @property {number} sigBytes The number of significant bytes in this word array.
*/
var WordArray = C_lib.WordArray = Base.extend({
/**
* Initializes a newly created word array.
*
* @param {Array} words (Optional) An array of 32-bit words.
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
*
* @example
*
* var wordArray = CryptoJS.lib.WordArray.create();
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
*/
init: function (words, sigBytes) {
words = this.words = words || [];
if (sigBytes != undefined) {
this.sigBytes = sigBytes;
} else {
this.sigBytes = words.length * 4;
}
},
/**
* Converts this word array to a string.
*
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
*
* @return {string} The stringified word array.
*
* @example
*
* var string = wordArray + '';
* var string = wordArray.toString();
* var string = wordArray.toString(CryptoJS.enc.Utf8);
*/
toString: function (encoder) {
return (encoder || Hex).stringify(this);
},
/**
* Concatenates a word array to this word array.
*
* @param {WordArray} wordArray The word array to append.
*
* @return {WordArray} This word array.
*
* @example
*
* wordArray1.concat(wordArray2);
*/
concat: function (wordArray) {
// Shortcuts
var thisWords = this.words;
var thatWords = wordArray.words;
var thisSigBytes = this.sigBytes;
var thatSigBytes = wordArray.sigBytes;
// Clamp excess bits
this.clamp();
// Concat
if (thisSigBytes % 4) {
// Copy one byte at a time
for (var i = 0; i < thatSigBytes; i++) {
var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
}
} else {
// Copy one word at a time
for (var j = 0; j < thatSigBytes; j += 4) {
thisWords[(thisSigBytes + j) >>> 2] = thatWords[j >>> 2];
}
}
this.sigBytes += thatSigBytes;
// Chainable
return this;
},
/**
* Removes insignificant bits.
*
* @example
*
* wordArray.clamp();
*/
clamp: function () {
// Shortcuts
var words = this.words;
var sigBytes = this.sigBytes;
// Clamp
words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
words.length = Math.ceil(sigBytes / 4);
},
/**
* Creates a copy of this word array.
*
* @return {WordArray} The clone.
*
* @example
*
* var clone = wordArray.clone();
*/
clone: function () {
var clone = Base.clone.call(this);
clone.words = this.words.slice(0);
return clone;
},
/**
* Creates a word array filled with random bytes.
*
* @param {number} nBytes The number of random bytes to generate.
*
* @return {WordArray} The random word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.lib.WordArray.random(16);
*/
random: function (nBytes) {
var words = [];
for (var i = 0; i < nBytes; i += 4) {
words.push(cryptoSecureRandomInt());
}
return new WordArray.init(words, nBytes);
}
});
/**
* Encoder namespace.
*/
var C_enc = C.enc = {};
/**
* Hex encoding strategy.
*/
var Hex = C_enc.Hex = {
/**
* Converts a word array to a hex string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The hex string.
*
* @static
*
* @example
*
* var hexString = CryptoJS.enc.Hex.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
// Convert
var hexChars = [];
for (var i = 0; i < sigBytes; i++) {
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
hexChars.push((bite >>> 4).toString(16));
hexChars.push((bite & 0x0f).toString(16));
}
return hexChars.join('');
},
/**
* Converts a hex string to a word array.
*
* @param {string} hexStr The hex string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Hex.parse(hexString);
*/
parse: function (hexStr) {
// Shortcut
var hexStrLength = hexStr.length;
// Convert
var words = [];
for (var i = 0; i < hexStrLength; i += 2) {
words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
}
return new WordArray.init(words, hexStrLength / 2);
}
};
/**
* Latin1 encoding strategy.
*/
var Latin1 = C_enc.Latin1 = {
/**
* Converts a word array to a Latin1 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The Latin1 string.
*
* @static
*
* @example
*
* var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
// Convert
var latin1Chars = [];
for (var i = 0; i < sigBytes; i++) {
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
latin1Chars.push(String.fromCharCode(bite));
}
return latin1Chars.join('');
},
/**
* Converts a Latin1 string to a word array.
*
* @param {string} latin1Str The Latin1 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
*/
parse: function (latin1Str) {
// Shortcut
var latin1StrLength = latin1Str.length;
// Convert
var words = [];
for (var i = 0; i < latin1StrLength; i++) {
words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
}
return new WordArray.init(words, latin1StrLength);
}
};
/**
* UTF-8 encoding strategy.
*/
var Utf8 = C_enc.Utf8 = {
/**
* Converts a word array to a UTF-8 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The UTF-8 string.
*
* @static
*
* @example
*
* var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
*/
stringify: function (wordArray) {
try {
return decodeURIComponent(escape(Latin1.stringify(wordArray)));
} catch (e) {
throw new Error('Malformed UTF-8 data');
}
},
/**
* Converts a UTF-8 string to a word array.
*
* @param {string} utf8Str The UTF-8 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
*/
parse: function (utf8Str) {
return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
}
};
/**
* Abstract buffered block algorithm template.
*
* The property blockSize must be implemented in a concrete subtype.
*
* @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
*/
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
/**
* Resets this block algorithm's data buffer to its initial state.
*
* @example
*
* bufferedBlockAlgorithm.reset();
*/
reset: function () {
// Initial values
this._data = new WordArray.init();
this._nDataBytes = 0;
},
/**
* Adds new data to this block algorithm's buffer.
*
* @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
*
* @example
*
* bufferedBlockAlgorithm._append('data');
* bufferedBlockAlgorithm._append(wordArray);
*/
_append: function (data) {
// Convert string to WordArray, else assume WordArray already
if (typeof data == 'string') {
data = Utf8.parse(data);
}
// Append
this._data.concat(data);
this._nDataBytes += data.sigBytes;
},
/**
* Processes available data blocks.
*
* This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
*
* @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
*
* @return {WordArray} The processed data.
*
* @example
*
* var processedData = bufferedBlockAlgorithm._process();
* var processedData = bufferedBlockAlgorithm._process(!!'flush');
*/
_process: function (doFlush) {
var processedWords;
// Shortcuts
var data = this._data;
var dataWords = data.words;
var dataSigBytes = data.sigBytes;
var blockSize = this.blockSize;
var blockSizeBytes = blockSize * 4;
// Count blocks ready
var nBlocksReady = dataSigBytes / blockSizeBytes;
if (doFlush) {
// Round up to include partial blocks
nBlocksReady = Math.ceil(nBlocksReady);
} else {
// Round down to include only full blocks,
// less the number of blocks that must remain in the buffer
nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
}
// Count words ready
var nWordsReady = nBlocksReady * blockSize;
// Count bytes ready
var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
// Process blocks
if (nWordsReady) {
for (var offset = 0; offset < nWordsReady; offset += blockSize) {
// Perform concrete-algorithm logic
this._doProcessBlock(dataWords, offset);
}
// Remove processed words
processedWords = dataWords.splice(0, nWordsReady);
data.sigBytes -= nBytesReady;
}
// Return processed words
return new WordArray.init(processedWords, nBytesReady);
},
/**
* Creates a copy of this object.
*
* @return {Object} The clone.
*
* @example
*
* var clone = bufferedBlockAlgorithm.clone();
*/
clone: function () {
var clone = Base.clone.call(this);
clone._data = this._data.clone();
return clone;
},
_minBufferSize: 0
});
/**
* Abstract hasher template.
*
* @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
*/
var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({
/**
* Configuration options.
*/
cfg: Base.extend(),
/**
* Initializes a newly created hasher.
*
* @param {Object} cfg (Optional) The configuration options to use for this hash computation.
*
* @example
*
* var hasher = CryptoJS.algo.SHA256.create();
*/
init: function (cfg) {
// Apply config defaults
this.cfg = this.cfg.extend(cfg);
// Set initial values
this.reset();
},
/**
* Resets this hasher to its initial state.
*
* @example
*
* hasher.reset();
*/
reset: function () {
// Reset data buffer
BufferedBlockAlgorithm.reset.call(this);
// Perform concrete-hasher logic
this._doReset();
},
/**
* Updates this hasher with a message.
*
* @param {WordArray|string} messageUpdate The message to append.
*
* @return {Hasher} This hasher.
*
* @example
*
* hasher.update('message');
* hasher.update(wordArray);
*/
update: function (messageUpdate) {
// Append
this._append(messageUpdate);
// Update the hash
this._process();
// Chainable
return this;
},
/**
* Finalizes the hash computation.
* Note that the finalize operation is effectively a destructive, read-once operation.
*
* @param {WordArray|string} messageUpdate (Optional) A final message update.
*
* @return {WordArray} The hash.
*
* @example
*
* var hash = hasher.finalize();
* var hash = hasher.finalize('message');
* var hash = hasher.finalize(wordArray);
*/
finalize: function (messageUpdate) {
// Final message update
if (messageUpdate) {
this._append(messageUpdate);
}
// Perform concrete-hasher logic
var hash = this._doFinalize();
return hash;
},
blockSize: 512/32,
/**
* Creates a shortcut function to a hasher's object interface.
*
* @param {Hasher} hasher The hasher to create a helper for.
*
* @return {Function} The shortcut function.
*
* @static
*
* @example
*
* var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
*/
_createHelper: function (hasher) {
return function (message, cfg) {
return new hasher.init(cfg).finalize(message);
};
},
/**
* Creates a shortcut function to the HMAC's object interface.
*
* @param {Hasher} hasher The hasher to use in this HMAC helper.
*
* @return {Function} The shortcut function.
*
* @static
*
* @example
*
* var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
*/
_createHmacHelper: function (hasher) {
return function (message, key) {
return new C_algo.HMAC.init(hasher, key).finalize(message);
};
}
});
/**
* Algorithm namespace.
*/
var C_algo = C.algo = {};
return C;
}(Math));
return CryptoJS;
}));
+136
View File
@@ -0,0 +1,136 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
(function () {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var C_enc = C.enc;
/**
* Base64 encoding strategy.
*/
var Base64 = C_enc.Base64 = {
/**
* Converts a word array to a Base64 string.
*
* @param {WordArray} wordArray The word array.
*
* @return {string} The Base64 string.
*
* @static
*
* @example
*
* var base64String = CryptoJS.enc.Base64.stringify(wordArray);
*/
stringify: function (wordArray) {
// Shortcuts
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
var map = this._map;
// Clamp excess bits
wordArray.clamp();
// Convert
var base64Chars = [];
for (var i = 0; i < sigBytes; i += 3) {
var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff;
var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff;
var triplet = (byte1 << 16) | (byte2 << 8) | byte3;
for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) {
base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f));
}
}
// Add padding
var paddingChar = map.charAt(64);
if (paddingChar) {
while (base64Chars.length % 4) {
base64Chars.push(paddingChar);
}
}
return base64Chars.join('');
},
/**
* Converts a Base64 string to a word array.
*
* @param {string} base64Str The Base64 string.
*
* @return {WordArray} The word array.
*
* @static
*
* @example
*
* var wordArray = CryptoJS.enc.Base64.parse(base64String);
*/
parse: function (base64Str) {
// Shortcuts
var base64StrLength = base64Str.length;
var map = this._map;
var reverseMap = this._reverseMap;
if (!reverseMap) {
reverseMap = this._reverseMap = [];
for (var j = 0; j < map.length; j++) {
reverseMap[map.charCodeAt(j)] = j;
}
}
// Ignore padding
var paddingChar = map.charAt(64);
if (paddingChar) {
var paddingIndex = base64Str.indexOf(paddingChar);
if (paddingIndex !== -1) {
base64StrLength = paddingIndex;
}
}
// Convert
return parseLoop(base64Str, base64StrLength, reverseMap);
},
_map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
};
function parseLoop(base64Str, base64StrLength, reverseMap) {
var words = [];
var nBytes = 0;
for (var i = 0; i < base64StrLength; i++) {
if (i % 4) {
var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2);
var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2);
var bitsCombined = bits1 | bits2;
words[nBytes >>> 2] |= bitsCombined << (24 - (nBytes % 4) * 8);
nBytes++;
}
}
return WordArray.create(words, nBytes);
}
}());
return CryptoJS.enc.Base64;
}));
+268
View File
@@ -0,0 +1,268 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
(function (Math) {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var Hasher = C_lib.Hasher;
var C_algo = C.algo;
// Constants table
var T = [];
// Compute constants
(function () {
for (var i = 0; i < 64; i++) {
T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
}
}());
/**
* MD5 hash algorithm.
*/
var MD5 = C_algo.MD5 = Hasher.extend({
_doReset: function () {
this._hash = new WordArray.init([
0x67452301, 0xefcdab89,
0x98badcfe, 0x10325476
]);
},
_doProcessBlock: function (M, offset) {
// Swap endian
for (var i = 0; i < 16; i++) {
// Shortcuts
var offset_i = offset + i;
var M_offset_i = M[offset_i];
M[offset_i] = (
(((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) |
(((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)
);
}
// Shortcuts
var H = this._hash.words;
var M_offset_0 = M[offset + 0];
var M_offset_1 = M[offset + 1];
var M_offset_2 = M[offset + 2];
var M_offset_3 = M[offset + 3];
var M_offset_4 = M[offset + 4];
var M_offset_5 = M[offset + 5];
var M_offset_6 = M[offset + 6];
var M_offset_7 = M[offset + 7];
var M_offset_8 = M[offset + 8];
var M_offset_9 = M[offset + 9];
var M_offset_10 = M[offset + 10];
var M_offset_11 = M[offset + 11];
var M_offset_12 = M[offset + 12];
var M_offset_13 = M[offset + 13];
var M_offset_14 = M[offset + 14];
var M_offset_15 = M[offset + 15];
// Working varialbes
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
// Computation
a = FF(a, b, c, d, M_offset_0, 7, T[0]);
d = FF(d, a, b, c, M_offset_1, 12, T[1]);
c = FF(c, d, a, b, M_offset_2, 17, T[2]);
b = FF(b, c, d, a, M_offset_3, 22, T[3]);
a = FF(a, b, c, d, M_offset_4, 7, T[4]);
d = FF(d, a, b, c, M_offset_5, 12, T[5]);
c = FF(c, d, a, b, M_offset_6, 17, T[6]);
b = FF(b, c, d, a, M_offset_7, 22, T[7]);
a = FF(a, b, c, d, M_offset_8, 7, T[8]);
d = FF(d, a, b, c, M_offset_9, 12, T[9]);
c = FF(c, d, a, b, M_offset_10, 17, T[10]);
b = FF(b, c, d, a, M_offset_11, 22, T[11]);
a = FF(a, b, c, d, M_offset_12, 7, T[12]);
d = FF(d, a, b, c, M_offset_13, 12, T[13]);
c = FF(c, d, a, b, M_offset_14, 17, T[14]);
b = FF(b, c, d, a, M_offset_15, 22, T[15]);
a = GG(a, b, c, d, M_offset_1, 5, T[16]);
d = GG(d, a, b, c, M_offset_6, 9, T[17]);
c = GG(c, d, a, b, M_offset_11, 14, T[18]);
b = GG(b, c, d, a, M_offset_0, 20, T[19]);
a = GG(a, b, c, d, M_offset_5, 5, T[20]);
d = GG(d, a, b, c, M_offset_10, 9, T[21]);
c = GG(c, d, a, b, M_offset_15, 14, T[22]);
b = GG(b, c, d, a, M_offset_4, 20, T[23]);
a = GG(a, b, c, d, M_offset_9, 5, T[24]);
d = GG(d, a, b, c, M_offset_14, 9, T[25]);
c = GG(c, d, a, b, M_offset_3, 14, T[26]);
b = GG(b, c, d, a, M_offset_8, 20, T[27]);
a = GG(a, b, c, d, M_offset_13, 5, T[28]);
d = GG(d, a, b, c, M_offset_2, 9, T[29]);
c = GG(c, d, a, b, M_offset_7, 14, T[30]);
b = GG(b, c, d, a, M_offset_12, 20, T[31]);
a = HH(a, b, c, d, M_offset_5, 4, T[32]);
d = HH(d, a, b, c, M_offset_8, 11, T[33]);
c = HH(c, d, a, b, M_offset_11, 16, T[34]);
b = HH(b, c, d, a, M_offset_14, 23, T[35]);
a = HH(a, b, c, d, M_offset_1, 4, T[36]);
d = HH(d, a, b, c, M_offset_4, 11, T[37]);
c = HH(c, d, a, b, M_offset_7, 16, T[38]);
b = HH(b, c, d, a, M_offset_10, 23, T[39]);
a = HH(a, b, c, d, M_offset_13, 4, T[40]);
d = HH(d, a, b, c, M_offset_0, 11, T[41]);
c = HH(c, d, a, b, M_offset_3, 16, T[42]);
b = HH(b, c, d, a, M_offset_6, 23, T[43]);
a = HH(a, b, c, d, M_offset_9, 4, T[44]);
d = HH(d, a, b, c, M_offset_12, 11, T[45]);
c = HH(c, d, a, b, M_offset_15, 16, T[46]);
b = HH(b, c, d, a, M_offset_2, 23, T[47]);
a = II(a, b, c, d, M_offset_0, 6, T[48]);
d = II(d, a, b, c, M_offset_7, 10, T[49]);
c = II(c, d, a, b, M_offset_14, 15, T[50]);
b = II(b, c, d, a, M_offset_5, 21, T[51]);
a = II(a, b, c, d, M_offset_12, 6, T[52]);
d = II(d, a, b, c, M_offset_3, 10, T[53]);
c = II(c, d, a, b, M_offset_10, 15, T[54]);
b = II(b, c, d, a, M_offset_1, 21, T[55]);
a = II(a, b, c, d, M_offset_8, 6, T[56]);
d = II(d, a, b, c, M_offset_15, 10, T[57]);
c = II(c, d, a, b, M_offset_6, 15, T[58]);
b = II(b, c, d, a, M_offset_13, 21, T[59]);
a = II(a, b, c, d, M_offset_4, 6, T[60]);
d = II(d, a, b, c, M_offset_11, 10, T[61]);
c = II(c, d, a, b, M_offset_2, 15, T[62]);
b = II(b, c, d, a, M_offset_9, 21, T[63]);
// Intermediate hash value
H[0] = (H[0] + a) | 0;
H[1] = (H[1] + b) | 0;
H[2] = (H[2] + c) | 0;
H[3] = (H[3] + d) | 0;
},
_doFinalize: function () {
// Shortcuts
var data = this._data;
var dataWords = data.words;
var nBitsTotal = this._nDataBytes * 8;
var nBitsLeft = data.sigBytes * 8;
// Add padding
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
var nBitsTotalL = nBitsTotal;
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = (
(((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) |
(((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00)
);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
(((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) |
(((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00)
);
data.sigBytes = (dataWords.length + 1) * 4;
// Hash final blocks
this._process();
// Shortcuts
var hash = this._hash;
var H = hash.words;
// Swap endian
for (var i = 0; i < 4; i++) {
// Shortcut
var H_i = H[i];
H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) |
(((H_i << 24) | (H_i >>> 8)) & 0xff00ff00);
}
// Return final computed hash
return hash;
},
clone: function () {
var clone = Hasher.clone.call(this);
clone._hash = this._hash.clone();
return clone;
}
});
function FF(a, b, c, d, x, s, t) {
var n = a + ((b & c) | (~b & d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function GG(a, b, c, d, x, s, t) {
var n = a + ((b & d) | (c & ~d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function HH(a, b, c, d, x, s, t) {
var n = a + (b ^ c ^ d) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function II(a, b, c, d, x, s, t) {
var n = a + (c ^ (b | ~d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
/**
* Shortcut function to the hasher's object interface.
*
* @param {WordArray|string} message The message to hash.
*
* @return {WordArray} The hash.
*
* @static
*
* @example
*
* var hash = CryptoJS.MD5('message');
* var hash = CryptoJS.MD5(wordArray);
*/
C.MD5 = Hasher._createHelper(MD5);
/**
* Shortcut function to the HMAC's object interface.
*
* @param {WordArray|string} message The message to hash.
* @param {WordArray|string} key The secret key.
*
* @return {WordArray} The HMAC.
*
* @static
*
* @example
*
* var hmac = CryptoJS.HmacMD5(message, key);
*/
C.HmacMD5 = Hasher._createHmacHelper(MD5);
}(Math));
return CryptoJS.MD5;
}));
+199
View File
@@ -0,0 +1,199 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
(function (Math) {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var Hasher = C_lib.Hasher;
var C_algo = C.algo;
// Initialization and round constants tables
var H = [];
var K = [];
// Compute constants
(function () {
function isPrime(n) {
var sqrtN = Math.sqrt(n);
for (var factor = 2; factor <= sqrtN; factor++) {
if (!(n % factor)) {
return false;
}
}
return true;
}
function getFractionalBits(n) {
return ((n - (n | 0)) * 0x100000000) | 0;
}
var n = 2;
var nPrime = 0;
while (nPrime < 64) {
if (isPrime(n)) {
if (nPrime < 8) {
H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
}
K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
nPrime++;
}
n++;
}
}());
// Reusable object
var W = [];
/**
* SHA-256 hash algorithm.
*/
var SHA256 = C_algo.SHA256 = Hasher.extend({
_doReset: function () {
this._hash = new WordArray.init(H.slice(0));
},
_doProcessBlock: function (M, offset) {
// Shortcut
var H = this._hash.words;
// Working variables
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
var e = H[4];
var f = H[5];
var g = H[6];
var h = H[7];
// Computation
for (var i = 0; i < 64; i++) {
if (i < 16) {
W[i] = M[offset + i] | 0;
} else {
var gamma0x = W[i - 15];
var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^
((gamma0x << 14) | (gamma0x >>> 18)) ^
(gamma0x >>> 3);
var gamma1x = W[i - 2];
var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^
((gamma1x << 13) | (gamma1x >>> 19)) ^
(gamma1x >>> 10);
W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
}
var ch = (e & f) ^ (~e & g);
var maj = (a & b) ^ (a & c) ^ (b & c);
var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25));
var t1 = h + sigma1 + ch + K[i] + W[i];
var t2 = sigma0 + maj;
h = g;
g = f;
f = e;
e = (d + t1) | 0;
d = c;
c = b;
b = a;
a = (t1 + t2) | 0;
}
// Intermediate hash value
H[0] = (H[0] + a) | 0;
H[1] = (H[1] + b) | 0;
H[2] = (H[2] + c) | 0;
H[3] = (H[3] + d) | 0;
H[4] = (H[4] + e) | 0;
H[5] = (H[5] + f) | 0;
H[6] = (H[6] + g) | 0;
H[7] = (H[7] + h) | 0;
},
_doFinalize: function () {
// Shortcuts
var data = this._data;
var dataWords = data.words;
var nBitsTotal = this._nDataBytes * 8;
var nBitsLeft = data.sigBytes * 8;
// Add padding
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
data.sigBytes = dataWords.length * 4;
// Hash final blocks
this._process();
// Return final computed hash
return this._hash;
},
clone: function () {
var clone = Hasher.clone.call(this);
clone._hash = this._hash.clone();
return clone;
}
});
/**
* Shortcut function to the hasher's object interface.
*
* @param {WordArray|string} message The message to hash.
*
* @return {WordArray} The hash.
*
* @static
*
* @example
*
* var hash = CryptoJS.SHA256('message');
* var hash = CryptoJS.SHA256(wordArray);
*/
C.SHA256 = Hasher._createHelper(SHA256);
/**
* Shortcut function to the HMAC's object interface.
*
* @param {WordArray|string} message The message to hash.
* @param {WordArray|string} key The secret key.
*
* @return {WordArray} The HMAC.
*
* @static
*
* @example
*
* var hmac = CryptoJS.HmacSHA256(message, key);
*/
C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
}(Math));
return CryptoJS.SHA256;
}));
+3 -1
View File
@@ -1004,7 +1004,9 @@ enableEmoji = true
[params.pangu]
# For Chinese writing
# 适用于中文写作用户
enable = false
enable = true
# TODO 为空则全局生效
selector = ''
# Watermark config since v0.2.12
# Detail config see https://github.com/Lruihao/watermark#readme
+2 -1
View File
@@ -129,4 +129,5 @@ Thanks to the authors of following resources included in the theme:
* [Waline](https://waline.js.org/)
* [Twikoo](https://twikoo.js.org/)
* [github-corners](https://github.com/tholman/github-corners)
* [giscus](https://giscus.app/)
* [giscus](https://giscus.app/)
* [crypto-js](https://github.com/brix/crypto-js)
+1
View File
@@ -130,3 +130,4 @@ FixIt 主题中用到了以下项目,感谢它们的作者:
* [Twikoo](https://twikoo.js.org/)
* [github-corners](https://github.com/tholman/github-corners)
* [giscus](https://giscus.app/zh-CN)
* [crypto-js](https://github.com/brix/crypto-js)
+260
View File
@@ -0,0 +1,260 @@
---
title: "Encrypt Test"
date: 2022-05-21T22:31:22+08:00
description: "Test for encrypting content"
type: 'posts'
draft: true
password: 1212
message: Password is 1212
lightgallery: true
math:
enable: true
twemoji: true
tags:
- Test
- Encryption
categories:
- Test
menu:
main:
title: "Test for encrypting content"
parent: "tests"
pre: "<i class='fa-solid fa-vial fa-fw fa-sm'></i>"
---
I was shy, so I hid.
<!--more-->
![Hugo Theme FixIt](/images/Apple-Devices-Preview.png "Hugo Theme FixIt")
## Encrypted Content
### twemoji
<!-- ### emoji -->
coffee ☕
Gone camping! :tent: Be back soon.
That is so funny! :joy:
### pangu
```
與PM戰鬥的人,應當小心自己不要成為PM
```
與PM戰鬥的人,應當小心自己不要成為PM
### ruby
[Hugo]^(An open-source static site generator)
### math
$$ \ce{CO2 + C -> 2 CO} $$
$$ \ce{Hg^2+ ->[I-] HgI2 ->[I-] [Hg^{II}I4]^2-} $$
## Shortcodes in Encrypted Content
### 1 style
{{< style "text-align:right; strong{color:#00b1ff;}" >}}
This is a **right-aligned** paragraph.
{{< /style >}}
### 2 link
{{< link "https://github.com/upstage/" Upstage "Visit Upstage!" >}}
{{< link "https://github.com/Lruihao/FixIt" "FixIt Theme" "source of FixIt Theme" true >}}
{{< link href="/music/Wavelength.mp3" content="Wavelength.mp3" title="Download Wavelength.mp3" download="Wavelength.mp3" >}}
{{< link href="/music/Wavelength.mp3" content="Wavelength.mp3" title="Download Wavelength.mp3" download="Wavelength.mp3" card=true >}}
### 3 image
{{< image src="/images/lighthouse.jpg" caption="Lighthouse (`image`)" src_s="/images/lighthouse-small.jpg" src_l="/images/lighthouse-large.jpg" >}}
### 4 admonition
{{< admonition tip "This is a tip" false >}}
A **tip** banner
{{< /admonition >}}
### 5 mermaid
{{< mermaid >}}
graph LR;
A[Hard edge] -->|Link text| B(Round edge)
B --> C{Decision}
C -->|One| D[Result one]
C -->|Two| E[Result two]
{{< /mermaid >}}
### 6 echarts
{{< echarts >}}
title:
text: Summary Line Chart
top: 2%
left: center
tooltip:
trigger: axis
legend:
data:
- Email Marketing
- Affiliate Advertising
- Video Advertising
- Direct View
- Search Engine
top: 10%
grid:
left: 5%
right: 5%
bottom: 5%
top: 20%
containLabel: true
toolbox:
feature:
saveAsImage:
title: Save as Image
xAxis:
type: category
boundaryGap: false
data:
- Monday
- Tuesday
- Wednesday
- Thursday
- Friday
- Saturday
- Sunday
yAxis:
type: value
series:
- name: Email Marketing
type: line
stack: Total
data:
- 120
- 132
- 101
- 134
- 90
- 230
- 210
- name: Affiliate Advertising
type: line
stack: Total
data:
- 220
- 182
- 191
- 234
- 290
- 330
- 310
- name: Video Advertising
type: line
stack: Total
data:
- 150
- 232
- 201
- 154
- 190
- 330
- 410
- name: Direct View
type: line
stack: Total
data:
- 320
- 332
- 301
- 334
- 390
- 330
- 320
- name: Search Engine
type: line
stack: Total
data:
- 820
- 932
- 901
- 934
- 1290
- 1330
- 1320
{{< /echarts >}}
### 7 mapbox
{{< mapbox 113.953277 22.559102 11 >}}
### 8 music
{{< music url="/music/Wavelength.mp3" name=Wavelength artist=oldmanyoung cover="/images/Wavelength.jpg" >}}
### 9 bilibili
{{< bilibili BV1Sx411T7QQ >}}
### 10 typeit
{{< typeit code=javascript >}}
console.log('before decrypting');
document.addEventListener('DOMContentLoaded', () => {
fixit.decryptor.addEventListener('decrypted', function() {
console.log('after decrypting')
})
});
{{< /typeit >}}
### 11 script
```go-html-template
{{</* script */>}}
console.log('before decrypting');
document.addEventListener('DOMContentLoaded', () => {
fixit.theme.decryptor.addEventListener('decrypted', function() {
console.log('after decrypting')
})
});
{{</* /script */>}}
```
You can see the output in the console of the developer tool.
{{< script >}}
console.log('before decrypting');
document.addEventListener('DOMContentLoaded', () => {
fixit.decryptor.addEventListener('decrypted', function() {
console.log('after decrypting')
})
});
{{< /script >}}
### 12 details
{{< details "**Copyright** 2022." >}}
*All pages and graphics on this web site are the property of FixIt.*
{{< /details >}}
### 13 center-quote
{{% center-quote %}}
**hello** *world*
this is a center-quote shortcode example.
{{% /center-quote %}}
+12
View File
@@ -189,6 +189,18 @@ other = "Mehr lesen"
[expirationReminder]
other = "Dieser Artikel wurde zuletzt auf {{ .Date }} aktualisiert, der Inhalt kann veraltet sein."
[encryptedAbstract]
other = "" # waitting for translation
[encryptedMessage]
other = "" # waitting for translation
[password]
other = "Passwort"
[encryptyAgain]
other = "" # waitting for translation
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -185,6 +185,18 @@ other = "Read More"
[expirationReminder]
other = "This article was last updated on {{ .Date }}, the content may be out of date."
[encryptedAbstract]
other = "This article has been encrypted, so its raw content is invisible!"
[encryptedMessage]
other = "Please enter the password"
[password]
other = "Password"
[encryptyAgain]
other = "Encrypt again"
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -189,6 +189,18 @@ other = "Leer más"
[expirationReminder]
other = "Este artículo se actualizó por última vez el {{ .Date }}, es posible que el contenido no esté actualizado."
[encryptedAbstract]
other = "" # waitting for translation
[encryptedMessage]
other = "" # waitting for translation
[password]
other = "Contraseña"
[encryptyAgain]
other = "" # waitting for translation
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -186,6 +186,18 @@ other = "Accueil"
[readMore]
other = "En savoir plus"
[encryptedAbstract]
other = "" # waitting for translation
[encryptedMessage]
other = "" # waitting for translation
[password]
other = "Mot de passe"
[encryptyAgain]
other = "" # waitting for translation
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -189,6 +189,18 @@ other = "Leggi di più"
[expirationReminder]
other = "Questo articolo è stato aggiornato l'ultima volta il {{ .Date }}, il contenuto potrebbe non essere aggiornato."
[encryptedAbstract]
other = "" # waitting for translation
[encryptedMessage]
other = "" # waitting for translation
[password]
other = "Password"
[encryptyAgain]
other = "" # waitting for translation
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -186,6 +186,18 @@ other = "Czytaj więcej"
[expirationReminder]
other = "Ten artykuł był ostatnio aktualizowany {{ .Date }}, jego treść może być nieaktualna."
[encryptedAbstract]
other = "" # waitting for translation
[encryptedMessage]
other = "" # waitting for translation
[password]
other = "Hasło"
[encryptyAgain]
other = "" # waitting for translation
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -189,6 +189,18 @@ other = "Leia mais"
[expirationReminder]
other = "Este artigo foi atualizado pela última vez em {{ .Date }}, o conteúdo pode estar desatualizado."
[encryptedAbstract]
other = "" # waitting for translation
[encryptedMessage]
other = "" # waitting for translation
[password]
other = "Contrasinha"
[encryptyAgain]
other = "" # waitting for translation
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -189,6 +189,18 @@ other = "Citește mai mult"
[expirationReminder]
other = "Acest articol a fost actualizat ultima dată pe {{ .Date }}, conținutul poate fi depășit."
[encryptedAbstract]
other = "" # waitting for translation
[encryptedMessage]
other = "" # waitting for translation
[password]
other = "Parolă"
[encryptyAgain]
other = "" # waitting for translation
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -189,6 +189,18 @@ other = "Читать больше"
[expirationReminder]
other = "Эта статья последний раз обновлялась {{ .Date }}, содержание может быть устаревшим."
[encryptedAbstract]
other = "" # waitting for translation
[encryptedMessage]
other = "" # waitting for translation
[password]
other = "арготизм"
[encryptyAgain]
other = "" # waitting for translation
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -186,6 +186,18 @@ other = "Прочитај више"
[expirationReminder]
other = "Овај чланак је последњи пут ажуриран {{ .Date }}, садржај је можда застарео."
[encryptedAbstract]
other = "" # waitting for translation
[encryptedMessage]
other = "" # waitting for translation
[password]
other = "Паролица"
[encryptyAgain]
other = "" # waitting for translation
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -188,6 +188,18 @@ other = "Đọc thêm"
[expirationReminder]
other = "Bài viết này được cập nhật lần cuối vào {{ .Date }}, nội dung có thể đã lỗi thời."
[encryptedAbstract]
other = "" # waitting for translation
[encryptedMessage]
other = "" # waitting for translation
[password]
other = "Mật khẩu"
[encryptyAgain]
other = "" # waitting for translation
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -189,6 +189,18 @@ other = "阅读全文"
[expirationReminder]
other = "本文最后更新于 {{ .Date }},文中内容可能已过时。"
[encryptedAbstract]
other = "本文已加密,因此其原始内容不可见!"
[encryptedMessage]
other = "请输入密码"
[password]
other = "密码"
[encryptyAgain]
other = "重新加密"
# === posts/single.html ===
# === 404.html ===
+12
View File
@@ -189,6 +189,18 @@ other = "閱讀全文"
[expirationReminder]
other = "本文最後更新於 {{ .Date }},文中內容可能已過時。"
[encryptedAbstract]
other = "本文已加密,囙此其原始內容不可見!"
[encryptedMessage]
other = "請輸入密碼"
[password]
other = "密碼"
[encryptyAgain]
other = "重新加密"
# === posts/single.html ===
# === 404.html ===
+22 -2
View File
@@ -12,8 +12,28 @@
</div>
{{- /* Content */ -}}
<div class="content" id="content">
{{- dict "Content" .Content "Ruby" $params.ruby "Fraction" $params.fraction "Fontawesome" $params.fontawesome | partial "function/content.html" | safeHTML -}}
{{- $content := dict "Content" .Content "Ruby" $params.ruby "Fraction" $params.fraction "Fontawesome" $params.fontawesome | partial "function/content.html" | safeHTML -}}
{{- if $params.password -}}
{{- $saltLen := strings.RuneCount (trim $params.password "") -}}
{{- $saltLen = cond (eq (mod $saltLen 2) 0) (add $saltLen 1) $saltLen -}}
{{- $base64EncodeContent := $content | base64Encode -}}
{{- $content = printf "%v%v%v"
(substr $base64EncodeContent 0 $saltLen)
(substr (sha256 $params.password) $saltLen)
(substr $base64EncodeContent $saltLen)
-}}
{{- end -}}
<div
class="content"
id="content"
{{ with $params.password }}data-password="{{ md5 $params.password }}"{{ end }}
{{ with $params.password }}data-content="{{ $content }}"{{ end }}
>
{{- if not $params.password -}}
{{- $content -}}
{{- else -}}
{{- partial "single/fixit-decryptor.html" . -}}
{{- end -}}
</div>
{{- /* Comment */ -}}
+11 -1
View File
@@ -1,3 +1,13 @@
{{- $params := .Scratch.Get "params" -}}
# {{ .Title }}
{{ .RawContent }}
{{ if $params.password -}}
***{{ T "encryptedAbstract" }}***
{{- else -}}
{{ .RawContent }}
{{- end }}
---
> {{ T "author"}}: {{ .Site.Author.name }}
> {{ .Permalink }}
+1 -1
View File
@@ -1,6 +1,6 @@
{{- if .Site.Params.search -}}
{{- $index := slice -}}
{{- $pages := .Site.RegularPages -}}
{{- $pages := where .Site.RegularPages "Params.password" "eq" nil -}}
{{- if .Site.Params.page.hiddenFromSearch -}}
{{- $pages = where $pages "Params.hiddenfromsearch" false -}}
{{- else -}}
+14 -1
View File
@@ -184,6 +184,19 @@
{{- $config = dict "watermark" .Site.Params.watermark | merge $config -}}
{{- end -}}
{{- /* Content Decryption */ -}}
{{- if $params.password -}}
{{- $cryptoCoreJS := $cdn.cryptoCoreJS | default "lib/crypto-js/core.js" -}}
{{- $cryptoEncBase64JS := $cdn.cryptoEncBase64JS | default "lib/crypto-js/enc-base64.js" -}}
{{- $cryptoMd5JS := $cdn.cryptoCoreJS | default "lib/crypto-js/md5.js" -}}
{{- $cryptoSha256JS := $cdn.cryptoCoreJS | default "lib/crypto-js/sha256.js" -}}
{{- dict "Source" $cryptoCoreJS "Minify" true "Fingerprint" $fingerprint "Defer" true | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
{{- dict "Source" $cryptoEncBase64JS "Minify" true "Fingerprint" $fingerprint "Defer" true | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
{{- dict "Source" $cryptoMd5JS "Minify" true "Fingerprint" $fingerprint "Defer" true | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
{{- dict "Source" $cryptoSha256JS "Minify" true "Fingerprint" $fingerprint "Defer" true | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
{{- dict "Source" "js/fixit-decryptor.js" "Minify" hugo.IsProduction "Fingerprint" $fingerprint "Defer" true | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
{{- end -}}
{{- /* 不蒜子 */ -}}
{{- if eq .Site.Params.ibruce.enable true -}}
{{- $source := "//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" -}}
@@ -224,7 +237,7 @@
{{- /* Custom script */ -}}
{{- if eq .Site.Params.customJS.enable true -}}
{{- $source = "js/_custom.js" -}}
{{- $source := "js/_custom.js" -}}
{{- dict "Source" $source "Minify" true "Fingerprint" $fingerprint "Defer" true | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
{{- end -}}
@@ -0,0 +1,9 @@
{{- $params := .Scratch.Get "params" -}}
<div class="fixit-decryptor-container">
{{- $msg := $params.message | default (T "encryptedMessage") -}}
<label for="fixit-decryptor-input" title='{{ T "password" }}'>
<input type="password" id="fixit-decryptor-input" class="d-none" placeholder="🔑 {{ $msg }}" />
</label>
<button class="fixit-encryptor-btn d-none">{{ T "encryptyAgain" }}</button>
</div>
+2 -2
View File
@@ -17,7 +17,7 @@
{{- end -}}
</span>
</div>
<div class="post-info-license">
<div class="post-info-license {{ with $params.password }} d-none{{ end }}">
{{- with $params.license | string -}}
<span>
{{- . | safeHTML -}}
@@ -25,7 +25,7 @@
{{- end -}}
</div>
</div>
<div class="post-info-line">
<div class="post-info-line{{ with $params.password }} d-none{{ end }}">
<div class="post-info-md">
{{- if $params.linktomarkdown -}}
{{- with .OutputFormats.Get "markdown" -}}
+27 -7
View File
@@ -8,8 +8,8 @@
{{- /* Auto TOC */ -}}
{{- $tocEmpty := eq .TableOfContents `<nav id="TableOfContents"></nav>` -}}
{{- if (ne $toc.enable false) | and (ne $tocEmpty true) -}}
<h2 class="toc-title">{{ T "contents" }} <i class="toc-icon fa-solid fa-angle-down fa-fw"></i></h2>
<div class="toc-content{{ if eq $toc.auto false }} always-active{{ end }}" id="toc-content-auto"></div>
<h2 class="toc-title{{ with $params.password }} d-none{{ end }}">{{ T "contents" }} <i class="toc-icon fa-solid fa-angle-down fa-fw"></i></h2>
<div class="toc-content{{ if eq $toc.auto false }} always-active{{ end }}{{ with $params.password }} d-none{{ end }}" id="toc-content-auto"></div>
{{- end -}}
</aside>
@@ -117,7 +117,7 @@
{{- /* Static TOC */ -}}
{{- if (ne $toc.enable false) | and (ne $tocEmpty true) -}}
<div class="details toc" id="toc-static" kept="{{ if $toc.keepStatic }}true{{ else }}false{{ end }}">
<div class="details toc{{ with $params.password }} d-none{{ end }}" id="toc-static" kept="{{ if $toc.keepStatic }}true{{ else }}false{{ end }}">
<div class="details-summary toc-title">
<span>{{ T "contents" }}</span>
<span><i class="details-icon fa-solid fa-angle-right"></i></span>
@@ -129,10 +129,30 @@
{{- end -}}
{{- /* Content */ -}}
<div class="content" id="content">
{{- /* Expiration Reminder */ -}}
{{- partial "single/expiration-reminder.html" . -}}
{{- dict "Content" .Content "Ruby" $params.ruby "Fraction" $params.fraction "Fontawesome" $params.fontawesome | partial "function/content.html" | safeHTML -}}
{{- $content := dict "Content" .Content "Ruby" $params.ruby "Fraction" $params.fraction "Fontawesome" $params.fontawesome | partial "function/content.html" | safeHTML -}}
{{- if $params.password -}}
{{- $saltLen := strings.RuneCount (trim $params.password "") -}}
{{- $saltLen = cond (eq (mod $saltLen 2) 0) (add $saltLen 1) $saltLen -}}
{{- $base64EncodeContent := $content | base64Encode -}}
{{- $content = printf "%v%v%v"
(substr $base64EncodeContent 0 $saltLen)
(substr (sha256 $params.password) $saltLen)
(substr $base64EncodeContent $saltLen)
-}}
{{- end -}}
<div
class="content"
id="content"
{{ with $params.password }}data-password="{{ md5 $params.password }}"{{ end }}
{{ with $params.password }}data-content="{{ $content }}"{{ end }}
>
{{- if not $params.password -}}
{{- /* Expiration Reminder */ -}}
{{- partial "single/expiration-reminder.html" . -}}
{{- $content -}}
{{- else -}}
{{- partial "single/fixit-decryptor.html" . -}}
{{- end -}}
</div>
{{- /* Footer */ -}}
+81 -37
View File
@@ -46,7 +46,9 @@ class Util {
}
}
class Theme {
class FixIt {
#encrypted = typeof FixItDecryptor !== 'undefined';
constructor() {
this.config = window.config;
this.data = this.config.data;
@@ -497,10 +499,8 @@ class Theme {
}
/**
* init table of contents
* @param {Boolean} [onInit=false]
* @returns
*/
initToc(onInit = false) {
initToc() {
const $tocCore = document.getElementById('TableOfContents');
if ($tocCore === null) {
return;
@@ -560,18 +560,22 @@ class Theme {
});
this._tocOnScroll();
this.scrollEventSet.add(this._tocOnScroll);
// only addEventListener once
onInit && document.querySelector('#toc-auto>.toc-title').addEventListener('click', () => {
const animation = ['animate__faster']
const tocHidden = $toc.classList.contains('toc-hidden');
animation.push(tocHidden ? 'animate__fadeIn' : 'animate__fadeOut');
$tocContentAuto.classList.remove(tocHidden ? 'animate__fadeOut' : 'animate__fadeIn');
this.util.animateCSS($tocContentAuto, animation, true);
$toc.classList.toggle('toc-hidden');
}, false)
}
}
initTocListener() {
const $toc = document.getElementById('toc-auto');
const $tocContentAuto = document.getElementById('toc-content-auto');
document.querySelector('#toc-auto>.toc-title')?.addEventListener('click', () => {
const animation = ['animate__faster']
const tocHidden = $toc.classList.contains('toc-hidden');
animation.push(tocHidden ? 'animate__fadeIn' : 'animate__fadeOut');
$tocContentAuto.classList.remove(tocHidden ? 'animate__fadeOut' : 'animate__fadeIn');
this.util.animateCSS($tocContentAuto, animation, true);
$toc.classList.toggle('toc-hidden');
}, false)
}
initMath() {
if (this.config.math) {
renderMathInElement(document.body, this.config.math);
@@ -891,9 +895,41 @@ class Theme {
}
initPangu() {
// TODO 待优化:只渲染
this.config.enablePangu && pangu.autoSpacingPage();
}
initFixItDecryptor() {
const $tocNodes = document.querySelectorAll('#toc-auto>.d-none, #toc-static.d-none');
this.decryptor = new FixItDecryptor({
decrypted: () => {
this.initTwemoji();
this.initDetails();
this.initLightGallery();
this.initHighlight();
this.initTable();
this.initHeaderLink();
this.initMath();
this.initMermaid();
this.initEcharts();
this.initTypeit();
this.initMapbox();
this.util.forEach($tocNodes, ($element) => {
$element.classList.remove('d-none');
});
this.initToc();
this.initTocListener();
this.initPangu();
},
reset: () => {
this.util.forEach($tocNodes, ($element) => {
$element.classList.add('d-none');
});
}
});
this.decryptor.init();
}
onScroll() {
const $headers = [];
if (document.body.getAttribute('header-desktop') === 'auto') $headers.push(document.getElementById('header-desktop'));
@@ -952,7 +988,9 @@ class Theme {
if (!this._resizeTimeout) {
this._resizeTimeout = window.setTimeout(() => {
this._resizeTimeout = null;
for (let event of this.resizeEventSet) event();
for (let event of this.resizeEventSet) {
event();
}
this.initToc();
this.initMermaid();
this.initSearch();
@@ -971,44 +1009,50 @@ class Theme {
init() {
try {
if (this.#encrypted) {
this.initFixItDecryptor();
} else {
this.initTwemoji();
this.initDetails();
this.initLightGallery();
this.initHighlight();
this.initTable();
this.initHeaderLink();
this.initMath();
this.initMermaid();
this.initEcharts();
this.initTypeit();
this.initMapbox();
this.initPangu();
}
this.initSVGIcon();
this.initTwemoji();
this.initMenu();
this.initSwitchTheme();
this.initSearch();
this.initDetails();
this.initLightGallery();
this.initHighlight();
this.initTable();
this.initHeaderLink();
this.initMath();
this.initMermaid();
this.initEcharts();
this.initTypeit();
this.initMapbox();
this.initCookieconsent();
this.initSiteTime();
this.initServiceWorker();
this.initWatermark();
this.initPangu();
window.setTimeout(() => {
this.initComment();
if (!this.#encrypted) {
this.initToc();
this.initTocListener();
}
this.onScroll();
this.onResize();
this.onClickMask();
}, 100);
} catch (err) {
console.error(err);
}
window.setTimeout(() => {
this.initComment();
this.initToc(true);
this.onScroll();
this.onResize();
this.onClickMask();
}, 100);
}
}
const themeInit = () => {
const theme = new Theme();
theme.init();
window.fixit = new FixIt();
window.fixit.init();
};
if (document.readyState !== 'loading') {