Skip to content

确保数据隐私

Material for MkDocs 非常容易满足数据隐私法规的要求,因为它提供了原生的[cookie 同意]解决方案,可以在设置分析之前征得用户的明确同意。此外,外部资源可以自动下载以进行自托管

配置

默认值:

实验性

Material for MkDocs 提供了一个原生且可扩展的 cookie 同意表单,可以在向第三方发送请求之前征得用户的同意。在mkdocs.yml中添加以下内容:

extra:
  consent:
    title: Cookie同意
    description: >-
      我们使用cookie来识别您的重复访问和偏好,并衡量我们的文档的有效性以及用户是否找到他们正在搜索的内容。在您同意的情况下,您正在帮助我们改进我们的文档。
  1. 您可以在description中添加任意的 HTML 标签,例如链接到您的服务条款或站点的其他部分。

可用的属性如下:

title

默认值: · 必填 – 此属性设置 cookie 同意的标题,显示在表单顶部,并且必须设置为非空字符串。

description

默认值: · 必填 – 此属性设置 cookie 同意的描述,显示在标题下方,可以包含原始 HTML(例如链接到服务条款)。

cookies

默认值: – 此属性允许添加自定义的 cookie 或更改内置 cookie 的初始checked状态和名称。 目前,内置了以下 cookie:

  • Google Analyticsanalytics(默认启用)
  • GitHubgithub(默认启用)

每个 cookie 必须使用唯一标识符,该标识符用作cookies映射中的键,可以设置为字符串或定义namechecked状态的映射:

自定义 cookie 名称

extra:
  consent: null
  cookies:
    analytics: 自定义名称

自定义初始状态

extra:
  consent: null
  cookies:
    analytics: null
    name: Google Analytics
    checked: false

自定义 cookie

extra:
  consent: null
  cookies:
    analytics: Google Analytics
    custom: 自定义cookie
  1. 如果在cookies属性中定义了自定义 cookie,则必须显式添加回analytics cookie,否则将不会触发分析。

如果通过mkdocs.yml配置了 Google Analytics,则 cookie 同意将自动包括一个用于禁用它的设置。可以从 JavaScript 中使用[自定义 cookie]。

actions

默认值:[accept, manage] – 此属性定义显示哪些按钮以及其顺序,例如允许用户接受 cookie 和管理设置:

extra:
  consent: null
  actions:
    - accept
    - manage # (1)!
  1. 如果从actions属性中省略了manage设置按钮,则始终显示设置。

cookie 同意表单包括三种类型的按钮:

  • accept – 接受选定的 cookie 的按钮
  • reject – 拒绝所有 cookie 的按钮
  • manage – 管理设置的按钮

当用户首次访问您的站点时,将呈现一个 cookie 同意表单:

启用Cookie同意

为了符合 GDPR,用户必须随时能够更改他们的 cookie 设置。可以通过在mkdocs.yml中的版权声明中添加一个简单的链接来实现:

copyright: >
  版权所有 © 2016 - 2023 Martin Donath –
  <a href="#__consent">更改Cookie设置</a>

内置隐私插件

仅限赞助商 | 插件 | 实验性

内置的隐私插件会自动识别外部资源作为构建过程的一部分,并下载所有资源以进行非常简单的自托管。在mkdocs.yml中添加以下行:

plugins:
  - privacy

如果您需要能够使用和不使用Insiders构建文档,请参考内置插件部分,了解共享配置如何帮助实现此目的。

可用的配置选项如下:

enabled

默认值:true – 此选项指定在构建项目时插件是否启用。如果要加快本地构建速度,可以使用环境变量

plugins:
    - privacy:
        enabled: !ENV [CI, false]

concurrency

默认值:CPU 数量 – 此选项指定在下载外部资源时插件允许使用的 CPU 数量。使用更多的 CPU,插件可以在相同的时间内完成更多的工作,从而更快地完成工作。可以使用以下方式禁用并发处理:

plugins:
  - privacy:
      concurrency: 1

外部资源

外部资源的可用配置选项如下:

assets

默认值:true – 此选项指定插件是否应扫描 HTML 输出以检测和处理外部资源:

plugins:
  - privacy:
      assets: true
如果通过[自定义]删除了项目中的所有外部资源,仍然建议启用插件,因为插件将确保在意外添加的任何Markdown文件中没有隐藏的外部链接。

在[严格模式]下使用`assets`将使构建失败,当检测到外部资源时。

assets_fetch

