This commit is contained in:
ClasWen 2024-05-18 19:44:09 +08:00
parent a3a0f10463
commit a9e311af3b
35 changed files with 3480 additions and 1710 deletions

1
.gitignore vendored
View file

@ -2,7 +2,6 @@
dist/ dist/
# generated types # generated types
.astro/ .astro/
.vscode/
# dependencies # dependencies
node_modules/ node_modules/

10
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,10 @@
{
"eslint.validate": [
"javascript",
"javascriptreact",
"astro", // Enable .astro
"typescript", // Enable .ts
"typescriptreact" // Enable .tsx
],
"eslint.experimental.useFlatConfig": true,
}

View file

@ -1,6 +1,4 @@
import { defineConfig } from "astro/config" import { defineConfig } from "astro/config"
import { visit } from "unist-util-visit"
import md5 from "md5"
import { SITE_URL } from "./src/consts" import { SITE_URL } from "./src/consts"
import vue from "@astrojs/vue" import vue from "@astrojs/vue"
import tailwind from "@astrojs/tailwind" import tailwind from "@astrojs/tailwind"
@ -21,7 +19,7 @@ function pipeline() {
// size = data[1] // size = data[1]
// } // }
// let classes = [ // let classes = [
// "image component image-fullbleed body-copy-wide nr-scroll-animation nr-scroll-animation--on", // "image component image-full-bleed body-copy-wide nr-scroll-animation nr-scroll-animation--on",
// ] // ]
// classes.push(`image-${size}`) // classes.push(`image-${size}`)
// node.properties.className = classes // node.properties.className = classes
@ -37,7 +35,7 @@ function pipeline() {
// type: "element", // type: "element",
// tagName: "div", // tagName: "div",
// properties: { // properties: {
// className: ["image-sharesheet"], // className: ["image-share-sheet"],
// }, // },
// children: [ // children: [
// { // {
@ -103,26 +101,26 @@ function pipeline() {
() => (tree) => { () => (tree) => {
tree.children.forEach((node) => { tree.children.forEach((node) => {
if (node.type === "raw") { if (node.type === "raw") {
node.value = `<div class="pagebody code component"><div class="component-content code"> ${node.value} </div></div>` node.value = `<div class="page-body code component"><div class="component-content code"> ${node.value} </div></div>`
// node.value = node.value.replace(/astro-code/g, 'astro-code') // node.value = node.value.replace(/astro-code/g, 'astro-code')
} }
}) })
}, },
() => (tree) => { () => (tree) => {
for (let i = 0; i < tree.children.length; i++) { for (let i = 0; i < tree.children.length; i++) {
let node = tree.children[i] const node = tree.children[i]
if ( if (
node.type === "element" && node.type === "element"
["p", "h1", "h2", "h3", "h4", "h5", "h6", "table"].includes( && ["p", "h1", "h2", "h3", "h4", "h5", "h6", "table"].includes(
node.tagName node.tagName,
) )
) { ) {
let next = tree.children[i + 1] let next = tree.children[i + 1]
let nodes = [node] const nodes = [node]
while ( while (
next && next
!["figure"].includes(next.tagName) && && !["figure"].includes(next.tagName)
next.type != "raw" && next.type != "raw"
) { ) {
nodes.push(next) nodes.push(next)
next = tree.children[tree.children.indexOf(next) + 1] next = tree.children[tree.children.indexOf(next) + 1]
@ -131,18 +129,18 @@ function pipeline() {
// rename label // rename label
nodes.forEach((node) => { nodes.forEach((node) => {
if (node.tagName === "p") { if (node.tagName === "p") {
node.properties.className = ["pagebody-copy"] node.properties.className = ["page-body-copy"]
node.tagName = "div" node.tagName = "div"
} }
if (["h1", "h2", "h3", "h4", "h5", "h6"].includes(node.tagName)) { if (["h1", "h2", "h3", "h4", "h5", "h6"].includes(node.tagName)) {
node.properties.className = ["pagebody-header"] node.properties.className = ["page-body-header"]
} }
}) })
tree.children.splice(i, nodes.length, { tree.children.splice(i, nodes.length, {
type: "element", type: "element",
tagName: "div", tagName: "div",
properties: { properties: {
className: ["pagebody text component"], className: ["page-body text component"],
}, },
children: [ children: [
{ {
@ -160,15 +158,15 @@ function pipeline() {
} }
}, },
() => (tree) => { () => (tree) => {
let len = tree.children.length const len = tree.children.length
for (let index = 0; index < len; index++) { for (let index = 0; index < len; index++) {
let node = tree.children[index] const node = tree.children[index]
if (node.type === "element" && node.tagName === "figure") { if (node.type === "element" && node.tagName === "figure") {
tree.children.splice(index, 0, { tree.children.splice(index, 0, {
type: "element", type: "element",
tagName: "div", tagName: "div",
properties: { properties: {
className: ["tertiarynav component"], className: ["tertiary-nav component"],
}, },
children: [ children: [
{ {

17
cspell.json Normal file
View file

@ -0,0 +1,17 @@
{
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
"version": "0.2",
"ignorePaths": [
"node_modules",
"dist",
],
"words": [
"astro",
"astrojs",
"frontmatter",
"NBTCA",
"m_lfit",
"N3ptune",
"rehypePlugins"
]
}

View file

@ -1,11 +1,12 @@
// ts-check
import globals from "globals" import globals from "globals"
import eslint from "@eslint/js" import eslint from "@eslint/js"
import eslintPluginAstro from "eslint-plugin-astro" import eslintPluginAstro from "eslint-plugin-astro"
import stylistic from "@stylistic/eslint-plugin" import stylistic from "@stylistic/eslint-plugin"
import cspellESLintPluginRecommended from "@cspell/eslint-plugin/recommended"
export default [ export default [
eslint.configs.recommended, eslint.configs.recommended,
cspellESLintPluginRecommended,
...eslintPluginAstro.configs.recommended, ...eslintPluginAstro.configs.recommended,
stylistic.configs.customize({ stylistic.configs.customize({
indent: 2, indent: 2,
@ -14,13 +15,26 @@ export default [
jsx: true, jsx: true,
}), }),
{ {
ignores: ["dist"], files: ["*.{ts,tsx}"],
parser: "@typescript-eslint/parser",
},
{
languageOptions: { languageOptions: {
globals: { globals: {
...globals.browser, ...globals.browser,
}, },
}, },
plugins: {
"@stylistic": stylistic,
},
rules: { rules: {
"@stylistic/jsx-one-expression-per-line": ["off"],
"@cspell/spellchecker": [
"warn",
{
configFile: new URL("./cspell.json", import.meta.url).toString(),
},
],
"prefer-const": [ "prefer-const": [
"error", "error",
{ {
@ -30,4 +44,7 @@ export default [
], ],
}, },
}, },
{
ignores: ["dist/**/*", "public/**/*", "node_modules/**/*"],
},
] ]

1413
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -32,6 +32,7 @@
"vue": "^3.4.21" "vue": "^3.4.21"
}, },
"devDependencies": { "devDependencies": {
"@cspell/eslint-plugin": "^8.8.1",
"@types/eslint__js": "^8.42.3", "@types/eslint__js": "^8.42.3",
"@types/react": "^18.2.79", "@types/react": "^18.2.79",
"@types/react-dom": "^18.2.25", "@types/react-dom": "^18.2.25",

View file

@ -1,82 +1,76 @@
var animationElements = []; var animationElements = []
var imageElements = []; var imageElements = []
var animationElementName = ".small-load"; var animationElementName = ".small-load"
// Hookable function // Hookable function
var loadAnimation = function (item) { var loadAnimation = function (item) {
let img = new Image(); const img = new Image()
img.src = item.children[0].children[0].dataset.src; img.src = item.children[0].children[0].dataset.src
img.onload = function () { img.onload = function () {
item.classList.remove("small-load", "medium-load", "large-load"); item.classList.remove("small-load", "medium-load", "large-load")
item.classList.add("small-loaded", "medium-loaded", "large-loaded"); item.classList.add("small-loaded", "medium-loaded", "large-loaded")
} }
} }
// Hookable function // Hookable function
var loadImage = function (index) { var loadImage = function (index) {
if (index >= imageElements.length) return; if (index >= imageElements.length) return
let item = imageElements[index]; const item = imageElements[index]
let image = new Image(); const image = new Image()
item.src = item.dataset.src; item.src = item.dataset.src
image.src = item.src; image.src = item.src
image.onload = function () { image.onload = function () {
loadImage(index + 1); loadImage(index + 1)
} }
} }
function initImage() { function initImage() {
// get all the images with data-src attribute // get all the images with data-src attribute
imageElements = document.querySelectorAll('img[data-src]') imageElements = document.querySelectorAll("img[data-src]")
// load the images one by one // load the images one by one
loadImage(0); loadImage(0)
animationElements = document.querySelectorAll(animationElementName)
animationElements = document.querySelectorAll(animationElementName);
// load the images which are in the viewport // load the images which are in the viewport
viewPortLoad(0); viewPortLoad(0)
const debouncedHandleScroll = debounce(lazyAnimation, 10); const debouncedHandleScroll = debounce(lazyAnimation, 10)
// add the event listener // add the event listener
window.addEventListener('scroll', debouncedHandleScroll); window.addEventListener("scroll", debouncedHandleScroll)
} }
function viewPortLoad(index) { function viewPortLoad(index) {
if (index >= animationElements.length) return; if (index >= animationElements.length) return
let item = animationElements[index]; const item = animationElements[index]
if (!isElementInView(item)) { if (!isElementInView(item)) {
viewPortLoad(index + 1) viewPortLoad(index + 1)
return; return
}; }
loadAnimation(item) loadAnimation(item)
viewPortLoad(index + 1); viewPortLoad(index + 1)
} }
function lazyAnimation() { function lazyAnimation() {
images = document.querySelectorAll(animationElementName); images = document.querySelectorAll(animationElementName)
viewPortLoad(0); viewPortLoad(0)
} }
// check if the element is in the viewport // check if the element is in the viewport
function isElementInView(element) { function isElementInView(element) {
const rect = element.getBoundingClientRect(); const rect = element.getBoundingClientRect()
const elementTop = rect.top; const elementTop = rect.top
const elementBottom = rect.bottom; const elementBottom = rect.bottom
return (elementTop >= 0 && elementBottom - 200 <= window.innerHeight); return (elementTop >= 0 && elementBottom - 200 <= window.innerHeight)
} }
function debounce(fn, delay) { function debounce(fn, delay) {
let timer = null; let timer = null
return function () { return function () {
let context = this; const context = this
let args = arguments; const args = arguments
clearTimeout(timer); clearTimeout(timer)
timer = setTimeout(function () { timer = setTimeout(function () {
fn.apply(context, args); fn.apply(context, args)
}, delay); }, delay)
}; }
} }

File diff suppressed because one or more lines are too long

View file

@ -1,65 +1,62 @@
console.log("postInit.js loaded")
console.log("postInit.js loaded"); var scriptMd5 = document.createElement("script")
var scriptMd5 = document.createElement("script"); scriptMd5.src = "/static/js/md5.js"
scriptMd5.src = "/static/js/md5.js"; document.head.appendChild(scriptMd5)
document.head.appendChild(scriptMd5);
scriptMd5.onload = function () { scriptMd5.onload = function () {
console.log("md5.js loaded") console.log("md5.js loaded")
// step1. sythx highlighting // step1. sythx highlighting
syntaxHighlight(); syntaxHighlight()
// step2. lazyload // step2. lazyload
initLazyLoad(); initLazyLoad()
} }
function initLazyLoad() { function initLazyLoad() {
var script = document.createElement("script"); var script = document.createElement("script")
script.src = "/static/js/animation.js"; script.src = "/static/js/animation.js"
document.head.appendChild(script); document.head.appendChild(script)
script.onload = function () { script.onload = function () {
console.log("lazyload.js loaded"); console.log("lazyload.js loaded")
animationElementName = ".image-load"; animationElementName = ".image-load"
// Hook the loadImage function // Hook the loadImage function
loadImage = (index) => { loadImage = (index) => {
if (index >= imageElements.length) return; if (index >= imageElements.length) return
let image = imageElements[index]; const image = imageElements[index]
image.src = image.dataset.src; image.src = image.dataset.src
let img = new Image(); const img = new Image()
img.src = image.src; img.src = image.src
img.onload = function () { img.onload = function () {
loadImage(index + 1); loadImage(index + 1)
}; }
} }
loadAnimation = (item) => { loadAnimation = (item) => {
let grandSon = item.firstChild.firstChild; const grandSon = item.firstChild.firstChild
let img = new Image(); const img = new Image()
img.src = grandSon.src; img.src = grandSon.src
let sign = md5(grandSon.src); const sign = md5(grandSon.src)
img.onload = function () { img.onload = function () {
let percent = ((img.height / img.width) * 100).toFixed(5); const percent = ((img.height / img.width) * 100).toFixed(5)
var style = document.createElement("style"); var style = document.createElement("style")
style.innerHTML = renderStyle(sign, percent); style.innerHTML = renderStyle(sign, percent)
let target = document.getElementById(`lht${sign}`) const target = document.getElementById(`lht${sign}`)
if (!target) return; if (!target) return
target.parentNode.insertBefore(style, target); target.parentNode.insertBefore(style, target)
item.classList.remove("image-load"); item.classList.remove("image-load")
item.classList.add("image-loaded"); item.classList.add("image-loaded")
} }
} }
initImage(); initImage()
}; }
} }
function renderStyle(sign, percent) { function renderStyle(sign, percent) {
return ` return `
.image-${sign} { .image-${sign} {
@ -86,28 +83,29 @@ function renderStyle(sign, percent) {
} }
function syntaxHighlight() { function syntaxHighlight() {
var script = document.createElement("script"); var script = document.createElement("script")
script.src = "/static/js/hljs.js"; script.src = "/static/js/hljs.js"
document.head.appendChild(script); document.head.appendChild(script)
var styleLight = document.createElement("link"); var styleLight = document.createElement("link")
styleLight.rel = "stylesheet"; styleLight.rel = "stylesheet"
styleLight.href = "/static/css/stackoverflow-light.min.css"; styleLight.href = "/static/css/stackoverflow-light.min.css"
var styleDark = document.createElement("link"); var styleDark = document.createElement("link")
styleDark.rel = "stylesheet"; styleDark.rel = "stylesheet"
styleDark.href = "/static/css/stackoverflow-dark.min.css"; styleDark.href = "/static/css/stackoverflow-dark.min.css"
if (document.querySelector("body").classList.contains("theme-dark")) { if (document.querySelector("body").classList.contains("theme-dark")) {
document.head.appendChild(styleDark); document.head.appendChild(styleDark)
} else { }
document.head.appendChild(styleLight); else {
document.head.appendChild(styleLight)
} }
script.onload = function () { script.onload = function () {
console.log("hljs.js loaded"); console.log("hljs.js loaded")
document.querySelectorAll("pre code").forEach(function (block) { document.querySelectorAll("pre code").forEach(function (block) {
hljs.highlightBlock(block); hljs.highlightBlock(block)
}); })
}; }
} }

View file

@ -1,121 +1,120 @@
function md5cycle(x, k) { function md5cycle(x, k) {
var a = x[0], b = x[1], c = x[2], d = x[3]; var a = x[0], b = x[1], c = x[2], d = x[3]
a = ff(a, b, c, d, k[0], 7, -680876936); a = ff(a, b, c, d, k[0], 7, -680876936)
d = ff(d, a, b, c, k[1], 12, -389564586); d = ff(d, a, b, c, k[1], 12, -389564586)
c = ff(c, d, a, b, k[2], 17, 606105819); c = ff(c, d, a, b, k[2], 17, 606105819)
b = ff(b, c, d, a, k[3], 22, -1044525330); b = ff(b, c, d, a, k[3], 22, -1044525330)
a = ff(a, b, c, d, k[4], 7, -176418897); a = ff(a, b, c, d, k[4], 7, -176418897)
d = ff(d, a, b, c, k[5], 12, 1200080426); d = ff(d, a, b, c, k[5], 12, 1200080426)
c = ff(c, d, a, b, k[6], 17, -1473231341); c = ff(c, d, a, b, k[6], 17, -1473231341)
b = ff(b, c, d, a, k[7], 22, -45705983); b = ff(b, c, d, a, k[7], 22, -45705983)
a = ff(a, b, c, d, k[8], 7, 1770035416); a = ff(a, b, c, d, k[8], 7, 1770035416)
d = ff(d, a, b, c, k[9], 12, -1958414417); d = ff(d, a, b, c, k[9], 12, -1958414417)
c = ff(c, d, a, b, k[10], 17, -42063); c = ff(c, d, a, b, k[10], 17, -42063)
b = ff(b, c, d, a, k[11], 22, -1990404162); b = ff(b, c, d, a, k[11], 22, -1990404162)
a = ff(a, b, c, d, k[12], 7, 1804603682); a = ff(a, b, c, d, k[12], 7, 1804603682)
d = ff(d, a, b, c, k[13], 12, -40341101); d = ff(d, a, b, c, k[13], 12, -40341101)
c = ff(c, d, a, b, k[14], 17, -1502002290); c = ff(c, d, a, b, k[14], 17, -1502002290)
b = ff(b, c, d, a, k[15], 22, 1236535329); b = ff(b, c, d, a, k[15], 22, 1236535329)
a = gg(a, b, c, d, k[1], 5, -165796510); a = gg(a, b, c, d, k[1], 5, -165796510)
d = gg(d, a, b, c, k[6], 9, -1069501632); d = gg(d, a, b, c, k[6], 9, -1069501632)
c = gg(c, d, a, b, k[11], 14, 643717713); c = gg(c, d, a, b, k[11], 14, 643717713)
b = gg(b, c, d, a, k[0], 20, -373897302); b = gg(b, c, d, a, k[0], 20, -373897302)
a = gg(a, b, c, d, k[5], 5, -701558691); a = gg(a, b, c, d, k[5], 5, -701558691)
d = gg(d, a, b, c, k[10], 9, 38016083); d = gg(d, a, b, c, k[10], 9, 38016083)
c = gg(c, d, a, b, k[15], 14, -660478335); c = gg(c, d, a, b, k[15], 14, -660478335)
b = gg(b, c, d, a, k[4], 20, -405537848); b = gg(b, c, d, a, k[4], 20, -405537848)
a = gg(a, b, c, d, k[9], 5, 568446438); a = gg(a, b, c, d, k[9], 5, 568446438)
d = gg(d, a, b, c, k[14], 9, -1019803690); d = gg(d, a, b, c, k[14], 9, -1019803690)
c = gg(c, d, a, b, k[3], 14, -187363961); c = gg(c, d, a, b, k[3], 14, -187363961)
b = gg(b, c, d, a, k[8], 20, 1163531501); b = gg(b, c, d, a, k[8], 20, 1163531501)
a = gg(a, b, c, d, k[13], 5, -1444681467); a = gg(a, b, c, d, k[13], 5, -1444681467)
d = gg(d, a, b, c, k[2], 9, -51403784); d = gg(d, a, b, c, k[2], 9, -51403784)
c = gg(c, d, a, b, k[7], 14, 1735328473); c = gg(c, d, a, b, k[7], 14, 1735328473)
b = gg(b, c, d, a, k[12], 20, -1926607734); b = gg(b, c, d, a, k[12], 20, -1926607734)
a = hh(a, b, c, d, k[5], 4, -378558); a = hh(a, b, c, d, k[5], 4, -378558)
d = hh(d, a, b, c, k[8], 11, -2022574463); d = hh(d, a, b, c, k[8], 11, -2022574463)
c = hh(c, d, a, b, k[11], 16, 1839030562); c = hh(c, d, a, b, k[11], 16, 1839030562)
b = hh(b, c, d, a, k[14], 23, -35309556); b = hh(b, c, d, a, k[14], 23, -35309556)
a = hh(a, b, c, d, k[1], 4, -1530992060); a = hh(a, b, c, d, k[1], 4, -1530992060)
d = hh(d, a, b, c, k[4], 11, 1272893353); d = hh(d, a, b, c, k[4], 11, 1272893353)
c = hh(c, d, a, b, k[7], 16, -155497632); c = hh(c, d, a, b, k[7], 16, -155497632)
b = hh(b, c, d, a, k[10], 23, -1094730640); b = hh(b, c, d, a, k[10], 23, -1094730640)
a = hh(a, b, c, d, k[13], 4, 681279174); a = hh(a, b, c, d, k[13], 4, 681279174)
d = hh(d, a, b, c, k[0], 11, -358537222); d = hh(d, a, b, c, k[0], 11, -358537222)
c = hh(c, d, a, b, k[3], 16, -722521979); c = hh(c, d, a, b, k[3], 16, -722521979)
b = hh(b, c, d, a, k[6], 23, 76029189); b = hh(b, c, d, a, k[6], 23, 76029189)
a = hh(a, b, c, d, k[9], 4, -640364487); a = hh(a, b, c, d, k[9], 4, -640364487)
d = hh(d, a, b, c, k[12], 11, -421815835); d = hh(d, a, b, c, k[12], 11, -421815835)
c = hh(c, d, a, b, k[15], 16, 530742520); c = hh(c, d, a, b, k[15], 16, 530742520)
b = hh(b, c, d, a, k[2], 23, -995338651); b = hh(b, c, d, a, k[2], 23, -995338651)
a = ii(a, b, c, d, k[0], 6, -198630844); a = ii(a, b, c, d, k[0], 6, -198630844)
d = ii(d, a, b, c, k[7], 10, 1126891415); d = ii(d, a, b, c, k[7], 10, 1126891415)
c = ii(c, d, a, b, k[14], 15, -1416354905); c = ii(c, d, a, b, k[14], 15, -1416354905)
b = ii(b, c, d, a, k[5], 21, -57434055); b = ii(b, c, d, a, k[5], 21, -57434055)
a = ii(a, b, c, d, k[12], 6, 1700485571); a = ii(a, b, c, d, k[12], 6, 1700485571)
d = ii(d, a, b, c, k[3], 10, -1894986606); d = ii(d, a, b, c, k[3], 10, -1894986606)
c = ii(c, d, a, b, k[10], 15, -1051523); c = ii(c, d, a, b, k[10], 15, -1051523)
b = ii(b, c, d, a, k[1], 21, -2054922799); b = ii(b, c, d, a, k[1], 21, -2054922799)
a = ii(a, b, c, d, k[8], 6, 1873313359); a = ii(a, b, c, d, k[8], 6, 1873313359)
d = ii(d, a, b, c, k[15], 10, -30611744); d = ii(d, a, b, c, k[15], 10, -30611744)
c = ii(c, d, a, b, k[6], 15, -1560198380); c = ii(c, d, a, b, k[6], 15, -1560198380)
b = ii(b, c, d, a, k[13], 21, 1309151649); b = ii(b, c, d, a, k[13], 21, 1309151649)
a = ii(a, b, c, d, k[4], 6, -145523070); a = ii(a, b, c, d, k[4], 6, -145523070)
d = ii(d, a, b, c, k[11], 10, -1120210379); d = ii(d, a, b, c, k[11], 10, -1120210379)
c = ii(c, d, a, b, k[2], 15, 718787259); c = ii(c, d, a, b, k[2], 15, 718787259)
b = ii(b, c, d, a, k[9], 21, -343485551); b = ii(b, c, d, a, k[9], 21, -343485551)
x[0] = add32(a, x[0]);
x[1] = add32(b, x[1]);
x[2] = add32(c, x[2]);
x[3] = add32(d, x[3]);
x[0] = add32(a, x[0])
x[1] = add32(b, x[1])
x[2] = add32(c, x[2])
x[3] = add32(d, x[3])
} }
function cmn(q, a, b, x, s, t) { function cmn(q, a, b, x, s, t) {
a = add32(add32(a, q), add32(x, t)); a = add32(add32(a, q), add32(x, t))
return add32((a << s) | (a >>> (32 - s)), b); return add32((a << s) | (a >>> (32 - s)), b)
} }
function ff(a, b, c, d, x, s, t) { function ff(a, b, c, d, x, s, t) {
return cmn((b & c) | ((~b) & d), a, b, x, s, t); return cmn((b & c) | ((~b) & d), a, b, x, s, t)
} }
function gg(a, b, c, d, x, s, t) { function gg(a, b, c, d, x, s, t) {
return cmn((b & d) | (c & (~d)), a, b, x, s, t); return cmn((b & d) | (c & (~d)), a, b, x, s, t)
} }
function hh(a, b, c, d, x, s, t) { function hh(a, b, c, d, x, s, t) {
return cmn(b ^ c ^ d, a, b, x, s, t); return cmn(b ^ c ^ d, a, b, x, s, t)
} }
function ii(a, b, c, d, x, s, t) { function ii(a, b, c, d, x, s, t) {
return cmn(c ^ (b | (~d)), a, b, x, s, t); return cmn(c ^ (b | (~d)), a, b, x, s, t)
} }
function md51(s) { function md51(s) {
txt = ''; txt = ""
var n = s.length, var n = s.length,
state = [1732584193, -271733879, -1732584194, 271733878], i; state = [1732584193, -271733879, -1732584194, 271733878], i
for (i=64; i<=s.length; i+=64) { for (i = 64; i <= s.length; i += 64) {
md5cycle(state, md5blk(s.substring(i-64, i))); md5cycle(state, md5blk(s.substring(i - 64, i)))
} }
s = s.substring(i-64); s = s.substring(i - 64)
var tail = [0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0]; var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
for (i=0; i<s.length; i++) for (i = 0; i < s.length; i++)
tail[i>>2] |= s.charCodeAt(i) << ((i%4) << 3); tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3)
tail[i>>2] |= 0x80 << ((i%4) << 3); tail[i >> 2] |= 0x80 << ((i % 4) << 3)
if (i > 55) { if (i > 55) {
md5cycle(state, tail); md5cycle(state, tail)
for (i=0; i<16; i++) tail[i] = 0; for (i = 0; i < 16; i++) tail[i] = 0
} }
tail[14] = n*8; tail[14] = n * 8
md5cycle(state, tail); md5cycle(state, tail)
return state; return state
} }
/* there needs to be support for Unicode here, /* there needs to be support for Unicode here,
@ -134,35 +133,34 @@ return state;
* 8-bit unsigned value arrays. * 8-bit unsigned value arrays.
*/ */
function md5blk(s) { /* I figured global was faster. */ function md5blk(s) { /* I figured global was faster. */
var md5blks = [], i; /* Andy King said do it this way. */ var md5blks = [], i /* Andy King said do it this way. */
for (i=0; i<64; i+=4) { for (i = 0; i < 64; i += 4) {
md5blks[i>>2] = s.charCodeAt(i) md5blks[i >> 2] = s.charCodeAt(i)
+ (s.charCodeAt(i+1) << 8) + (s.charCodeAt(i + 1) << 8)
+ (s.charCodeAt(i+2) << 16) + (s.charCodeAt(i + 2) << 16)
+ (s.charCodeAt(i+3) << 24); + (s.charCodeAt(i + 3) << 24)
} }
return md5blks; return md5blks
} }
var hex_chr = '0123456789abcdef'.split(''); var hex_chr = "0123456789abcdef".split("")
function rhex(n) function rhex(n) {
{ var s = "", j = 0
var s='', j=0; for (; j < 4; j++)
for(; j<4; j++) s += hex_chr[(n >> (j * 8 + 4)) & 0x0F]
s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F]
+ hex_chr[(n >> (j * 8)) & 0x0F]; return s
return s;
} }
function hex(x) { function hex(x) {
for (var i=0; i<x.length; i++) for (var i = 0; i < x.length; i++)
x[i] = rhex(x[i]); x[i] = rhex(x[i])
return x.join(''); return x.join("")
} }
function md5(s) { function md5(s) {
return hex(md51(s)); return hex(md51(s))
} }
/* this function is much faster, /* this function is much faster,
@ -172,13 +170,13 @@ need the idiotic second function,
generated by an if clause. */ generated by an if clause. */
function add32(a, b) { function add32(a, b) {
return (a + b) & 0xFFFFFFFF; return (a + b) & 0xFFFFFFFF
} }
if (md5('hello') != '5d41402abc4b2a76b9719d911017c592') { if (md5("hello") != "5d41402abc4b2a76b9719d911017c592") {
function add32(x, y) { function add32(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF), var lsw = (x & 0xFFFF) + (y & 0xFFFF),
msw = (x >> 16) + (y >> 16) + (lsw >> 16); msw = (x >> 16) + (y >> 16) + (lsw >> 16)
return (msw << 16) | (lsw & 0xFFFF); return (msw << 16) | (lsw & 0xFFFF)
} }
} }

View file

@ -1,33 +1,33 @@
--- ---
// Import the global.css file here so that it is included on // Import the global.css file here so that it is included on
// all pages through the use of the <BaseHead /> component. // all pages through the use of the <BaseHead /> component.
import "../styles/global.css"; import "../styles/global.css"
const { title, description, image = "/preview.png" } = Astro.props; const { title, description, image = "/preview.png" } = Astro.props
import { SITE_URL } from "../consts"; import { SITE_URL } from "../consts"
const { pathname } = Astro.url; const { pathname } = Astro.url;
--- ---
<!-- Global Metadata --> <!-- Global Metadata -->
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<!-- Primary Meta Tags --> <!-- Primary Meta Tags -->
<title>{title}</title> <title>{title}</title>
<meta name="title" content={title} /> <meta name="title" content={title} />
<meta name="description" content={description} /> <meta name="description" content={description} />
<!-- Open Graph / Facebook --> <!-- Open Graph / Facebook -->
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content={`${SITE_URL}${pathname}`} /> <meta property="og:url" content={`${SITE_URL}${pathname}`} />
<meta property="og:title" content={title} /> <meta property="og:title" content={title} />
<meta property="og:description" content={description} /> <meta property="og:description" content={description} />
<meta property="og:image" content={new URL(image, `${SITE_URL}${pathname}`)} /> <meta property="og:image" content={new URL(image, `${SITE_URL}${pathname}`)} />
<!-- Twitter --> <!-- Twitter -->
<meta property="twitter:card" content="summary_large_image" /> <meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={`${SITE_URL}${pathname}`} /> <meta property="twitter:url" content={`${SITE_URL}${pathname}`} />
<meta property="twitter:title" content={title} /> <meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} /> <meta property="twitter:description" content={description} />
<meta property="twitter:image" content={new URL(image, `${SITE_URL}${pathname}`)} /> <meta property="twitter:image" content={new URL(image, `${SITE_URL}${pathname}`)} />

View file

@ -1,45 +1,45 @@
--- ---
import { SITE_TITLE, SITE_EMAIL } from "../consts"; import { SITE_TITLE, SITE_EMAIL } from "../consts"
const { theme } = Astro.props; const { theme } = Astro.props
import { SITE_NAME } from "../consts"; import { SITE_NAME } from "../consts"
const date = new Date(); const date = new Date()
const year = date.getFullYear(); const year = date.getFullYear();
--- ---
<div class:list={["footer-main", { "footer-dark": theme === "dark" }]}> <div class:list={["footer-main", { "footer-dark": theme === "dark" }]}>
<div class="content-body footer-wraper"> <div class="content-body footer-wrapper">
<div class="footer-box"> <div class="footer-box">
<div class="foot-nav"> <div class="foot-nav">
<div class="foot-nav-items"> <div class="foot-nav-items">
<div class="item"> <div class="item">
<div class="logo">{SITE_TITLE}</div> <div class="logo">{SITE_TITLE}</div>
<div class="email">Email: {SITE_EMAIL}</div> <div class="email">Email: {SITE_EMAIL}</div>
</div> </div>
<div class="item products"> <div class="item products">
<div class="item-title">作品</div> <div class="item-title">作品</div>
<a href="/" target="_blank">本站</a> <a href="/" target="_blank">本站</a>
<a href="https://repair.nbtca.space" target="_blank">维修管理</a> <a href="https://repair.nbtca.space" target="_blank">维修管理</a>
</div> </div>
<div class="item community"> <div class="item community">
<div class="item-title">社媒</div> <div class="item-title">社媒</div>
<a href="https://github.com/nbtca" target="_blank">Github</a> <a href="https://github.com/nbtca" target="_blank">Github</a>
</div> </div>
<div class="item resources"> <div class="item resources">
<div class="item-title">友链</div> <div class="item-title">友链</div>
<a href="https://www.cnblogs.com/N3ptune">N3ptune</a> <a href="https://www.cnblogs.com/N3ptune">N3ptune</a>
</div>
</div> </div>
</div> </div>
</div> <div class="bottom">
<div class="bottom"> <div class="copyright">
<div class="copyright"> &copy; {`2018-${year} ${SITE_NAME}`}
&copy; {`2018-${year} ${SITE_NAME}`} <a href="//github.com/austin2035/astro-air-blog">astro-air-blog</a>
<a href="//github.com/austin2035/astro-air-blog">astro-air-blog</a> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>

View file

@ -2,6 +2,6 @@
import Navigation from "./Navigation.astro"; import Navigation from "./Navigation.astro";
--- ---
<header> <header>
<Navigation /> <Navigation />
</header> </header>

View file

@ -5,20 +5,22 @@ import "../styles/global.css"
const { member } = Astro.props const { member } = Astro.props
--- ---
<div class="flex flex-col gap-2 w-full"> <div class="flex flex-col gap-2 w-full">
<div class="w-full rounded-lg overflow-hidden"> <div class="w-full rounded-lg overflow-hidden">
<div class="w-full aspect-square overflow-hidden flex items-center justify-center bg-gradient-to-b from-gray-300/70"> <div class="w-full aspect-square overflow-hidden flex items-center justify-center bg-gradient-to-b from-gray-300/70">
{ {
member.avatar ? ( member.avatar
<img class="object-cover h-full" src={member.avatar + "?x-oss-process=image/resize,h_512,m_lfit"} alt="" /> ? (
) : ( <img class="object-cover h-full" src={member.avatar + "?x-oss-process=image/resize,h_512,m_lfit"} alt="" />
<img class="object-cover h-3/4" src="https://oss.nbtca.space/CA-logo.svg" alt="" /> )
) : (
<img class="object-cover h-3/4" src="https://oss.nbtca.space/CA-logo.svg" alt="" />
)
} }
</div>
</div>
<div class="h-16">
<div class="text-lg">{member.alias}</div>
<div class="text-sm mt-0.5">{member.profile}</div>
</div> </div>
</div> </div>
<div class="h-16">
<div class="text-lg">{member.alias}</div>
<div class="text-sm mt-0.5">{member.profile}</div>
</div>
</div>

View file

@ -2,40 +2,40 @@
import { SITE_TITLE } from "../consts" import { SITE_TITLE } from "../consts"
--- ---
<nav class="nav"> <nav class="nav">
<div class="nav-wrapper"> <div class="nav-wrapper">
<div class="nav-content-wrapper"> <div class="nav-content-wrapper">
<div class="nav-content"> <div class="nav-content">
<a href="/" class="nav-title flex items-center gap-3"> <a href="/" class="nav-title flex items-center gap-3">
<img <img
src="https://oss.nbtca.space/CA-logo.svg" src="https://oss.nbtca.space/CA-logo.svg"
alt="" alt=""
style="width: 28px; aspect-ratio: 1;" style="width: 28px; aspect-ratio: 1;"
/> />
<span class="hidden md:block"> <span class="hidden md:block">
{SITE_TITLE} {SITE_TITLE}
</span> </span>
</a> </a>
<div class="nav-menu"> <div class="nav-menu">
<div class="nav-item-wrapper"> <div class="nav-item-wrapper">
<a href="/archive" class="nav-item-content">目录</a> <a href="/archive" class="nav-item-content">目录</a>
</div> </div>
<div class="nav-item-wrapper"> <div class="nav-item-wrapper">
<a href="https://repair.nbtca.space" class="nav-item-content"> <a href="https://repair.nbtca.space" class="nav-item-content">
维修 维修
</a> </a>
</div> </div>
<div class="nav-item-wrapper"> <div class="nav-item-wrapper">
<a href="/calendar" class="nav-item-content">日历</a> <a href="/calendar" class="nav-item-content">日历</a>
</div> </div>
<div class="nav-item-wrapper"> <div class="nav-item-wrapper">
<a href="/about" class="nav-item-content">关于</a> <a href="/about" class="nav-item-content">关于</a>
</div> </div>
<div class="nav-item-wrapper"> <div class="nav-item-wrapper">
<a href="/join-us" class="nav-item-content">加入我们</a> <a href="/join-us" class="nav-item-content">加入我们</a>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </nav>
</nav>

View file

@ -20,10 +20,8 @@ class CalendarComponment extends React.Component {
url: "https://ical.nbtca.space/", url: "https://ical.nbtca.space/",
format: "ics", format: "ics",
success: function (data) { success: function (data) {
data.forEach((element) => { data.forEach(element => {
element.color = element.title.includes("生日") element.color = element.title.includes("生日") ? "#fc7399" : "#5172dc"
? "#fc7399"
: "#5172dc"
}) })
}, },
}} }}

View file

@ -1,5 +1,5 @@
export const SITE_TITLE = `计算机协会`; export const SITE_TITLE = `计算机协会`
export const SITE_EMAIL = 'contact@nbtca.space' export const SITE_EMAIL = "contact@nbtca.space"
export const SITE_NAME = 'Computer Association'; export const SITE_NAME = "Computer Association"
export const SITE_DESCRIPTION = 'Computer Association'; export const SITE_DESCRIPTION = "Computer Association"
export const SITE_URL = "https://www.nbtca.space"; export const SITE_URL = "https://www.nbtca.space"

View file

@ -1,11 +1,11 @@
--- ---
import { formatDateV2 } from "../utils"; import { formatDateV2 } from "../utils"
const { posts } = Astro.props; const { posts } = Astro.props
posts.sort((a, b) => Date.parse(b.frontmatter.pubDate) - Date.parse(a.frontmatter.pubDate)); posts.sort((a, b) => Date.parse(b.frontmatter.pubDate) - Date.parse(a.frontmatter.pubDate));
--- ---
<ul> <ul>
{ {
posts.map((post) => { posts.map((post) => {
return ( return (
<li> <li>
@ -14,7 +14,7 @@ posts.sort((a, b) => Date.parse(b.frontmatter.pubDate) - Date.parse(a.frontmatte
{post.frontmatter.title} {post.frontmatter.title}
</a> </a>
</li> </li>
); )
}) })
} }
</ul> </ul>

View file

@ -1,19 +1,19 @@
--- ---
import BaseHead from "../components/BaseHead.astro"; import BaseHead from "../components/BaseHead.astro"
import Header from "../components/Header.astro"; import Header from "../components/Header.astro"
import Footer from "../components/Footer.astro"; import Footer from "../components/Footer.astro"
import { SITE_TITLE, SITE_DESCRIPTION } from "../consts"; import { SITE_TITLE, SITE_DESCRIPTION } from "../consts"
const { primaryTitle } = Astro.props; const { primaryTitle } = Astro.props
const title = primaryTitle ? `${primaryTitle} - ${SITE_TITLE}` : SITE_TITLE; const title = primaryTitle ? `${primaryTitle} - ${SITE_TITLE}` : SITE_TITLE;
--- ---
<html class="js no-touch progressive-image no-reduced-motion progressive" lang="zh-CN" dir="ltr"> <html class="js no-touch progressive-image no-reduced-motion progressive" lang="zh-CN" dir="ltr">
<head> <head>
<BaseHead title={title} description={SITE_DESCRIPTION} /> <BaseHead title={title} description={SITE_DESCRIPTION} />
</head> </head>
<body class="page-landing"> <body class="page-landing">
<Header /> <Header />
<slot /> <slot />
<Footer /> <Footer />
</body> </body>
</html> </html>

View file

@ -8,63 +8,63 @@ import { SITE_TITLE } from "../consts"
const { frontmatter } = Astro.props const { frontmatter } = Astro.props
const type = frontmatter.tags?.[0] ?? "默认" const type = frontmatter.tags?.[0] ?? "默认"
const { pubDate, title, description, featured } = frontmatter const { pubDate, title, description, featured } = frontmatter
const dateFormated = formatDate(pubDate) const dateFormatted = formatDate(pubDate)
--- ---
<html <html
lang="zh-CN" lang="zh-CN"
dir="ltr" dir="ltr"
class="js no-touch progressive-image no-reduced-motion progressive" class="js no-touch progressive-image no-reduced-motion progressive"
>
<head>
<BaseHead
title={`${title} - ${SITE_TITLE}`}
description={description}
image={frontmatter.cover?.square}
/>
</head>
<body
class:list={[
"page-article",
{ "theme-dark": frontmatter.theme === "dark" },
]}
> >
<Header /> <head>
<main id="main" class="main"> <BaseHead
<section> title={`${title} - ${SITE_TITLE}`}
<article class="article"> description={description}
<div image={frontmatter.cover?.square}
class:list={[ />
{ "featured-header": featured, "article-header": !featured }, </head>
]} <body
> class:list={[
<div class="category component"> "page-article",
<div class="component-content"> { "theme-dark": frontmatter.theme === "dark" },
<div class="category-eyebrow"> ]}
<span class="category-eyebrow__category category_original" >
>{type}</span <Header />
> <main id="main" class="main">
<span class="category-eyebrow__date">{dateFormated}</span> <section>
</div> <article class="article">
</div>
</div>
<div class="pagetitle component">
<div class="component-content">
<h1 class="hero-headline">{title}</h1>
</div>
</div>
<div <div
class:list={[ class:list={[
{ "featured-subhead": featured, "article-subhead": !featured }, { "featured-header": featured, "article-header": !featured },
"component",
]} ]}
> >
<div class="component-content">{description}</div> <div class="category component">
</div> <div class="component-content">
<div class="category-eyebrow">
<span class="category-eyebrow__category category_original">{type}
</span
>
<span class="category-eyebrow__date">{dateFormatted}</span>
</div>
</div>
</div>
<div class="page-title component">
<div class="component-content">
<h1 class="hero-headline">{title}</h1>
</div>
</div>
<div
class:list={[
{ "featured-subhead": featured, "article-subhead": !featured },
"component",
]}
>
<div class="component-content">{description}</div>
</div>
<div class:list={["tagssheet component"]}> <div class:list={["tags-sheet component"]}>
<div class="component-content"> <div class="component-content">
{ {
frontmatter.tags?.map((tag) => { frontmatter.tags?.map((tag) => {
return ( return (
<a href={`/tags/${tag}`} class="tag"> <a href={`/tags/${tag}`} class="tag">
@ -73,33 +73,34 @@ const dateFormated = formatDate(pubDate)
) )
}) })
} }
</div>
</div> </div>
</div> </div>
</div> <slot />
<slot /> <div class="component">
<div class="component"> <div class="component-content">
<div class="component-content"> <div class="article-copyright">
<div class="article-copyright"> <a
<a class="content"
class="content" href="https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh"
href="https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh" target="_blank"
target="_blank" >版权声明:自由转载-非商用-非衍生-保持署名创意共享3.0许可证)
>版权声明:自由转载-非商用-非衍生-保持署名创意共享3.0许可证)</a </a
> >
<p class="content"> <p class="content">
作者: {frontmatter.author} 发表日期:{dateFormated} 作者: {frontmatter.author} 发表日期:{dateFormatted}
</p> </p>
</div>
</div> </div>
</div> </div>
</div> </article>
</article> </section>
</section> </main>
</main> <Footer />
<Footer /> <script is:inline>
<script is:inline>
var script = document.createElement("script") var script = document.createElement("script")
script.src = "/static/js/initPost.js" script.src = "/static/js/initPost.js"
document.head.appendChild(script) document.head.appendChild(script)
</script> </script>
</body> </body>
</html> </html>

View file

@ -2,35 +2,35 @@
import { formatDate } from "../utils" import { formatDate } from "../utils"
const { title, href, cover, tags, date } = Astro.props const { title, href, cover, tags, date } = Astro.props
const dateFormated = formatDate(date) const dateFormatted = formatDate(date)
const type = tags?.[0] ?? "默认" const type = tags?.[0] ?? "默认"
const image = cover ? cover : "https://oss.nbtca.space/CA-logo.svg" const image = cover ? cover : "https://oss.nbtca.space/CA-logo.svg"
const label = `${title} - ${type} - 发表时间 ${dateFormated}` const label = `${title} - ${type} - 发表时间 ${dateFormatted}`
--- ---
<li <li
role="listitem" role="list-item"
class="tile-item item-list nr-scroll-animation" class="tile-item item-list nr-scroll-animation"
style="--nr-animation-transform-y:20%;" style="--nr-animation-transform-y:20%;"
>
<a
href={href}
class="tile tile-list medium-load small-load large-load"
aria-label={label}
> >
<div class="tile__media" aria-hidden="true"> <a
<img class="cover image" data-src={image} alt="lt" /> href={href}
</div> class="tile tile-list medium-load small-load large-load"
<div class="tile__description" aria-hidden="true"> aria-label={label}
<div class="tile__head"> >
<div class="tile__category">{type}</div> <div class="tile__media" aria-hidden="true">
<div class="tile__headline">{title}</div> <img class="cover image" data-src={image} alt="lt" />
</div> </div>
<div class="tile__timestamp icon-hide icon icon-before icon-clock"> <div class="tile__description" aria-hidden="true">
{dateFormated} <div class="tile__head">
<div class="tile__category">{type}</div>
<div class="tile__headline">{title}</div>
</div>
<div class="tile__timestamp icon-hide icon icon-before icon-clock">
{dateFormatted}
</div>
</div> </div>
</div> </a>
</a> </li>
</li>

View file

@ -1,35 +1,35 @@
--- ---
import { formatDate } from "../utils"; import { formatDate } from "../utils"
const { title, href, cover, tags, date, level} = Astro.props; const { title, href, cover, tags, date, level } = Astro.props
const dateFormated = formatDate(date); const dateFormatted = formatDate(date)
const type = tags[0]; const type = tags[0]
const label = `${title} - ${type} - 发表时间 ${dateFormated}`; const label = `${title} - ${type} - 发表时间 ${dateFormatted}`;
// level 1: hreo // level 1: hero
// level 2: 2up // level 2: 2up
// level 3: 3up // level 3: 3up
--- ---
<li <li
role="listitem" role="list-item"
class:list={["tile-item", "nr-scroll-animation", { "item-hero": level === "1", "item-2up": level === "2", "item-3up": level === "3" }]} class:list={["tile-item", "nr-scroll-animation", { "item-hero": level === "1", "item-2up": level === "2", "item-3up": level === "3" }]}
style="--nr-animation-transform-y:20%;" style="--nr-animation-transform-y:20%;"
>
<a
href={href}
class:list={["tile", "large-load", "medium-load", "small-load", { "tile-hero": level === "1", "tile-2up": level === "2", "tile-3up": level === "3" }]}
aria-label={label}
> >
<div class="tile__media" aria-hidden="true"> <a
<img class="cover image" data-src={cover} alt="lt"/> href={href}
</div> class:list={["tile", "large-load", "medium-load", "small-load", { "tile-hero": level === "1", "tile-2up": level === "2", "tile-3up": level === "3" }]}
aria-label={label}
<div class="tile__description" aria-hidden="true"> >
<div class="tile__head"> <div class="tile__media" aria-hidden="true">
<div class="tile__category">{type}</div> <img class="cover image" data-src={cover} alt="lt" />
<div class="tile__headline">{title}</div>
</div> </div>
<div class="tile__timestamp icon-hide icon icon-before icon-clock">{dateFormated}</div>
</div> <div class="tile__description" aria-hidden="true">
</a> <div class="tile__head">
</li> <div class="tile__category">{type}</div>
<div class="tile__headline">{title}</div>
</div>
<div class="tile__timestamp icon-hide icon icon-before icon-clock">{dateFormatted}</div>
</div>
</a>
</li>

View file

@ -1,15 +1,14 @@
--- ---
import BaseLayout from "../layouts/BaseLayout.astro"; import BaseLayout from "../layouts/BaseLayout.astro"
import ArchivePostList from "../layouts/ArchivePostList.astro";
--- ---
<BaseLayout primaryTitle="404 Not Found"> <BaseLayout primaryTitle="404 Not Found">
<section class="archive"> <section class="archive">
<div class="section-content section-tag"> <div class="section-content section-tag">
<div class="archive-tag"> <div class="archive-tag">
<h2 class="tag-header">404 Not Found</h2> <h2 class="tag-header">404 Not Found</h2>
<div class="tag-post-list">来到了一片荒原,这里什么都没有。</div> <div class="tag-post-list">来到了一片荒原,这里什么都没有。</div>
</div>
</div> </div>
</div> </section>
</section> </BaseLayout>
</BaseLayout>

View file

@ -4,7 +4,7 @@ import { computed } from "vue"
import MemberCard from "../components/MemberCard.astro" import MemberCard from "../components/MemberCard.astro"
import { type Member, otherMembers } from "../store/member.ts" import { type Member, otherMembers } from "../store/member.ts"
const members: Member[] = await fetch("https://api.nbtca.space/v2/members").then(res => { const members: Member[] = await fetch("https://api.nbtca.space/v2/members").then((res) => {
return res.json() return res.json()
}) })
@ -22,23 +22,23 @@ const memberGroupByYear = computed(() => {
acc[year].push(cur) acc[year].push(cur)
return acc return acc
}, },
{} as Record<string, Member[]> {} as Record<string, Member[]>,
) )
group["往届"] = otherMembers group["往届"] = otherMembers
return group return group
}) })
--- ---
<BaseLayout primaryTitle="关于"> <BaseLayout primaryTitle="关于">
<section class="pb-20 bg-[#f5f5f7]"> <section class="pb-20 bg-[#f5f5f7]">
<div class="section-content"> <div class="section-content">
<!-- <div class="text-[32px] leading-[1.125] font-bold py-6">友情链接</div> --> <!-- <div class="text-[32px] leading-[1.125] font-bold py-6">友情链接</div> -->
<div class="text-[32px] leading-[1.125] font-bold py-6">协会成员</div> <div class="text-[32px] leading-[1.125] font-bold py-6">协会成员</div>
<div> <div>
{ {
Object.keys(memberGroupByYear.value) Object.keys(memberGroupByYear.value)
.sort((a, b) => parseInt(b) - parseInt(a)) .sort((a, b) => parseInt(b) - parseInt(a))
.map(year => { .map((year) => {
return ( return (
<div class="py-4 first:pt-2"> <div class="py-4 first:pt-2">
<div class="text-[24px] font-bold pb-2">{year}</div> <div class="text-[24px] font-bold pb-2">{year}</div>
@ -51,7 +51,7 @@ const memberGroupByYear = computed(() => {
) )
}) })
} }
</div>
</div> </div>
</div> </section>
</section> </BaseLayout>
</BaseLayout>

View file

@ -7,35 +7,37 @@ const tags = ["寝室", "技术", "学习", "其他"]
const posts = [] const posts = []
tags.forEach((tag) => { tags.forEach((tag) => {
let filteredPosts = allPosts.filter((post) => const filteredPosts = allPosts.filter(post =>
post.frontmatter.tags.includes(tag) post.frontmatter.tags.includes(tag),
) )
let filteredBlogs = Blogs.filter( const filteredBlogs = Blogs.filter(
(post) => post.frontmatter.tags?.includes(tag) ?? tag === "其他" post => post.frontmatter.tags?.includes(tag) ?? tag === "其他",
) )
posts.push([...filteredPosts, ...filteredBlogs]) posts.push([...filteredPosts, ...filteredBlogs])
}) })
--- ---
<BaseLayout primaryTitle="归档"> <BaseLayout primaryTitle="归档">
<section class="archive"> <section class="archive">
<div class="section-content section-tag"> <div class="section-content section-tag">
{ {
tags.map((tag, index) => { tags.map((tag, index) => {
return ( return (
<div class="archive-tag"> <div class="archive-tag">
<h2 class="tag-header">{tag}</h2> <h2 class="tag-header">{tag}</h2>
<div class="tag-post-list"> <div class="tag-post-list">
{posts[index].length !== 0 ? ( {posts[index].length !== 0
<ArchivePostList posts={posts[index]} /> ? (
) : ( <ArchivePostList posts={posts[index]} />
<div class="no-posts">暂无文章</div> )
)} : (
<div class="no-posts">暂无文章</div>
)}
</div> </div>
</div> </div>
) )
}) })
} }
</div> </div>
</section> </section>
</BaseLayout> </BaseLayout>

View file

@ -3,6 +3,6 @@ import FullCalendar from "../components/react/Calendar"
import BaseLayout from "../layouts/BaseLayout.astro" import BaseLayout from "../layouts/BaseLayout.astro"
--- ---
<BaseLayout primaryTitle="日历"> <BaseLayout primaryTitle="日历">
<FullCalendar client:load /> <FullCalendar client:load />
</BaseLayout> </BaseLayout>

View file

@ -6,16 +6,16 @@ const allPosts = await Astro.glob("../pages/posts/*.md")
const Blogs = await Astro.glob("../pages/posts/blogs/**/*.md") const Blogs = await Astro.glob("../pages/posts/blogs/**/*.md")
allPosts.sort( allPosts.sort(
(a, b) => (a, b) =>
Date.parse(b.frontmatter.pubDate) - Date.parse(a.frontmatter.pubDate) Date.parse(b.frontmatter.pubDate) - Date.parse(a.frontmatter.pubDate),
) )
--- ---
<BaseLayout> <BaseLayout>
<section class="everydayfeed"> <section class="every-day-feed">
<div class="section-content"> <div class="section-content">
<h2 class="section-head">最新文章</h2> <h2 class="section-head">最新文章</h2>
<ul role="list" class="section-tiles"> <ul role="list" class="section-tiles">
{ {
// tile-hero // tile-hero
allPosts.slice(0, 1).map((post) => { allPosts.slice(0, 1).map((post) => {
return ( return (
@ -31,7 +31,7 @@ allPosts.sort(
}) })
} }
{ {
// tile-2up // tile-2up
allPosts.slice(1, 5).map((post) => { allPosts.slice(1, 5).map((post) => {
return ( return (
@ -47,7 +47,7 @@ allPosts.sort(
}) })
} }
{ {
// tile-3up // tile-3up
allPosts.slice(5, 11).map((post) => { allPosts.slice(5, 11).map((post) => {
return ( return (
@ -62,16 +62,16 @@ allPosts.sort(
) )
}) })
} }
</ul> </ul>
</div> </div>
</section> </section>
<section class="more-from-newsroom"> <section class="more-from-newsroom">
<div class="section-content"> <div class="section-content">
<h2 class="section-head">更多文章</h2> <h2 class="section-head">更多文章</h2>
<ul role="list" class="section-tiles"> <ul role="list" class="section-tiles">
{ {
// tile-2up // tile-2up
allPosts.slice(0, 6).map((post) => { allPosts.slice(0, 6).map((post) => {
return ( return (
@ -85,7 +85,7 @@ allPosts.sort(
) )
}) })
} }
{ {
Blogs.slice(1, 7).map((post) => { Blogs.slice(1, 7).map((post) => {
return ( return (
<MoreTile <MoreTile
@ -97,29 +97,32 @@ allPosts.sort(
) )
}) })
} }
</ul> </ul>
<div class="view-archive-wrapper"> <div class="view-archive-wrapper">
<a <a
href="/archive" href="/archive"
class="cta-primary-light" class="cta-primary-light"
data-analytics-region="router" data-analytics-region="router"
data-analytics-title="view archive">阅读历史文章</a data-analytics-title="view archive"
> >
阅读历史文章
</a>
</div>
</div> </div>
</div> </section>
</section>
<script is:inline> <script is:inline>
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
var script = document.createElement("script") var script = document.createElement("script")
script.src = "/static/js/animation.js" script.src = "/static/js/animation.js"
document.head.appendChild(script) document.head.appendChild(script)
script.onload = function () { script.onload = function () {
console.log("lazyload.js loaded") console.log("LazyLoad.js loaded")
// when layout is loaded, load the images // when layout is loaded, load the images
// eslint-disable-next-line no-undef
initImage() initImage()
} }
}) })
</script> </script>
</BaseLayout> </BaseLayout>

View file

@ -2,34 +2,36 @@
import BaseLayout from "../layouts/BaseLayout.astro"; import BaseLayout from "../layouts/BaseLayout.astro";
--- ---
<BaseLayout primaryTitle="加入我们"> <BaseLayout primaryTitle="加入我们">
<div class="container"> <div class="container">
<h2 class="life-at-apple__eyebrow">在 NBTCA 生活</h2> <h2 class="life-at-apple__eyebrow">在 NBTCA 生活</h2>
<p class="t-hero-headline-oversized"> <p class="t-hero-headline-oversized">
<span <span
class="t-hero-headline-oversized-span" class="t-hero-headline-oversized-span"
aria-label="加入我们,共同创造我们的社区。" aria-label="加入我们,共同创造我们的社区。"
> >
<span class="gradient-warm">加入我们,共同创造我们的社区。</span> <span class="gradient-warm">加入我们,共同创造我们的社区。</span>
</span> </span>
</p>
<div class="body-container">
<p class="life-at-apple__body-text">
探索我们的资源和文化:这里有丰富的资源和注重包容、成长和独创性的协作文化,助你缔造精彩人生。
</p> </p>
</div> <div class="body-container">
<div class="learn-more-link-container"> <p class="life-at-apple__body-text">
<a 探索我们的资源和文化:这里有丰富的资源和注重包容、成长和独创性的协作文化,助你缔造精彩人生。
href="/careers/cn/life-at-apple.html" </p>
class="learn-more-link" </div>
aria-label="进一步了解 NBTCA 的社区和文化">了解在 NBTCA 生活</a <div class="learn-more-link-container">
<a
href="/careers/cn/life-at-apple.html"
class="learn-more-link"
aria-label="进一步了解 NBTCA 的社区和文化"
>了解在 NBTCA 生活
</a
> >
<a class="learn-more-link-after">&gt; </a> <a class="learn-more-link-after">&gt; </a>
</div>
</div> </div>
</div> </BaseLayout>
</BaseLayout>
<style> <style>
@media screen and (min-width: 680px) { @media screen and (min-width: 680px) {
/*PC*/ /*PC*/
.container { .container {
@ -251,4 +253,4 @@ import BaseLayout from "../layouts/BaseLayout.astro";
justify-content: center; justify-content: center;
height: 100px; height: 100px;
} }
</style> </style>

View file

@ -1,11 +1,11 @@
import rss, { pagesGlobToRssItems } from '@astrojs/rss'; import rss, { pagesGlobToRssItems } from "@astrojs/rss"
export async function get() { export async function get() {
return rss({ return rss({
title: "Austin's Blog", title: "Austin's Blog",
description: "Site description", description: "Site description",
site: 'https://astro-blog.qum.cc', site: "https://astro-blog.qum.cc",
items: await pagesGlobToRssItems(import.meta.glob('./**/*.md')), items: await pagesGlobToRssItems(import.meta.glob("./**/*.md")),
customData: `<language>zh-cn</language>`, customData: `<language>zh-cn</language>`,
}); })
} }

View file

@ -1,32 +1,34 @@
--- ---
import BaseLayout from "../../layouts/BaseLayout.astro"; import BaseLayout from "../../layouts/BaseLayout.astro"
import ArchivePostList from "../../layouts/ArchivePostList.astro"; import ArchivePostList from "../../layouts/ArchivePostList.astro"
const { tag } = Astro.params; const { tag } = Astro.params
const { posts } = Astro.props; const { posts } = Astro.props
export async function getStaticPaths() { export async function getStaticPaths() {
const allPosts = await Astro.glob("../posts/*.md"); const allPosts = await Astro.glob("../posts/*.md")
const uniqueTags = [...new Set(allPosts.map((post) => post.frontmatter.tags).flat())]; const uniqueTags = [...new Set(allPosts.map(post => post.frontmatter.tags).flat())]
return uniqueTags.map((tag) => { return uniqueTags.map((tag) => {
const filteredPosts = allPosts.filter((post) => post.frontmatter.tags.includes(tag)); const filteredPosts = allPosts.filter(post => post.frontmatter.tags.includes(tag))
return { return {
params: { tag }, params: { tag },
props: { posts: filteredPosts }, props: { posts: filteredPosts },
}; }
}); })
} }
--- ---
<BaseLayout primaryTitle={tag}> <BaseLayout primaryTitle={tag}>
<section class="archive"> <section class="archive">
<div class="section-content section-tag"> <div class="section-content section-tag">
<div class="archive-tag"> <div class="archive-tag">
<h2 class="tag-header">{tag}</h2> <h2 class="tag-header">{tag}</h2>
<div class="tag-post-list">{ <div class="tag-post-list">{
posts.length !== 0 ? <ArchivePostList posts={posts} /> : <div class="no-posts">暂无文章</div>}</div> posts.length !== 0 ? <ArchivePostList posts={posts} /> : <div class="no-posts">暂无文章</div>
}
</div>
</div>
</div> </div>
</div> </section>
</section> </BaseLayout>
</BaseLayout>

File diff suppressed because it is too large Load diff

View file

@ -1,32 +1,31 @@
export function formatDate(dateString) { export function formatDate(dateString) {
const date = new Date(dateString); const date = new Date(dateString)
const year = date.getFullYear(); const year = date.getFullYear()
const month = date.getMonth() + 1; const month = date.getMonth() + 1
const day = date.getDate(); const day = date.getDate()
return year + " 年 " + month + " 月 " + day + " 日"; return year + " 年 " + month + " 月 " + day + " 日"
} }
// debounce function // debounce function
export function debounce(fn, delay) { export function debounce(fn, delay) {
let timer = null; let timer = null
return function () { return function () {
let context = this; const context = this
let args = arguments; const args = arguments
clearTimeout(timer); clearTimeout(timer)
timer = setTimeout(function () { timer = setTimeout(function () {
fn.apply(context, args); fn.apply(context, args)
}, delay); }, delay)
}; }
} }
export function formatDateV2(date) { export function formatDateV2(date) {
// 创建一个Date对象 // 创建一个Date对象
let d = new Date(date); const d = new Date(date)
// 使用toLocaleString方法返回本地时间字符串 // 使用toLocaleString方法返回本地时间字符串
let localTime = d.toLocaleString("zh-CN", {year: "numeric", month: "2-digit", day: "2-digit"}); const localTime = d.toLocaleString("zh-CN", { year: "numeric", month: "2-digit", day: "2-digit" })
// 去掉字符串中的斜杠和空格 // 去掉字符串中的斜杠和空格
let formattedDate = localTime.replace(/\//g, "-").replace(/\s/g, ""); const formattedDate = localTime.replace(/\//g, "-").replace(/\s/g, "")
// 返回格式化后的日期 // 返回格式化后的日期
return formattedDate; return formattedDate
} }

View file

@ -1,8 +1,8 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
export default { export default {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
theme: { theme: {
extend: {}, extend: {},
}, },
plugins: [], plugins: [],
} }