# 免登录一键复制 (codebox-浏览器插件)

## 背景
前段时间有小伙伴提了个烦恼，说是 `CSDN`和`知乎`的博客在未登录状态下无法复制代码，必须登录才能复制，不像博客园、掘金能直接复制，很不方便。为了解决一个问题我决定做一个浏览器插件——`codebox`。

对于那些对此插件感兴趣的用户，可以轻松地通过`谷歌、火狐、Edge`扩展商店进行`下载`和`安装`。使用这个插件，他们将能够更加高效地获取所需的代码，无论是学习还是工作中。

在此基础上，小编根据自身需要，另外加了几个功能，还支持解除关注博主即可阅读全文的提示、去除了登陆弹窗、自动展开代码块。并且还只支持了`知乎/脚本之家/博客园/博客园/51CTO博客/php中文网`等网站。

这里先介绍下如何使用和基本原理。

## 安装

### 安装方式一：插件商店(推荐)

直接下载安装：
1. 进入应用商店
    - [Chrome网上应用商店](https://chrome.google.com/webstore/category/extensions?hl=zh-CN)
    - [Firefox网上应用商店](https://addons.mozilla.org/zh-CN/firefox/)
    - [Edge网上应用商店](https://microsoftedge.microsoft.com/addons/Microsoft-Edge-Extensions-Home?hl=zh-CN)
2. 搜索：`codebox`

![img](https://raw.githubusercontent.com/027xiguapi/code-box/main/public/img.png)


### 安装方式二：直接安装

1. 安装地址：
    - [前往 Chrome 扩展商店](https://chrome.google.com/webstore/detail/acnnhjllgegbndgknlliobjlekgilbdf)
    - [前往 火狐 扩展商店](https://addons.mozilla.org/zh-CN/firefox/addon/code-box/)
    - [前往 Edge 扩展商店](https://microsoftedge.microsoft.com/addons/detail/code-box/cfpdbfmncaampihkmejogihjkenkonbn)

### 安装方式三：源码安装

1. clone源码
   ```sh
   git clone https://github.com/027xiguapi/code-box.git
   ```
2. 安装和打包
   ```sh
   pnpm install
   pnpm dev
   pnpm build
   ```
3. 谷歌浏览器，从右上角菜单->更多工具->扩展程序可以进入插件管理页面，也可以直接在地址栏输入 chrome://extensions 访问
4. 勾选开发者模式，即可以文件夹的形式直接加载插件

## 功能

![img-1](https://raw.githubusercontent.com/027xiguapi/code-box/main/public/img_1.jpg)

### 自定义

1. 插入自定义样式(css代码)

### CSDN

1. 打开任意一个`CSDN`博客即可开始复制代码
2. 未登录`CSDN`状态下，支持选中代码
3. 未登录`CSDN`状态下，代码右上角按钮一键复制
4. 未登录`CSDN`状态下，不会再出现强制登录弹窗
5. 未关注博主状态下，不再提示关注博主即可阅读全文，且完整展示文章
6. 自动展开代码块
7. 移动端屏蔽跳转APP

### 知乎

1. 一键复制代码
2. 未登录`知乎`状态下，不再提示展开阅读全文，且完整展示文章
3. 未登录`知乎`状态下，不会再出现强制登录弹窗

### 简书

1. 移动端，一键复制代码
2. 不再提示展开阅读全文，且完整展示文章
3. 不会再出现强制登录弹窗

### 脚本之家

1. 打开任意一个`脚本之家`博客即可开始复制代码
2. 未登录`脚本之家`状态下，支持选中代码
3. 屏蔽广告
4. 移动端未登录`脚本之家`状态下，代码右上角按钮一键复制

### 博客园

1. 一键复制代码

### 51CTO博客

1. 未登录`51CTO博客`状态下，支持选中代码
2. 未登录`51CTO博客`状态下，代码右上角按钮一键复制
3. 未登录`51CTO博客`状态下，不会再出现强制登录弹窗
4. 移动端未登录`51CTO博客`状态下，代码右上角按钮一键复制

### php中文网

1. 未登录`php中文网`状态下，支持选中代码
2. 未登录`php中文网`状态下，代码右上角按钮一键复制
3. 未登录`php中文网`状态下，不会再出现强制登录弹窗
4. 未登录`php中文网`状态下，移动端代码右上角按钮一键复制

![img](https://raw.githubusercontent.com/027xiguapi/code-box/main/public/4.jpg)
![img](https://raw.githubusercontent.com/027xiguapi/code-box/main/public/5.jpg)
![img](https://raw.githubusercontent.com/027xiguapi/code-box/main/public/6.jpg)
![img](https://raw.githubusercontent.com/027xiguapi/code-box/main/public/7.jpg)

## 原理

这里简要介绍下实现原理。

### 复制功能

![img](https://raw.githubusercontent.com/027xiguapi/code-box/main/public/1.jpg)

首先不能框选代码的问题比较好解决，因为我发现是 `CSS` 控制的，我们把代码`pre`和`code`标签的`user-select`样式修改掉。

```css
#content_views pre,
#content_views pre code {
    -webkit-touch-callout: auto !important;
    -webkit-user-select: auto !important;
    -khtml-user-select: auto !important;
    -moz-user-select: auto !important;
    -ms-user-select: auto !important;
    user-select: auto !important;
}
```

然后处理代码块右上角的复制按钮，在未登陆状态下点击这个复制按钮后会触发登陆弹窗，所以我们从控制 js 入手。

1. 找到所有的复制按钮
2. 将按钮上的点击事件移除掉，克隆按钮再替回去
3. 重新添加点击事件

下面贴一段核心代码

```js
buttons.forEach((btn) => {
    // 更改标题
    btn.dataset.title = "复制";

    // 移除点击事件
    btn.setAttribute("onclick", "");

    // 克隆按钮
    elClone = btn.cloneNode(true);

    // 替回按钮
    btn.parentNode.replaceChild(elClone, btn);

    // 重新添加点击事件
    elClone.addEventListener("click", (e) => {
        // 实现复制
        const parentPreBlock = e.target.closest("pre");
        const codeBlock = $$("code", parentPreBlock);
        copy(codeBlock.innerText);

        e.target.dataset.title = "复制成功";
        setTimeout(() => {
            e.target.dataset.title = "复制";
        }, 1000);
        e.stopPropagation();
        e.preventDefault();
    });
});
```
### 去除登陆弹窗
![img](https://raw.githubusercontent.com/027xiguapi/code-box/main/public/3.jpg)
直接将登陆弹窗通过 CSS 隐藏

```css
.passport-login-container {
    display: none !important;
}
```

### 去除阅读更多提示
![img](https://raw.githubusercontent.com/027xiguapi/code-box/main/public/2.png)
1. 首先将关注博主即可阅读全文所在的容器去除掉，隐藏或者降低层级都行，我这里用的是降低层级。因为还有个 VIP 文章的拦截容器和这个阅读全文类似，这里需要排除下，所以这里用 js 去添加 CSS 代码

```js
let readMore = document.querySelector(".btn-readmore");
let style = `
  .hide-article-box{
    z-index: -1 !important;
  }
  `;
if (readMore) {
    addCSS(style);
}
```
2. 再设置 `CSS` 将文章的高度放开

```css
/* 关注博主才能查看文章，开放文章 */
#article_content {
    height: auto !important;
}
```
### 自动展开代码块
1. 首先将查看更多的容器去除掉
2. 再设置 `CSS` 将文章的高度放开
```js
    const pres = Array.from(
      document.querySelectorAll<HTMLElement>(
        "main div.blog-content-box pre.set-code-hide"
      )
    )
    const presBox = Array.from(
      document.querySelectorAll<HTMLElement>(".hide-preCode-box")
    )

    const readallBox = document.querySelector<HTMLElement>(".readall_box")

    pres.forEach((pre) => {
      pre.style.height = "unset"
      pre.style.maxHeight = "unset"
    })
    presBox.forEach((box) => {
      box.style.display = "none"
    })

    if (readallBox) {
      const articleContent =
        document.querySelector<HTMLElement>(".article_content")

      articleContent.style.height = "unset"
      readallBox.style.display = "none"
    }
```

## 总结

>因为这款插件的源代码是开源的，完整代码大家可以直接看我的 Github 仓库：
> 
> https://github.com/027xiguapi/code-box
>

本浏览器插件可以用于`CSDN/知乎/脚本之家/博客园/博客园/51CTO博客/php中文网`等网站，实现无需登录一键复制代码;支持选中代码;或者代码右上角按钮的一键复制;解除关注博主即可阅读全文提示;去除登录弹窗;去除跳转APP弹窗。功能上已经可以满足要求。可能还有很多不足的地方，大家发现了问题或者有其他需求的话，欢迎向我反馈。


