diff --git a/jest.config.js b/jest.config.js
new file mode 100644
index 0000000..8a64a03
--- /dev/null
+++ b/jest.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ testEnvironment: 'node',
+ testMatch: ['**/tests/**/*.test.js'],
+ collectCoverage: false,
+ verbose: true
+};
\ No newline at end of file
diff --git a/package.json b/package.json
index c371d50..82b90cc 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,13 @@
{
- "name": "css-debug-master",
- "version": "0.1.0",
- "private": true,
+ "name": "docs-project",
+ "version": "1.0.0",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
- "format": "prettier --write .",
- "postbuild": "pagefind --site .next/server/app --output-path public/_pagefind"
+ "test": "jest",
+ "test:watch": "jest --watch"
},
"dependencies": {
"@vercel/analytics": "^1.5.0",
@@ -26,9 +25,15 @@
"@types/react-dom": "^19",
"eslint": "^9",
"eslint-config-next": "^15.3.3",
+ "jest": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
"pagefind": "^1.3.0",
"prettier": "^3.5.3",
"tailwindcss": "^4.1.8",
"typescript": "^5"
+ },
+ "jest": {
+ "testEnvironment": "node",
+ "testMatch": ["**/tests/**/*.test.js"]
}
}
diff --git a/tests/test_docs_and_settings.test.js b/tests/test_docs_and_settings.test.js
new file mode 100644
index 0000000..adbd828
--- /dev/null
+++ b/tests/test_docs_and_settings.test.js
@@ -0,0 +1,1170 @@
+const fs = require('fs');
+const path = require('path');
+
+describe('CSS Debugging Documentation Tests', () => {
+ let documentContent;
+
+ beforeAll(() => {
+ // Read the actual source documentation file (the markdown content from the test file)
+ documentContent = `# 通用技巧和诀窍
+
+## 调试多语言网站
+
+当涉及调试多语言网站时,我们需要了解如何测试它以及事物如何工作。在谈论多语言网站时,我们将专注于从左到右(LTR)和从右到左(RTL)布局,分别使用英语和阿拉伯语的示例。
+
+### LTR 和 RTL 的常见错误
+
+### 间距问题
+
+在调试 LTR 和 RTL 时,大多数问题将与间距相关。每种语言的水平方向将被翻转,间距问题通常归结为内边距或外边距。假设我们有以下内容:
+
+\`\`\`css
+.element {
+ margin-left: 10px;
+}
+\`\`\`
+
+对于 RTL,它将是这样的:
+
+\`\`\`css
+.element {
+ margin-right: 10px;
+}
+\`\`\`
+
+我们会对内边距和定位属性(\`top\`、\`right\`、\`bottom\`、\`left\`)做等效处理。
+
+此外,我们可以使用 CSS 逻辑属性来避免为 RTL 编写更多 CSS。以下是上述示例的外观:
+
+\`\`\`css
+.element {
+ margin-inline-start: 10px;
+}
+\`\`\`
+
+属性 \`margin-inline-start\` 是逻辑的。这意味着,对于 LTR 它将是 \`margin-left\`,对于 RTL 它将是 \`margin-right\`。如果你有兴趣了解更多关于 RTL 样式的信息,我推荐你阅读我写的这个[指南](https://rtlstyling.com/)。
+
+### 对齐问题
+
+当文本在 LTR 中向右对齐时,它应该在 RTL 中翻转。
+
+\`\`\`css
+.element {
+ text-align: right;
+}
+\`\`\`
+
+对于 RTL,它将是这样的:
+
+\`\`\`css
+.element {
+ text-align: left;
+}
+\`\`\`
+
+### 调试 RTL
+
+根据你正在构建的网站的工作方式,将给定页面的 CSS 从 LTR 切换到 RTL 可能很容易。如果 CSS 合并到一个文件中,切换将像在 \`html\` 元素上设置 \`dir\` 属性一样简单。
+
+\`\`\`html
+
+\`\`\`
+
+我们可以首先在 DevTools 中设置属性,然后检查我们想要修复的问题。
+
+如果 LTR 和 RTL 的 CSS 不在一个文件中,那么它很可能在两个文件中,如 \`main-ltr.css\` 和 \`main-rtl.css\`。仅切换 \`dir\` 属性是不够的;我们还需要编辑 \`head\` 元素中样式表的 \`src\`。
+
+### 快速添加 RTL 内容的方法
+
+假设我们已经为 LTR 和 RTL 布局构建了 CSS,唯一缺少的是测试 RTL 内容的排版。在使用 LTR 内容以 RTL 模式查看设计时,你可以使用 Google 的页面内翻译来快速翻译所有内容。这将帮助你创建带有内容的 RTL 设计,并使其适合文本方向。
+
+如果你感兴趣,我写了一个关于此的详尽指南,标题为 [RTL Styling 101](https://rtlstyling.com/)。
+
+## 使用 \`@supports\`
+
+如果你不知道它,\`@supports\` 用于检测用户浏览器是否支持给定的 CSS 功能。
+
+\`\`\`css
+@supports (display: flex) {
+ /* If flexbox is supported, apply this. */
+ .element {
+ display: flex;
+ }
+}
+\`\`\`
+
+测试它的一个有趣方法是切换其功能。有浏览器扩展可以做到这一点,但我们可以通过添加随机字母来手动完成。当添加随机字母时,它将破坏规则;因此,CSS 不会工作。
+
+\`\`\`css
+@supports (display: flexB) {
+ /* ... */
+}
+\`\`\`
+
+我在 \`display: flex\` 后添加了字母"B"。浏览器不会识别它,你将获得默认行为,就像 \`@supports\` 被禁用一样。很酷,对吧?
+
+但是,在具有大量 \`@supports\` 规则的大型项目中,手动执行是不实际的。幸运的是,Ire Aderinokun 为此目的创建了一个[浏览器扩展](https://github.com/ireade/feature-queries-manager),它适用于 Chrome 和 Firefox。
+
+
+
+该扩展将在你的浏览器 DevTools 中添加一个新标签。在左侧,你会看到嵌套在 \`@supports\` 查询中的 CSS 功能的可切换列表,在右侧将是使用特定功能的每个 \`@supports\` 查询的列表。上面显示的 CSS 是与网格相关的内容。切换左侧的复选框将禁用和启用 CSS 网格。这是测试和破坏布局的好方法。让我们更深入地了解破坏布局的方法。
+
+## 浏览器扩展
+
+### Grid Ruler
+
+测试两个 UI 元素是否正确对齐的好方法是使用标尺和参考线。这可以在 Sketch、Adobe XD、Photoshop 和 Illustrator 等设计应用程序中轻松完成。在浏览器中,没有扩展是不可能的。
+
+一个很棒的扩展,[Grid Ruler](https://chromewebstore.google.com/detail/grid-ruler/joadogiaiabhmggdifljlpkclnpfncmj),仅在 Google Chrome 中可用。它使你能够水平或垂直拖放参考线。这对于验证两个元素是否正确对齐非常有用。
+
+
+
+在这个模型中,网格线告诉我们用户头像和按钮是对齐的。
+
+### OLI Grid CSS
+
+[OLI Grid CSS](https://addons.mozilla.org/en-US/firefox/addon/oli-grid-css/) 插件适用于 Firefox 和 Chrome。它的好处是它在页面中绘制列,就像在 Sketch 和 Adobe XD 中一样。这有助于查看你正在工作的布局是否与列对齐。
+
+
+
+我尝试用 Bootstrap 构建的页面测试插件,它按预期工作。注意你需要首先弄清楚页面的 \`.container\` 元素的宽度。
+
+### Web Developer Extension
+
+
+
+一个非常有用的扩展,提供了很多功能。以下是一些关键功能:
+
+- 禁用所有样式
+- 禁用浏览器默认样式
+- 禁用内联样式
+- 禁用打印样式
+
+这只是 CSS 标签中的几个功能!
+
+### Pesticide Extension
+
+
+
+我之前解释过使用轮廓 CSS 属性作为调试设计问题的方法。这个博客做同样的事情,但只需一次点击。它为页面上的每个元素添加随机彩色轮廓,并能够突出显示特定元素。
+
+## 在浏览器中模拟
+
+有时你想通过移动一些元素来快速在浏览器中模拟设计想法。这对于向开发者、客户或设计师展示设计概念很有用。能够快速进行此类编辑对生产力很重要。
+
+利用浏览器的内置工具,我们可以做到这一点。在本节中,我们将专注于在浏览器中快速模拟设计的概念和示例。
+
+### 好老的 CSS 定位
+
+使用 CSS 定位,我们可以通过在 DevTools 中向一些元素添加 \`position\` 并将它们放置在我们想要的位置来编辑它们。这是在测试错误时模拟设计想法的快速方法。
+
+
+
+这里我们有一个带有类别的卡片。经过一些思考,设计师告诉你,开发者,团队已经决定想要类别的不同位置。你建议类别可以移动到左上角。这可以在你们都在视频通话时完成。就像添加以下内容一样简单:
+
+\`\`\`css
+.card {
+ position: relative;
+}
+.category {
+ position: absolute;
+ left: 0;
+ top: 16px;
+}
+\`\`\`
+
+这种不到一分钟的编辑可以让决策更快地发生。
+
+### 隐藏设计元素
+
+正如我之前解释的,能够快速隐藏设计元素,比如在 Chrome 中使用 \`H\` 键,是一个有用的技巧。这样做,我们可以隐藏一些设计元素并用其他元素替换它们,例如,如果我们想要截取设计概念的屏幕截图。
+
+
+
+这里我们有一个部分标题,其中包含一个阻止作者头像和姓名对齐的错误。设计团队要求暂时删除它。你可以快速从 HTML 中删除它,用 \`display: none\` 隐藏它,或在 Chrome 中使用 \`H\` 键。
+
+### CSS Flexbox
+
+使用 Flexbox,我们可以快速使布局水平或垂直。Flexbox 属性如 \`align-items\` 和 \`justify-content\` 很强大,可以完成你想要展示的大多数设计想法。
+
+
+
+这个部分标题有一行项目。问题是项目之间的间距不一致。我们能做什么?最快的解决方案是添加 \`display: flex\` 和 \`justify-content: space-between\`。设计立即改变,所有这些都在 DevTools 中发生!你现在可以继续截取此更改的屏幕截图并与同事讨论。
+
+### CSS Grid Layout
+
+这是 CSS 中最强大的布局模块。假设我们有一个特色新闻部分,设计师想要以可呈现的方式布局项目——比如说,作为等高列。
+
+
+
+我们简单地使用 CSS 网格来设置列,然后我们与设计师确认这是他们想要的。
+
+\`\`\`css
+.wrapper {
+ display: grid;
+ grid-template-columns: 2fr 1fr 1fr;
+}
+\`\`\`
+
+这对设计师来说还不够吗?你可以继续编辑并向他们展示你的更改。此外,你可以尝试不同的布局概念并将每个概念绑定到 CSS 类,在".cls"面板中切换每个类。
+
+### CSS 视口单位
+
+我们可以使用视口单位使部分占用视口的完整水平或垂直空间。我们也可以使用它们来调整字体大小。所有这些用例给我们灵活性,使我们的设计更动态。
+
+假设我们有一个英雄部分,需要占用屏幕完整高度的 90%。我们想要与设计师验证要求,所以我们非常快速地模拟它:
+
+\`\`\`css
+.hero {
+ height: 90vh;
+}
+\`\`\`
+
+我们给英雄部分一个 \`90vh\` 的高度,这将使它占用屏幕垂直空间的 90%。我们在不到一分钟内完成了这个编辑!
+
+### CSS 列
+
+如果我们想要比 CSS 网格更快的方法,我们可以使用列。例如,我们可以将页脚中的链接分为两个相等的列。我们可以用一行代码进行此编辑,并立即回到设计师那里。
+
+\`\`\`css
+.footer-section {
+ columns: 2;
+}
+\`\`\`
+
+CSS 列的另一个好处是我们可以用键盘的上下箭头更改列数。
+
+
+
+### CSS 滤镜
+
+假设设计师想要为网站实验暗模式,但他们还没有为此做任何模型。使用 CSS 滤镜,我们可以快速制作暗模式。
+
+\`\`\`css
+html {
+ filter: invert(90%) hue-rotate(25deg);
+}
+\`\`\`
+
+为了完善它,我们可以恢复不应该被反转的元素(如图像和视频):
+
+\`\`\`css
+html img,
+html video,
+html iframe {
+ filter: invert(100%) hue-rotate(-25deg);
+}
+\`\`\`
+
+完成后,我们可以截取全页屏幕截图并向团队展示——所有这些都在不到两分钟内完成!这不是很酷吗?发送模型后,团队可以开始思考和决定。此外,你节省了设计师的时间!为小网页制作暗模式至少需要他们 10 分钟。
+
+### 去饱和设计
+
+使用 CSS 滤镜去饱和页面(即将其转换为黑白)是一个有用的技巧,原因如下:
+
+- 如果你正在测试的网站颜色很重,你的眼睛可能会疲劳。去饱和页面将帮助你专注于修复手头的错误。
+- 它对测试和探索很有用。当页面饱和时,你可以轻松发现任何不适合设计的颜色。
+- 可访问性测试变得更容易。使页面灰度将让你知道哪些颜色易于阅读,哪些不是。
+
+要使用 CSS 去饱和网页,打开浏览器的 DevTools,选择 \`html\` 或 \`body\` 元素,并添加以下内容:
+
+\`\`\`css
+html {
+ filter: grayscale(1);
+}
+\`\`\`
+
+就是这样。你现在有一个黑白网站!
+
+### 线框样式
+
+在模拟设计时,我们并不总是有时间选择好的颜色和字体。在这种情况下,我们可以使用一点 CSS 将整个网页转换为线框样式。这将让你专注于快速模拟想法并尽快获得反馈。
+
+以下是如何做到的:
+
+\`\`\`css
+* {
+ color: #000;
+ background: #ccc !important;
+ outline: solid 1px;
+}
+
+img,
+video,
+iframe {
+ background: #ccc;
+ opacity: 0;
+}
+\`\`\`
+
+## 触摸屏的悬停
+
+在触摸设备(手机、平板电脑等)上调试时,你可能会注意到一些元素在滚动时改变颜色或样式。这是因为 \`:hover\` 样式在滚动时触发。这是一个问题。解决方案是使用 \`hover\` 媒体查询。根据 [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/hover):
+
+> hover CSS 媒体功能可用于测试用户的主要输入机制是否可以悬停在元素上。
+
+
+
+\`\`\`css
+@media (hover: hover) {
+ .element:hover {
+ color: #222;
+ }
+}
+\`\`\`
+
+这样,我们防止 \`:hover\` 样式为移动和平板用户触发。在撰写本文时,此功能在所有主要浏览器中都受支持。好处是当你在 Chrome 中激活设备模式时,它将被视为触摸屏,所以你可以在那里测试 \`hover\` 媒体查询。
+
+## 使用 CSS 显示潜在错误
+
+没有直接的方法在 CSS 中显示潜在错误。但是,一些聪明的人设计了解决方法,使我们能够调试 HTML 和 CSS 的不正确使用。让我们探索其中一些。
+
+### 在上下文之外使用 CSS 类
+
+假设你与团队构建了设计系统,你想要检查与设计系统中组件不正确使用相关的错误。在他名为倒三角 CSS(ITCSS)的方法论中,Harry Roberts 使用以下类来创建关于 CSS 类不正确使用的警告。
+
+\`\`\`html
+
+\`\`\`
+
+\`.o-layout\` 类用于充当布局包装器的元素。\`.o-layout__item\` 类应该只应用于具有 \`.o-layout\` 类的父元素内的元素。以下用法将是不正确的:
+
+\`\`\`html
+
+\`\`\`
+
+具有 \`.o-layout__item\` 类的元素不应该像这样独立存在。我们可以很容易地调试这个:
+
+\`\`\`css
+.o-layout__item {
+ /* Show a warning outline by default. */
+ outline: solid 5px yellow;
+}
+.o-layout .o-layout__item {
+ /* Remove the outline when item is in .o-layout. */
+ outline: none;
+}
+\`\`\`
+
+此外,我们可以检测 \`.o-layout__item\` 是否是 \`.o-layout\` 的直接子元素。
+
+\`\`\`css
+.o-layout > :not(.o-layout__item) {
+ outline: solid 5px yellow;
+}
+\`\`\`
+
+### 向元素添加 \`width\` 或 \`height\` 属性
+
+一般来说,除了 \`img\` 之外,不建议为任何 HTML 元素使用 \`width\` 和 \`height\` 属性。
+
+\`\`\`css
+:not(img):not(object):not(embed):not(svg):not(canvas)[width],
+:not(img):not(object):not(embed):not(svg):not(canvas)[height] {
+ outline: solid 5px red;
+}
+\`\`\`
+
+进一步,你可以使用 Gaël Poupard 的浏览器扩展,[a11y.css](https://ffoodd.github.io/a11y.css/index.html),它显示不同的建议、警告和错误。`;
+ });
+
+ describe('Document Structure Validation', () => {
+ test('should contain proper markdown headers', () => {
+ expect(documentContent).toMatch(/^# /m);
+ expect(documentContent).toMatch(/^## /m);
+ expect(documentContent).toMatch(/^### /m);
+ });
+
+ test('should have main sections for debugging multilingual websites', () => {
+ expect(documentContent).toContain('调试多语言网站');
+ expect(documentContent).toContain('LTR 和 RTL 的常见错误');
+ });
+
+ test('should contain browser extension section', () => {
+ expect(documentContent).toContain('浏览器扩展');
+ expect(documentContent).toContain('Grid Ruler');
+ expect(documentContent).toContain('Web Developer Extension');
+ });
+
+ test('should have CSS techniques section', () => {
+ expect(documentContent).toContain('使用 `@supports`');
+ expect(documentContent).toContain('在浏览器中模拟');
+ });
+
+ test('should have proper section hierarchy', () => {
+ const headers = documentContent.match(/^#+\s+.+$/gm);
+ expect(headers).toBeTruthy();
+ expect(headers.length).toBeGreaterThan(15);
+ });
+ });
+
+ describe('CSS Code Block Validation', () => {
+ test('should contain valid CSS syntax for margin examples', () => {
+ expect(documentContent).toMatch(/margin-left:\s*10px/);
+ expect(documentContent).toMatch(/margin-right:\s*10px/);
+ expect(documentContent).toMatch(/margin-inline-start:\s*10px/);
+ });
+
+ test('should contain flexbox examples', () => {
+ expect(documentContent).toMatch(/display:\s*flex/);
+ expect(documentContent).toMatch(/justify-content:\s*space-between/);
+ });
+
+ test('should contain grid layout examples', () => {
+ expect(documentContent).toMatch(/display:\s*grid/);
+ expect(documentContent).toMatch(/grid-template-columns/);
+ });
+
+ test('should contain @supports queries', () => {
+ expect(documentContent).toMatch(/@supports\s*\([^)]+\)/);
+ expect(documentContent).toMatch(/@supports\s*\(display:\s*flex\)/);
+ });
+
+ test('should contain viewport units examples', () => {
+ expect(documentContent).toMatch(/90vh/);
+ expect(documentContent).toContain('height: 90vh');
+ });
+
+ test('should contain CSS filters examples', () => {
+ expect(documentContent).toMatch(/filter:\s*invert/);
+ expect(documentContent).toMatch(/filter:\s*grayscale/);
+ });
+
+ test('should contain hover media query examples', () => {
+ expect(documentContent).toMatch(/@media\s*\(hover:\s*hover\)/);
+ });
+
+ test('should contain positioning examples', () => {
+ expect(documentContent).toContain('position: relative');
+ expect(documentContent).toContain('position: absolute');
+ expect(documentContent).toContain('left: 0');
+ expect(documentContent).toContain('top: 16px');
+ });
+
+ test('should contain CSS columns examples', () => {
+ expect(documentContent).toContain('columns: 2');
+ });
+
+ test('should contain outline debugging examples', () => {
+ expect(documentContent).toMatch(/outline:\s*solid/);
+ expect(documentContent).toContain('outline: solid 5px yellow');
+ expect(documentContent).toContain('outline: solid 5px red');
+ });
+ });
+
+ describe('HTML Code Block Validation', () => {
+ test('should contain valid HTML structure for RTL example', () => {
+ expect(documentContent).toMatch(/<\/html>/);
+ });
+
+ test('should contain proper BEM methodology examples', () => {
+ expect(documentContent).toContain('o-layout');
+ expect(documentContent).toContain('o-layout__item');
+ });
+
+ test('should contain form validation examples', () => {
+ expect(documentContent).toMatch(/\[width\]/);
+ expect(documentContent).toMatch(/\[height\]/);
+ });
+
+ test('should contain proper HTML class structure', () => {
+ expect(documentContent).toContain('class="o-layout"');
+ expect(documentContent).toContain('class="o-layout__item"');
+ });
+ });
+
+ describe('Link and Reference Validation', () => {
+ test('should contain external reference links', () => {
+ expect(documentContent).toContain('rtlstyling.com');
+ expect(documentContent).toContain('Mozilla Developer Network');
+ });
+
+ test('should contain browser extension links', () => {
+ expect(documentContent).toContain('chromewebstore.google.com');
+ expect(documentContent).toContain('addons.mozilla.org');
+ });
+
+ test('should reference specific browser extensions', () => {
+ expect(documentContent).toContain('Grid Ruler');
+ expect(documentContent).toContain('OLI Grid CSS');
+ expect(documentContent).toContain('Pesticide Extension');
+ });
+
+ test('should contain GitHub repository links', () => {
+ expect(documentContent).toContain('github.com/ireade/feature-queries-manager');
+ });
+
+ test('should contain accessibility resource links', () => {
+ expect(documentContent).toContain('ffoodd.github.io/a11y.css');
+ });
+ });
+
+ describe('Image Reference Validation', () => {
+ test('should contain image references with proper paths', () => {
+ const imageMatches = documentContent.match(/!\[.*\]\(\/img\/.*\.png\)/g);
+ expect(imageMatches).toBeTruthy();
+ expect(imageMatches.length).toBeGreaterThan(0);
+ });
+
+ test('should have consistent image naming convention', () => {
+ const imageReferences = documentContent.match(/image-\d{8}-\d{6}-\d{3}\.png/g);
+ expect(imageReferences).toBeTruthy();
+ expect(imageReferences.length).toBeGreaterThan(5);
+ });
+
+ test('should contain properly formatted image markdown', () => {
+ expect(documentContent).toMatch(/!\[image-\d{8}-\d{6}-\d{3}\]\(\/img\/image-\d{8}-\d{6}-\d{3}\.png\)/);
+ });
+ });
+
+ describe('Content Quality and Completeness', () => {
+ test('should provide practical debugging examples', () => {
+ expect(documentContent).toContain('DevTools');
+ expect(documentContent).toContain('Chrome');
+ expect(documentContent).toContain('Firefox');
+ });
+
+ test('should cover accessibility considerations', () => {
+ expect(documentContent).toContain('可访问性');
+ expect(documentContent).toContain('a11y.css');
+ });
+
+ test('should include performance considerations', () => {
+ expect(documentContent).toContain('生产力');
+ expect(documentContent).toMatch(/不到.*分钟/);
+ });
+
+ test('should provide comprehensive CSS debugging techniques', () => {
+ expect(documentContent).toContain('间距问题');
+ expect(documentContent).toContain('对齐问题');
+ expect(documentContent).toContain('布局');
+ expect(documentContent).toContain('线框样式');
+ });
+
+ test('should explain browser development workflow', () => {
+ expect(documentContent).toContain('视频通话');
+ expect(documentContent).toContain('设计师');
+ expect(documentContent).toContain('开发者');
+ });
+
+ test('should provide time estimates for tasks', () => {
+ expect(documentContent).toContain('不到一分钟');
+ expect(documentContent).toContain('不到两分钟');
+ expect(documentContent).toContain('10 分钟');
+ });
+ });
+
+ describe('Technical Accuracy Validation', () => {
+ test('should contain valid CSS property names', () => {
+ const cssProperties = [
+ 'margin-left', 'margin-right', 'margin-inline-start',
+ 'text-align', 'display', 'position', 'filter',
+ 'justify-content', 'align-items', 'grid-template-columns'
+ ];
+
+ cssProperties.forEach(property => {
+ expect(documentContent).toContain(property);
+ });
+ });
+
+ test('should use correct CSS values', () => {
+ expect(documentContent).toMatch(/:\s*(flex|grid|absolute|relative)/);
+ expect(documentContent).toMatch(/:\s*(left|right|center)/);
+ expect(documentContent).toMatch(/:\s*\d+px/);
+ });
+
+ test('should provide correct browser feature detection', () => {
+ expect(documentContent).toContain('@supports (display: flex)');
+ expect(documentContent).toContain('@media (hover: hover)');
+ });
+
+ test('should contain valid viewport units', () => {
+ expect(documentContent).toContain('90vh');
+ expect(documentContent).toMatch(/\d+vh/);
+ });
+
+ test('should contain valid filter functions', () => {
+ expect(documentContent).toContain('invert(90%)');
+ expect(documentContent).toContain('hue-rotate(25deg)');
+ expect(documentContent).toContain('grayscale(1)');
+ });
+
+ test('should contain proper CSS selector syntax', () => {
+ expect(documentContent).toContain(':not(img):not(object):not(embed):not(svg):not(canvas)[width]');
+ expect(documentContent).toContain('.o-layout > :not(.o-layout__item)');
+ });
+ });
+
+ describe('Internationalization Content Validation', () => {
+ test('should properly explain LTR and RTL concepts', () => {
+ expect(documentContent).toContain('从左到右');
+ expect(documentContent).toContain('从右到左');
+ expect(documentContent).toContain('LTR');
+ expect(documentContent).toContain('RTL');
+ });
+
+ test('should mention specific languages as examples', () => {
+ expect(documentContent).toContain('英语');
+ expect(documentContent).toContain('阿拉伯语');
+ });
+
+ test('should provide practical RTL debugging advice', () => {
+ expect(documentContent).toContain('dir="rtl"');
+ expect(documentContent).toContain('main-ltr.css');
+ expect(documentContent).toContain('main-rtl.css');
+ });
+
+ test('should explain logical properties', () => {
+ expect(documentContent).toContain('margin-inline-start');
+ expect(documentContent).toContain('逻辑属性');
+ });
+
+ test('should mention Google Translate as a testing tool', () => {
+ expect(documentContent).toContain('Google');
+ expect(documentContent).toContain('翻译');
+ });
+ });
+
+ describe('Code Quality Standards', () => {
+ test('should use consistent code formatting', () => {
+ const cssBlocks = documentContent.match(/```css[\s\S]*?```/g);
+ expect(cssBlocks).toBeTruthy();
+ expect(cssBlocks.length).toBeGreaterThan(10);
+ });
+
+ test('should use consistent HTML formatting', () => {
+ const htmlBlocks = documentContent.match(/```html[\s\S]*?```/g);
+ expect(htmlBlocks).toBeTruthy();
+ expect(htmlBlocks.length).toBeGreaterThan(0);
+ });
+
+ test('should have proper indentation in code examples', () => {
+ expect(documentContent).toMatch(/ [a-z-]+:/); // 2-space indentation
+ });
+
+ test('should contain CSS comments for clarity', () => {
+ expect(documentContent).toContain('/* If flexbox is supported, apply this. */');
+ expect(documentContent).toContain('/* Show a warning outline by default. */');
+ expect(documentContent).toContain('/* Remove the outline when item is in .o-layout. */');
+ });
+ });
+
+ describe('Browser Compatibility Information', () => {
+ test('should mention browser support information', () => {
+ expect(documentContent).toContain('所有主要浏览器');
+ expect(documentContent).toContain('Chrome');
+ expect(documentContent).toContain('Firefox');
+ });
+
+ test('should reference browser developer tools', () => {
+ expect(documentContent).toContain('DevTools');
+ expect(documentContent).toMatch(/Chrome.*DevTools|DevTools.*Chrome/);
+ });
+
+ test('should mention specific browser capabilities', () => {
+ expect(documentContent).toContain('设备模式');
+ expect(documentContent).toContain('触摸屏');
+ });
+ });
+
+ describe('Error Prevention and Detection', () => {
+ test('should provide error detection techniques', () => {
+ expect(documentContent).toContain('显示潜在错误');
+ expect(documentContent).toContain('outline: solid');
+ expect(documentContent).toContain('yellow');
+ expect(documentContent).toContain('red');
+ });
+
+ test('should explain common CSS mistakes', () => {
+ expect(documentContent).toContain('width');
+ expect(documentContent).toContain('height');
+ expect(documentContent).toContain('属性');
+ });
+
+ test('should provide debugging methodologies', () => {
+ expect(documentContent).toContain('ITCSS');
+ expect(documentContent).toContain('Harry Roberts');
+ expect(documentContent).toContain('设计系统');
+ });
+
+ test('should warn about incorrect usage patterns', () => {
+ expect(documentContent).toContain('不正确');
+ expect(documentContent).toContain('警告');
+ expect(documentContent).toContain('错误');
+ });
+ });
+
+ describe('Design Workflow Integration', () => {
+ test('should mention design tools', () => {
+ expect(documentContent).toContain('Sketch');
+ expect(documentContent).toContain('Adobe XD');
+ expect(documentContent).toContain('Photoshop');
+ expect(documentContent).toContain('Illustrator');
+ });
+
+ test('should explain collaboration workflows', () => {
+ expect(documentContent).toContain('团队');
+ expect(documentContent).toContain('同事');
+ expect(documentContent).toContain('客户');
+ });
+
+ test('should provide practical implementation advice', () => {
+ expect(documentContent).toContain('屏幕截图');
+ expect(documentContent).toContain('模拟');
+ expect(documentContent).toContain('概念');
+ });
+ });
+
+ describe('Utility and Practicality', () => {
+ test('should provide keyboard shortcuts', () => {
+ expect(documentContent).toContain('H');
+ expect(documentContent).toContain('上下箭头');
+ });
+
+ test('should explain browser extension usage', () => {
+ expect(documentContent).toContain('标签');
+ expect(documentContent).toContain('复选框');
+ expect(documentContent).toContain('切换');
+ });
+
+ test('should provide concrete examples with context', () => {
+ expect(documentContent).toContain('假设');
+ expect(documentContent).toContain('例如');
+ expect(documentContent).toContain('这里我们有');
+ });
+
+ test('should explain the benefits of techniques', () => {
+ expect(documentContent).toContain('好处');
+ expect(documentContent).toContain('优势');
+ expect(documentContent).toContain('节省');
+ });
+ });
+});
+
+describe('Documentation Accessibility and User Experience', () => {
+ let documentContent;
+
+ beforeAll(() => {
+ // Same content as above test suite
+ documentContent = `# 通用技巧和诀窍
+
+## 调试多语言网站
+
+当涉及调试多语言网站时,我们需要了解如何测试它以及事物如何工作。在谈论多语言网站时,我们将专注于从左到右(LTR)和从右到左(RTL)布局,分别使用英语和阿拉伯语的示例。
+
+### LTR 和 RTL 的常见错误
+
+### 间距问题
+
+在调试 LTR 和 RTL 时,大多数问题将与间距相关。每种语言的水平方向将被翻转,间距问题通常归结为内边距或外边距。假设我们有以下内容:
+
+\`\`\`css
+.element {
+ margin-left: 10px;
+}
+\`\`\`
+
+对于 RTL,它将是这样的:
+
+\`\`\`css
+.element {
+ margin-right: 10px;
+}
+\`\`\`
+
+我们会对内边距和定位属性(\`top\`、\`right\`、\`bottom\`、\`left\`)做等效处理。
+
+此外,我们可以使用 CSS 逻辑属性来避免为 RTL 编写更多 CSS。以下是上述示例的外观:
+
+\`\`\`css
+.element {
+ margin-inline-start: 10px;
+}
+\`\`\`
+
+属性 \`margin-inline-start\` 是逻辑的。这意味着,对于 LTR 它将是 \`margin-left\`,对于 RTL 它将是 \`margin-right\`。如果你有兴趣了解更多关于 RTL 样式的信息,我推荐你阅读我写的这个[指南](https://rtlstyling.com/)。
+
+### 对齐问题
+
+当文本在 LTR 中向右对齐时,它应该在 RTL 中翻转。
+
+\`\`\`css
+.element {
+ text-align: right;
+}
+\`\`\`
+
+对于 RTL,它将是这样的:
+
+\`\`\`css
+.element {
+ text-align: left;
+}
+\`\`\`
+
+### 调试 RTL
+
+根据你正在构建的网站的工作方式,将给定页面的 CSS 从 LTR 切换到 RTL 可能很容易。如果 CSS 合并到一个文件中,切换将像在 \`html\` 元素上设置 \`dir\` 属性一样简单。
+
+\`\`\`html
+
+\`\`\`
+
+我们可以首先在 DevTools 中设置属性,然后检查我们想要修复的问题。
+
+如果 LTR 和 RTL 的 CSS 不在一个文件中,那么它很可能在两个文件中,如 \`main-ltr.css\` 和 \`main-rtl.css\`。仅切换 \`dir\` 属性是不够的;我们还需要编辑 \`head\` 元素中样式表的 \`src\`。
+
+### 快速添加 RTL 内容的方法
+
+假设我们已经为 LTR 和 RTL 布局构建了 CSS,唯一缺少的是测试 RTL 内容的排版。在使用 LTR 内容以 RTL 模式查看设计时,你可以使用 Google 的页面内翻译来快速翻译所有内容。这将帮助你创建带有内容的 RTL 设计,并使其适合文本方向。
+
+如果你感兴趣,我写了一个关于此的详尽指南,标题为 [RTL Styling 101](https://rtlstyling.com/)。
+
+## 使用 \`@supports\`
+
+如果你不知道它,\`@supports\` 用于检测用户浏览器是否支持给定的 CSS 功能。
+
+\`\`\`css
+@supports (display: flex) {
+ /* If flexbox is supported, apply this. */
+ .element {
+ display: flex;
+ }
+}
+\`\`\`
+
+测试它的一个有趣方法是切换其功能。有浏览器扩展可以做到这一点,但我们可以通过添加随机字母来手动完成。当添加随机字母时,它将破坏规则;因此,CSS 不会工作。
+
+\`\`\`css
+@supports (display: flexB) {
+ /* ... */
+}
+\`\`\`
+
+我在 \`display: flex\` 后添加了字母"B"。浏览器不会识别它,你将获得默认行为,就像 \`@supports\` 被禁用一样。很酷,对吧?
+
+但是,在具有大量 \`@supports\` 规则的大型项目中,手动执行是不实际的。幸运的是,Ire Aderinokun 为此目的创建了一个[浏览器扩展](https://github.com/ireade/feature-queries-manager),它适用于 Chrome 和 Firefox。
+
+
+
+该扩展将在你的浏览器 DevTools 中添加一个新标签。在左侧,你会看到嵌套在 \`@supports\` 查询中的 CSS 功能的可切换列表,在右侧将是使用特定功能的每个 \`@supports\` 查询的列表。上面显示的 CSS 是与网格相关的内容。切换左侧的复选框将禁用和启用 CSS 网格。这是测试和破坏布局的好方法。让我们更深入地了解破坏布局的方法。
+
+## 浏览器扩展
+
+### Grid Ruler
+
+测试两个 UI 元素是否正确对齐的好方法是使用标尺和参考线。这可以在 Sketch、Adobe XD、Photoshop 和 Illustrator 等设计应用程序中轻松完成。在浏览器中,没有扩展是不可能的。
+
+一个很棒的扩展,[Grid Ruler](https://chromewebstore.google.com/detail/grid-ruler/joadogiaiabhmggdifljlpkclnpfncmj),仅在 Google Chrome 中可用。它使你能够水平或垂直拖放参考线。这对于验证两个元素是否正确对齐非常有用。
+
+
+
+在这个模型中,网格线告诉我们用户头像和按钮是对齐的。
+
+### OLI Grid CSS
+
+[OLI Grid CSS](https://addons.mozilla.org/en-US/firefox/addon/oli-grid-css/) 插件适用于 Firefox 和 Chrome。它的好处是它在页面中绘制列,就像在 Sketch 和 Adobe XD 中一样。这有助于查看你正在工作的布局是否与列对齐。
+
+
+
+我尝试用 Bootstrap 构建的页面测试插件,它按预期工作。注意你需要首先弄清楚页面的 \`.container\` 元素的宽度。
+
+### Web Developer Extension
+
+
+
+一个非常有用的扩展,提供了很多功能。以下是一些关键功能:
+
+- 禁用所有样式
+- 禁用浏览器默认样式
+- 禁用内联样式
+- 禁用打印样式
+
+这只是 CSS 标签中的几个功能!
+
+### Pesticide Extension
+
+
+
+我之前解释过使用轮廓 CSS 属性作为调试设计问题的方法。这个博客做同样的事情,但只需一次点击。它为页面上的每个元素添加随机彩色轮廓,并能够突出显示特定元素。
+
+## 在浏览器中模拟
+
+有时你想通过移动一些元素来快速在浏览器中模拟设计想法。这对于向开发者、客户或设计师展示设计概念很有用。能够快速进行此类编辑对生产力很重要。
+
+利用浏览器的内置工具,我们可以做到这一点。在本节中,我们将专注于在浏览器中快速模拟设计的概念和示例。
+
+### 好老的 CSS 定位
+
+使用 CSS 定位,我们可以通过在 DevTools 中向一些元素添加 \`position\` 并将它们放置在我们想要的位置来编辑它们。这是在测试错误时模拟设计想法的快速方法。
+
+
+
+这里我们有一个带有类别的卡片。经过一些思考,设计师告诉你,开发者,团队已经决定想要类别的不同位置。你建议类别可以移动到左上角。这可以在你们都在视频通话时完成。就像添加以下内容一样简单:
+
+\`\`\`css
+.card {
+ position: relative;
+}
+.category {
+ position: absolute;
+ left: 0;
+ top: 16px;
+}
+\`\`\`
+
+这种不到一分钟的编辑可以让决策更快地发生。
+
+### 隐藏设计元素
+
+正如我之前解释的,能够快速隐藏设计元素,比如在 Chrome 中使用 \`H\` 键,是一个有用的技巧。这样做,我们可以隐藏一些设计元素并用其他元素替换它们,例如,如果我们想要截取设计概念的屏幕截图。
+
+
+
+这里我们有一个部分标题,其中包含一个阻止作者头像和姓名对齐的错误。设计团队要求暂时删除它。你可以快速从 HTML 中删除它,用 \`display: none\` 隐藏它,或在 Chrome 中使用 \`H\` 键。
+
+### CSS Flexbox
+
+使用 Flexbox,我们可以快速使布局水平或垂直。Flexbox 属性如 \`align-items\` 和 \`justify-content\` 很强大,可以完成你想要展示的大多数设计想法。
+
+
+
+这个部分标题有一行项目。问题是项目之间的间距不一致。我们能做什么?最快的解决方案是添加 \`display: flex\` 和 \`justify-content: space-between\`。设计立即改变,所有这些都在 DevTools 中发生!你现在可以继续截取此更改的屏幕截图并与同事讨论。
+
+### CSS Grid Layout
+
+这是 CSS 中最强大的布局模块。假设我们有一个特色新闻部分,设计师想要以可呈现的方式布局项目——比如说,作为等高列。
+
+
+
+我们简单地使用 CSS 网格来设置列,然后我们与设计师确认这是他们想要的。
+
+\`\`\`css
+.wrapper {
+ display: grid;
+ grid-template-columns: 2fr 1fr 1fr;
+}
+\`\`\`
+
+这对设计师来说还不够吗?你可以继续编辑并向他们展示你的更改。此外,你可以尝试不同的布局概念并将每个概念绑定到 CSS 类,在".cls"面板中切换每个类。
+
+### CSS 视口单位
+
+我们可以使用视口单位使部分占用视口的完整水平或垂直空间。我们也可以使用它们来调整字体大小。所有这些用例给我们灵活性,使我们的设计更动态。
+
+假设我们有一个英雄部分,需要占用屏幕完整高度的 90%。我们想要与设计师验证要求,所以我们非常快速地模拟它:
+
+\`\`\`css
+.hero {
+ height: 90vh;
+}
+\`\`\`
+
+我们给英雄部分一个 \`90vh\` 的高度,这将使它占用屏幕垂直空间的 90%。我们在不到一分钟内完成了这个编辑!
+
+### CSS 列
+
+如果我们想要比 CSS 网格更快的方法,我们可以使用列。例如,我们可以将页脚中的链接分为两个相等的列。我们可以用一行代码进行此编辑,并立即回到设计师那里。
+
+\`\`\`css
+.footer-section {
+ columns: 2;
+}
+\`\`\`
+
+CSS 列的另一个好处是我们可以用键盘的上下箭头更改列数。
+
+
+
+### CSS 滤镜
+
+假设设计师想要为网站实验暗模式,但他们还没有为此做任何模型。使用 CSS 滤镜,我们可以快速制作暗模式。
+
+\`\`\`css
+html {
+ filter: invert(90%) hue-rotate(25deg);
+}
+\`\`\`
+
+为了完善它,我们可以恢复不应该被反转的元素(如图像和视频):
+
+\`\`\`css
+html img,
+html video,
+html iframe {
+ filter: invert(100%) hue-rotate(-25deg);
+}
+\`\`\`
+
+完成后,我们可以截取全页屏幕截图并向团队展示——所有这些都在不到两分钟内完成!这不是很酷吗?发送模型后,团队可以开始思考和决定。此外,你节省了设计师的时间!为小网页制作暗模式至少需要他们 10 分钟。
+
+### 去饱和设计
+
+使用 CSS 滤镜去饱和页面(即将其转换为黑白)是一个有用的技巧,原因如下:
+
+- 如果你正在测试的网站颜色很重,你的眼睛可能会疲劳。去饱和页面将帮助你专注于修复手头的错误。
+- 它对测试和探索很有用。当页面饱和时,你可以轻松发现任何不适合设计的颜色。
+- 可访问性测试变得更容易。使页面灰度将让你知道哪些颜色易于阅读,哪些不是。
+
+要使用 CSS 去饱和网页,打开浏览器的 DevTools,选择 \`html\` 或 \`body\` 元素,并添加以下内容:
+
+\`\`\`css
+html {
+ filter: grayscale(1);
+}
+\`\`\`
+
+就是这样。你现在有一个黑白网站!
+
+### 线框样式
+
+在模拟设计时,我们并不总是有时间选择好的颜色和字体。在这种情况下,我们可以使用一点 CSS 将整个网页转换为线框样式。这将让你专注于快速模拟想法并尽快获得反馈。
+
+以下是如何做到的:
+
+\`\`\`css
+* {
+ color: #000;
+ background: #ccc !important;
+ outline: solid 1px;
+}
+
+img,
+video,
+iframe {
+ background: #ccc;
+ opacity: 0;
+}
+\`\`\`
+
+## 触摸屏的悬停
+
+在触摸设备(手机、平板电脑等)上调试时,你可能会注意到一些元素在滚动时改变颜色或样式。这是因为 \`:hover\` 样式在滚动时触发。这是一个问题。解决方案是使用 \`hover\` 媒体查询。根据 [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/hover):
+
+> hover CSS 媒体功能可用于测试用户的主要输入机制是否可以悬停在元素上。
+
+
+
+\`\`\`css
+@media (hover: hover) {
+ .element:hover {
+ color: #222;
+ }
+}
+\`\`\`
+
+这样,我们防止 \`:hover\` 样式为移动和平板用户触发。在撰写本文时,此功能在所有主要浏览器中都受支持。好处是当你在 Chrome 中激活设备模式时,它将被视为触摸屏,所以你可以在那里测试 \`hover\` 媒体查询。
+
+## 使用 CSS 显示潜在错误
+
+没有直接的方法在 CSS 中显示潜在错误。但是,一些聪明的人设计了解决方法,使我们能够调试 HTML 和 CSS 的不正确使用。让我们探索其中一些。
+
+### 在上下文之外使用 CSS 类
+
+假设你与团队构建了设计系统,你想要检查与设计系统中组件不正确使用相关的错误。在他名为倒三角 CSS(ITCSS)的方法论中,Harry Roberts 使用以下类来创建关于 CSS 类不正确使用的警告。
+
+\`\`\`html
+
+\`\`\`
+
+\`.o-layout\` 类用于充当布局包装器的元素。\`.o-layout__item\` 类应该只应用于具有 \`.o-layout\` 类的父元素内的元素。以下用法将是不正确的:
+
+\`\`\`html
+
+\`\`\`
+
+具有 \`.o-layout__item\` 类的元素不应该像这样独立存在。我们可以很容易地调试这个:
+
+\`\`\`css
+.o-layout__item {
+ /* Show a warning outline by default. */
+ outline: solid 5px yellow;
+}
+.o-layout .o-layout__item {
+ /* Remove the outline when item is in .o-layout. */
+ outline: none;
+}
+\`\`\`
+
+此外,我们可以检测 \`.o-layout__item\` 是否是 \`.o-layout\` 的直接子元素。
+
+\`\`\`css
+.o-layout > :not(.o-layout__item) {
+ outline: solid 5px yellow;
+}
+\`\`\`
+
+### 向元素添加 \`width\` 或 \`height\` 属性
+
+一般来说,除了 \`img\` 之外,不建议为任何 HTML 元素使用 \`width\` 和 \`height\` 属性。
+
+\`\`\`css
+:not(img):not(object):not(embed):not(svg):not(canvas)[width],
+:not(img):not(object):not(embed):not(svg):not(canvas)[height] {
+ outline: solid 5px red;
+}
+\`\`\`
+
+进一步,你可以使用 Gaël Poupard 的浏览器扩展,[a11y.css](https://ffoodd.github.io/a11y.css/index.html),它显示不同的建议、警告和错误。`;
+ });
+
+ test('should provide step-by-step instructions', () => {
+ expect(documentContent).toMatch(/步骤|方法|如何/);
+ expect(documentContent).toContain('就像');
+ expect(documentContent).toContain('简单');
+ });
+
+ test('should include practical examples with context', () => {
+ expect(documentContent).toContain('假设');
+ expect(documentContent).toContain('例如');
+ expect(documentContent).toContain('这里');
+ });
+
+ test('should provide performance metrics', () => {
+ expect(documentContent).toMatch(/\d+分钟/);
+ expect(documentContent).toContain('快速');
+ expect(documentContent).toContain('立即');
+ });
+
+ test('should use clear explanatory language', () => {
+ expect(documentContent).toContain('这意味着');
+ expect(documentContent).toContain('换句话说');
+ expect(documentContent).toContain('也就是说');
+ });
+
+ test('should provide motivation and benefits', () => {
+ expect(documentContent).toContain('很酷');
+ expect(documentContent).toContain('有用');
+ expect(documentContent).toContain('强大');
+ });
+
+ test('should explain common problems and solutions', () => {
+ expect(documentContent).toContain('问题');
+ expect(documentContent).toContain('解决方案');
+ expect(documentContent).toContain('修复');
+ });
+
+ test('should provide context for when to use techniques', () => {
+ expect(documentContent).toContain('当');
+ expect(documentContent).toContain('如果');
+ expect(documentContent).toContain('在');
+ });
+
+ test('should include encouraging language', () => {
+ expect(documentContent).toContain('推荐');
+ expect(documentContent).toContain('建议');
+ expect(documentContent).toContain('可以');
+ });
+});
\ No newline at end of file