some little tweaks, modify Twikoo.astro to support auto reload when first loading; add new post add_twikoo_for_fuwari.md
This commit is contained in:
@ -34,7 +34,7 @@ export default defineConfig({
|
||||
nesting: true,
|
||||
}),
|
||||
swup({
|
||||
theme: false,
|
||||
theme: true,
|
||||
animationClass: "transition-swup-", // see https://swup.js.org/options/#animationselector
|
||||
// the default value `transition-` cause transition delay
|
||||
// when the Tailwind class `transition-all` is used
|
||||
|
||||
30
package.json
30
package.json
@ -17,28 +17,28 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.9.6",
|
||||
"@astrojs/rss": "^4.0.14",
|
||||
"@astrojs/sitemap": "^3.6.0",
|
||||
"@astrojs/svelte": "7.2.3",
|
||||
"@astrojs/rss": "^4.0.15",
|
||||
"@astrojs/sitemap": "^3.7.0",
|
||||
"@astrojs/svelte": "7.2.5",
|
||||
"@astrojs/tailwind": "^6.0.2",
|
||||
"@expressive-code/core": "^0.41.4",
|
||||
"@expressive-code/plugin-collapsible-sections": "^0.41.4",
|
||||
"@expressive-code/plugin-line-numbers": "^0.41.4",
|
||||
"@expressive-code/core": "^0.41.7",
|
||||
"@expressive-code/plugin-collapsible-sections": "^0.41.7",
|
||||
"@expressive-code/plugin-line-numbers": "^0.41.7",
|
||||
"@fontsource-variable/jetbrains-mono": "^5.2.8",
|
||||
"@fontsource/roboto": "^5.2.9",
|
||||
"@fontsource/roboto": "^5.2.10",
|
||||
"@iconify-json/fa6-brands": "^1.2.6",
|
||||
"@iconify-json/fa6-regular": "^1.2.4",
|
||||
"@iconify-json/fa6-solid": "^1.2.4",
|
||||
"@iconify-json/material-symbols": "^1.2.50",
|
||||
"@iconify-json/material-symbols": "^1.2.60",
|
||||
"@iconify/svelte": "^4.2.0",
|
||||
"@swup/astro": "^1.7.0",
|
||||
"@swup/astro": "^1.8.0",
|
||||
"@tailwindcss/typography": "^0.5.19",
|
||||
"astro": "5.13.10",
|
||||
"astro-expressive-code": "^0.41.4",
|
||||
"astro-expressive-code": "^0.41.7",
|
||||
"astro-icon": "^1.1.5",
|
||||
"hastscript": "^9.0.1",
|
||||
"katex": "^0.16.27",
|
||||
"markdown-it": "^14.1.0",
|
||||
"katex": "^0.16.35",
|
||||
"markdown-it": "^14.1.1",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"overlayscrollbars": "^2.12.0",
|
||||
"pagefind": "^1.4.0",
|
||||
@ -53,10 +53,10 @@
|
||||
"remark-github-admonitions-to-directives": "^1.0.5",
|
||||
"remark-math": "^6.0.0",
|
||||
"remark-sectionize": "^2.1.0",
|
||||
"sanitize-html": "^2.17.0",
|
||||
"sanitize-html": "^2.17.1",
|
||||
"sharp": "^0.34.5",
|
||||
"stylus": "^0.64.0",
|
||||
"svelte": "^5.39.8",
|
||||
"svelte": "^5.53.7",
|
||||
"tailwindcss": "^3.4.19",
|
||||
"typescript": "^5.9.3",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
@ -68,7 +68,7 @@
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"@types/sanitize-html": "^2.16.0",
|
||||
"@types/sanitize-html": "^2.16.1",
|
||||
"postcss-import": "^16.1.1",
|
||||
"postcss-nesting": "^13.0.2"
|
||||
},
|
||||
|
||||
2724
pnpm-lock.yaml
generated
2724
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -51,7 +51,7 @@ let links: NavBarLink[] = navBarConfig.links.map(
|
||||
<Icon name="material-symbols:palette-outline" class="text-[1.25rem]"></Icon>
|
||||
</button>
|
||||
)}
|
||||
{/* @ts-expect-error – client:only 是 Astro 指令,非组件 Prop */}
|
||||
|
||||
<LightDarkSwitch client:only="svelte"></LightDarkSwitch>
|
||||
<button aria-label="Menu" name="Nav Menu" class="btn-plain scale-animation rounded-lg w-11 h-11 active:scale-90 md:!hidden" id="nav-menu-switch">
|
||||
<Icon name="material-symbols:menu-rounded" class="text-[1.25rem]"></Icon>
|
||||
|
||||
@ -7,19 +7,87 @@ const shouldRender = enable && envId;
|
||||
---
|
||||
|
||||
{shouldRender && (
|
||||
<div id="twikoo-comment"></div>
|
||||
<div id="twikoo-comment" class="card-base p-6 mb-4 text-black/75 dark:text-white/75 transition">
|
||||
<p>加载评论中...</p>
|
||||
</div>
|
||||
|
||||
<script is:inline src="https://s4.zstatic.net/npm/twikoo@1.7.1/dist/twikoo.min.js"></script>
|
||||
<script is:inline define:vars={{ envId, lang }}>
|
||||
(function() {
|
||||
const MAX_RETRIES = 3;
|
||||
const RETRY_DELAY = 2000;
|
||||
|
||||
<script define:vars={{ envId, lang }}>
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
if (typeof twikoo !== 'undefined') {
|
||||
twikoo.init({
|
||||
envId,
|
||||
el: '#twikoo-comment',
|
||||
lang,
|
||||
}).catch(console.error);
|
||||
let scriptRetryCount = 0;
|
||||
let initRetryCount = 0;
|
||||
|
||||
// 尝试初始化 Twikoo
|
||||
function initTwikoo() {
|
||||
if (typeof twikoo === 'undefined') {
|
||||
// Twikoo 对象不存在,说明脚本还没加载成功,重试加载脚本
|
||||
if (scriptRetryCount < MAX_RETRIES) {
|
||||
scriptRetryCount++;
|
||||
console.log(`Twikoo 库未加载,尝试重新加载脚本 (${scriptRetryCount}/${MAX_RETRIES})……`);
|
||||
setTimeout(loadScript, RETRY_DELAY);
|
||||
} else {
|
||||
console.error('Twikoo 库加载失败,已达到最大重试次数。');
|
||||
showError('评论加载失败,请刷新页面重试。');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
twikoo.init({ envId, el: '#twikoo-comment', lang })
|
||||
.then(() => {
|
||||
console.log('Twikoo 初始化成功');
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Twikoo 初始化失败:', err);
|
||||
if (initRetryCount < MAX_RETRIES) {
|
||||
initRetryCount++;
|
||||
console.log(`尝试重新初始化 (${initRetryCount}/${MAX_RETRIES})……`);
|
||||
setTimeout(initTwikoo, RETRY_DELAY);
|
||||
} else {
|
||||
showError('评论加载失败,请刷新页面重试。');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function loadScript() {
|
||||
const script = document.createElement('script');
|
||||
|
||||
// 推荐在中国使用
|
||||
// https://registry.npmmirror.com/twikoo/1.7.1/files/dist/twikoo.min.js
|
||||
// https://s4.zstatic.net/npm/twikoo@1.7.1/dist/twikoo.min.js
|
||||
// 推荐在全球使用
|
||||
// https://cdn.jsdelivr.net/npm/twikoo@1.7.1/dist/twikoo.min.js
|
||||
// 备用选项
|
||||
// https://s4.zstatic.net/ajax/libs/twikoo/1.6.41/twikoo.min.js
|
||||
// https://lib.baomitu.com/twikoo/1.6.39/twikoo.min.js
|
||||
|
||||
script.src = 'https://s4.zstatic.net/npm/twikoo@1.7.1/dist/twikoo.min.js';
|
||||
script.onload = () => {
|
||||
console.log('Twikoo 脚本加载成功');
|
||||
scriptRetryCount = 0;
|
||||
initTwikoo();
|
||||
};
|
||||
script.onerror = () => {
|
||||
console.error('Twikoo 脚本加载失败');
|
||||
if (scriptRetryCount < MAX_RETRIES) {
|
||||
scriptRetryCount++;
|
||||
console.log(`尝试重新加载脚本 (${scriptRetryCount}/${MAX_RETRIES})……`);
|
||||
setTimeout(loadScript, RETRY_DELAY);
|
||||
} else {
|
||||
showError('评论加载失败,请刷新页面重试。');
|
||||
}
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
// 显示错误信息到评论区
|
||||
function showError(msg) {
|
||||
const container = document.querySelector('#twikoo-comment');
|
||||
if (container) container.innerHTML = `<p style="color: red;">${msg}</p>`;
|
||||
}
|
||||
|
||||
loadScript();
|
||||
})();
|
||||
</script>
|
||||
)}
|
||||
311
src/content/posts/Expressive_Code_Example.md
Normal file
311
src/content/posts/Expressive_Code_Example.md
Normal file
@ -0,0 +1,311 @@
|
||||
---
|
||||
title: Expressive Code Example
|
||||
published: 2024-04-10
|
||||
description: How code blocks look in Markdown using Expressive Code.
|
||||
tags: [Markdown, Blogging, Demo]
|
||||
category: Examples
|
||||
draft: false
|
||||
---
|
||||
|
||||
Here, we'll explore how code blocks look using [Expressive Code](https://expressive-code.com/). The provided examples are based on the official documentation, which you can refer to for further details.
|
||||
|
||||
## Expressive Code
|
||||
|
||||
### Syntax Highlighting
|
||||
|
||||
[Syntax Highlighting](https://expressive-code.com/key-features/syntax-highlighting/)
|
||||
|
||||
#### Regular syntax highlighting
|
||||
|
||||
```js
|
||||
console.log('This code is syntax highlighted!')
|
||||
```
|
||||
|
||||
#### Rendering ANSI escape sequences
|
||||
|
||||
```ansi
|
||||
ANSI colors:
|
||||
- Regular: [31mRed[0m [32mGreen[0m [33mYellow[0m [34mBlue[0m [35mMagenta[0m [36mCyan[0m
|
||||
- Bold: [1;31mRed[0m [1;32mGreen[0m [1;33mYellow[0m [1;34mBlue[0m [1;35mMagenta[0m [1;36mCyan[0m
|
||||
- Dimmed: [2;31mRed[0m [2;32mGreen[0m [2;33mYellow[0m [2;34mBlue[0m [2;35mMagenta[0m [2;36mCyan[0m
|
||||
|
||||
256 colors (showing colors 160-177):
|
||||
[38;5;160m160 [38;5;161m161 [38;5;162m162 [38;5;163m163 [38;5;164m164 [38;5;165m165[0m
|
||||
[38;5;166m166 [38;5;167m167 [38;5;168m168 [38;5;169m169 [38;5;170m170 [38;5;171m171[0m
|
||||
[38;5;172m172 [38;5;173m173 [38;5;174m174 [38;5;175m175 [38;5;176m176 [38;5;177m177[0m
|
||||
|
||||
Full RGB colors:
|
||||
[38;2;34;139;34mForestGreen - RGB(34, 139, 34)[0m
|
||||
|
||||
Text formatting: [1mBold[0m [2mDimmed[0m [3mItalic[0m [4mUnderline[0m
|
||||
```
|
||||
|
||||
### Editor & Terminal Frames
|
||||
|
||||
[Editor & Terminal Frames](https://expressive-code.com/key-features/frames/)
|
||||
|
||||
#### Code editor frames
|
||||
|
||||
```js title="my-test-file.js"
|
||||
console.log('Title attribute example')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```html
|
||||
<!-- src/content/index.html -->
|
||||
<div>File name comment example</div>
|
||||
```
|
||||
|
||||
#### Terminal frames
|
||||
|
||||
```bash
|
||||
echo "This terminal frame has no title"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```powershell title="PowerShell terminal example"
|
||||
Write-Output "This one has a title!"
|
||||
```
|
||||
|
||||
#### Overriding frame types
|
||||
|
||||
```sh frame="none"
|
||||
echo "Look ma, no frame!"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```ps frame="code" title="PowerShell Profile.ps1"
|
||||
# Without overriding, this would be a terminal frame
|
||||
function Watch-Tail { Get-Content -Tail 20 -Wait $args }
|
||||
New-Alias tail Watch-Tail
|
||||
```
|
||||
|
||||
### Text & Line Markers
|
||||
|
||||
[Text & Line Markers](https://expressive-code.com/key-features/text-markers/)
|
||||
|
||||
#### Marking full lines & line ranges
|
||||
|
||||
```js {1, 4, 7-8}
|
||||
// Line 1 - targeted by line number
|
||||
// Line 2
|
||||
// Line 3
|
||||
// Line 4 - targeted by line number
|
||||
// Line 5
|
||||
// Line 6
|
||||
// Line 7 - targeted by range "7-8"
|
||||
// Line 8 - targeted by range "7-8"
|
||||
```
|
||||
|
||||
#### Selecting line marker types (mark, ins, del)
|
||||
|
||||
```js title="line-markers.js" del={2} ins={3-4} {6}
|
||||
function demo() {
|
||||
console.log('this line is marked as deleted')
|
||||
// This line and the next one are marked as inserted
|
||||
console.log('this is the second inserted line')
|
||||
|
||||
return 'this line uses the neutral default marker type'
|
||||
}
|
||||
```
|
||||
|
||||
#### Adding labels to line markers
|
||||
|
||||
```jsx {"1":5} del={"2":7-8} ins={"3":10-12}
|
||||
// labeled-line-markers.jsx
|
||||
<button
|
||||
role="button"
|
||||
{...props}
|
||||
value={value}
|
||||
className={buttonClassName}
|
||||
disabled={disabled}
|
||||
active={active}
|
||||
>
|
||||
{children &&
|
||||
!active &&
|
||||
(typeof children === 'string' ? <span>{children}</span> : children)}
|
||||
</button>
|
||||
```
|
||||
|
||||
#### Adding long labels on their own lines
|
||||
|
||||
```jsx {"1. Provide the value prop here:":5-6} del={"2. Remove the disabled and active states:":8-10} ins={"3. Add this to render the children inside the button:":12-15}
|
||||
// labeled-line-markers.jsx
|
||||
<button
|
||||
role="button"
|
||||
{...props}
|
||||
|
||||
value={value}
|
||||
className={buttonClassName}
|
||||
|
||||
disabled={disabled}
|
||||
active={active}
|
||||
>
|
||||
|
||||
{children &&
|
||||
!active &&
|
||||
(typeof children === 'string' ? <span>{children}</span> : children)}
|
||||
</button>
|
||||
```
|
||||
|
||||
#### Using diff-like syntax
|
||||
|
||||
```diff
|
||||
+this line will be marked as inserted
|
||||
-this line will be marked as deleted
|
||||
this is a regular line
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```diff
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -1,3 +1,4 @@
|
||||
+this is an actual diff file
|
||||
-all contents will remain unmodified
|
||||
no whitespace will be removed either
|
||||
```
|
||||
|
||||
#### Combining syntax highlighting with diff-like syntax
|
||||
|
||||
```diff lang="js"
|
||||
function thisIsJavaScript() {
|
||||
// This entire block gets highlighted as JavaScript,
|
||||
// and we can still add diff markers to it!
|
||||
- console.log('Old code to be removed')
|
||||
+ console.log('New and shiny code!')
|
||||
}
|
||||
```
|
||||
|
||||
#### Marking individual text inside lines
|
||||
|
||||
```js "given text"
|
||||
function demo() {
|
||||
// Mark any given text inside lines
|
||||
return 'Multiple matches of the given text are supported';
|
||||
}
|
||||
```
|
||||
|
||||
#### Regular expressions
|
||||
|
||||
```ts /ye[sp]/
|
||||
console.log('The words yes and yep will be marked.')
|
||||
```
|
||||
|
||||
#### Escaping forward slashes
|
||||
|
||||
```sh /\/ho.*\//
|
||||
echo "Test" > /home/test.txt
|
||||
```
|
||||
|
||||
#### Selecting inline marker types (mark, ins, del)
|
||||
|
||||
```js "return true;" ins="inserted" del="deleted"
|
||||
function demo() {
|
||||
console.log('These are inserted and deleted marker types');
|
||||
// The return statement uses the default marker type
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
### Word Wrap
|
||||
|
||||
[Word Wrap](https://expressive-code.com/key-features/word-wrap/)
|
||||
|
||||
#### Configuring word wrap per block
|
||||
|
||||
```js wrap
|
||||
// Example with wrap
|
||||
function getLongString() {
|
||||
return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js wrap=false
|
||||
// Example with wrap=false
|
||||
function getLongString() {
|
||||
return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
|
||||
}
|
||||
```
|
||||
|
||||
#### Configuring indentation of wrapped lines
|
||||
|
||||
```js wrap preserveIndent
|
||||
// Example with preserveIndent (enabled by default)
|
||||
function getLongString() {
|
||||
return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js wrap preserveIndent=false
|
||||
// Example with preserveIndent=false
|
||||
function getLongString() {
|
||||
return 'This is a very long string that will most probably not fit into the available space unless the container is extremely wide'
|
||||
}
|
||||
```
|
||||
|
||||
## Collapsible Sections
|
||||
|
||||
[Collapsible Sections](https://expressive-code.com/plugins/collapsible-sections/)
|
||||
|
||||
```js collapse={1-5, 12-14, 21-24}
|
||||
// All this boilerplate setup code will be collapsed
|
||||
import { someBoilerplateEngine } from '@example/some-boilerplate'
|
||||
import { evenMoreBoilerplate } from '@example/even-more-boilerplate'
|
||||
|
||||
const engine = someBoilerplateEngine(evenMoreBoilerplate())
|
||||
|
||||
// This part of the code will be visible by default
|
||||
engine.doSomething(1, 2, 3, calcFn)
|
||||
|
||||
function calcFn() {
|
||||
// You can have multiple collapsed sections
|
||||
const a = 1
|
||||
const b = 2
|
||||
const c = a + b
|
||||
|
||||
// This will remain visible
|
||||
console.log(`Calculation result: ${a} + ${b} = ${c}`)
|
||||
return c
|
||||
}
|
||||
|
||||
// All this code until the end of the block will be collapsed again
|
||||
engine.closeConnection()
|
||||
engine.freeMemory()
|
||||
engine.shutdown({ reason: 'End of example boilerplate code' })
|
||||
```
|
||||
|
||||
## Line Numbers
|
||||
|
||||
[Line Numbers](https://expressive-code.com/plugins/line-numbers/)
|
||||
|
||||
### Displaying line numbers per block
|
||||
|
||||
```js showLineNumbers
|
||||
// This code block will show line numbers
|
||||
console.log('Greetings from line 2!')
|
||||
console.log('I am on line 3')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
```js showLineNumbers=false
|
||||
// Line numbers are disabled for this block
|
||||
console.log('Hello?')
|
||||
console.log('Sorry, do you know what line I am on?')
|
||||
```
|
||||
|
||||
### Changing the starting line number
|
||||
|
||||
```js showLineNumbers startLineNumber=5
|
||||
console.log('Greetings from line 5!')
|
||||
console.log('I am on line 6')
|
||||
```
|
||||
206
src/content/posts/add_twikoo_for_fuwari.md
Normal file
206
src/content/posts/add_twikoo_for_fuwari.md
Normal file
@ -0,0 +1,206 @@
|
||||
---
|
||||
title: 为 Fuwari 添加Twikoo评论组件
|
||||
published: 2026-03-07
|
||||
description: ''
|
||||
image: ''
|
||||
tags: [fuwari, twikoo]
|
||||
category: '教程'
|
||||
draft: false
|
||||
lang: ''
|
||||
---
|
||||
|
||||
|
||||
## Twikoo 一个简洁、安全、免费的静态网站评论系统。
|
||||
|
||||
## 部署Twikoo
|
||||
|
||||
我部署[Twikoo](https://twikoo.js.org/)用的方案是 mongodb altas 云数据库后端 (具有免费的数据存储空间,大约512MB左右,对于评论系统已经很足够了) + [vercel](https://vercel.com/) 云函数部署.
|
||||
|
||||
也就是这个Twikoo的[文档](https://twikoo.js.org/backend.html#vercel-%E9%83%A8%E7%BD%B2).
|
||||
|
||||
### MongoDB Atlas 数据库创建
|
||||
|
||||
Twikoo提供的 [注册MongoDB Atlas教程](https://twikoo.js.org/mongodb-atlas.html)
|
||||
|
||||
最后记得要保管好 我们的`连接字符串`.
|
||||
|
||||
### Vercel 部署
|
||||
|
||||
Twikoo提供的 [Vercel 部署教程](https://twikoo.js.org/backend.html#vercel-%E9%83%A8%E7%BD%B2)
|
||||
|
||||
|
||||
vercel 部署,由于域名的原因,中国境内无法直接访问 vercel分配的域名,需要自己手动添加一个自己的自定义域名才能访问。
|
||||
|
||||
## 前端部署
|
||||
|
||||
首先打开项目的 `src/components`位置,新建一个Twikoo.astro组件
|
||||
并填入一下内容
|
||||
```astro title="src/components/Twikoo.astro"
|
||||
---
|
||||
// src/components/Twikoo.astro
|
||||
import { twikooConfig } from "../config";
|
||||
|
||||
const { enable, envId, lang = "zh_CN" } = twikooConfig;
|
||||
const shouldRender = enable && envId;
|
||||
---
|
||||
|
||||
{shouldRender && (
|
||||
<div id="twikoo-comment">
|
||||
<p>加载评论中...</p>
|
||||
</div>
|
||||
|
||||
<script is:inline define:vars={{ envId, lang }}>
|
||||
(function() {
|
||||
const MAX_RETRIES = 3;
|
||||
const RETRY_DELAY = 2000;
|
||||
|
||||
let scriptRetryCount = 0;
|
||||
let initRetryCount = 0;
|
||||
|
||||
// 尝试初始化 Twikoo
|
||||
function initTwikoo() {
|
||||
if (typeof twikoo === 'undefined') {
|
||||
// Twikoo 对象不存在,说明脚本还没加载成功,重试加载脚本
|
||||
if (scriptRetryCount < MAX_RETRIES) {
|
||||
scriptRetryCount++;
|
||||
console.log(`Twikoo 库未加载,尝试重新加载脚本 (${scriptRetryCount}/${MAX_RETRIES})...`);
|
||||
setTimeout(loadScript, RETRY_DELAY);
|
||||
} else {
|
||||
console.error('Twikoo 库加载失败,已达到最大重试次数。');
|
||||
showError('评论加载失败,请刷新页面重试。');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
twikoo.init({ envId, el: '#twikoo-comment', lang })
|
||||
.then(() => {
|
||||
console.log('Twikoo 初始化成功');
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Twikoo 初始化失败:', err);
|
||||
if (initRetryCount < MAX_RETRIES) {
|
||||
initRetryCount++;
|
||||
console.log(`尝试重新初始化 (${initRetryCount}/${MAX_RETRIES})……`);
|
||||
setTimeout(initTwikoo, RETRY_DELAY);
|
||||
} else {
|
||||
showError('评论加载失败,请刷新页面重试。');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadScript() {
|
||||
const script = document.createElement('script');
|
||||
|
||||
// 推荐在中国使用
|
||||
// https://registry.npmmirror.com/twikoo/1.7.1/files/dist/twikoo.min.js
|
||||
// https://s4.zstatic.net/npm/twikoo@1.7.1/dist/twikoo.min.js
|
||||
// 推荐在全球使用
|
||||
// https://cdn.jsdelivr.net/npm/twikoo@1.7.1/dist/twikoo.min.js
|
||||
// 备用选项
|
||||
// https://s4.zstatic.net/ajax/libs/twikoo/1.6.41/twikoo.min.js
|
||||
// https://lib.baomitu.com/twikoo/1.6.39/twikoo.min.js
|
||||
|
||||
script.src = 'https://s4.zstatic.net/npm/twikoo@1.7.1/dist/twikoo.min.js';
|
||||
script.onload = () => {
|
||||
console.log('Twikoo 脚本加载成功');
|
||||
scriptRetryCount = 0;
|
||||
initTwikoo();
|
||||
};
|
||||
script.onerror = () => {
|
||||
console.error('Twikoo 脚本加载失败');
|
||||
if (scriptRetryCount < MAX_RETRIES) {
|
||||
scriptRetryCount++;
|
||||
console.log(`尝试重新加载脚本 (${scriptRetryCount}/${MAX_RETRIES})……`);
|
||||
setTimeout(loadScript, RETRY_DELAY);
|
||||
} else {
|
||||
showError('评论加载失败,请刷新页面重试。');
|
||||
}
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
// 显示错误信息到评论区
|
||||
function showError(msg) {
|
||||
const container = document.querySelector('#twikoo-comment');
|
||||
if (container) container.innerHTML = `<p style="color: red;">${msg}</p>`;
|
||||
}
|
||||
|
||||
loadScript();
|
||||
})();
|
||||
</script>
|
||||
)}
|
||||
```
|
||||
|
||||
在`src/pages/posts/[...slug].astro`文件中的大概 113行左右结束就是文章整个模块的渲染区域
|
||||
|
||||
我们在他之后添加一下内容
|
||||
```diff title="src/pages/posts/[...slug].astro" lang="astro" startLineNumber=103
|
||||
...
|
||||
<Markdown class="mb-6 markdown-content onload-animation">
|
||||
<Content />
|
||||
</Markdown>
|
||||
|
||||
{licenseConfig.enable && <License title={entry.data.title} slug={entry.slug} pubDate={entry.data.published} class="mb-6 rounded-xl license-container onload-animation"></License>}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+ <div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative mb-4">
|
||||
+ <div id="post-container" class="card-base p-6 mb-4 text-black/75 dark:text-white/75 transition" class:list={["card-base z-10 px-6 md:px-9 pt-6 pb-4 relative w-full ", {} ]}>
|
||||
+ <Twikoo />
|
||||
+ </div>
|
||||
+ </div>
|
||||
|
||||
<div class="flex flex-col md:flex-row justify-between mb-4 gap-4 overflow-hidden w-full">
|
||||
<a href={entry.data.nextSlug ? getPostUrlBySlug(entry.data.nextSlug) : "#"}
|
||||
...
|
||||
```
|
||||
|
||||
Twikoo 在初始化时候需要调用init函数,如下
|
||||
```html
|
||||
<!-- from https://twikoo.js.org/frontend.html#%E9%80%9A%E8%BF%87-cdn-%E5%BC%95%E5%85%A5 -->
|
||||
|
||||
<script>
|
||||
twikoo.init({
|
||||
envId: '您的环境id', // 腾讯云环境填 envId;Vercel 环境填地址(https://xxx.vercel.app)
|
||||
el: '#tcomment', // 容器元素
|
||||
// region: 'ap-guangzhou', // 环境地域,默认为 ap-shanghai,腾讯云环境填 ap-shanghai 或 ap-guangzhou;Vercel 环境不填
|
||||
// path: location.pathname, // 用于区分不同文章的自定义 js 路径,如果您的文章路径不是 location.pathname,需传此参数
|
||||
// lang: 'zh-CN', // 用于手动设定评论区语言,支持的语言列表 https://github.com/twikoojs/twikoo/blob/main/src/client/utils/i18n/index.js
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
为了方便传参数,我们需要在 `src/types/config.ts`中添加一个twikooConfig配置
|
||||
```ts title="src/types/config.ts"
|
||||
export type TwikooConfig = {
|
||||
enable?: boolean;
|
||||
envId?: string;
|
||||
lang?: string;
|
||||
};
|
||||
```
|
||||
|
||||
最后在`src/config.ts`中添加一下修改并配置自己的`envId`
|
||||
```diff title="src/config.ts" lang="ts" "填入之前在Twikoo云函数部署时拿到的Id"
|
||||
import type {
|
||||
ExpressiveCodeConfig,
|
||||
LicenseConfig,
|
||||
NavBarConfig,
|
||||
ProfileConfig,
|
||||
SiteConfig,
|
||||
+ TwikooConfig,
|
||||
} from "./types/config";
|
||||
|
||||
...
|
||||
|
||||
// 在文件最后添加一下内容
|
||||
+ export const twikooConfig: TwikooConfig = {
|
||||
+ enable: true,
|
||||
+ envId: "填入之前在Twikoo云函数部署时拿到的Id",
|
||||
+ };
|
||||
|
||||
```
|
||||
|
||||
配置好后`pnpm dev`测试一下,能看到文章底下的评论区了。
|
||||
|
||||
最后记得点击Twikoo评论区的小设置齿轮配置一下Twikoo的一些通知系统。
|
||||
@ -207,7 +207,7 @@ fdisk /dev/sda #对sda磁盘进行分区
|
||||
> - n: 创建分区
|
||||
> - p: 查看分区
|
||||
> - q: 不保存退出
|
||||
> - w: 保存并退出 所有操作在执行”w”前都不会生效
|
||||
> - w: 保存并退出 所有操作在执行"w"前都不会生效
|
||||
|
||||

|
||||
|
||||
|
||||
@ -62,7 +62,7 @@ C 语言最初是用于系统开发工作,特别是组成操作系统的程序
|
||||
|
||||
C 程序
|
||||
|
||||
一个 C 语言程序,可以是 3 行,也可以是数百万行,它可以写在一个或多个扩展名为 “.c” 的文本文件中,例如,hello.c。可以使用 VScode/Dev-C++/Vim或者其他编辑器来编写 C 语言程序。
|
||||
一个 C 语言程序,可以是 3 行,也可以是数百万行,它可以写在一个或多个扩展名为 ".c" 的文本文件中,例如,hello.c。可以使用 VScode/Dev-C++/Vim或者其他编辑器来编写 C 语言程序。
|
||||
|
||||
|
||||
|
||||
@ -86,7 +86,7 @@ C11(也被称为C1X)指ISO标准ISO/IEC 9899:2011。在它之前的C语言
|
||||
- 增加了更多浮点处理宏(宏)。
|
||||
- 匿名结构体/联合体支持。这个在gcc早已存在,C11将其引入标准。
|
||||
- 静态断言(Static assertions),_Static_assert(),在解释 #if 和 #error 之后被处理。
|
||||
- 新的 fopen() 模式,(“…x”)。类似 POSIX 中的 O_CREAT|O_EXCL,在文件锁中比较常用。
|
||||
- 新的 fopen() 模式,("…x")。类似 POSIX 中的 O_CREAT|O_EXCL,在文件锁中比较常用。
|
||||
- 新增 quick_exit() 函数作为第三种终止程序的方式。当 exit()失败时可以做最少的清理工作。
|
||||
|
||||
## 环境配置
|
||||
@ -103,7 +103,7 @@ C11(也被称为C1X)指ISO标准ISO/IEC 9899:2011。在它之前的C语言
|
||||
|
||||
## 程序结构
|
||||
|
||||
### C “hello world” 实例
|
||||
### C "hello world" 实例
|
||||
|
||||
C 程序主要包括以下几个部分:
|
||||
|
||||
@ -128,8 +128,8 @@ int main() {
|
||||
| :---------------: | :----------------------------------------------------------: |
|
||||
| #include<stdio.h> | 预处理指令,告诉 C 编译器在实际编译之前要包含 stdio.h 文件。 |
|
||||
| int main() | 程序的主函数,程序从这里开始运行 |
|
||||
| /*…*/ | “…”里的内容会被编译器忽略,这里放置程序的注释内容。它们被称为程序的注释 |
|
||||
| printf(…) | C语言 中一个可用的函数,会在屏幕上显示消息”…(括号内的内容)” |
|
||||
| /*…*/ | "…"里的内容会被编译器忽略,这里放置程序的注释内容。它们被称为程序的注释 |
|
||||
| printf(…) | C语言 中一个可用的函数,会在屏幕上显示消息"…(括号内的内容)" |
|
||||
| return 0; | 终止main()函数,并返回值0. |
|
||||
|
||||
### 编译 & 执行 C 程序
|
||||
@ -150,7 +150,7 @@ printf("hello world! \n");
|
||||
|
||||
- printf
|
||||
- (
|
||||
- “Hello, World! \n”
|
||||
- "Hello, World! \n"
|
||||
- )
|
||||
- ;
|
||||
|
||||
@ -208,7 +208,7 @@ hideToggle 点我查看
|
||||
| char | 声明字符型变量或函数返回值类型 |
|
||||
| const | 定义常量,如果一个变量被 const 修饰,那么它的值就不能再被改变 |
|
||||
| continue | 结束当前循环,开始下一轮循环 |
|
||||
| default | 开关语句中的”其它”分支 |
|
||||
| default | 开关语句中的"其它"分支 |
|
||||
| do 循环语句的循环体 | |
|
||||
| double | 声明双精度浮点型变量或函数返回值类型 |
|
||||
| else | 条件语句否定分支(与 if 连用) |
|
||||
@ -575,7 +575,7 @@ int g = 20;
|
||||
| ---------- | -------------------------- |
|
||||
| \ | \ 字符 |
|
||||
| ' | ‘ 字符 |
|
||||
| " | “ 字符 |
|
||||
| " | " 字符 |
|
||||
| ? | ? 字符 |
|
||||
| \a | 警报铃声 |
|
||||
| \b | 退格键 |
|
||||
@ -609,7 +609,7 @@ Hello World
|
||||
|
||||
### 字符串常量
|
||||
|
||||
字符串字面值或常量是括在双引号 “” 中的。一个字符串包含类似于字符常量的字符:普通的字符、转义序列和通用的字符。
|
||||
字符串字面值或常量是括在双引号 "" 中的。一个字符串包含类似于字符常量的字符:普通的字符、转义序列和通用的字符。
|
||||
|
||||
您可以使用空格做分隔符,把一个很长的字符串常量进行分行。
|
||||
|
||||
@ -931,10 +931,10 @@ A^B = 0011 0001
|
||||
|
||||
| 运算符 | 描述 | 实例 |
|
||||
| ------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||
| & | 按位与操作,按二进制位进行”与”运算。运算规则:`0&0=0; 0&1=0; 1&0=0; 1&1=1;` | (A & B) 将得到 12,即为 0000 1100 |
|
||||
| \| | 按位或运算符,按二进制位进行”或”运算。运算规则:`0 | 0=0; 0 |
|
||||
| ^ | 异或运算符,按二进制位进行”异或”运算。运算规则:`0^0=0; 0^1=1; 1^0=1; 1^1=0;` | (A ^ B) 将得到 49,即为 0011 0001 |
|
||||
| ~ | 取反运算符,按二进制位进行”取反”运算。运算规则:`~1=-2; ~0=-1;` | (~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。 |
|
||||
| & | 按位与操作,按二进制位进行"与"运算。运算规则:`0&0=0; 0&1=0; 1&0=0; 1&1=1;` | (A & B) 将得到 12,即为 0000 1100 |
|
||||
| \| | 按位或运算符,按二进制位进行"或"运算。运算规则:`0 | 0=0; 0 |
|
||||
| ^ | 异或运算符,按二进制位进行"异或"运算。运算规则:`0^0=0; 0^1=1; 1^0=1; 1^1=0;` | (A ^ B) 将得到 49,即为 0011 0001 |
|
||||
| ~ | 取反运算符,按二进制位进行"取反"运算。运算规则:`~1=-2; ~0=-1;` | (~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。 |
|
||||
| << | 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 | A << 2 将得到 240,即为 1111 0000 |
|
||||
| >> | 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。 | A >> 2 将得到 15,即为 0000 1111 |
|
||||
|
||||
|
||||
@ -290,11 +290,11 @@ printf("%s%s%s",a,b,c); // 输出How are you
|
||||
|
||||
- put(字符数组)
|
||||
将一个字符串输出到终端
|
||||
作用等效于printf(“%s”,c);也可以输出转义字符
|
||||
作用等效于printf("%s",c);也可以输出转义字符
|
||||

|
||||
- gets(字符数组)
|
||||
从终端输入一个字符串到字符数组,并且得到一个函数值,该函数值为字符数组的起始地址。
|
||||
相比于scanf(“%s”,c);可以返回数组的地址值
|
||||
相比于scanf("%s",c);可以返回数组的地址值
|
||||
|
||||

|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ lang: ''
|
||||
|
||||
### 1、为什么要定义
|
||||
|
||||
- 程序中用到的所有函数必须“先定义,后使用”
|
||||
- 程序中用到的所有函数必须"先定义,后使用"
|
||||
|
||||
- 同变量定义的道理类似,需要事先告知系统该函数功能、参数等信息,具体包括:
|
||||
|
||||
@ -136,7 +136,7 @@ m=max(a,max(b,c)); //将调用max函数的结果再重新作为下一次
|
||||
**1.形参:定义函数时,函数名括号后面的变量称为形式参数(或虚拟参数)**
|
||||
|
||||
- 形参在函数调用时被分配内存单元,调用结束后立即释放
|
||||
- 形参为变量时,实参与形参的数据传递是“值传递”,即“单向传递”。
|
||||
- 形参为变量时,实参与形参的数据传递是"值传递",即"单向传递"。
|
||||
|
||||
**2.实参:在主调函数中调用一个函数时,函数名后面括号中的参数称为实际参数**
|
||||
|
||||
@ -145,7 +145,7 @@ m=max(a,max(b,c)); //将调用max函数的结果再重新作为下一次
|
||||
- 形参与实参的类型应相同或i赋值兼容。
|
||||
|
||||
note red modern
|
||||
注:实参向形参的数据传递是“值传递”,单向传递,只能由实参传给形参,而不能由形参传给实参。
|
||||
注:实参向形参的数据传递是"值传递",单向传递,只能由实参传给形参,而不能由形参传给实参。
|
||||
实参和形参在内存中占有不同的存储单元,实参无法得到形参的值。
|
||||
endnote
|
||||
|
||||
|
||||
@ -55,10 +55,10 @@ lang: ''
|
||||
|
||||
注意事项:
|
||||
note red modern
|
||||
指针变量前面的”*”表示该变量为指针型变量,指针变量名是p,而不是 *p。
|
||||
指针变量前面的"*"表示该变量为指针型变量,指针变量名是p,而不是 *p。
|
||||
|
||||
在定义指针变量时必须指定**基类型**(因为不同类型的数据在内存中所占的字节数和存放方式是不同的)
|
||||
指向整形数据的指针类型表示为“int*”,读作指向int的指针,或 int指针
|
||||
指向整形数据的指针类型表示为"int*",读作指向int的指针,或 int指针
|
||||
|
||||
指针变量中只能存放地址(指针),试图将一个整数赋给一个指针变量是不合法的。
|
||||
|
||||
@ -87,8 +87,8 @@ endnote
|
||||
|
||||
- **强调两个运算符。**
|
||||
|
||||
> “&”取地址运算符 &a是变量a的地址
|
||||
> “*” 指针运算符(间接访问运算符) *p代表指针变量p指向的对象
|
||||
> "&"取地址运算符 &a是变量a的地址
|
||||
> "*" 指针运算符(间接访问运算符) *p代表指针变量p指向的对象
|
||||
|
||||
例:
|
||||
|
||||
|
||||
@ -99,7 +99,7 @@ lang: ''
|
||||
> - 有几百种不同的license
|
||||
> - 有些license去遵守是有点难度的
|
||||
> - GNU GPL说如果被修改,发布的代码也要在GPL下发布,你只能用GPL代码
|
||||
> - “copyleft”(非盈利版权)
|
||||
> - "copyleft"(非盈利版权)
|
||||
> - **自由软件 && 免费软件**
|
||||
> - 自由软件不一定免费
|
||||
> - 免费软件并不公开源码
|
||||
@ -230,10 +230,10 @@ endfolding
|
||||
|
||||
- 项与项之间以空格隔开
|
||||
- options修饰一个命令的行为
|
||||
- 单字母选项一般带有”-“,例如:-a,-b,-c,或者-abc
|
||||
- 全字母选项前常带有”–”,例如:–help
|
||||
- 单字母选项一般带有"-",例如:-a,-b,-c,或者-abc
|
||||
- 全字母选项前常带有"–",例如:–help
|
||||
- 参数是一个文件名或者其他被该命令需要的数据
|
||||
- 多个命令用”;”进行分隔
|
||||
- 多个命令用";"进行分隔
|
||||
|
||||
> - 多种层次的帮助
|
||||
> - [whatis](https://www.atdunbg.xyz/2023/03/19/cloud_linux_1/#whatis)
|
||||
@ -256,7 +256,7 @@ whatis是查询一个命令执行什么功能,并把查询结果打印到显
|
||||
|
||||
> - 为名提供相关帮助文档
|
||||
|
||||
- 几乎所有的命令都有 man “页”
|
||||
- 几乎所有的命令都有 man "页"
|
||||
|
||||
- 页面分成章节,共八章
|
||||
|
||||
@ -302,8 +302,8 @@ whereis命令用于查找文件。
|
||||
- 在[]中的参数是可以选择的
|
||||
- 大写的参数在<>中表示变量
|
||||
- 文本后面跟随…表示一个列表
|
||||
- x|y|z表示 “x或者y或者z”
|
||||
*-abc表示 “任意-a,-b,或者-c的任意组合”
|
||||
- x|y|z表示 "x或者y或者z"
|
||||
*-abc表示 "任意-a,-b,或者-c的任意组合"
|
||||
|
||||
## SHELl的常用命令
|
||||
|
||||
@ -687,11 +687,11 @@ note info modern
|
||||
- 撤销改变
|
||||
- u 撤销最近的改变
|
||||
- U 撤销当前行自从光标定位在上面开始的所有改变
|
||||
- Ctrl+r 重做最后一次 “撤销” 改变
|
||||
- Ctrl+r 重做最后一次 "撤销" 改变
|
||||
|
||||
## SHELL基础
|
||||
|
||||
** Shell 一种特殊的程序,被称为脚本语言,他是用户与unix/Linux系统 “心脏” 之间的接口.**
|
||||
** Shell 一种特殊的程序,被称为脚本语言,他是用户与unix/Linux系统 "心脏" 之间的接口.**
|
||||
|
||||

|
||||
|
||||
@ -968,7 +968,7 @@ export
|
||||
|
||||
- 字符测试
|
||||
|
||||
- =:等于,比如:[“$A”=“$B”]
|
||||
- =:等于,比如:["$A"="$B"]
|
||||
|
||||
- != :不等于
|
||||
|
||||
@ -976,9 +976,9 @@ export
|
||||
|
||||
- > :大于
|
||||
|
||||
- -z:字符串长度为”null”
|
||||
- -z:字符串长度为"null"
|
||||
|
||||
- -n:字符串长度不为”null”
|
||||
- -n:字符串长度不为"null"
|
||||
|
||||
- 整数测试
|
||||
|
||||
@ -1289,7 +1289,7 @@ continue [n] # 跳出指定循环(未指定默认为1)
|
||||
|
||||
> - 默认匹配是与
|
||||
|
||||
- 可以用-0或者是-not表示”或”或者是
|
||||
- 可以用-0或者是-not表示"或"或者是
|
||||
- 括号可以用来检测逻辑操作的顺序,但必须用斜线转义
|
||||
- find -user joe -not -group joe
|
||||
- find -user joe -0 -user jane
|
||||
@ -1335,7 +1335,7 @@ continue [n] # 跳出指定循环(未指定默认为1)
|
||||
|
||||
- 必须用-exec或者-ok打头执行命令
|
||||
- -ok在对每个文件进行动作前提示
|
||||
- 命令必须以空格+斜线(“" )+分号结尾
|
||||
- 命令必须以空格+斜线("" )+分号结尾
|
||||
- 可以使用{}作为文件名字占位符
|
||||
- find -size + 100M -ok mv {} /tmp/largefiles/ \ ;
|
||||
|
||||
@ -1501,7 +1501,7 @@ gpgcheck=1
|
||||
|
||||
- 从这些文件进行读写是合法的操作:
|
||||
|
||||
- echo “Message” > /dev/tty1
|
||||
- echo "Message" > /dev/tty1
|
||||
|
||||
- 三种文件属性决定访问哪种驱动:
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ lang: ''
|
||||
|
||||
### Socket 通讯
|
||||
|
||||
- 所谓socket通常也称作”套接字” ,用于描述IR地址和端口,是一个通信链的句柄。应用程序通常通过”套接字”向网络发出请求或者应答网络请求。
|
||||
- 所谓socket通常也称作"套接字" ,用于描述IR地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
|
||||
|
||||

|
||||
|
||||
@ -45,15 +45,15 @@ linux下的服务管理有两类:
|
||||
|
||||
### System V 服务
|
||||
|
||||
System V, 曾经也被称为 AT&T System V,是Unix操作系统众多版本中的一支。它最初由 AT&T 开发,在1983年第一次发布。一共发行了4个 System V 的主要版本:版本1、2、3 和 4。System V Release 4,或者称为SVR4,是最成功的版本,成为一些UNIX共同特性的源头,例如 ”SysV 初始化脚本“ (/etc/init.d),用来控制系统启动和关闭,System V Interface Definition (SVID) 是一个System V 如何工作的标准定义。
|
||||
System V, 曾经也被称为 AT&T System V,是Unix操作系统众多版本中的一支。它最初由 AT&T 开发,在1983年第一次发布。一共发行了4个 System V 的主要版本:版本1、2、3 和 4。System V Release 4,或者称为SVR4,是最成功的版本,成为一些UNIX共同特性的源头,例如 "SysV 初始化脚本" (/etc/init.d),用来控制系统启动和关闭,System V Interface Definition (SVID) 是一个System V 如何工作的标准定义。
|
||||
|
||||
> - 通常被成为”System V” 或 “SysV”
|
||||
> - 通常被成为"System V" 或 "SysV"
|
||||
|
||||
- 许多脚本都是用文件系统目录的格式来组织的
|
||||
- 可启用或者禁用资源服务
|
||||
- 经常使用几个配置文件
|
||||
- 大多数服务启动一个或多个进程
|
||||
- 命令被“包裹”在脚本中.
|
||||
- 命令被"包裹"在脚本中.
|
||||
- 服务由/etc/init.d/目录中的脚本管理
|
||||
- 例如: /etc/init.d/sshd status
|
||||
- service sshd status
|
||||
@ -143,7 +143,7 @@ System V, 曾经也被称为 AT&T System V,是Unix操作系统众多版本
|
||||
|
||||
### Rsyslog 服务
|
||||
|
||||
**把日志集中存储在一个安全的地方, 通过日志分析系统的运行情况. Rsyslog全称”the Rocket-fast SYStem for LOG processing”,是一种应用于UNIX和Linux计算机系统在IP网络转发日志消息开源软件实用的程序。它实现了基本的syslog协议,扩展了基于内容过滤的过滤能力,丰富灵活的配置选项,并增加了诸如使用TCP传输的特点。**
|
||||
**把日志集中存储在一个安全的地方, 通过日志分析系统的运行情况. Rsyslog全称"the Rocket-fast SYStem for LOG processing",是一种应用于UNIX和Linux计算机系统在IP网络转发日志消息开源软件实用的程序。它实现了基本的syslog协议,扩展了基于内容过滤的过滤能力,丰富灵活的配置选项,并增加了诸如使用TCP传输的特点。**
|
||||
|
||||
> - 格式: selector action
|
||||
> - selector : facility.level
|
||||
@ -230,7 +230,7 @@ endfolding
|
||||
- 启用TCP
|
||||
- $ModLoad imtcp
|
||||
- $InputTCPServerRun 514
|
||||
- $template TemplateName, “格式”, < options>
|
||||
- $template TemplateName, "格式", < options>
|
||||
- 引号模板:
|
||||
- ? TemplateName
|
||||
|
||||
@ -300,7 +300,7 @@ endfolding
|
||||
- can be used to start additional programs
|
||||
- special expansions are available (%C, %s)
|
||||
- 例如:
|
||||
- in.telnetd: ALL : spawn echo “login attempt from %C to %s”| mail -S warning root
|
||||
- in.telnetd: ALL : spawn echo "login attempt from %C to %s"| mail -S warning root
|
||||
- deny:
|
||||
- 可作为hosts.allow中的一个选项
|
||||
- 例如:
|
||||
@ -331,7 +331,7 @@ endfolding
|
||||
|
||||

|
||||
|
||||
> - 所有文件和进程都具备“安全环境”( security context )
|
||||
> - 所有文件和进程都具备"安全环境"( security context )
|
||||
|
||||
- 环境包含几个元素,根据安全的需要使用不同的元素
|
||||
- user.role:type:sensitivity:category
|
||||
@ -353,7 +353,7 @@ endfolding
|
||||
|
||||
- system_ _r - - -般为进程的角色
|
||||
|
||||
> - 一组叫做”策略( policy)”的规则会决定控制的严格程度
|
||||
> - 一组叫做"策略( policy)"的规则会决定控制的严格程度
|
||||
|
||||
- 进程要么是被限制的(restricted) ,要么是无束缚的( unconfined)
|
||||
- 策略被用来定义被限制的进程能够使用哪些资源
|
||||
@ -450,7 +450,7 @@ endfolding
|
||||
- 域字段叫做始发地址
|
||||
- rdata字段被引申为支持额外数据r 下-一个演示片对此进行了解释
|
||||
- 一般来说, -一个域通常有一 个主名称服务器,它保存数据的主要副本
|
||||
- 域或区块的其它规范性名称服务器被称为“从服务器”,它们会将其数据与主服务器同步
|
||||
- 域或区块的其它规范性名称服务器被称为"从服务器",它们会将其数据与主服务器同步
|
||||
- SOA rdata
|
||||
- 主名称服务器的FQDN
|
||||
- 联系邮件地址
|
||||
@ -458,7 +458,7 @@ endfolding
|
||||
- 在刷新序列号码之前刷新延迟时间
|
||||
- 从服务器的重试间隔
|
||||
- 当从服务器无法连接它的主服务器时,记录会过期
|
||||
- 否定性答复(“no such host”)的TTL最小值
|
||||
- 否定性答复("no such host")的TTL最小值
|
||||
|
||||
| 记录类型 | 说明 |
|
||||
| -------- | ---------------------- |
|
||||
@ -494,11 +494,11 @@ zone "example.com"
|
||||
- 一般可以用来代替匹配列表(允许嵌套! )
|
||||
- 最好的办法是在/etc/named.conf文件的开始处定义ACL
|
||||
- 声明示例
|
||||
- acly”trusted {192.168.1.21; }
|
||||
- acl “classroom” { 192.168.0.0/24; trusted;};
|
||||
- acl “cracker” { 192.168.1.0/24; };
|
||||
- acl “mymasters” { 192.168.0.254; };
|
||||
- acl “myaddresses” { 127.0.0.1; 192.168.0.1; };
|
||||
- acly"trusted {192.168.1.21; }
|
||||
- acl "classroom" { 192.168.0.0/24; trusted;};
|
||||
- acl "cracker" { 192.168.1.0/24; };
|
||||
- acl "mymasters" { 192.168.0.254; };
|
||||
- acl "myaddresses" { 127.0.0.1; 192.168.0.1; };
|
||||
- 内置ACL
|
||||
- BIND预定义了几个ACL:
|
||||
- none - 不匹配任何IP地址
|
||||
@ -567,10 +567,10 @@ zone "example.com"
|
||||
> - mountd, statd和lockd可以被强制使用一个静态端口
|
||||
|
||||
- 在/etc/sysconfig/nfs中设置MOUNTD_ PORT、STATD_ PORT LOCKD_ TCPPORTHE和LOCKD_ UDPPORT变量
|
||||
- MOUNTD_ PORT=”4002”
|
||||
- STATD_ PORT= “4003”
|
||||
- LOCKD_ TCPPORT= “4004”
|
||||
- LOCKD_ UDPPORT= “4004”
|
||||
- MOUNTD_ PORT="4002"
|
||||
- STATD_ PORT= "4003"
|
||||
- LOCKD_ TCPPORT= "4004"
|
||||
- LOCKD_ UDPPORT= "4004"
|
||||
|
||||
## WEB 服务
|
||||
|
||||
@ -726,7 +726,7 @@ iptable -t filter -A INPUT -s 192.168.0.1 -j DROP
|
||||
| 2 | 密码 | 在旧的unix系统中,该字段是用户加密后的密码,现在已经不再使用,而是将密码放在/etc/shadow中,所以此处都只是一个字母X |
|
||||
| 3 | UID | 系统用来区分不同用户的整数 |
|
||||
| 4 | GID | 系统用来区分不同用户组的整数 |
|
||||
| 5 | 说明栏 | 类似于“注释” |
|
||||
| 5 | 说明栏 | 类似于"注释" |
|
||||
| 6 | 家目录 | 用户登录后,默认所处的目录,即家目录 |
|
||||
| 7 | 登录SHELL | 用户登录后,所使用的SHELL |
|
||||
|
||||
|
||||
@ -104,7 +104,7 @@ lang: ''
|
||||
|
||||
- 目前,多数服务器基础桌面计算机均处理启用状态.
|
||||
|
||||
> - “嵌套”式实验环境
|
||||
> - "嵌套"式实验环境
|
||||
> - 在虚拟机中再做虚拟化
|
||||
|
||||
- VMware嵌套虚拟化
|
||||
@ -117,7 +117,7 @@ lang: ''
|
||||
|
||||
### 实验环境准备
|
||||
|
||||
> - “嵌套” 式实验环境
|
||||
> - "嵌套" 式实验环境
|
||||
> - VMware Workstation Player或VMware Workstation
|
||||
> - 创建虚拟机,在此虚拟机上安装KVM
|
||||
|
||||
|
||||
@ -239,7 +239,7 @@ sqlmap.py -u "http://127.0.0.1/vul/sqli/sqli_str.php?name=1&submit=%E6%9F%A5%E8%
|
||||
|
||||
### 搜索型注入
|
||||
|
||||
由于没有过滤“%”,“%”可以进行匹配任意字符,与linux中的”*“类似
|
||||
由于没有过滤"%","%"可以进行匹配任意字符,与linux中的"*"类似
|
||||
|
||||
**sqlmap**
|
||||
|
||||
@ -265,7 +265,7 @@ sqlmap.py -u "http://127.0.0.1/vul/sqli/sqli_search.php?name=1&submit=%E6%90%9C%
|
||||
python sqlmap.py -u "http://127.0.0.1/vul/sqli/sqli_x.php?name=1&submit=%E6%9F%A5%E8%AF%A2" --batch -D pikachu -T member --dump
|
||||
```
|
||||
|
||||
### “insert/update”注入
|
||||
### "insert/update"注入
|
||||
|
||||
注册一下账户,然后brup抓包,随便选一个变量,修改如下
|
||||
|
||||
@ -281,11 +281,11 @@ extractvalue() 是mysql对xml文档数据进行查询和修改的xpath函数
|
||||
updatexml() 是mysql对xml文档数据进行查询的xpath函数
|
||||
```
|
||||
|
||||
### “delete”注入
|
||||
### "delete"注入
|
||||
|
||||
操作同上,在点击删除留言时进行抓包,发现有一个id参数可以进行注入,不过发现注入的参数中不能出现空格,否则空格后面不会进行处理
|
||||
|
||||
可以用“+”代替空格
|
||||
可以用"+"代替空格
|
||||
|
||||
```txt
|
||||
+and+updatexml(1,concat(0x7e,database(),0x7e),1)
|
||||
@ -293,7 +293,7 @@ updatexml() 是mysql对xml文档数据进行查询的xpath函数
|
||||
|
||||

|
||||
|
||||
### “http header”注入
|
||||
### "http header"注入
|
||||
|
||||

|
||||
|
||||
@ -344,7 +344,7 @@ kobe' and substr(database(),1,1)='a'#
|
||||
|
||||

|
||||
|
||||
第二个参数修改,爆破字符为a-z ,顺带着添加一个”_”
|
||||
第二个参数修改,爆破字符为a-z ,顺带着添加一个"_"
|
||||
|
||||

|
||||
|
||||
@ -383,27 +383,27 @@ sqlmap.py -u "http://127.0.0.1/vul/sqli/sqli_blind_t.php?name=123&submit=%E6%9F%
|
||||
|
||||
输入%df和函数执行添加的%5C,被合并成%df%5C。由于GBK是两字节,这个%df%5C被MYSQL识别为GBK。导致本应的%df\变成%df%5C。%df%5C在GBK编码中没有对应,所以被当成无效字符。
|
||||
|
||||
%DF’ :会被PHP当中的addslashes函数转义为“%DF\'” ,“\”既URL里的“%5C”,那么也就是说,“%DF'”会被转成“%DF%5C%27”倘若网站的字符集是GBK,MYSQL使用的编码也是GBK的话,就会认为“%DF%5C%27”是一个宽字符。也就是“縗’”
|
||||
%DF’ :会被PHP当中的addslashes函数转义为"%DF\'" ,"\"既URL里的"%5C",那么也就是说,"%DF'"会被转成"%DF%5C%27"倘若网站的字符集是GBK,MYSQL使用的编码也是GBK的话,就会认为"%DF%5C%27"是一个宽字符。也就是"縗’"
|
||||
|
||||
例如:http://www.xxx.com/login.php?user=%df’ or 1=1 limit 1,1%23&pass=
|
||||
|
||||
其对应的sql就是:
|
||||
|
||||
select * fromcms_user where username = ‘運’ or 1=1 limit 1,1#’ and password=”
|
||||
select * fromcms_user where username = ‘運’ or 1=1 limit 1,1#’ and password="
|
||||
```
|
||||
|
||||
在’前面加个%df也就可以实现逃逸转义,然后burp抓包,剩下操作同上
|
||||
|
||||
## 0x06 RCE
|
||||
|
||||
### exec”ping”
|
||||
### exec"ping"
|
||||
|
||||
```txt
|
||||
127.0.0.1&&dir
|
||||
#执行完ping指令后同时执行dir指令
|
||||
```
|
||||
|
||||
### exec”eval”
|
||||
### exec"eval"
|
||||
|
||||
```txt
|
||||
直接输入 phpinfo();
|
||||
@ -654,7 +654,7 @@ dict://192.168.1.66:80
|
||||
|
||||
### SSRF(file_get_content)
|
||||
|
||||
利用file_get_content(“path”)利用传递的参数,通过file参数访问内部资源,或者跳转到其他服务器页面
|
||||
利用file_get_content("path")利用传递的参数,通过file参数访问内部资源,或者跳转到其他服务器页面
|
||||
|
||||
```txt
|
||||
//直接读取内部文件
|
||||
|
||||
@ -113,7 +113,6 @@ const jsonLd = {
|
||||
</div>
|
||||
|
||||
<div class="flex w-full rounded-[var(--radius-large)] overflow-hidden relative mb-4">
|
||||
<div ></div>
|
||||
<div id="post-container" class="card-base p-6 mb-4 text-black/75 dark:text-white/75 transition" class:list={["card-base z-10 px-6 md:px-9 pt-6 pb-4 relative w-full ", {} ]}>
|
||||
<Twikoo />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user