默认值:true – 此选项指定插件是否应下载遇到的外部资源并将其与文档一起打包:

plugins:
  - privacy:
      assets_fetch: true

assets_fetch_dir

默认值:assets/external – 此选项指定下载的外部资源将存储在的位置。通常不需要更改此选项:

plugins:
  - privacy:
      assets_fetch_dir: assets/external
路径必须相对于[`docs_dir`][docs_dir]定义。

assets_include

默认值: – 此选项允许仅包括某些外部资源以供隐私插件处理,以便在构建过程中下载和打包它们:

plugins:
  - privacy:
      assets_include:
        - unsplash.com/*
!!! tip "在外部托管图像并自动优化"

    此选项使[内置隐私插件]成为一个很好的选择,当您希望在Git存储库之外的其他位置托管图像等资源,以保持它们的新鲜性和存储库的精简性。

    此外,从[:octicons-tag-24: insiders-4.30.0][Insiders]开始,内置隐私插件已完全重写,现在可以与[内置优化插件]完美配合使用,这意味着外部资源可以通过与文档的其余部分相同的优化流程。这意味着您可以在存储库之外存储和编辑未优化的文件,并让两个插件为您构建高度优化的站点。

    如果您想实现单独的流水线,例如对某些图像进行不同的优化或排除某些图像的下载,可以使用多个[内置隐私插件]实例。

assets_exclude

默认值: – 此选项允许排除某些外部资源的处理,以便在构建过程中不下载和打包它们:

plugins:
  - privacy:
      assets_exclude:
        - cdn.jsdelivr.net/npm/mathjax@3/*
        - giscus.app/*
1.  [MathJax]通过相对URL加载用于排版数学内容的Web字体,因此无法由隐私插件自动打包。[MathJax可以自托管]。

    我们建议使用作为[评论系统]的Giscus使用称为代码分割的技术仅加载必要的代码,该技术通过相对URL实现。[Giscus也可以自托管]。

如果外部资源包含动态创建或相对URL,无法由隐私插件解析,因此可能需要排除特定的外部资源。

为什么 Material for MkDocs 不能默认打包所有资源?

Material for MkDocs不能打包所有自身资源的主要原因是与Google Fonts的集成,后者提供了一千多种不同的字体,可用于呈现您的文档。大多数字体包括多个字重,并分为不同的字符集,以保持下载大小较小,因此浏览器只下载所需的内容。对于我们的默认常规字体Roboto来说,总共有42个*.woff2文件

如果Material for MkDocs打包所有字体文件,下载大小将达到几百兆字节,导致自动化构建变慢。此外,作者可能会添加外部资源,如第三方脚本或样式表,需要记住将其定义为其他本地资源。

这也是内置隐私插件存在的原因——它自动下载所有外部资源,以确保符合GDPR,但存在一些技术限制

外部链接

仅限赞助商 | 实验性

外部链接的可用配置选项如下:

links

默认值:true – 此选项指定插件是否应解析和处理外部链接。如果要加快本地构建速度,可以使用环境变量

plugins:
    - privacy:
        links: !ENV [CI, false]

links_attr_map

默认值: – 此选项指定应添加到外部链接的自定义属性,例如target="_blank",以便所有外部链接在新窗口中打开:

plugins:
  - privacy:
      links_attr_map: null
      target: _blank

links_noopener

默认值:true – 此选项指定插件是否应自动将rel="noopener"添加到所有具有target="_blank"的链接,以提高安全性:

plugins:
  - privacy:
    links_noopener: true

工作原理

内置隐私插件会扫描生成的 HTML,查找指向外部资源的链接,包括外部脚本、样式表、图像和 Web 字体,并下载它们以与您的文档站点一起打包。每个指向外部资源的 URL,无论是模板还是 Markdown 文件的一部分,都会被替换为本地副本的 URL。以下是一个示例:

<script src="https://example.com/script.js"></script>

外部脚本将被下载,并将链接替换为:

<script src="assets/external/example.com/script.js"></script>

样式表会被扫描以查找外部的url(...)引用,例如图像和 Web 字体,然后也会被下载并与您的文档站点一起打包。这意味着可以像往常一样在mkdocs.yml中配置Google Fonts,因为内置隐私插件会自动下载和打包所有相关资源。

作为第三个措施,构建过程中会自动删除用于 DNS 预取的preconnect提示,这可能会将访问者的 IP 地址泄露给第三方。

展开以查看示例

对于官方文档,内置隐私插件会下载以下资源:

.
└─ assets/external/
   ├─ unpkg.com/tablesort@5.3.0/dist/tablesort.min.js
   ├─ fonts.googleapis.com/css
   ├─ fonts.gstatic.com/s/
     ├─ roboto/v29/
       ├─ KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2
       ├─ KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2
       ├─ KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2
       ├─ KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2
       ├─ KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2
       ├─ KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2
       ├─ KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2
       ├─ KFOkCnqEu92Fr1Mu51xIIzI.woff2
       ├─ KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2
       ├─ KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2
       ├─ KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2
       ├─ KFOlCnqEu92Fr1MmSU5fBBc4.woff2
       ├─ KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2
       ├─ KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2
       ├─ KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2
       ├─ KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2
       ├─ KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2
       ├─ KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2
       ├─ KFOlCnqEu92Fr1MmWUlfBBc4.woff2
       ├─ KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2
       ├─ KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2
       ├─ KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2
       ├─ KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2
       ├─ KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2
       ├─ KFOmCnqEu92Fr1Mu4WxKOzY.woff2
       ├─ KFOmCnqEu92Fr1Mu4mxK.woff2
       ├─ KFOmCnqEu92Fr1Mu5mxKOzY.woff2
       ├─ KFOmCnqEu92Fr1Mu72xKOzY.woff2
       ├─ KFOmCnqEu92Fr1Mu7GxKOzY.woff2
       ├─ KFOmCnqEu92Fr1Mu7WxKOzY.woff2
       └─ KFOmCnqEu92Fr1Mu7mxKOzY.woff2
     └─ robotomono/v13/
        ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSV0mf0h.woff2
        ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSZ0mf0h.woff2
        ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSd0mf0h.woff2
        ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSh0mQ.woff2
        ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSt0mf0h.woff2
        ├─ L0xTDF4xlVMF-BfR8bXMIhJHg45mwgGEFl0_3vrtSM1J-gEPT5Ese6hmHSx0mf0h.woff2
        ├─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtElOUlYIw.woff2
        ├─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEleUlYIw.woff2
        ├─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEluUlYIw.woff2
        ├─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEm-Ul.woff2
        ├─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEmOUlYIw.woff2
        └─ L0xdDF4xlVMF-BfR8bXMIjhOsXG-q2oeuFoqFrlnAIe2Imhk1T8rbociImtEn-UlYIw.woff2
   └─ polyfill.io/v3/polyfill.min.js

缓存推荐

所有下载的文件都将写入.cache目录,这将显著减少后续构建的持续时间,因为只需要进行替换操作。您可能希望:

  1. 在项目中忽略.cache目录,将其添加到.gitignore中。
  2. 在发布时构建站点时,使用构建缓存在构建之间保存.cache目录。参考发布指南的示例,添加以下行:
    name: ci
      on:
        push:
          branches:
            - master
            - main
    jobs:
      deploy:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - uses: actions/setup-python@v4
            with:
              python-version: 3.x
          - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
          - uses: actions/cache@v3
            with:
              key: mkdocs-material-${{ env.cache_id }}
              path: .cache
              restore-keys: |
                mkdocs-material-
          - run: pip install mkdocs-material
          - run: mkdocs gh-deploy --force

限制

请注意,脚本的一部分动态创建的 URL 将无法检测到,因此无法自动下载。内置隐私插件不执行脚本,它只能检测到完全合格的 URL 以进行下载和替换。

简而言之,请不要这样做:

const cdn = "https://polyfill.io";
const url = `${cdn}/v3/polyfill.min.js`;

而是始终使用完全合格的 URL:

const url = "https://polyfill.io/v3/polyfill.min.js";

自定义

如果您自定义了[cookie 同意]并添加了一个custom cookie,用户将被提示接受或拒绝您的自定义 cookie。一旦用户接受或拒绝了 cookie 同意,或者更改了设置,页面将重新加载1。使用[附加的 JavaScript]来查询结果:

docs/javascripts/consent.js

var consent = __md_get("__consent")
if (consent && consent.custom) {
  /* 用户接受了cookie */
} else {
  /* 用户拒绝了cookie */
}

mkdocs.yml

extra_javascript:
    - javascripts/consent.js

  1. 我们重新加载页面是为了使与自定义 cookie 的互操作更简单。如果 Material for MkDocs 采用了基于回调的方法,作者需要确保正确更新所有使用 cookie 的脚本。此外,cookie 同意只在最初回答一次,这就是为什么我们认为这是 DX 和 UX 之间的一个很好的权衡。