diff --git a/components/RUA/RUACodeSandbox.tsx b/components/RUA/RUACodeSandbox.tsx
index a4954c0..93a0626 100644
--- a/components/RUA/RUACodeSandbox.tsx
+++ b/components/RUA/RUACodeSandbox.tsx
@@ -6,7 +6,7 @@ import RUALoading from './loading/RUALoading';
const partten =
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
-const commonClass = classNames(
+export const commonClass = classNames(
'rounded-lg h-[500px] border-0',
'overflow-hidden w-full'
);
diff --git a/components/RUA/RUACodepen.tsx b/components/RUA/RUACodepen.tsx
new file mode 100644
index 0000000..1d5fa54
--- /dev/null
+++ b/components/RUA/RUACodepen.tsx
@@ -0,0 +1,84 @@
+import classNames from 'classnames';
+import useInView from 'lib/hooks/useInView';
+import { useTheme } from 'next-themes';
+import { useEffect, useState } from 'react';
+import RUALoading from './loading/RUALoading';
+
+export const commonClass = classNames(
+ 'rounded-lg h-[400px] border-0',
+ 'overflow-hidden w-full'
+);
+
+type Props = {
+ defaultTab?: 'html' | 'css' | 'js' | '';
+ url: string;
+};
+
+const RUACodepen = ({ defaultTab, url }: Props) => {
+ const urlArr = url.split('/');
+ const { systemTheme, theme } = useTheme();
+ const currentTheme = theme === 'system' ? systemTheme : theme ?? 'light';
+
+ const { ref, inView } = useInView();
+
+ const [src, setSrc] = useState('');
+ useEffect(() => {
+ inView &&
+ setSrc(
+ `https://codepen.io/${urlArr[3]}/embed/${urlArr[5]}?default-tab=${defaultTab}%2Cresult&theme-id=${currentTheme}`
+ );
+ }, [currentTheme, defaultTab, inView, urlArr]);
+
+ const [load, setLoad] = useState(false);
+ const handleLoad = () => {
+ setLoad(true);
+ };
+
+ return (
+ <>
+
+ >
+ );
+};
+
+export default RUACodepen;
diff --git a/components/mdx/components.ts b/components/mdx/components.ts
index be1bb46..73cfda1 100644
--- a/components/mdx/components.ts
+++ b/components/mdx/components.ts
@@ -1,6 +1,7 @@
import Anchor from 'components/mdx/Anchor';
import Image from 'components/mdx/Image';
import Pre from 'components/mdx/Pre';
+import RUACodepen from 'components/RUA/RUACodepen';
import RUACodeSandbox from 'components/RUA/RUACodeSandbox';
import RUASandpack from 'components/RUA/RUASandpack';
import Tab from 'components/RUA/tab';
@@ -14,6 +15,7 @@ const components = {
Tab,
TabItem,
RUACodeSandbox,
+ RUACodepen,
};
export default components;
diff --git a/data/posts/javascript-practice-multiplication-table.mdx b/data/posts/javascript-practice-multiplication-table.mdx
new file mode 100644
index 0000000..32b5f97
--- /dev/null
+++ b/data/posts/javascript-practice-multiplication-table.mdx
@@ -0,0 +1,294 @@
+---
+title: JavaScript practice multiplication table
+date: '2020-12-11'
+tags: JavaScript
+---
+
+
+
+从学习 js 到现在,也有一段时间了。曾经也尝试过写一些复杂的实践。后来经过测试,就算在入门阶段到了会写,那么距离最优代码还是有一定的差距。可能隔个几天回来自己都看不懂自己写的是什么了,杂乱无章。
+
+最近打算先开始写一些简单的案例做做练习。无意中想到了经典的乘法口诀表,正好 for 循环也有过实践了,可以尝试一下。
+
+> for 循环嵌套的一次练习。
+
+## 思路
+
+有了想法之后,就要开始构建实现的思路。由于 css 还没跨过门槛,所以决定就打算输出到 console 里。
+
+
+
+而在 console 输出类似于一个梯形的结构也是需要一个思考的问题。可以打印正确的形状之后,就可以考虑如何输出数字与结果了。
+
+所以构思分为几步:
+
+1. 打印正确的形状
+2. 输出内容
+
+## 打印正确的形状
+
+首先先忽略内容,一步一步的打印出所有东西。所以先将内容用`*`代替,只在意形状。
+
+### 正方形
+
+要想正确打印出一个正三角,可以先考虑从一个 10x10 正方形开始。
+
+第一个想法就是将行和列分别输出。首先定义两个变量,一个用于保存`*`,等会打印再同一行循环打印 10 次,第一行的`*`就输出完成。另一个变量用于保存第一行输出的内容。
+
+使用一个简单的 for 循环就能打印出第一行来:
+
+```js
+let x = '*'; //输出“*”
+let s = ''; //保存列输出
+for (let i = 0; i < 10; i++) {
+ s += x + ' '; //打印10列“*”
+}
+console.log(s);
+```
+
+此时就能看到第一行的效果:
+
+```js
+console.log(s);
+//输出:
+* * * * * * * * * *
+```
+
+现在已经完成了 1x10,也就是说再打印出 9 行通用的内容就可以打印出一个 10x10 的正方形了。
+
+那么接下来的思路和上面的也很相似,只需要**再**定义一个变量用于保存最后 10 行的结果就可以了。for 循环也差不多,只需要将`s`加上换行符打印十次就可以了。
+
+```js
+let x = '*'; //输出“*”
+let s = ''; //保存列输出
+for (let i = 0; i < 10; i++) {
+ s += x + ' '; //打印10列“*”
+}
+let t = ''; //保存行输出
+for (let i = 0; i < 10; i++) {
+ t += s + '\n'; //再将10列打印10行
+}
+console.log(t);
+```
+
+这样一个正方形就被打印出来了:
+
+```js
+console.log(t);
+//输出:
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+```
+
+### 更好的正方形
+
+现在离乘法表的三角形应该差切掉一半了。但是在此之前,上述打印一个正方形就用掉了三个变量,并且变量`s`在第一个用完之后便没用了,只是个简单的中间人。思路虽然很清晰,但是最后实现的步骤比较繁琐。
+
+后来思索了一下,只需要将两个 for 循环嵌套一下,就可以节省下来两个变量,并且整体更加的简洁。
+
+此时只需要一个变量`s`来保存最后的输出结果。将两个 for 循环嵌套在一起时,它们的运算步骤就变成为:
+
+1. 进入第一层循环
+2. 第一层循环内的 for 循环到指定的次数后退出
+3. 再次执行第一层循环,并重述步骤 2,直到第一层循环达到次数
+
+这样一个步骤就能够更加简洁的打印出一个正方形。步骤总结就是第一个 for 循环第一次,第二个 for 循环就循环了 10 次,正好可以打印以后 10 个`*`。随后第一个 for 循环进入第二次,并换行,第二个 for 循环再次打印 10 次。这样就两行了,以此类推,就可以打印出 10x10。
+
+```js
+let s = ''; //保存结果
+for (let i = 0; i < 10; i++) {
+ for (let o = 0; o < 10; o++) {
+ s += '* '; //保存行
+ }
+ s += '\n'; //换行
+}
+console.log(s);
+```
+
+最后的结果和上述还是一样的,但是整体的代码简洁了很多。
+
+```js
+console.log(s);
+//输出:
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+* * * * * * * * * *
+```
+
+### 三角形
+
+有了更好的正方形加持下,就可以轻松的打印出三角形了。
+
+再看一次上述的 10x10 的步骤,第一个 for 循环第一次,第二个 for 循环就循环了 10 次,正好可以打印以后 10 个`*`。那么一个正三角形的第一行是只有一个`*`的,也就是说 for 循环第一次,第二个 for 循环就循环了 1 次,这样第一行就只有一个`*`。
+
+实现的整体和打印正方形是没有多少区别的,是需要限制第二个循环的次数,循环到指定的次数后跳出,再由第一个循环换行。
+
+根据“第一行一个`*`,第二行两个`*`”的规律,正好第一个循环的变量`i`是自增的。只需要将内循环的那个限制条件改为第一个循环的变量。就可以正好根据第一个循环打印出一个三角。
+
+```js
+let s = '';
+for (let i = 0; i < 10; i++) {
+ for (let o = 0; o <= i; o++) {
+ //条件换成第一个循环的次数,达到“递增换行”的效果
+ s += '* ';
+ }
+ s += '\n';
+}
+console.log(s);
+```
+
+详细工作方式:当`i`等于 1 时,第一个循环进入第二个循环,第二个循环限制条件为`i`,只循环一次,输出一个`*`。随后跳出到第一个循环打印换行,然后第一个循环进入第二次,`i`等于 2。第二个循环正好沿着`i`的自增依次打印出对应数量的`*`。
+
+输出:
+
+```js
+console.log(s);
+*
+* *
+* * *
+* * * *
+* * * * *
+* * * * * *
+* * * * * * *
+* * * * * * * *
+* * * * * * * * *
+* * * * * * * * * *
+```
+
+## 添加内容
+
+已经跟着第一次打印的正方形,一步一步的能够打印出需要的正三角了。接下来就只需要将`*`替换为乘法表里的内容就可以了。
+
+### 乘法表
+
+要想实现一个有规律的方法,诀窍就是仔细观察其实现的规律。在 9 行的乘法表中,乘数和被乘数的关系在随着行数和列数增加而增加。被乘数总是与行数相等,而乘数则是与列数相等。
+
+首先第一次的想法是,将乘法表的两个乘数由两个变量代替。只要控制好变量的变化就可以了。这种方法用到的变量比较多,完全用两个变量来代替乘数和被乘数。
+
+第一次的想法没有确切的观察乘法表的规律,在打印正三角的基础上。通过对比大小来控制两个变量的变化。乘数随着行的增加时,是从 1 开始随着列增加的,被乘数一直等于行数。于是在第二个控制行的 for 循环中添加 if 语句,当乘数小于被乘数时++。
+
+被乘数是随着行增加而增加的,于是当第二个 for 循环结束后,被乘数也++。而乘数则是从头开始,所以重新复制=1。
+
+```js
+let a = 1;
+let b = 1;
+let s = '';
+for (let i = 0; i < 9; i++) {
+ for (let o = 0; o <= i; o++) {
+ s += a + '*' + b + '=' + a * b + ' ';
+ if (a < b) {
+ a++;
+ }
+ }
+ b++;
+ a = 1;
+ s += '\n';
+}
+```
+
+这样的方法可以成功的实现所有的效果,但是用的变量还是比较多的。并且语句结构也比较复杂。
+
+### 更好的乘法表
+
+前面都是没有仔细去观察乘法表的规律而写出来的,从而使用了好几个变量以及复杂的多的语句。
+
+只需要详细观察了乘法表里的乘数与被乘数之间的变化关系,就能够发现两次嵌套循环之间变量的关系刚好一样。
+
+```js
+let res = '';
+// i随着行变化(被乘数)
+for (let i = 1; i <= 9; i++) {
+ // o始终从1开始,小于行数(乘数)
+ for (let o = 1; o <= i; o++) {
+ res += `${o}*${i}=${o * i} `;
+ }
+ res += '\n';
+}
+```
+
+也就是说`i`相当于乘数,它随着每行的增加而增加,并且每行都一样,同时它控制着换行。而变量`o`相当于被乘数,每行从 1 开始,并且小于等于`i`。
+
+## 操作 DOM
+
+当时水这篇的时候我还没有学到使用 js 操作 DOM,时隔一年以后,我才想起来这篇还没水完。同时一年后,我还在乘法口诀表(◎﹏◎)
+
+操作 DOM 并不是很复杂,打印乘法口诀表的主要方法也还是相同的。
+
+### 插入节点
+
+本次操作 DOM 最主要的一点还是循环添加 DOM 节点,通过`document.appendChild()`方法来添加生成的节点。HTML 结构也非常简单,外部一个`div`,内部通过`span`和`br`来插入内容。就类似于这样:
+
+```html
+
+ 1 ✖ 1 = 1
+
+ 2 ✖ 1 = 2
+
+```
+
+虽然这是个小测试,这里还是使用了文档片段( [`DocumentFragment`](https://developer.mozilla.org/en-US/docs/DOM/DocumentFragment))来插入节点。
+
+```js
+wrapper = document.querySelector('.wrapper');
+fragment = document.createDocumentFragment();
+
+for (let i = 1; i <= 9; i++) {
+ for (let o = 1; o <= i; o++) {
+ cont = fragment.appendChild(document.createElement('span'));
+ cont.textContent = `${i} ✖ ${o} = ${i * o}`;
+ }
+ fragment.appendChild(document.createElement('br'));
+}
+wrapper.appendChild(fragment);
+```
+
+思维也很简单,`appendChild()`方法会将插入的节点返回,返回后就可以直接使用`textContent`来插入生成的内容。同样的换行也是在外部的 for 循环内插入一个`
`标签。
+
+```js
+let wrapper, cont, fragment;
+
+window.onload = function () {
+ wrapper = document.querySelector('.wrapper');
+ fragment = document.createDocumentFragment();
+
+ function x99() {
+ for (let i = 1; i <= 9; i++) {
+ for (let o = 1; o <= i; o++) {
+ cont = fragment.appendChild(document.createElement('span'));
+ cont.textContent = `${i} ✖ ${o} = ${i * o}`;
+ }
+ fragment.appendChild(document.createElement('br'));
+ }
+ wrapper.appendChild(fragment);
+ }
+ x99();
+};
+```
+
+
diff --git a/data/posts/public-key-cryptgraphy.mdx b/data/posts/public-key-cryptgraphy.mdx
index 282ff28..95caf1a 100644
--- a/data/posts/public-key-cryptgraphy.mdx
+++ b/data/posts/public-key-cryptgraphy.mdx
@@ -7,6 +7,7 @@ tags: Linux
diff --git a/public/images/p/javascript-practice-multiplication-table/logo.webp b/public/images/p/javascript-practice-multiplication-table/logo.webp
new file mode 100644
index 0000000..f4af9f9
Binary files /dev/null and b/public/images/p/javascript-practice-multiplication-table/logo.webp differ
diff --git a/public/images/p/javascript-practice-multiplication-table/multiplication-table.webp b/public/images/p/javascript-practice-multiplication-table/multiplication-table.webp
new file mode 100644
index 0000000..1f0d214
Binary files /dev/null and b/public/images/p/javascript-practice-multiplication-table/multiplication-table.webp differ