<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>ciics</title>
  
  <subtitle>光があなたと共にあらんことを。 | 光よ！</subtitle>
  <link href="https://c2ics.com/atom.xml" rel="self"/>
  
  <link href="https://c2ics.com/"/>
  <updated>2025-03-14T11:42:57.000Z</updated>
  <id>https://c2ics.com/</id>
  
  <author>
    <name>C2iCs</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Windows 24H2 Chrome 滚动时部分区块卡顿（画面撕裂）</title>
    <link href="https://c2ics.com/posts/d52a3296dc72/"/>
    <id>https://c2ics.com/posts/d52a3296dc72/</id>
    <published>2025-03-14T11:42:57.000Z</published>
    <updated>2025-03-14T11:42:57.000Z</updated>
    
    <content type="html"><![CDATA[<p>更新至 Windows 24H2 后，以 Chrome 为主的应用<strong>画面撕裂</strong>，具体表现为滚动页面时，一部分区块静止不动，而其余部分正常滚动，同时伴随着不同程度的卡顿。我是 i7-12700 + RTX 3060 的组合，但有很多A卡用户也出现过问题，推测影响范围蛮大的。</p><p>简单查询后发现是 <strong>Multi-Plane Overlay (MPO)</strong> 的问题，可能是由于微软重写 GDI，导致意想不到的问题发生。</p><p>英伟达客户服务里给了关闭 MPO 的注册表，分享一下：</p><ul><li>禁用MPO <a href="https://nvidia.custhelp.com/ci/fattach/get/824301808/0/filename/mpo_disable.reg">mpo_disable.reg</a><em>(252 bytes)</em></li><li>恢复MPO <a href="https://nvidia.custhelp.com/ci/fattach/get/824301809/0/filename/mpo_restore.reg">mpo_restore.reg</a><em>(226 bytes)</em></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;更新至 Windows 24H2 后，以 Chrome 为主的应用&lt;strong&gt;画面撕裂&lt;/strong&gt;，具体表现为滚动页面时，一部分区块静止不动，而其余部分正常滚动，同时伴随着不同程度的卡顿。我是 i7-12700 + RTX 3060 的组合，但有很多A卡用户也出现</summary>
      
    
    
    
    <category term="Tech" scheme="https://c2ics.com/categories/Tech/"/>
    
    
    <category term="Windows" scheme="https://c2ics.com/tags/Windows/"/>
    
  </entry>
  
  <entry>
    <title>VSCode 插件：侧边栏 Webview 容器</title>
    <link href="https://c2ics.com/posts/b6a70c1ab4c7/"/>
    <id>https://c2ics.com/posts/b6a70c1ab4c7/</id>
    <published>2024-04-17T14:41:23.000Z</published>
    <updated>2024-04-17T14:41:23.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="什么是-VSCode-Webview"><a href="#什么是-VSCode-Webview" class="headerlink" title="什么是 VSCode Webview"></a>什么是 VSCode Webview</h2><p>在VSCode中，仅靠原生插件API，无法做到自定义交互页面，这时需要 Webview 来嵌入自定义 Web 应用程序。使用Webview可以构建复杂的、支持各种操作的用户界面。Webview就像一个 iframe 一样，无法与外界（VSCode主界面）<strong>直接</strong>交互，需要使用<code>acquireVsCodeApi</code>特殊方法，这不是本文讨论的内容，不再深入。</p><p>显示一个 Webview 界面有两种方法，这篇文章主要说明第二个。</p><ol><li>直接创建一个 Webview 标签页</li><li><strong>将 Webview 添加进视图容器</strong></li></ol><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2024/vscode-extension-webview/sidewebview.png" data-fancybox="true"/></div></div><div class="tag-plugin colorful note" color="yellow"><div class="body"><p>在使用Webview前，你需要考虑几个问题：</p><ul><li>你的webview是否会带来足够的用户价值，以作为<strong>提高资源占用</strong>的交换？</li><li>你的webview是否设计合理、美观？</li><li>这个功能必须放在VSCode中吗，能否作为单独的网页？</li></ul></div></div><h2 id="构建-Webview-Provider"><a href="#构建-Webview-Provider" class="headerlink" title="构建 Webview Provider"></a>构建 Webview Provider</h2><p>顾名思义，Webview提供者，是提供webview视图的类，为谁提供？当然是视图容器（viewcontainer），<strong>视图放在视图容器内</strong>。</p><p>这个类继承自接口<code>WebviewViewProvider</code>，该接口只有一个定义<code>resolveWebviewView</code>。在这个类中，还额外保存了extensionUri，以供后续定位文件。</p><h3 id="主逻辑"><a href="#主逻辑" class="headerlink" title="主逻辑"></a>主逻辑</h3><figure class="highlight typescript"><figcaption><span>"src/panels/someWebviewProvider.ts"</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">CancellationToken</span>, <span class="title class_">WebviewView</span>, <span class="title class_">WebviewViewProvider</span>, <span class="title class_">WebviewViewResolveContext</span>, <span class="title class_">Webview</span>, <span class="title class_">Uri</span> &#125; <span class="keyword">from</span> <span class="string">&quot;vscode&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">class</span> <span class="title class_">SomeWebviewProvider</span> <span class="keyword">implements</span> <span class="title class_">WebviewViewProvider</span> &#123;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">public</span> <span class="title function_">constructor</span>(<span class="params"></span></span><br><span class="line"><span class="params">    <span class="keyword">private</span> <span class="keyword">readonly</span> <span class="attr">_extensionUri</span>: <span class="title class_">Uri</span>,</span></span><br><span class="line"><span class="params">  </span>) &#123; &#125;</span><br><span class="line"></span><br><span class="line">  <span class="title function_">resolveWebviewView</span>(<span class="params"></span></span><br><span class="line"><span class="params">    <span class="attr">webviewView</span>: <span class="title class_">WebviewView</span>,</span></span><br><span class="line"><span class="params">    <span class="attr">context</span>: <span class="title class_">WebviewViewResolveContext</span>,</span></span><br><span class="line"><span class="params">    <span class="attr">token</span>: <span class="title class_">CancellationToken</span></span></span><br><span class="line"><span class="params">  </span>) &#123;</span><br><span class="line">      <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">&quot;Not Implemented&quot;</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="Webview-的独特标识符"><a href="#Webview-的独特标识符" class="headerlink" title="Webview 的独特标识符"></a>Webview 的独特标识符</h3><p>另外，建议添加一个字段来表明此 Webview 的独特类型。这个类型在最后一步 <strong>添加插件贡献</strong> 处会用到。</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">readonly</span> viewType = <span class="string">&#x27;example-extension.webview.test&#x27;</span>; <span class="comment">// 随意命名，在最后一步要用到</span></span><br></pre></td></tr></table></figure><h3 id="resolveWebviewView"><a href="#resolveWebviewView" class="headerlink" title="resolveWebviewView"></a>resolveWebviewView</h3><p>这个方法的作用是，在视图（View）可见前解析Webview内容，这个<code>webviewView</code>参数就是视图。</p><p>至于解析，<strong>就是放进去HTML啦</strong>，直接为<code>webviewView.webview.html</code>赋值！</p><p>在这一段代码中，还可以</p><ul><li>使用<code>onDidReceiveMessage</code>和vscode通信</li><li>更改webview的设置</li></ul><figure class="highlight typescript"><figcaption><span>"src/panels/someWebviewProvider.ts"</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">webviewView.<span class="property">webview</span>.<span class="property">options</span> = &#123;</span><br><span class="line">  <span class="comment">// Allow scripts in the webview</span></span><br><span class="line">  <span class="attr">enableScripts</span>: <span class="literal">true</span>,</span><br><span class="line"></span><br><span class="line">  <span class="attr">localResourceRoots</span>: [</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">_extensionUri</span>,</span><br><span class="line">  ]</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">webviewView.<span class="property">webview</span>.<span class="property">html</span> = <span class="variable language_">this</span>.<span class="title function_">_getHtmlForWebview</span>(webviewView.<span class="property">webview</span>);</span><br></pre></td></tr></table></figure><h3 id="静态资源"><a href="#静态资源" class="headerlink" title="静态资源"></a>静态资源</h3><p>出于安全考虑，<strong>Webview不能直接访问本地资源，想要加载静态资源，必须通过特殊的<code>vscode-resource:</code>协议</strong>，网页里面所有的静态资源都要转换成这种格式，否则无法被正常加载。我推荐封装一个工具函数：</p><figure class="highlight typescript"><figcaption><span>"src/utilities/getUri.ts"</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Uri</span>, <span class="title class_">Webview</span> &#125; <span class="keyword">from</span> <span class="string">&quot;vscode&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">getUri</span>(<span class="params"><span class="attr">webview</span>: <span class="title class_">Webview</span>, <span class="attr">extensionUri</span>: <span class="title class_">Uri</span>, <span class="attr">pathList</span>: <span class="built_in">string</span>[]</span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> webview.<span class="title function_">asWebviewUri</span>(<span class="title class_">Uri</span>.<span class="title function_">joinPath</span>(extensionUri, ...pathList));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>我们使用 <code>getUri(webview, this._extensionUri, [&quot;out&quot;, &quot;webview.js&quot;])</code> 获取到了<strong>项目目录</strong>中的<code>/out/webview.js</code>，这是webview的具体逻辑。这 js 通常由 ts 编译而来，以 esbuild 为例:</p><figure class="highlight javascript"><figcaption><span>"esbuild.js"</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> webviewConfig = &#123;</span><br><span class="line">  <span class="attr">bundle</span>: <span class="literal">true</span>,</span><br><span class="line">  <span class="attr">minify</span>: process.<span class="property">env</span>.<span class="property">NODE_ENV</span> === <span class="string">&quot;production&quot;</span>,</span><br><span class="line">  <span class="attr">sourcemap</span>: process.<span class="property">env</span>.<span class="property">NODE_ENV</span> !== <span class="string">&quot;production&quot;</span>,</span><br><span class="line">  <span class="attr">target</span>: <span class="string">&quot;es2020&quot;</span>,</span><br><span class="line">  <span class="attr">format</span>: <span class="string">&quot;esm&quot;</span>,</span><br><span class="line">  <span class="attr">entryPoints</span>: [<span class="string">&quot;./src/webview/main.ts&quot;</span>],  <span class="comment">// 源代码文件位置</span></span><br><span class="line">  <span class="attr">outfile</span>: <span class="string">&quot;./out/webview.js&quot;</span>,  <span class="comment">// 输出位置</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><h3 id="getHtmlForWebview"><a href="#getHtmlForWebview" class="headerlink" title="_getHtmlForWebview"></a>_getHtmlForWebview</h3><p>解析资源路径，然后返回字符串HTML。<code>getUri</code>和<code>getNonce</code>为工具函数，下文有提及。</p><figure class="highlight typescript"><figcaption><span>"src/panels/someWebviewProvider.ts"</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="title function_">_getHtmlForWebview</span>(<span class="params"><span class="attr">webview</span>: <span class="title class_">Webview</span></span>) &#123;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> webviewUri = <span class="title function_">getUri</span>(webview, <span class="variable language_">this</span>.<span class="property">_extensionUri</span>, [<span class="string">&quot;out&quot;</span>, <span class="string">&quot;webview.js&quot;</span>]);</span><br><span class="line">  <span class="keyword">const</span> cssUri = <span class="title function_">getUri</span>(webview, <span class="variable language_">this</span>.<span class="property">_extensionUri</span>, [<span class="string">&quot;out&quot;</span>, <span class="string">&quot;style.css&quot;</span>]);</span><br><span class="line">  <span class="keyword">const</span> nonce = <span class="title function_">getNonce</span>();</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="comment">/*html*/</span> <span class="string">`</span></span><br><span class="line"><span class="string">  &lt;!DOCTYPE html&gt;</span></span><br><span class="line"><span class="string">  &lt;html lang=&quot;en&quot;&gt;</span></span><br><span class="line"><span class="string">    &lt;head&gt;</span></span><br><span class="line"><span class="string">      &lt;meta charset=&quot;UTF-8&quot;&gt;</span></span><br><span class="line"><span class="string">      &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;          </span></span><br><span class="line"><span class="string">      &lt;title&gt;Hello World!&lt;/title&gt;</span></span><br><span class="line"><span class="string">      &lt;link rel=&quot;stylesheet&quot; href=&quot;<span class="subst">$&#123;cssUri&#125;</span>&quot;&gt;</span></span><br><span class="line"><span class="string">    &lt;/head&gt;</span></span><br><span class="line"><span class="string">    &lt;body&gt;</span></span><br><span class="line"><span class="string">    &lt;script type=&quot;module&quot; nonce=&quot;<span class="subst">$&#123;nonce&#125;</span>&quot; src=&quot;<span class="subst">$&#123;webviewUri&#125;</span>&quot;&gt;&lt;/script&gt;</span></span><br><span class="line"><span class="string">    &lt;/body&gt;</span></span><br><span class="line"><span class="string">  &lt;/html&gt;</span></span><br><span class="line"><span class="string">`</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="一些无关痛痒的工具函数，上文用到"><a href="#一些无关痛痒的工具函数，上文用到" class="headerlink" title="一些无关痛痒的工具函数，上文用到"></a>一些无关痛痒的工具函数，上文用到</h3><figure class="highlight typescript"><figcaption><span>"src/utilities/getNonce.ts"</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">getNonce</span>(<span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">let</span> text = <span class="string">&quot;&quot;</span>;</span><br><span class="line">  <span class="keyword">const</span> possible = <span class="string">&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789&quot;</span>;</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="number">32</span>; i++) &#123;</span><br><span class="line">    text += possible.<span class="title function_">charAt</span>(<span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * possible.<span class="property">length</span>));</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> text;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="注册"><a href="#注册" class="headerlink" title="注册"></a>注册</h2><p>在插件的激活方法中注册 Provider：</p><figure class="highlight typescript"><figcaption><span>"src/extension.js"</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">activate</span>(<span class="params"><span class="attr">context</span>: <span class="title class_">ExtensionContext</span></span>) &#123;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">const</span> webview = <span class="variable language_">window</span>.<span class="title function_">registerWebviewViewProvider</span>(</span><br><span class="line">    <span class="title class_">SomeWebviewProvider</span>.<span class="property">viewType</span>,</span><br><span class="line">    <span class="keyword">new</span> <span class="title class_">SomeWebviewProvider</span>(context.<span class="property">extensionUri</span>)</span><br><span class="line">  );</span><br><span class="line"></span><br><span class="line">  context.<span class="property">subscriptions</span>.<span class="title function_">push</span>(webview);</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="定义-Contributes-插件贡献"><a href="#定义-Contributes-插件贡献" class="headerlink" title="定义 Contributes 插件贡献"></a>定义 Contributes 插件贡献</h2><p>与其翻译成插件贡献，不如说是插件的功能，注册了哪些命令啊，提供了什么视图……</p><p>在<code>pakage.json</code>中指定插件的“贡献”：</p><ul><li><code>viewsContainers</code> 视图容器，可以被放置在侧边栏，就像“资源管理器”、“搜索”和“插件”一样。</li><li><code>views</code> 视图，为上面定义的视图容器，添加视图，就像“资源管理器”中的“大纲”、“时间线”等小栏目。</li></ul><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2024/vscode-extension-webview/viewcontainers.png" data-fancybox="true" style="width:400px;"/></div></div><figure class="highlight json"><figcaption><span>"package.json"</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">&quot;contributes&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">    <span class="attr">&quot;viewsContainers&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;activitybar&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span></span><br><span class="line">          <span class="attr">&quot;id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;example-extension-container&quot;</span><span class="punctuation">,</span>   <span class="comment">// 容器的id，下面要在这个容器内添加 webview 视图</span></span><br><span class="line">          <span class="attr">&quot;title&quot;</span><span class="punctuation">:</span> <span class="string">&quot;Example&quot;</span><span class="punctuation">,</span></span><br><span class="line">          <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;./assets/extension-icon.png&quot;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">]</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="attr">&quot;views&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;example-extension-container&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">        <span class="punctuation">&#123;</span></span><br><span class="line">          <span class="attr">&quot;type&quot;</span><span class="punctuation">:</span> <span class="string">&quot;webview&quot;</span><span class="punctuation">,</span></span><br><span class="line">          <span class="attr">&quot;id&quot;</span><span class="punctuation">:</span> <span class="string">&quot;example-extension.webview.test&quot;</span><span class="punctuation">,</span>  <span class="comment">// 刚刚定义的独特标识符</span></span><br><span class="line">          <span class="attr">&quot;name&quot;</span><span class="punctuation">:</span> <span class="string">&quot;View 1&quot;</span><span class="punctuation">,</span></span><br><span class="line">          <span class="attr">&quot;icon&quot;</span><span class="punctuation">:</span> <span class="string">&quot;./assets/extension-icon.png&quot;</span></span><br><span class="line">        <span class="punctuation">&#125;</span></span><br><span class="line">      <span class="punctuation">]</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
    <summary type="html">&lt;h2 id=&quot;什么是-VSCode-Webview&quot;&gt;&lt;a href=&quot;#什么是-VSCode-Webview&quot; class=&quot;headerlink&quot; title=&quot;什么是 VSCode Webview&quot;&gt;&lt;/a&gt;什么是 VSCode Webview&lt;/h2&gt;&lt;p&gt;在VSCod</summary>
      
    
    
    
    <category term="Tech" scheme="https://c2ics.com/categories/Tech/"/>
    
    
    <category term="Typescript" scheme="https://c2ics.com/tags/Typescript/"/>
    
    <category term="VSCode" scheme="https://c2ics.com/tags/VSCode/"/>
    
  </entry>
  
  <entry>
    <title>What happened to apex configs?</title>
    <link href="https://c2ics.com/posts/6db83d43a103/"/>
    <id>https://c2ics.com/posts/6db83d43a103/</id>
    <published>2024-02-03T02:28:54.000Z</published>
    <updated>2024-02-03T02:28:54.000Z</updated>
    
    <content type="html"><![CDATA[<p><em>Respawn Inc</em> banned “configs” and said it is cheating, was that true? Yes, but partially: Config itself does not entail cheating, but <strong>Config Chaining</strong> does.</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2024/apex-chaining-cfg/apex_config_banned.jpg" data-fancybox="true" style="width:400px;"/></div></div><ul><li><a href="https://twitter.com/Respawn/status/1752851828130341315">https://twitter.com/Respawn/status/1752851828130341315</a></li><li><a href="https://twitter.com/Respawn/status/1753121964456321302">https://twitter.com/Respawn/status/1753121964456321302</a></li></ul><h2 id="Config-chaining"><a href="#Config-chaining" class="headerlink" title="Config chaining"></a>Config chaining</h2><p>Config chaining is a way to process complex&#x2F;difficult movements through a single key ( usually the mouse scroll ). It functions through the Source Engine’s configuration system, <strong>binding multiple commands to a solitary key</strong> The syntax is descripted below.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bind_US_standard &lt;key&gt; &lt;command&gt;</span><br></pre></td></tr></table></figure><p>You can execute another cfg file by commanding <code>exec &lt;filename&gt;</code>, which is allowed in binding commands.</p><p>Take <em>superglide</em> as an example. To trigger a superglide, you have to JUMP and then CROUCH at correct timing.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">bind_US_standard &quot;CAPSLOCK&quot; &quot;+jump; exec sg_phase_1.cfg&quot;</span><br><span class="line"></span><br><span class="line"># sg_phase_1.cfg</span><br><span class="line">bind_US_standard &quot;mWhellDown&quot; &quot;+jump; fps_max 30; exec sg_phase_2.cfg&quot;</span><br><span class="line"></span><br><span class="line"># sg_phase_2.cfg</span><br><span class="line">bind_US_standard &quot;mWhellDown&quot; &quot;+toggle_duck; fps_max 0; exec recover.cfg&quot;</span><br><span class="line"></span><br><span class="line"># recover.cfg</span><br><span class="line">bind_US_standard &quot;mWhellDown&quot; &quot;+jump;&quot;</span><br></pre></td></tr></table></figure><p>This set of configs do all the things. When you tapped CAPSLOCK, it will change wheel down actions. Scroll to jump &amp; lock fps, scroll again to duck and unlock fps, scroll last to set wheel down to jump. By using this set of configs, you can simply scrolling down and do a superglide.</p><pre class="mermaid">graph TD  a([CAPSLOCK Tapped]) -- Execute sg_1.cfg --> c  c[Bind wheel down to JUMP, lock fps to 30] --> d([Scroll once]) --> e[Jump] -- Execute sg_2.cfg --> f[Bind wheel down to CROUCH, recover fps]  f --> g([Scroll once]) --> h[Crouch] -- Execute recover.cfg --> i[Bind wheel down to normal jump] --> a</pre><p>Currently they are malfunctioned. To fix this, you can divide these actions into multiple bindings and invoke them using Logi Macros.</p><h2 id="Unaffected-Configs"><a href="#Unaffected-Configs" class="headerlink" title="Unaffected Configs"></a>Unaffected Configs</h2><p>All the exec and configs out gameplay time is allowed, such as static bindings of simple tap-strafe( bind scroll to jump and move foward ) and sneak( a kind of walk config used by auto-sprint players ), because they do not includes dynamic binding modification.</p><!-- flag of hidden posts -->]]></content>
    
    
    <summary type="html">Configs are not banned, but config chaining is banned.</summary>
    
    
    
    <category term="游戏" scheme="https://c2ics.com/categories/%E6%B8%B8%E6%88%8F/"/>
    
    
    <category term="Apex" scheme="https://c2ics.com/tags/Apex/"/>
    
  </entry>
  
  <entry>
    <title>Apex泄露的更新计划汇总</title>
    <link href="https://c2ics.com/posts/6cbfe662c2a8/"/>
    <id>https://c2ics.com/posts/6cbfe662c2a8/</id>
    <published>2024-01-21T13:55:59.000Z</published>
    <updated>2024-01-21T13:55:59.000Z</updated>
    
    <content type="html"><![CDATA[<p>根据海外博主 Thordan Smash 泄露出的更新计划，Apex Legends 在接下来的几年中会进行如下更新。</p><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>世界边缘的地图迭代中会更新碎片，烂尾楼（原句“主播楼”）将消失</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>没有新传奇，但会有角色的平衡性改动，包括有命脉的空投落速加快</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>风暴点更新，推出电妹小镇，取代避雷针</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>会在某个时间点推出硬核大逃杀模式（没有 HUD、只有白甲、子弹医疗变少、无金色物品、伤害提高）</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox"/><span>下张地图将是一张泰坦陨落地图，且支持滑墙和双持手枪</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>竞技场将移除</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>会出团队死斗</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox"/><span>第23赛季的地图代号目前为“District”，Smash 认为这是一张 TTF2地图（他没玩过所以不确定），这张地图支持滑墙，且在这张地图发布后，所有地图都会更新滑墙</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>战术技能缴械、被动技能第三把武器的 ballistic（弹道学）是 S17的新传奇</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>突击位专属战利品箱，呈红色，能刷出更多武器配件及子弹</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>所有支援位传奇都能像命脉一样从蓝色战利品箱中获得额外物品</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>散兵（skirmisher）能看到空投仓里的东西</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>控制会取代竞技场</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>情人节，新的双排模式</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>热浪模式：每隔一段时间全地图会被毒圈浪潮席卷，如果处于门外就会受到伤害，空头仓会掉落名为“墨镜”的装备帮助玩家抵挡伤害</span></div><p>截止目前（2023&#x2F;12&#x2F;3），该列表中多项内容已被证实，剩余内容可信度高。不过也是最难的几项，涉及到引擎底层的修改、游戏机制的修改。我认为亡灵重做的被动和接下来的“滑墙”有关，那么重生该怎么平衡 <em>蹬墙跳与疲劳蹬墙跳</em> 呢？</p><hr><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox" checked="true"/><span>黑市功能</span></div><div class="tag-plugin colorful checkbox" color="green"><input type="checkbox"/><span>新地图滑墙</span></div><!-- flag of hidden posts -->]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;根据海外博主 Thordan Smash 泄露出的更新计划，Apex Legends 在接下来的几年中会进行如下更新。&lt;/p&gt;
&lt;div class=&quot;tag-plugin colorful checkbox&quot; color=&quot;green&quot;&gt;&lt;input type=&quot;chec</summary>
      
    
    
    
    <category term="游戏" scheme="https://c2ics.com/categories/%E6%B8%B8%E6%88%8F/"/>
    
    
    <category term="Apex" scheme="https://c2ics.com/tags/Apex/"/>
    
  </entry>
  
  <entry>
    <title>升级stellar 1.25</title>
    <link href="https://c2ics.com/posts/ea23a8487ee5/"/>
    <id>https://c2ics.com/posts/ea23a8487ee5/</id>
    <published>2024-01-21T03:05:16.000Z</published>
    <updated>2024-01-21T03:05:16.000Z</updated>
    
    <content type="html"><![CDATA[<p>半年没更新主题了，今天从<code>v1.19.0</code>更新到<code>v1.25.0</code>，发现好多功能都失效了，下面是升级指南。</p><span id="more"></span><h2 id="【严重】Tag-Plugins-改名"><a href="#【严重】Tag-Plugins-改名" class="headerlink" title="【严重】Tag Plugins 改名"></a>【严重】Tag Plugins 改名</h2><ol><li><code>ablock</code>改名为<code>box</code>，<code>tag</code>改名为<code>hashtag</code>，功能不变。<br>  替换方法：VSCode中转到搜索和替换页面，将{% ablock 替换为 {% box，记得替换结束标签 {% endablock ，其他标签同理。</li><li><code>about</code>标签即将废弃，请参考新标签<code>banner</code>。<a class="tag-plugin colorful hashtag" color="cyan" href="https://xaoxuu.com/wiki/stellar/tag-plugins/container/#banner-%E6%A8%AA%E5%B9%85%E5%AE%B9%E5%99%A8"><svg t="1701408144765" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4228" width="200" height="200"><path d="M426.6 64.8c34.8 5.8 58.4 38.8 52.6 73.6l-19.6 117.6h190.2l23-138.6c5.8-34.8 38.8-58.4 73.6-52.6s58.4 38.8 52.6 73.6l-19.4 117.6H896c35.4 0 64 28.6 64 64s-28.6 64-64 64h-137.8l-42.6 256H832c35.4 0 64 28.6 64 64s-28.6 64-64 64h-137.8l-23 138.6c-5.8 34.8-38.8 58.4-73.6 52.6s-58.4-38.8-52.6-73.6l19.6-117.4h-190.4l-23 138.6c-5.8 34.8-38.8 58.4-73.6 52.6s-58.4-38.8-52.6-73.6l19.4-117.8H128c-35.4 0-64-28.6-64-64s28.6-64 64-64h137.8l42.6-256H192c-35.4 0-64-28.6-64-64s28.6-64 64-64h137.8l23-138.6c5.8-34.8 38.8-58.4 73.6-52.6z m11.6 319.2l-42.6 256h190.2l42.6-256h-190.2z" p-id="4229"></path></svg><span>了解详情</span></a></li></ol><h2 id="【严重】Frontmatter-references-格式更改"><a href="#【严重】Frontmatter-references-格式更改" class="headerlink" title="【严重】Frontmatter references 格式更改"></a>【严重】Frontmatter references 格式更改</h2><p>Frontmatter references 不再使用 标题-连接 的形式，而是直接使用字符串，可以直接写Markdown。</p><p>这里需要注意双引号，否则会错误解析为YAML列表引起报错。</p><div class="tag-plugin grid"  style="grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));"><div class="cell" style="">    <p><strong>旧写法</strong></p><div class="tag-plugin colorful note" color="default" child="codeblock"><div class="body"><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">references:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">title:</span> <span class="string">&quot;A&quot;</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">&quot;B&quot;</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">title:</span> <span class="string">&quot;C&quot;</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">&quot;D&quot;</span></span><br></pre></td></tr></table></figure></div></div>    </div>    <div class="cell" style="">    <p><strong>新写法</strong></p><div class="tag-plugin colorful note" color="green" child="codeblock"><div class="body"><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">references:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">&quot;[A](B)&quot;</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">&quot;[C](D)&quot;</span></span><br></pre></td></tr></table></figure></div></div>    </div>    </div><h2 id="配置文件"><a href="#配置文件" class="headerlink" title="配置文件"></a>配置文件</h2><div class="tag-plugin colorful note" color="blue"><div class="body"><p>由于现在配置文件变动非常频繁，建议按照对应版本仓库里的<code>_config.yml</code>改写，而不是去迁移。</p><ul><li><a href="https://github.com/xaoxuu/hexo-theme-stellar/blob/1.25.0/_config.yml">1.25.0 配置文件</a></li><li><a href="https://github.com/xaoxuu/hexo-theme-stellar/blob/main/_config.yml">最新配置文件</a></li></ul><p>下面我将给出几个比较难找的修改。</p></div></div><p>在<code>_config.stellar.yml</code>中，</p><ul><li>原配置 sidebar 部分重构，其中的 logo 和 menu 提升一个层级，widgets 转移到 site_tree 中的 sidebar 配置</li><li>原配置 post-index 和 post_list 移除，现在转移到 site_tree 中的 nav_tabs 配置</li><li>原配置 wiki_dir 和 author_dir 移除，现在转移到 site_tree 中的 base_dir 部分配置</li></ul><div class="tag-plugin colorful note" color="red"><div class="title">说不清楚</div><div class="body"><p>每个版本好像都有变化，建议去主题仓库里参考</p></div></div><div class="tag-plugin grid"  style="grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));"><div class="cell" style="">    <p><strong>旧写法</strong></p><div class="tag-plugin colorful note" color="default" child="codeblock"><div class="body"><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">sidebar:</span></span><br><span class="line">  <span class="attr">menu:</span></span><br><span class="line">    <span class="attr">post:</span> <span class="string">&#x27;[btn.blog](/)&#x27;</span></span><br><span class="line">    <span class="attr">friends:</span> <span class="string">&#x27;[关于](/about/)&#x27;</span></span><br><span class="line">  <span class="attr">widgets:</span></span><br><span class="line">    <span class="attr">home:</span> <span class="string">welcome,</span> <span class="string">search,</span> <span class="string">recent</span></span><br><span class="line">    <span class="attr">blog_index:</span> <span class="string">welcome,</span> <span class="string">search_blog,</span> <span class="string">recent</span></span><br><span class="line">    <span class="attr">wiki_index:</span> <span class="string">search_docs,</span> <span class="string">recent</span></span><br><span class="line">    <span class="attr">others:</span> <span class="string">welcome,</span> <span class="string">search,</span> <span class="string">recent</span></span><br><span class="line">    <span class="attr">post:</span> <span class="string">toc,</span> <span class="string">search</span></span><br><span class="line">    <span class="attr">wiki:</span> <span class="string">search,</span> <span class="string">toc</span></span><br><span class="line">    <span class="attr">page:</span> <span class="string">toc,</span> <span class="string">search</span></span><br><span class="line"></span><br><span class="line"><span class="attr">post-index:</span></span><br><span class="line">  <span class="string">&#x27;首页上方菜单添加项&#x27;</span><span class="string">:</span> <span class="string">&#x27;/hello&#x27;</span></span><br></pre></td></tr></table></figure></div></div>    </div>    <div class="cell" style="">    <p><strong>新写法</strong></p><div class="tag-plugin colorful note" color="green" child="codeblock"><div class="body"><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">site_tree:</span></span><br><span class="line">  <span class="attr">home:</span></span><br><span class="line">    <span class="attr">sidebar:</span> <span class="string">welcome,</span> <span class="string">search,</span> <span class="string">recent</span></span><br><span class="line">  <span class="attr">blog:</span></span><br><span class="line">    <span class="attr">sidebar:</span> <span class="string">welcome,</span> <span class="string">search_blog,</span> <span class="string">recent</span></span><br><span class="line">    <span class="attr">menu_id:</span> <span class="string">post</span></span><br><span class="line">    <span class="attr">nav_tabs:</span>  <span class="comment"># 这里是post-index</span></span><br><span class="line">      <span class="string">&#x27;首页上方菜单添加项&#x27;</span><span class="string">:</span> <span class="string">&#x27;/hello&#x27;</span></span><br><span class="line">  <span class="attr">post:</span></span><br><span class="line">    <span class="attr">menu_id:</span> <span class="string">post</span></span><br><span class="line">    <span class="attr">sidebar:</span> <span class="string">toc,</span> <span class="string">search</span></span><br><span class="line">  <span class="attr">wiki:</span></span><br><span class="line">    <span class="attr">sidebar:</span> <span class="string">search,</span> <span class="string">toc</span> </span><br><span class="line">  <span class="attr">error_page:</span></span><br><span class="line">    <span class="attr">menu_id:</span> <span class="string">post</span></span><br><span class="line">    <span class="attr">&quot;404&quot;:</span> <span class="string">&quot;/404.html&quot;</span></span><br><span class="line">    <span class="attr">sidebar:</span> <span class="string">welcome,</span> <span class="string">search,</span> <span class="string">recent</span></span><br><span class="line">  <span class="attr">page:</span></span><br><span class="line">    <span class="attr">sidebar:</span> <span class="string">toc,</span> <span class="string">search</span></span><br></pre></td></tr></table></figure></div></div>    </div>    </div><ul><li>原配置 subtitle 从站点配置文件转移到主题配置文件的 logo 中</li></ul><p><code>_config.yml</code>中的description，需要改到<code>_config.stellar.yml</code>:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">logo:</span></span><br><span class="line">  <span class="attr">avatar:</span> <span class="string">&quot;[config.avatar](/about/)&quot;</span></span><br><span class="line">  <span class="attr">title:</span> <span class="string">&quot;[config.title](/)&quot;</span></span><br><span class="line">  <span class="attr">subtitle:</span> <span class="string">&quot;XXXXXXX | YYYYYYY&quot;</span></span><br></pre></td></tr></table></figure><ul><li>friends 和 sites 组件使用的 <code>_data/links.yml</code> 文件需要按组拆分成 <code>_data/links/xxx.yml</code></li></ul><div class="tag-plugin grid"  style="grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));"><div class="cell" style="">    <p><strong>旧写法</strong></p><div class="tag-plugin colorful note" color="default" child="codeblock"><div class="body"><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># _data/links.yml</span></span><br><span class="line"><span class="string">&quot;group1&quot;</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">title:</span> </span><br><span class="line">    <span class="attr">url:</span> </span><br></pre></td></tr></table></figure></div></div>    </div>    <div class="cell" style="">    <p><strong>新写法</strong></p><div class="tag-plugin colorful note" color="green" child="codeblock"><div class="body"><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># _data/links/group1.yml</span></span><br><span class="line">  <span class="bullet">-</span> <span class="attr">title:</span> </span><br><span class="line">    <span class="attr">url:</span> </span><br></pre></td></tr></table></figure></div></div>    </div>    </div><ul><li>Grid 重构，原来使用双栏布局的需要删掉<code><!-- cell right/left --></code>中的right和left！</li></ul><h2 id="一些新功能（不完整）"><a href="#一些新功能（不完整）" class="headerlink" title="一些新功能（不完整）"></a>一些新功能（不完整）</h2><ul><li>新的标签 <code>audio</code>, <code>video</code>, <code>gallery</code>, <code>poster</code>, <code>album</code>, <code>banner</code>, <code>md</code></li><li>MathJax Frontmatter 开关 <code>mathjax: boolean</code></li><li>文章分享，主题配置文件<code>article.share: [wechat, email, weibo, link]</code></li><li>专栏功能 <a class="tag-plugin colorful hashtag" color="cyan" href="https://xaoxuu.com/wiki/stellar/topic.html"><svg t="1701408144765" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4228" width="200" height="200"><path d="M426.6 64.8c34.8 5.8 58.4 38.8 52.6 73.6l-19.6 117.6h190.2l23-138.6c5.8-34.8 38.8-58.4 73.6-52.6s58.4 38.8 52.6 73.6l-19.4 117.6H896c35.4 0 64 28.6 64 64s-28.6 64-64 64h-137.8l-42.6 256H832c35.4 0 64 28.6 64 64s-28.6 64-64 64h-137.8l-23 138.6c-5.8 34.8-38.8 58.4-73.6 52.6s-58.4-38.8-52.6-73.6l19.6-117.4h-190.4l-23 138.6c-5.8 34.8-38.8 58.4-73.6 52.6s-58.4-38.8-52.6-73.6l19.4-117.8H128c-35.4 0-64-28.6-64-64s28.6-64 64-64h137.8l42.6-256H192c-35.4 0-64-28.6-64-64s28.6-64 64-64h137.8l23-138.6c5.8-34.8 38.8-58.4 73.6-52.6z m11.6 319.2l-42.6 256h190.2l42.6-256h-190.2z" p-id="4229"></path></svg><span>了解详情</span></a></li><li>各种 Tag Plugins 的默认设置</li><li>H1 Frontmatter 隐藏标题 <code>h1: &#39;&#39;</code></li><li>支持使用自建的 giscus 服务</li><li>Inject Frontmatter 插入代码</li><li>一站点多作者</li></ul><p>阅读更多，详见更新日志：<a href="https://github.com/xaoxuu/hexo-theme-stellar/releases">https://github.com/xaoxuu/hexo-theme-stellar/releases</a></p><!-- flag of hidden posts -->]]></content>
    
    
    <summary type="html">&lt;p&gt;半年没更新主题了，今天从&lt;code&gt;v1.19.0&lt;/code&gt;更新到&lt;code&gt;v1.25.0&lt;/code&gt;，发现好多功能都失效了，下面是升级指南。&lt;/p&gt;</summary>
    
    
    
    <category term="瞎折腾" scheme="https://c2ics.com/categories/%E7%9E%8E%E6%8A%98%E8%85%BE/"/>
    
    
    <category term="Hexo" scheme="https://c2ics.com/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>Nunjuck plugin for Quartz 4</title>
    <link href="https://c2ics.com/posts/6c1b50416710/"/>
    <id>https://c2ics.com/posts/6c1b50416710/</id>
    <published>2023-12-21T08:17:04.000Z</published>
    <updated>2023-12-21T08:17:04.000Z</updated>
    
    <content type="html"><![CDATA[<div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2023/quartz-obsidian-nunjuck/quartz-transform-pipeline-fix.png" alt="Quartz Transfrom Pipleine" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">Quartz Transfrom Pipleine</span></div></div><p>Quartz 支持 Obsidian Callouts，但是 Callouts 非常难用，于是我想为 Quartz 实现<code>Nunjucks</code>模板引擎，就像 Hexo 那样。</p><p>首先，要明确它的渲染管线。第一步处理<code>Transformer</code>中有一步骤<code>textTransform</code>，在解析 markdown 前进行文本预处理。<strong>模板引擎所干的事只是替换文本</strong>，所以要在 <code>textTransform</code> 这里注册插件，这时源 Markdown 文件还没有被转化为 Markdown AST，可以进行字符串到字符串的操作。</p><h2 id="造轮子"><a href="#造轮子" class="headerlink" title="造轮子"></a>造轮子</h2><p>Nunjucks 的自定义标签注册很麻烦，所以我稍微借用了下 Hexo 封装好的自定义标签管理，简单来说，就是保存了一个 Nunjuck <code>Enviroment</code>，并封装了一系列注册、删除自定义标签的机制和相关类型，注册者只需关注标签的<strong>具体逻辑</strong>，而不是解析过程。</p><p>我删除了一些用不到的代码，但里面还有好多问题，碍于时间不去进一步精简了。</p><details class="tag-plugin colorful folding" child="codeblock"><summary><p>quartz&#x2F;plugins&#x2F;tags.ts</p></summary><div class="body"><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Environment</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;nunjucks&#x27;</span>;</span><br><span class="line"><span class="keyword">import</span> stripIndent <span class="keyword">from</span> <span class="string">&#x27;strip-indent&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">interface</span> <span class="title class_">TagFunction</span> &#123;</span><br><span class="line">    (<span class="attr">args</span>: <span class="built_in">any</span>[], <span class="attr">content</span>: <span class="built_in">string</span>): <span class="built_in">string</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">NunjucksTag</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="attr">tags</span>: <span class="built_in">string</span>[];</span><br><span class="line">    <span class="keyword">public</span> <span class="attr">fn</span>: <span class="title class_">TagFunction</span>;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params"><span class="attr">name</span>: <span class="built_in">string</span>, <span class="attr">fn</span>: <span class="title class_">TagFunction</span></span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">tags</span> = [name];</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">fn</span> = fn;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">parse</span>(<span class="params"><span class="attr">parser</span>: <span class="built_in">any</span>, <span class="attr">nodes</span>: <span class="built_in">any</span>, <span class="attr">lexer</span>: <span class="built_in">any</span></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> node = <span class="variable language_">this</span>.<span class="title function_">_parseArgs</span>(parser, nodes, lexer);</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> nodes.<span class="title class_">CallExtension</span>(<span class="variable language_">this</span>, <span class="string">&#x27;run&#x27;</span>, node, []);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">_parseArgs</span>(<span class="params"><span class="attr">parser</span>: <span class="built_in">any</span>, <span class="attr">nodes</span>: <span class="built_in">any</span>, <span class="attr">lexer</span>: <span class="built_in">any</span></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> tag = parser.<span class="title function_">nextToken</span>();</span><br><span class="line">        <span class="keyword">const</span> node = <span class="keyword">new</span> nodes.<span class="title class_">NodeList</span>(tag.<span class="property">lineno</span>, tag.<span class="property">colno</span>);</span><br><span class="line">        <span class="keyword">const</span> argarray = <span class="keyword">new</span> nodes.<span class="title class_">Array</span>(tag.<span class="property">lineno</span>, tag.<span class="property">colno</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">let</span> token;</span><br><span class="line">        <span class="keyword">let</span> argitem = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">while</span> ((token = parser.<span class="title function_">nextToken</span>(<span class="literal">true</span>))) &#123;</span><br><span class="line">            <span class="keyword">if</span> (token.<span class="property">type</span> === lexer.<span class="property">TOKEN_WHITESPACE</span> || token.<span class="property">type</span> === lexer.<span class="property">TOKEN_BLOCK_END</span>) &#123;</span><br><span class="line">                <span class="keyword">if</span> (argitem !== <span class="string">&#x27;&#x27;</span>) &#123;</span><br><span class="line">                    <span class="keyword">const</span> argnode = <span class="keyword">new</span> nodes.<span class="title class_">Literal</span>(tag.<span class="property">lineno</span>, tag.<span class="property">colno</span>, argitem.<span class="title function_">trim</span>());</span><br><span class="line">                    argarray.<span class="title function_">addChild</span>(argnode);</span><br><span class="line">                    argitem = <span class="string">&#x27;&#x27;</span>;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">if</span> (token.<span class="property">type</span> === lexer.<span class="property">TOKEN_BLOCK_END</span>) &#123;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                argitem += token.<span class="property">value</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        node.<span class="title function_">addChild</span>(argarray);</span><br><span class="line">        <span class="keyword">return</span> node;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">run</span>(<span class="params"><span class="attr">context</span>: <span class="built_in">any</span>, <span class="attr">args</span>: <span class="built_in">any</span>, <span class="attr">body</span>: <span class="built_in">any</span>, <span class="attr">callback</span>: <span class="built_in">any</span></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="title function_">_run</span>(context, args, <span class="string">&#x27;&#x27;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">_run</span>(<span class="attr">context</span>: <span class="built_in">any</span>, <span class="attr">args</span>: <span class="built_in">any</span>, <span class="attr">body</span>: <span class="built_in">any</span>): <span class="built_in">any</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">Reflect</span>.<span class="title function_">apply</span>(<span class="variable language_">this</span>.<span class="property">fn</span>, context.<span class="property">ctx</span>, [args, body]);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">trimBody</span> = (<span class="params"><span class="attr">body</span>: () =&gt; <span class="built_in">any</span></span>) =&gt; &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title function_">stripIndent</span>(<span class="title function_">body</span>()).<span class="title function_">replace</span>(<span class="regexp">/^\n?|\n?$/g</span>, <span class="string">&#x27;&#x27;</span>);</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">NunjucksBlock</span> <span class="keyword">extends</span> <span class="title class_ inherited__">NunjucksTag</span> &#123;</span><br><span class="line">    <span class="title function_">parse</span>(<span class="params"><span class="attr">parser</span>: <span class="built_in">any</span>, <span class="attr">nodes</span>: <span class="built_in">any</span>, <span class="attr">lexer</span>: <span class="built_in">any</span></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> node = <span class="variable language_">this</span>.<span class="title function_">_parseArgs</span>(parser, nodes, lexer);</span><br><span class="line">        <span class="keyword">const</span> body = <span class="variable language_">this</span>.<span class="title function_">_parseBody</span>(parser, nodes, lexer);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> nodes.<span class="title class_">CallExtension</span>(<span class="variable language_">this</span>, <span class="string">&#x27;run&#x27;</span>, node, [body]);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">_parseBody</span>(<span class="params"><span class="attr">parser</span>: <span class="built_in">any</span>, <span class="attr">nodes</span>: <span class="built_in">any</span>, <span class="attr">lexer</span>: <span class="built_in">any</span></span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> body = parser.<span class="title function_">parseUntilBlocks</span>(<span class="string">`end<span class="subst">$&#123;<span class="variable language_">this</span>.tags[<span class="number">0</span>]&#125;</span>`</span>);</span><br><span class="line"></span><br><span class="line">        parser.<span class="title function_">advanceAfterBlockEnd</span>();</span><br><span class="line">        <span class="keyword">return</span> body;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">run</span>(<span class="params"><span class="attr">context</span>: <span class="built_in">any</span>, <span class="attr">args</span>: <span class="built_in">any</span>, <span class="attr">body</span>: <span class="built_in">any</span>, <span class="attr">callback</span>: <span class="built_in">any</span></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="title function_">_run</span>(context, args, <span class="title function_">trimBody</span>(body));</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Tag</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="attr">env</span>: <span class="title class_">Environment</span>;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">env</span> = <span class="keyword">new</span> <span class="title class_">Environment</span>(<span class="literal">null</span>, &#123;</span><br><span class="line">            <span class="attr">autoescape</span>: <span class="literal">false</span></span><br><span class="line">        &#125;);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">register</span>(<span class="attr">name</span>: <span class="built_in">string</span>, <span class="attr">fn</span>: <span class="title class_">TagFunction</span>, <span class="attr">ends</span>: <span class="built_in">boolean</span> = <span class="literal">false</span>): <span class="built_in">void</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (!name) <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;name is required&#x27;</span>);</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">typeof</span> fn !== <span class="string">&#x27;function&#x27;</span>) <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;fn must be a function&#x27;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">let</span> <span class="attr">tag</span>: <span class="title class_">NunjucksTag</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (ends) &#123;</span><br><span class="line">            tag = <span class="keyword">new</span> <span class="title class_">NunjucksBlock</span>(name, fn);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            tag = <span class="keyword">new</span> <span class="title class_">NunjucksTag</span>(name, fn);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">env</span>.<span class="title function_">addExtension</span>(name, tag);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">unregister</span>(<span class="attr">name</span>: <span class="built_in">string</span>): <span class="built_in">void</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (!name) <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&#x27;name is required&#x27;</span>);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> &#123; env &#125; = <span class="variable language_">this</span>;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (env.<span class="title function_">hasExtension</span>(name)) env.<span class="title function_">removeExtension</span>(name);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title class_">Tag</span>;</span><br></pre></td></tr></table></figure></div></details><h2 id="插件"><a href="#插件" class="headerlink" title="插件"></a>插件</h2><figure class="highlight typescript"><figcaption><span>def</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">type</span> <span class="title class_">QuartzTransformerPluginInstance</span> = &#123;</span><br><span class="line">    <span class="attr">name</span>: <span class="built_in">string</span></span><br><span class="line">    <span class="attr">textTransform</span>?: <span class="function">(<span class="params"><span class="attr">ctx</span>: <span class="title class_">BuildCtx</span>, <span class="attr">src</span>: <span class="built_in">string</span> | <span class="title class_">Buffer</span></span>) =&gt;</span> <span class="built_in">string</span> | <span class="title class_">Buffer</span></span><br><span class="line">    <span class="attr">markdownPlugins</span>?: <span class="function">(<span class="params"><span class="attr">ctx</span>: <span class="title class_">BuildCtx</span></span>) =&gt;</span> <span class="title class_">PluggableList</span></span><br><span class="line">    <span class="attr">htmlPlugins</span>?: <span class="function">(<span class="params"><span class="attr">ctx</span>: <span class="title class_">BuildCtx</span></span>) =&gt;</span> <span class="title class_">PluggableList</span></span><br><span class="line">    <span class="attr">externalResources</span>?: <span class="function">(<span class="params"><span class="attr">ctx</span>: <span class="title class_">BuildCtx</span></span>) =&gt;</span> <span class="title class_">Partial</span>&lt;<span class="title class_">StaticResources</span>&gt;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这是插件的定义，创建源文件 <code>quartz/plugins/transformers/nunjucks.ts</code>，按照官方文档中的写法，搭建插件基本结构。在这个案例中，我们只需用到<code>textTransform</code>。</p><figure class="highlight typescript"><figcaption><span>quartz/plugins/transformers/nunjucks.ts</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Tag</span> <span class="keyword">from</span> <span class="string">&quot;../tags&quot;</span>;</span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">QuartzTransformerPlugin</span> &#125; <span class="keyword">from</span> <span class="string">&quot;../types&quot;</span></span><br><span class="line"><span class="keyword">import</span> nunjucks, &#123; <span class="title class_">Environment</span>, <span class="title class_">Extension</span> &#125; <span class="keyword">from</span> <span class="string">&quot;nunjucks&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">interface</span> <span class="title class_">Options</span> &#123; &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> tags = <span class="keyword">new</span> <span class="title class_">Tag</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 注册你想要的标签</span></span><br><span class="line">tags.<span class="title function_">register</span>(<span class="string">&quot;helloworld&quot;</span>, <span class="function">() =&gt;</span> <span class="string">&#x27;helloworld parsed.&#x27;</span>)</span><br><span class="line">tags.<span class="title function_">register</span>(<span class="string">&quot;blocked&quot;</span>, <span class="function">(<span class="params">args, con</span>) =&gt;</span></span><br><span class="line">    <span class="string">`parsed blocked, args [<span class="subst">$&#123;args[<span class="number">0</span>]&#125;</span>]: \n<span class="subst">$&#123;con&#125;</span>`</span>, <span class="literal">true</span>)</span><br><span class="line">tags.<span class="title function_">register</span>(<span class="string">&#x27;hide&#x27;</span>, <span class="function">() =&gt;</span> <span class="string">&#x27;&#x27;</span>, <span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> env = tags.<span class="property">env</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title class_">Nunjucks</span>: <span class="title class_">QuartzTransformerPlugin</span>&lt;<span class="title class_">Partial</span>&lt;<span class="title class_">Options</span>&gt; | <span class="literal">undefined</span>&gt; = <span class="function">(<span class="params">userOpts</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="comment">//const opts = &#123; ...userOpts &#125;</span></span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&quot;Nunjucks&quot;</span>,</span><br><span class="line">        <span class="title function_">textTransform</span>(<span class="params">ctx, src</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> nunjucks</span><br><span class="line">                .<span class="title function_">compile</span>(src.<span class="title function_">toString</span>(), env)</span><br><span class="line">                .<span class="title function_">render</span>();</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>最后，在 <code>quartz.config.ts</code> 中加入插件的引用即可。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li>编译和预处理时间增长，这也很无奈。</li><li>没有处理 Nunjucks 模板引擎的异常，若模板错误，将中止 Build 过程。</li><li>可以不使用该方法，而是使用CSS选择器自定义样式<br><a href="https://publish.obsidian.md/slrvb-docs/ITS+Theme/Image+Adjustments">https://publish.obsidian.md/slrvb-docs/ITS+Theme/Image+Adjustments</a>。<br>不过，要在 Quartz 中正常显示，需要把选择器中的 <code>[alt]</code> 改为 <code>[width]</code>，因为它不支持图片说明文字，而会把 <code>[XXXX]()</code> 直接变为属性 width&#x3D;XXXX。</li></ul>]]></content>
    
    
    <summary type="html">Quartz 支持 Obsidian Callouts，但是 Callouts 非常难用，于是我想为 Quartz 实现Nunjucks模板引擎，就像 Hexo 那样。</summary>
    
    
    
    <category term="Tech" scheme="https://c2ics.com/categories/Tech/"/>
    
    
    <category term="Typescript" scheme="https://c2ics.com/tags/Typescript/"/>
    
  </entry>
  
  <entry>
    <title>禁用Chrome新UI</title>
    <link href="https://c2ics.com/posts/f53e1fae60db/"/>
    <id>https://c2ics.com/posts/f53e1fae60db/</id>
    <published>2023-10-20T15:39:46.000Z</published>
    <updated>2023-10-20T15:39:46.000Z</updated>
    
    <content type="html"><![CDATA[<p>Chrome在2023年给我推送了新UI，怎么禁用呢？</p><span id="more"></span><h2 id="一步解决"><a href="#一步解决" class="headerlink" title="一步解决"></a>一步解决</h2><p>在地址栏输入 <u>chrome://flags</u>，进入页面后搜索“refresh”，禁用列表中的 Chrome Refresh 2023 和 Chrome WebUI Refresh 2023 。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2023/disable-chrome-newUI/flags.jpg" alt="禁用" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">禁用</span></div></div><p>随后重启，即可还原老UI。</p><h2 id="吐槽"><a href="#吐槽" class="headerlink" title="吐槽"></a>吐槽</h2><p>Chrome刚刚更新的 New UI。现在的流行设计都喜欢这么臃肿的上下文菜单吗，这line spacing有啥意义？右键后占据半个屏幕…</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2023/disable-chrome-newUI/context-menu.png" alt="上下文菜单" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">上下文菜单</span></div></div><p>真看不出来新的有什么好，反而变得不那么”productive”了，浏览器不是toolbox更不是用来观赏着玩的，照我的看法生产力工具就该他妈的奉行实用主义，搞这么多花里胡哨的还嫌不够卡吗？</p><p>最弱智的是空间不够还要被wrap，高度增加后触发几率大大增加。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2023/disable-chrome-newUI/wrapping.jpg" alt="Wrapping" data-fancybox="true" style="width:400px;"/></div><div class="image-meta"><span class="image-caption center">Wrapping</span></div></div><p>现在还有办法用chrome:&#x2F;&#x2F;flags把它禁用掉，但以google这种独断且opinionated的公司，我觉得这选项在一年内就要消失。 <psw>“这是实验性功能，提供此选项是为了解决您出现bug后需要降级的麻烦，我们的新UI已经开发好了，非常稳定，就把这选项移除了，你有意见？”</psw></p><!-- flag of hidden posts -->]]></content>
    
    
    <summary type="html">&lt;p&gt;Chrome在2023年给我推送了新UI，怎么禁用呢？&lt;/p&gt;</summary>
    
    
    
    <category term="日常" scheme="https://c2ics.com/categories/%E6%97%A5%E5%B8%B8/"/>
    
    
  </entry>
  
  <entry>
    <title>十月Vercel被墙的临时解决方案：GitHub Actions 与 Rsync 自动部署</title>
    <link href="https://c2ics.com/posts/28c39c1c83a9/"/>
    <id>https://c2ics.com/posts/28c39c1c83a9/</id>
    <published>2023-10-02T05:30:39.000Z</published>
    <updated>2023-10-02T05:30:39.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Vercel暂时被墙"><a href="#Vercel暂时被墙" class="headerlink" title="Vercel暂时被墙"></a>Vercel暂时被墙</h2><p>十月初Vercel被墙的临时解决方案，先用自己的服务器部署博客。</p><p>要求：不手动部署，希望像之前在Vercel一样，在提交git后能够自动生成并部署。</p><p>需要使用 Github Actions 来生成，Rsync 来部署。</p><h2 id="创建部署用户"><a href="#创建部署用户" class="headerlink" title="创建部署用户"></a>创建部署用户</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 创建名为 deploy 的用户</span></span><br><span class="line"><span class="built_in">sudo</span> adduser deploy</span><br><span class="line"><span class="built_in">sudo</span> usermod -s /bin/bash -d /home/deploy deploy</span><br><span class="line"></span><br><span class="line"><span class="comment"># 创建博客部署目录</span></span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">mkdir</span> -p /www/blog</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">chown</span> -R deploy:deploy /www/blog</span><br><span class="line"><span class="built_in">sudo</span> <span class="built_in">chmod</span> -R 775 /www/blog</span><br></pre></td></tr></table></figure><h3 id="生成SSH登录秘钥"><a href="#生成SSH登录秘钥" class="headerlink" title="生成SSH登录秘钥"></a>生成SSH登录秘钥</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 生成秘钥并添加到 authorized_keys</span></span><br><span class="line">su deploy</span><br><span class="line">ssh-keygen -t ed25519 -C <span class="string">&quot;your_email@example.com&quot;</span></span><br><span class="line"><span class="built_in">cat</span> id_ed25519.pub &gt;&gt; authorized_keys</span><br><span class="line"></span><br><span class="line"><span class="comment"># 输出私钥，复制并保存以备后续使用</span></span><br><span class="line"><span class="built_in">cat</span> id_ed25519.pub</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" color="red"><div class="body"><p>出于安全考虑，建议禁用该用户的密码登录，仅允许使用密钥登录。</p></div></div><h2 id="配置Github-Actions"><a href="#配置Github-Actions" class="headerlink" title="配置Github Actions"></a>配置Github Actions</h2><p>在仓库中创建文件<code>/.github/workflows/deploy-to-server.yml</code>，并写入以下内容：</p><details class="tag-plugin colorful folding" child="codeblock"><summary><p>&#x2F;.github&#x2F;workflows&#x2F;deploy-to-server.yml</p></summary><div class="body"><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">name:</span> <span class="string">Deploy</span> <span class="string">to</span> <span class="string">Server</span></span><br><span class="line"></span><br><span class="line"><span class="attr">on:</span></span><br><span class="line">  <span class="attr">push:</span></span><br><span class="line">    <span class="attr">branches:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">main</span></span><br><span class="line">  <span class="attr">workflow_dispatch:</span></span><br><span class="line"></span><br><span class="line"><span class="attr">jobs:</span></span><br><span class="line">  <span class="attr">deploy:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">Deploy</span> <span class="string">to</span> <span class="string">Server</span></span><br><span class="line">    <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line"></span><br><span class="line">    <span class="attr">steps:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Checkout</span> <span class="string">Repository</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/checkout@v4</span></span><br><span class="line"><span class="comment"># 如果你的项目使用到了 git 子模块，请删除下面的注释</span></span><br><span class="line"><span class="comment">#        with:</span></span><br><span class="line"><span class="comment">#          submodules: recursive</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Set</span> <span class="string">up</span> <span class="string">Node.js</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">actions/setup-node@v3</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">node-version:</span> <span class="number">18</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Install</span> <span class="string">Dependencies</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">npm</span> <span class="string">install</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Build</span> <span class="string">Hexo</span> <span class="string">Application</span></span><br><span class="line">        <span class="attr">run:</span> <span class="string">npm</span> <span class="string">run</span> <span class="string">build</span></span><br><span class="line"></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Deploy</span> <span class="string">to</span> <span class="string">server</span></span><br><span class="line">        <span class="attr">uses:</span> <span class="string">burnett01/rsync-deployments@6.0.0</span></span><br><span class="line">        <span class="attr">with:</span></span><br><span class="line">          <span class="attr">switches:</span> <span class="string">-avzr</span> <span class="string">--delete</span></span><br><span class="line">          <span class="attr">path:</span> <span class="string">public/</span>     <span class="comment"># Hexo的默认生成目录</span></span><br><span class="line">          <span class="attr">remote_host:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.DEPLOY_SERVER</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">remote_port:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.DEPLOY_PORT</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">remote_user:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.REMOTE_USER</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">remote_key:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.SSH_KEY</span> <span class="string">&#125;&#125;</span></span><br><span class="line">          <span class="attr">remote_path:</span> <span class="string">$&#123;&#123;</span> <span class="string">secrets.DEPLOY_PATH</span> <span class="string">&#125;&#125;</span></span><br></pre></td></tr></table></figure></div></details><p>然后进入你的Github仓库，选择 Settings &gt; Secrets and Variables &gt; Actions &gt; New Repository Secret 添加上面用到的环境变量。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2023/auto-deploy-ghactions/action-secrets.png" alt="添加仓库Secrets" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">添加仓库Secrets</span></div></div><ul><li><code>DEPLOY_SERVER</code> 服务器IP</li><li><code>DEPLOY_PORT</code> SSH端口，一般为22</li><li><code>REMOTE_USER</code> 登录用户名</li><li><code>SSH_KEY</code> 私钥</li><li><code>DEPLOY_PATH</code> 服务器上的部署路径，例如&#x2F;www&#x2F;blog&#x2F;</li></ul><p>如果不想在本次提交中触发自动部署，请在提交信息的最后添加<code>[skip actions]</code>，详见<a href="https://docs.github.com/en/actions/managing-workflow-runs/skipping-workflow-runs">Skipping workflow runs</a>。</p><h2 id="可能遇到的问题"><a href="#可能遇到的问题" class="headerlink" title="可能遇到的问题"></a>可能遇到的问题</h2><h3 id="bash-line-1-rsync-command-not-found"><a href="#bash-line-1-rsync-command-not-found" class="headerlink" title="bash: line 1: rsync: command not found"></a>bash: line 1: rsync: command not found</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Warning: Permanently added <span class="string">&#x27;***&#x27;</span> (ED25519) to the list of known hosts.</span><br><span class="line">bash: line 1: rsync: <span class="built_in">command</span> not found</span><br><span class="line">rsync: connection unexpectedly closed (0 bytes received so far) [sender]</span><br></pre></td></tr></table></figure><p>请在你的目标服务器上安装 rsync</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> apt-get update</span><br><span class="line"><span class="built_in">sudo</span> apt-get -y install rsync</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">十月初Vercel被阻挡的临时解决方案，先用自己的服务器部署博客，配合Github Actions 实现自动化部署。</summary>
    
    
    
    <category term="瞎折腾" scheme="https://c2ics.com/categories/%E7%9E%8E%E6%8A%98%E8%85%BE/"/>
    
    
    <category term="Hexo" scheme="https://c2ics.com/tags/Hexo/"/>
    
    <category term="Github" scheme="https://c2ics.com/tags/Github/"/>
    
  </entry>
  
  <entry>
    <title>Hexo Stellar 主题隐藏文章、和隐藏文章列表</title>
    <link href="https://c2ics.com/posts/6e7c7e574ab6/"/>
    <id>https://c2ics.com/posts/6e7c7e574ab6/</id>
    <published>2023-09-03T05:58:57.000Z</published>
    <updated>2023-09-03T05:58:57.000Z</updated>
    
    <content type="html"><![CDATA[<p>原生Hexo不支持隐藏文章，Stellar主题也没有提供。我们可以使用插件<code>hexo-hide-posts</code>来解决这问题。</p><span id="more"></span><h2 id="安装并配置插件"><a href="#安装并配置插件" class="headerlink" title="安装并配置插件"></a>安装并配置插件</h2><p>请参考<a href="https://github.com/prinsss/hexo-hide-posts/blob/master/README_ZH.md">Hexo-hide-posts中文文档</a>安装插件。</p><div class="tag-plugin copy"><span>$</span><input class="copy-area" id="copy_1" value="npm install hexo-hide-posts"><button class="copy-btn" onclick="util.copy(&quot;copy_1&quot;,&quot;复制成功&quot;)"><svg class="icon copy-btn" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M5.75 1a.75.75 0 00-.75.75v3c0 .414.336.75.75.75h4.5a.75.75 0 00.75-.75v-3a.75.75 0 00-.75-.75h-4.5zm.75 3V2.5h3V4h-3zm-2.874-.467a.75.75 0 00-.752-1.298A1.75 1.75 0 002 3.75v9.5c0 .966.784 1.75 1.75 1.75h8.5A1.75 1.75 0 0014 13.25v-9.5a1.75 1.75 0 00-.874-1.515.75.75 0 10-.752 1.298.25.25 0 01.126.217v9.5a.25.25 0 01-.25.25h-8.5a.25.25 0 01-.25-.25v-9.5a.25.25 0 01.126-.217z"></path></svg></button></div><p>完成安装后，按照文档进行配置。在配置完成后，修改<code>hide_posts</code>中的以下两个选项。这个配置的意思是，先允许所有生成器（generator）访问隐藏文章，但不允许index generator（首页）访问隐藏文章，黑名单。<code>filter</code>是指判断文章是否要隐藏的 YAML Frontmatter，在你需要隐藏的文章的 Frontmatter 里写上 <code>hidden: true</code>即可，这个字段的名称可以改成别的。</p><figure class="highlight yaml"><figcaption><span>_config.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">hide_posts:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">filter:</span> <span class="string">hidden</span></span><br><span class="line">  <span class="attr">noindex:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">allowlist_generators:</span> [<span class="string">&#x27;*&#x27;</span>]</span><br><span class="line">  <span class="attr">blocklist_generators:</span> [<span class="string">&#x27;index&#x27;</span>]</span><br></pre></td></tr></table></figure><p>白名单同理，将 allowlist 改为可见，blocklist 设置为 <code>*</code>。如果同时设置了黑名单和白名单，白名单的优先级更高。这个插件还支持精细到每篇文章的管理，不局限于白&#x2F;黑名单，详见<a href="https://github.com/prinsss/hexo-hide-posts/blob/master/README_ZH.md#%E8%87%AA%E5%AE%9A%E4%B9%89-acl-%E5%87%BD%E6%95%B0">自定义 ACL 函数</a>。</p><h2 id="解决问题"><a href="#解决问题" class="headerlink" title="解决问题"></a>解决问题</h2><p>在Hexo中，每个生成器都有属于自己的数据上下文<code>page</code>，在归档页面中可以使用<code>page.posts</code>获取文章列表。问题是，这个列表是有分页的，许多主题没有设计分页，就直接从全局变量<code>site.post</code>中取数据了，因为后者是完整的文章列表。</p><p>然而，这插件的原理是，先从<code>page</code>和<code>site</code>中隐藏指定文章，再为允许的生成器重新生成一个Query对象，里面包含完整的文章列表。</p><p>因此，这样操作下来，会发现归档页面中<strong>不含隐藏的文章</strong>，我们需要修改主题——</p><h3 id="修改文章获取方式"><a href="#修改文章获取方式" class="headerlink" title="修改文章获取方式"></a>修改文章获取方式</h3><p>&#x2F;themes&#x2F;hexo-theme-stellar&#x2F;layouts&#x2F;archive.ejs 中，将第14行和第23行的<code>site.posts</code>改为<code>page.posts</code>，如图所示。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2023/stellar-hide-posts/archive.ejs.png" alt="修改" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">修改</span></div></div><div class="tag-plugin colorful note" color="green"><div class="body"><p>建议Fork一份主题，作为 Git Submodules 使用，这样可以在修改的同时保持原主题更新。</p></div></div><h3 id="取消归档分页"><a href="#取消归档分页" class="headerlink" title="取消归档分页"></a>取消归档分页</h3><p><code>page.posts</code>获取的是经过index_generator分页处理后的文章列表，不完整，因此需要禁用分页。</p><p>在_config.yml文件中找到或添加以下配置：</p><figure class="highlight yml"><figcaption><span>_config.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">archive_generator:</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">per_page:</span> <span class="number">0</span> <span class="comment"># 无分页，输出全部文章</span></span><br></pre></td></tr></table></figure><h2 id="创建隐藏文章列表"><a href="#创建隐藏文章列表" class="headerlink" title="创建隐藏文章列表"></a>创建隐藏文章列表</h2><p>我原来使用 tags 标记隐藏文章，但是这样会造成 hexo-related-posts 的异常。</p><p>因此，建议创建一个hexo generator（生成器）来生成隐藏文章列表，可以使用index（首页）模板，也可以使用archives（归档）模板，或者自己手写一个新的。</p><p>创建 <code>/theme/hexo-theme-stellar/scripts/generators/hidden.js</code>，并添加以下代码：</p><figure class="highlight javascript"><figcaption><span>/theme/hexo-theme-stellar/scripts/generators/hidden.js</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> config = hexo.<span class="property">config</span>.<span class="property">hide_posts</span></span><br><span class="line"><span class="keyword">if</span> (config != <span class="literal">undefined</span> &amp;&amp; config.<span class="property">enable</span>) &#123;</span><br><span class="line">  hexo.<span class="property">extend</span>.<span class="property">generator</span>.<span class="title function_">register</span>(<span class="string">&#x27;hidden_page&#x27;</span>, <span class="keyword">function</span> (<span class="params">locals</span>) &#123;</span><br><span class="line">    locals.<span class="property">posts</span> = locals.<span class="property">hidden_posts</span>.<span class="title function_">sort</span>(<span class="string">&#x27;date&#x27;</span>, -<span class="number">1</span>)</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      <span class="attr">path</span>: <span class="string">&#x27;hidden/index.html&#x27;</span>, <span class="comment">// 自定路由，我选择的是 /hidden/</span></span><br><span class="line">      <span class="attr">data</span>: locals,</span><br><span class="line">      <span class="attr">layout</span>: [<span class="string">&#x27;index&#x27;</span>]  <span class="comment">// 这里也可改为 archive</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;);</span><br><span class="line">&#125; <span class="keyword">else</span> hexo.<span class="property">log</span>.<span class="title function_">warn</span>(<span class="string">&quot;Please install or activate hexo-hide-posts&quot;</span>);</span><br></pre></td></tr></table></figure><p>效果如本站 <a href="/hidden/">隐藏文章列表</a>。</p><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>本文只解决了一出由<code>site.posts</code>引发的问题，实际上主题中还有非常多类似的地方，不过我用不到，请自行查找修改。</p><p>最终配置示例：</p><figure class="highlight yaml"><figcaption><span>_config.yml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">hide_posts:</span></span><br><span class="line">  <span class="attr">enable:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">filter:</span> <span class="string">hidden</span></span><br><span class="line">  <span class="attr">blocklist_generators:</span> [<span class="string">&#x27;index&#x27;</span>]</span><br><span class="line">  <span class="attr">allowlist_generators:</span> [<span class="string">&#x27;*&#x27;</span>]</span><br><span class="line">  <span class="attr">noindex:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="attr">archive_generator:</span></span><br><span class="line">  <span class="attr">enabled:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">per_page:</span> <span class="number">0</span></span><br><span class="line">  <span class="attr">yearly:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">monthly:</span> <span class="literal">true</span></span><br><span class="line">  <span class="attr">daily:</span> <span class="literal">false</span></span><br><span class="line">  <span class="attr">order_by:</span> <span class="string">-date</span></span><br></pre></td></tr></table></figure><p>在文章的 YAML Frontmatter 中写入<code>hidden: true</code>即可隐藏文章，如：</p><figure class="highlight markdown"><figcaption><span>some-post.md</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line"><span class="section">hidden: true</span></span><br><span class="line"><span class="section">---</span></span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;原生Hexo不支持隐藏文章，Stellar主题也没有提供。我们可以使用插件&lt;code&gt;hexo-hide-posts&lt;/code&gt;来解决这问题。&lt;/p&gt;</summary>
    
    
    
    <category term="瞎折腾" scheme="https://c2ics.com/categories/%E7%9E%8E%E6%8A%98%E8%85%BE/"/>
    
    
    <category term="Hexo" scheme="https://c2ics.com/tags/Hexo/"/>
    
  </entry>
  
  <entry>
    <title>安卓透明代理 Box4Magisk 最简可用配置</title>
    <link href="https://c2ics.com/posts/f0a6e4b6da8a/"/>
    <id>https://c2ics.com/posts/f0a6e4b6da8a/</id>
    <published>2023-08-17T11:18:14.000Z</published>
    <updated>2023-08-17T11:18:14.000Z</updated>
    
    <content type="html"><![CDATA[<p>使用 Clash.META 内核最简配置安卓透明代理“Box4Magisk”。</p><span id="more"></span><h2 id="什么是透明代理？"><a href="#什么是透明代理？" class="headerlink" title="什么是透明代理？"></a>什么是透明代理？</h2><p>透明代理是指被代理的设备无感知代理的存在。被代理的设备无需运行任何代理软件（如Clash for Android），只需连接至网络即可自动被代理。透明代理常用于以下场景：某些国产软件会检测系统是否连接了VPN，以防止抓包和保护数据安全；还有反诈中心&#x2F;系统病毒检测报告危险应用程序。</p><h3 id="前置条件"><a href="#前置条件" class="headerlink" title="前置条件"></a>前置条件</h3><div class="tag-plugin colorful checkbox" ><input type="checkbox" checked="true"/><span>机器已经Root，Magisk正常工作</span></div><div class="tag-plugin colorful checkbox" ><input type="checkbox" checked="true"/><span>机场支持Clash订阅</span></div><div class="tag-plugin colorful checkbox" ><input type="checkbox" checked="true"/><span>可以访问 /data 的文件管理器</span></div><h3 id="下载资源"><a href="#下载资源" class="headerlink" title="下载资源"></a>下载资源</h3><ul><li>Box4Magisk 透明代理工具 <a href="https://github.com/CHIZI-0618/box4magisk/releases">Release</a></li><li>Clash.META 可执行文件（选择android-arm64版本） <a href="https://github.com/MetaCubeX/mihomo/releases/latest">Release</a></li></ul><p>需要注意，这里使用的是clash.meta，而不是clash-core。</p><h2 id="Magisk部分"><a href="#Magisk部分" class="headerlink" title="Magisk部分"></a>Magisk部分</h2><h3 id="安装模块"><a href="#安装模块" class="headerlink" title="安装模块"></a>安装模块</h3><p>进入Magisk，在底部选择“模块”，点击“从本地安装”，选择下载好的box4magisk zip包，安装后重启设备。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2023/android-transparent-proxy-easiest/magisk-instl.webp" alt="安装流程" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">安装流程</span></div></div><h3 id="配置模块"><a href="#配置模块" class="headerlink" title="配置模块"></a>配置模块</h3><p>打开文件管理器，转到目录&#x2F;data&#x2F;adb&#x2F;box&#x2F;，您将看到以下目录结构：</p><figure class="highlight plaintext"><figcaption><span>/data/adb/box/</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">├─bin               : 存放二进制程序的目录，如果你要用其他内核，请参照文档</span><br><span class="line">│      clash        : clash.meta的可执行文件，需要改名成clash</span><br><span class="line">├─clash             : clash.meta的工作目录，配置文件、日志都存放在此</span><br><span class="line">│      config.yaml  : 配置文件</span><br><span class="line">├─run               : box4magisk的日志</span><br><span class="line">├─scripts</span><br><span class="line">│      box.config   : box4magisk的配置</span><br><span class="line">├─sing-box</span><br><span class="line">└─xray</span><br></pre></td></tr></table></figure><p>解压下载好的clash.META.gz文件，**将其中的文件重命名为<code>clash</code>，**放入bin目录中（完整路径为：&#x2F;data&#x2F;adb&#x2F;box&#x2F;bin&#x2F;clash）。</p><h3 id="进阶配置"><a href="#进阶配置" class="headerlink" title="进阶配置"></a>进阶配置</h3><p>更多配置需要到 <code>scripts/box.config</code> 中修改，默认的配置已经适用于本教程，无需额外修改。修改此配置有风险，请谨慎按照<a href="https://github.com/CHIZI-0618/box4magisk/blob/main/README.md">说明文档</a>操作。</p><h4 id="使用其他核心"><a href="#使用其他核心" class="headerlink" title="使用其他核心"></a>使用其他核心</h4><p>各核心工作在 <code>/data/adb/box/核心名字</code> 目录，核心名字由 <code>/data/adb/box/scripts/box.config</code> 文件中 <code>bin_name</code> 定义，有效值只有 <code>clash</code>、<code>xray</code>、<code>v2ray</code>、<code>sing-box</code>，bin_name 决定模块启用的核心。——这就是为什么你需要将解压后的可执行文件重命名为clash。</p><h2 id="Clash部分"><a href="#Clash部分" class="headerlink" title="Clash部分"></a>Clash部分</h2><h3 id="配置Clash"><a href="#配置Clash" class="headerlink" title="配置Clash"></a>配置Clash</h3><p>编辑 clash&#x2F;config.yaml 文件，上面的部分无需修改，只需要修改下面的一小部分内容：</p><figure class="highlight yaml"><figcaption><span>clash/config.yaml</span></figcaption><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">proxies:</span></span><br><span class="line"><span class="attr">p:</span> <span class="meta">&amp;p</span></span><br><span class="line">  &#123;<span class="attr">type:</span> <span class="string">http</span>, <span class="attr">interval:</span> <span class="number">3600</span>, <span class="attr">health-check:</span> &#123;<span class="attr">enable:</span> <span class="literal">true</span>, <span class="attr">url:</span> <span class="string">https://www.gstatic.com/generate_204</span>, <span class="attr">interval:</span> <span class="number">300</span>&#125;&#125;</span><br><span class="line"><span class="attr">pr:</span> <span class="meta">&amp;pr</span></span><br><span class="line">  &#123;<span class="attr">type:</span> <span class="string">select</span>, <span class="attr">proxies:</span> [<span class="string">默认</span>, <span class="string">香港</span>, <span class="string">台湾</span>, <span class="string">日本</span>, <span class="string">新加坡</span>, <span class="string">美国</span>, <span class="string">其它地区</span>, <span class="string">全部节点</span>, <span class="string">自动选择</span>, <span class="string">DIRECT</span>]&#125;</span><br><span class="line"></span><br><span class="line"><span class="attr">u:</span> <span class="meta">&amp;u</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">select</span></span><br><span class="line">  <span class="attr">use:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">provider1</span></span><br><span class="line"></span><br><span class="line"><span class="attr">proxy-providers:</span></span><br><span class="line">  <span class="attr">provider1:</span></span><br><span class="line">    <span class="string">&lt;&lt;:</span> <span class="meta">*p</span></span><br><span class="line">    <span class="attr">url:</span> <span class="string">&quot;订阅链接&quot;</span></span><br><span class="line">    <span class="attr">path:</span> <span class="string">./proxy_providers/provider1.yaml</span></span><br></pre></td></tr></table></figure><p>把订阅链接改为你自己的，后返回Magisk，重新加载模块（关闭再启用即可，无需重启设备）。</p><h3 id="控制面板"><a href="#控制面板" class="headerlink" title="控制面板"></a>控制面板</h3><p>访问控制面板<a href="https://yacd.metacubex.one/#/proxies">https://yacd.metacubex.one/#/proxies</a>，在地址栏中输入<code>http://127.0.0.1:9999</code>，然后点击“Add”。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2023/android-transparent-proxy-easiest/yacd.png" data-fancybox="true"/></div></div><p>至此，配置完成。您可以根据需求选择相应节点进行分流，如果不想解锁哔哩哔哩的地区限制，请在该位置选择 DIRECT 模式。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2023/android-transparent-proxy-easiest/proxymng.webp" data-fancybox="true"/></div></div><h2 id="遇到问题？"><a href="#遇到问题？" class="headerlink" title="遇到问题？"></a>遇到问题？</h2><p>模块的运行日志位于<code>/data/adb/box/run/</code>目录下，Clash.Meta的运行日志位于<code>/data/adb/box/clash/</code>目录下，请自行排查！</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;使用 Clash.META 内核最简配置安卓透明代理“Box4Magisk”。&lt;/p&gt;</summary>
    
    
    
    <category term="瞎折腾" scheme="https://c2ics.com/categories/%E7%9E%8E%E6%8A%98%E8%85%BE/"/>
    
    
    <category term="Android" scheme="https://c2ics.com/tags/Android/"/>
    
    <category term="Clash" scheme="https://c2ics.com/tags/Clash/"/>
    
  </entry>
  
  <entry>
    <title>使用NVENC编码OBS推流</title>
    <link href="https://c2ics.com/posts/a61cf9fd3a22/"/>
    <id>https://c2ics.com/posts/a61cf9fd3a22/</id>
    <published>2023-08-14T02:29:02.000Z</published>
    <updated>2023-08-14T02:29:02.000Z</updated>
    
    <content type="html"><![CDATA[<p>简单写个最近发现的东西。</p><p>我使用搭载 i7-12700H 和 RTX 3060 100W 的笔记本电脑，通过OBS进行推流直播到B站。在默认设置下，使用X264软件编码器，游戏帧数在100~160之间波动，这对游戏体验和推流效果都有影响。</p><p>我们可以通过使用NVENC来减轻CPU的负担，在OBS的设置中进行相应配置即可。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/2023/rtx3060-obs-stream/obs-settings.png" alt="OBS设置" data-fancybox="true"/><a class="image-download blur" style="opacity:0" target="_blank" download="OBS设置" href="/assets/articles/2023/rtx3060-obs-stream/obs-settings.png"><svg class="icon" style="width: 1em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3734"><path d="M561.00682908 685.55838913a111.03077546 111.03077546 0 0 1-106.8895062 0L256.23182837 487.72885783a55.96309219 55.96309219 0 0 1 79.13181253-79.18777574L450.70357448 523.88101491V181.55477937a55.96309219 55.96309219 0 0 1 111.92618438 0v344.06109173l117.07478902-117.07478901a55.96309219 55.96309219 0 0 1 79.13181252 79.18777574zM282.81429711 797.1487951h447.70473912a55.96309219 55.96309219 0 0 1 0 111.92618438H282.81429711a55.96309219 55.96309219 0 0 1 0-111.92618438z" p-id="3735"></path></svg></a></div><div class="image-meta"><span class="image-caption center">OBS设置</span></div></div><p>通过将《Apex英雄》的画质设置为最低，稳定保持144帧。</p><!-- flag of hidden posts -->]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;简单写个最近发现的东西。&lt;/p&gt;
&lt;p&gt;我使用搭载 i7-12700H 和 RTX 3060 100W 的笔记本电脑，通过OBS进行推流直播到B站。在默认设置下，使用X264软件编码器，游戏帧数在100~160之间波动，这对游戏体验和推流效果都有影响。&lt;/p&gt;
&lt;p&gt;我们可</summary>
      
    
    
    
    <category term="瞎折腾" scheme="https://c2ics.com/categories/%E7%9E%8E%E6%8A%98%E8%85%BE/"/>
    
    
  </entry>
  
  <entry>
    <title>Hello World</title>
    <link href="https://c2ics.com/posts/4555078a8a8e/"/>
    <id>https://c2ics.com/posts/4555078a8a8e/</id>
    <published>2023-05-18T17:23:00.000Z</published>
    <updated>2023-05-18T17:23:00.000Z</updated>
    
    <content type="html"><![CDATA[<p>Welcome to <a href="https://hexo.io/">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new <span class="string">&quot;My New Post&quot;</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/one-command-deployment.html">Deployment</a></p><!-- flag of hidden posts -->]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;Welcome to &lt;a href=&quot;https://hexo.io/&quot;&gt;Hexo&lt;/a&gt;! This is your very first post. Check &lt;a href=&quot;https://hexo.io/docs/&quot;&gt;documentation&lt;/a&gt; for</summary>
      
    
    
    
    
  </entry>
  
  <entry>
    <title>Win11 TranslucentTB失效</title>
    <link href="https://c2ics.com/posts/871431357c4d/"/>
    <id>https://c2ics.com/posts/871431357c4d/</id>
    <published>2023-03-18T13:37:00.000Z</published>
    <updated>2023-03-27T12:35:00.000Z</updated>
    
    <content type="html"><![CDATA[<p>TranslucentTB 是一款适用于 Win10&#x2F;11 系统的「任务栏透明」工具。然而，微软最近推送 Build 22621 后，该软件无法正常工作。本文将分享一种折中的方法，通过 ViVeTool 禁用新的任务栏，在作者更新软件前保持任务栏透明。</p><p>Build 22563 更新后，TranslucentTB 失效，无论怎么设置都无法使任务栏透明。2023 年 3 月，微软已向稳定通道推送 Build 22621，正常用户也受到影响。</p><p>Github Issue 追踪：<a href="https://github.com/TranslucentTB/TranslucentTB/issues/537">https://github.com/TranslucentTB/TranslucentTB/issues/537</a></p><details class="tag-plugin colorful folding" ><summary><p>可能的问题原因</p></summary><div class="body"><blockquote><p><em>The new update brings a brand new taskbar called Foldable Taskbar. It have a pointer to judge the taskbar is folded. But old version dont have this function, so it’s a null pointer. There is a dilemma in choosing between brand new taskbar without any bug and Translucent TB with a crush while right click on Windows. To use new taskbar, enter “vivetool addconfig 26008830 2” in vivetool. Enter “vivetool delconfig 26008830 2” in vivetool to use old taskbar.</em></p></blockquote><p><a href="https://blogs.windows.com/windows-insider/2022/02/24/announcing-windows-11-insider-preview-build-22563/">Build 22563 更新日志</a>中提到「平板优化的任务栏」(Tablet-optimized taskbar)，可能是这个更改造成的问题。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/translucenttb-malfunctioning/tablet-taskbar-graphic-1024x654-1.png" data-fancybox="true"/></div></div><p>Tablet-optimized taskbar in both collapsed and expanded states.</p><p>也有可能是这个最新的托盘动画导致的….（图源未知）</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/translucenttb-malfunctioning/windowsnewtrayplt.gif" data-fancybox="true"/></div></div></div></details><p>作者提到，自己在学业和生活上比较忙，暂时没有时间适配最新版本的 Windows。因此，我们要么使用新的任务栏，要么重新启用旧任务栏享受透明化。</p><p>我们需要使用 ViVeTool 来禁用最新的任务栏。</p><div class="tag-plugin grid" bg="block" style="grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));"><div class="cell" style="">    <div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/translucenttb-malfunctioning/contextmenu.png" data-fancybox="true" style="width:100px;"/></div></div>    </div>    <div class="cell" style="">    <p>按住 <kbd>⊞ Windows</kbd> + <kbd>X</kbd> 或者 右键任务栏中的 Windows 徽标，选择「终端**（管理员）**」，依次键入以下命令：</p>    </div>    </div><figure class="highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">iwr</span> https://github.com/thebookisclosed/ViVe/releases/download/v0.<span class="number">3.2</span>/ViVeTool<span class="literal">-v0</span>.<span class="number">3.2</span>.zip <span class="literal">-OutFile</span> vive.zip  <span class="comment"># 下载工具</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">Expand-Archive</span> vive.zip <span class="comment"># 解压工具</span></span><br><span class="line"></span><br><span class="line">./vive/vivetool.exe /disable /id:<span class="number">26008830</span> /variant:<span class="number">2</span> <span class="comment"># 使用工具设置任务栏</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">ri</span> <span class="literal">-Recurse</span> vive*.*   <span class="comment"># 删除下载的工具</span></span><br></pre></td></tr></table></figure><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/translucenttb-malfunctioning/WindowsTerminal_c8WutsdMz0.png" alt="成功禁用新任务栏" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">成功禁用新任务栏</span></div></div><p>出现 <code>Successfully set feature configuration(s)</code> 后<strong>重启电脑</strong>，即可正常使用 TranslucentTB。</p><details class="tag-plugin colorful folding" ><summary><p>其他方法</p></summary><div class="body"><p>如果你有 Vivetool，那么直接执行 vivetool.exe &#x2F;disable &#x2F;id:26008830 &#x2F;variant:2 即可。</p><p>如果你倾向使用包管理器，可以通过 Scoop 等包管理器安装 ViVeTool：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">scoop bucket add extras</span><br><span class="line">scoop install vivetool</span><br><span class="line">vivetool /disable /id:26008830 /variant:2</span><br></pre></td></tr></table></figure></div></details><div class="tag-plugin colorful note" color="yellow"><div class="title"><strong><p>警告</p></strong></div><div class="body"><p>使用 ViVeTool 修改系统有风险，微软在未来可能会删除旧版本的任务栏，届时您的资源管理器将无法正确运行（可能会黑屏）。<br>要重新启用新任务栏，请输入命令 <code>vivetool /enable /id:26008830</code>。</p></div></div><!-- flag of hidden posts -->]]></content>
    
    
    <summary type="html">TranslucentTB 是一款适用于 Win10/11 系统的“任务栏透明”工具。然而，微软最近推送 Build 22621 后，该软件无法正常工作。本文将分享一种折中的方法，通过 ViVeTool 禁用新的任务栏，在作者更新软件前保持任务栏透明。</summary>
    
    
    
    <category term="Tech" scheme="https://c2ics.com/categories/Tech/"/>
    
    
    <category term="Windows" scheme="https://c2ics.com/tags/Windows/"/>
    
  </entry>
  
  <entry>
    <title>C# field 半自动实现属性</title>
    <link href="https://c2ics.com/posts/a8fdba0a8281/"/>
    <id>https://c2ics.com/posts/a8fdba0a8281/</id>
    <published>2023-01-06T08:20:00.000Z</published>
    <updated>2023-03-17T14:44:00.000Z</updated>
    
    <content type="html"><![CDATA[<div class="tag-plugin colorful note" color="yellow"><div class="title"><strong><p>现在还用不了^_^</p></strong></div><div class="body"><p>原计划 C#11 可用，后来跳票到 C#12，不确定何时可用。</p></div></div><p>在C#3中我们拥有了<em>自动实现属性</em>，编译器自动生成一个匿名、私有的字段来保存值，仅访问器可使用。</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="built_in">string</span> Prop &#123; <span class="keyword">get</span>; <span class="keyword">set</span>; &#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// in the background...</span></span><br><span class="line">[<span class="meta">CompilerGenerated</span>]</span><br><span class="line"><span class="keyword">private</span> <span class="built_in">string</span> &lt;Prop&gt;k__BackingField;</span><br></pre></td></tr></table></figure><p>但我们有时候要给Getter和Setter添加自定义逻辑，例如</p><ul><li>验证输入值是否合法</li><li>通知值已更新（…<code>INotifyPropertyChanged.PropertyChanged</code>）</li></ul><p>这时<em>自动实现属性</em>便无法胜任，只能使用传统写法，自己创建一个字段：</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="built_in">string</span> _prop;</span><br><span class="line"><span class="keyword">public</span> <span class="built_in">string</span> Prop</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">get</span> =&gt; _prop;</span><br><span class="line">    <span class="keyword">set</span></span><br><span class="line">    &#123;</span><br><span class="line">        ArgumentException.ThrowIfNullOrEmpty(<span class="keyword">value</span>, <span class="keyword">nameof</span>(Prop));</span><br><span class="line">        _prop = <span class="keyword">value</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这样做后有这样几个问题：</p><ol><li><code>_prop</code> 可以被类中其他部分访问，有潜在隐患。</li><li>增加了代码量，可读性下降。</li></ol><p>在即将到来的 C# 12 中，我们可以使用 <code>field</code> 关键字，来实现<em>半自动属性</em>。半自动属性与全自动属性类似，编译器都会生成辅助字段，<strong>但该字段可以在访问器块中使用 <code>field</code> 来访问</strong>。因此，我们的代码可以简化成：</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="built_in">string</span> Prop</span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// No more _prop, compiler generates it automatically accessed by the `field` keyword.</span></span><br><span class="line">    <span class="keyword">get</span> =&gt; field; </span><br><span class="line">    <span class="keyword">set</span></span><br><span class="line">    &#123;</span><br><span class="line">        ArgumentException.ThrowIfNullOrEmpty(<span class="keyword">value</span>, <span class="keyword">nameof</span>(Prop));</span><br><span class="line">        field = <span class="keyword">value</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/csharp-next-semiautoprops/sharplabio-field.png" alt="SharpLab.io&nbsp;C#&nbsp;and&nbsp;decompiled&nbsp;c#&nbsp;code&nbsp;of&nbsp;field&nbsp;keyword" data-fancybox="true"/><a class="image-download blur" style="opacity:0" target="_blank" download="SharpLab.io&nbsp;C#&nbsp;and&nbsp;decompiled&nbsp;c#&nbsp;code&nbsp;of&nbsp;field&nbsp;keyword" href="/assets/articles/old/csharp-next-semiautoprops/sharplabio-field.png"><svg class="icon" style="width: 1em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3734"><path d="M561.00682908 685.55838913a111.03077546 111.03077546 0 0 1-106.8895062 0L256.23182837 487.72885783a55.96309219 55.96309219 0 0 1 79.13181253-79.18777574L450.70357448 523.88101491V181.55477937a55.96309219 55.96309219 0 0 1 111.92618438 0v344.06109173l117.07478902-117.07478901a55.96309219 55.96309219 0 0 1 79.13181252 79.18777574zM282.81429711 797.1487951h447.70473912a55.96309219 55.96309219 0 0 1 0 111.92618438H282.81429711a55.96309219 55.96309219 0 0 1 0-111.92618438z" p-id="3735"></path></svg></a></div><div class="image-meta"><span class="image-caption center">SharpLab.io&nbsp;C#&nbsp;and&nbsp;decompiled&nbsp;c#&nbsp;code&nbsp;of&nbsp;field&nbsp;keyword</span></div></div><p>完整代码：</p><figure class="highlight csharp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">namespace</span> <span class="title">SemiAutoProperty</span>;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">using</span> System;</span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title">User</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// Use of field: semi-auto property.</span></span><br><span class="line">    <span class="comment">// In this case, a constraint is applied to setter.</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">required</span> <span class="built_in">string</span> Name</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">get</span> =&gt; field;</span><br><span class="line">        <span class="keyword">set</span></span><br><span class="line">        &#123;</span><br><span class="line">            ArgumentException.ThrowIfNullOrEmpty(<span class="keyword">value</span>, <span class="keyword">nameof</span>(Prop));</span><br><span class="line">            field = <span class="keyword">value</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// No accessor body: auto property. </span></span><br><span class="line">    <span class="keyword">public</span> <span class="built_in">string</span> Nickname &#123;<span class="keyword">get</span>; <span class="keyword">set</span>;&#125; = String.Empty;</span><br><span class="line"> </span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">User</span>()</span> &#123;&#125;</span><br><span class="line"> </span><br><span class="line">    [<span class="meta">System.Diagnostics.CodeAnalysis.SetsRequiredMembers</span>]</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">User</span>(<span class="params"><span class="built_in">string</span> name</span>):<span class="title">this</span>()</span> =&gt; Name = name;</span><br><span class="line">&#125;</span><br><span class="line"> </span><br><span class="line"><span class="keyword">internal</span> <span class="keyword">static</span> <span class="keyword">class</span> <span class="title">Program</span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">Main</span>()</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">var</span> f = <span class="keyword">new</span> User()</span><br><span class="line">        &#123;</span><br><span class="line">           Name=<span class="string">&quot;John&quot;</span>,</span><br><span class="line">        &#125;;</span><br><span class="line">        Console.WriteLine(f.Name);</span><br><span class="line"> </span><br><span class="line">        <span class="keyword">try</span></span><br><span class="line">        &#123;</span><br><span class="line">            f.Name = <span class="string">&quot;&quot;</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">catch</span> (ArgumentException)</span><br><span class="line">        &#123;</span><br><span class="line">            Console.WriteLine(<span class="string">&quot;ArgumentException Thrown&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><div class="tag-plugin colorful note" color="blue"><div class="title">P.S.</div><div class="body"><p>这段代码还用到了一个required关键字，搜索一下就知道怎么用啦。</p></div></div><!-- flag of hidden posts -->]]></content>
    
    
    <summary type="html">半自动属性可自动生成背后的辅助字段，简化你的代码。此特性预计在 C#12 中添加。</summary>
    
    
    
    <category term="Tech" scheme="https://c2ics.com/categories/Tech/"/>
    
    
    <category term="CSharp" scheme="https://c2ics.com/tags/CSharp/"/>
    
  </entry>
  
  <entry>
    <title>Cloudflare 的神奇故障</title>
    <link href="https://c2ics.com/posts/1a939856b8d9/"/>
    <id>https://c2ics.com/posts/1a939856b8d9/</id>
    <published>2022-12-28T01:31:00.000Z</published>
    <updated>2022-12-28T01:31:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="TL-DR"><a href="#TL-DR" class="headerlink" title="TL;DR"></a>TL;DR</h2><p>Cloudflare 后台 API 认证错误，账户可以正常登陆，但无法操作任何资源。工单中给出的回复：重新创建账户，重新导入站点。但这会丢失所有数据！</p><h2 id="事发经过"><a href="#事发经过" class="headerlink" title="事发经过"></a>事发经过</h2><p>今晚，我通过 Cloudflare 面板更新了账户名称（dashboard→manage account→configurations→preferences→account name）。随后，面板下方不停弹出 Authentication Error (Code: 10000)，我失去了我账户所有资源的访问权限，好在站点仍可正常运行，只是不能更改 DNS 等设置。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/cloudflare-drove-me-crazy/cloudflare-authentication-error.png" alt="Cloudflare的错误信息" data-fancybox="true"/><a class="image-download blur" style="opacity:0" target="_blank" download="Cloudflare的错误信息" href="/assets/articles/old/cloudflare-drove-me-crazy/cloudflare-authentication-error.png"><svg class="icon" style="width: 1em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3734"><path d="M561.00682908 685.55838913a111.03077546 111.03077546 0 0 1-106.8895062 0L256.23182837 487.72885783a55.96309219 55.96309219 0 0 1 79.13181253-79.18777574L450.70357448 523.88101491V181.55477937a55.96309219 55.96309219 0 0 1 111.92618438 0v344.06109173l117.07478902-117.07478901a55.96309219 55.96309219 0 0 1 79.13181252 79.18777574zM282.81429711 797.1487951h447.70473912a55.96309219 55.96309219 0 0 1 0 111.92618438H282.81429711a55.96309219 55.96309219 0 0 1 0-111.92618438z" p-id="3735"></path></svg></a></div><div class="image-meta"><span class="image-caption center">Cloudflare的错误信息</span></div></div><p>我尝试了很多方法，包括但不限于：</p><ul><li>清除浏览器缓存</li><li>重启电脑</li><li>使用代理在不同地域访问我的账户（Asia&#x2F;HK,TW,CN,SG,JP; Na&#x2F;CA,US; Eu&#x2F;ENG,FR;）</li><li>重新登录</li><li>更换设备</li><li>更换浏览器</li><li>浏览器使用匿名模式（–incognito）</li></ul><p>均无效。</p><p>我还看了一下 DevTools，发现只有关于“计费和订阅”的 API 返回认证错误。</p><p><a href="https://dash.cloudflare.com/api/v4/accounts/%7Bid%7D">https://dash.cloudflare.com/api/v4/accounts/{id}</a></p><ul><li>&#x2F;subscriptions</li><li>&#x2F;billing&#x2F;history?page&#x3D;1&amp;status&#x3D;OPEN</li><li>&#x2F;billing&#x2F;bad-debt</li><li>&#x2F;payment-methods</li><li>&#x2F;billing&#x2F;credits</li><li>&#x2F;billing&#x2F;pre-verification-captcha</li><li>&#x2F;billing&#x2F;profiles</li></ul><p>其余 API 均返回成功结果，还包含了正确的权限信息。例如 <code>/memberships</code> 返回的 JSON 对象中，<code>result[0].permissions</code> 全部权限项 <code>read/edit</code> 的值为 <code>true</code>、<code>roles</code>为 <code>[&quot;Super Administrator - All Privileges&quot;]</code>。</p><h2 id="解决方案"><a href="#解决方案" class="headerlink" title="解决方案"></a>解决方案</h2><p>提交工单，CF给我的回复是…</p><details class="tag-plugin colorful folding" color="yellow" open><summary><p>回复原文</p></summary><div class="body"><p>Hi there,</p><p>thank you for contacting Cloudflare.</p><p>Sorry to hear you are experiencing issues here.</p><p>Please delete the account and re create the account adding your domain.</p><ol><li><p>See: Delete Account</p></li><li><p>See: Add Site to Cloudflare</p></li></ol></div></details><p>让我重新创建账户并导入站点。</p><p>这是不可接受的，因为删除账户等于删除一切配置和记录，Web Analytics、DNS设置、Workers都会丢失！<u>然而我不得不这样做。</u></p><h2 id="这不是个例"><a href="#这不是个例" class="headerlink" title="这不是个例"></a>这不是个例</h2><p><a href="https://community.cloudflare.com/t/website-authentication-errors-after-email-change/445995">https://community.cloudflare.com/t/website-authentication-errors-after-email-change/445995</a></p><h2 id="教训"><a href="#教训" class="headerlink" title="教训"></a>教训</h2><p>这件事给我了一个教训：<mark class="tag-plugin colorful mark" color="cyan">Don’t touch, it works.</mark> 永远不要手贱去修改无需修改且正常工作的东西。我是 Free Plan 用户，无法得到高级别的支持服务。</p>]]></content>
    
    
    <summary type="html">Cloudflare的奇怪错误使我丢失了我的站点信息</summary>
    
    
    
    <category term="日常" scheme="https://c2ics.com/categories/%E6%97%A5%E5%B8%B8/"/>
    
    
    <category term="Cloudflare" scheme="https://c2ics.com/tags/Cloudflare/"/>
    
  </entry>
  
  <entry>
    <title>我也阳了</title>
    <link href="https://c2ics.com/posts/9cfb2d2ee58e/"/>
    <id>https://c2ics.com/posts/9cfb2d2ee58e/</id>
    <published>2022-12-22T01:39:00.000Z</published>
    <updated>2022-12-22T01:39:00.000Z</updated>
    
    <content type="html"><![CDATA[<p>诶您别说，这不前些日子国家疫情放开吗，网课足不出户的我居然阳了。</p><span id="more"></span><p>这是下水道传来的病毒吗<span class="tag-plugin emoji"><img no-lazy="" class="inline" src="https://gcore.jsdelivr.net/gh/cdn-x/emoji/tieba/呀咩爹.png"/></span>？</p><mark class="tag-plugin colorful mark" color="green">注：封面图片来源参见文章末尾“参考资料”列表</mark><h2 id="药"><a href="#药" class="headerlink" title="药"></a>药</h2><p>周边的药店早已售罄，幸好并未出现哄抬物价的情况。</p><p>最首先被抢购一空的是连花清瘟胶囊，我对其效果并不抱有信心，所以只购买了些许退烧药，和一盒清火的中药。</p><p>我还购买了二十支抗原试剂，花了不少人民币，结果还真用上了……</p><h2 id="阳？"><a href="#阳？" class="headerlink" title="阳？"></a>阳？</h2><p>早晨醒来，感觉身体热得难以忍受，下床后双腿一软，差点以后仰的姿态摔倒。体温计测了一下，38.2℃，看来今天什么也做不了了。虽然难受，但我不想吃药。请完假后，在床上打开网课会议，想着：“能听多少就听多少吧。”，没过多久竟然睡着了，幸好没开摄像头。醒来一看，体温不降反升，连忙服用一颗布洛芬，大约一小时后体温恢复正常，身体也不再难受。</p><p>阳性的前三天，大概就是如此反复发烧——吃药——退烧度过的。</p><p>发烧过后，嗓子开始疼痛。那感觉像吞下玻璃碎片一样疼痛难忍，每一次下咽都要做好充分的心理准备！</p><p>最后，味、嗅觉丧失，整个人无精打采，食欲下降，属实折磨。</p><h2 id="阴。"><a href="#阴。" class="headerlink" title="阴。"></a>阴。</h2><p>距离第一天发烧一周后，上述症状逐步消失。拿出抗原试剂测了一下，阴性。</p><p>没什么特别的感受，疫情放开了，早晚都会阳，只是时间问题。早阳早受罪，趁着这段时间高峰期，挺过去便无事发生，后面应该问题不大。</p><p>你问我支不支持开放政策？我当然支持，人们再也不需要提心吊胆，生怕自己阳了，耽误了身边的所有人；更不用害怕无处不在的健康码，哪怕是一个密接，就要暂停手头的所有工作，进入酒店集中隔离，也不再会排长队核酸检测了——</p><p>可这只是对我自己而言，因为我身边没有因此去世的朋友、家人。每一个数字的背后都是一个家庭，节哀！</p><h2 id="一些现象，仅做记录"><a href="#一些现象，仅做记录" class="headerlink" title="一些现象，仅做记录"></a>一些现象，仅做记录</h2><p>网络上能看到布洛芬的稀缺，某儿童医院门口出现黄牛，兜售数千元一瓶的儿童退烧药，仍有人购买。各大医院医疗资源紧张，挂号排队，挂出号，才只是开始，因为前方还有数百人排队。</p><p>看同学发的朋友圈，这几天物流和外卖系统近乎瘫痪，中午订的外卖，吃晚饭时才有骑手接单，而自己在京东购买的商品，已在快递网点停留数天，毫无动静。</p><p>仅做记录，没有评论哦。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;诶您别说，这不前些日子国家疫情放开吗，网课足不出户的我居然阳了。&lt;/p&gt;</summary>
    
    
    
    <category term="日常" scheme="https://c2ics.com/categories/%E6%97%A5%E5%B8%B8/"/>
    
    
    <category term="COVID19" scheme="https://c2ics.com/tags/COVID19/"/>
    
  </entry>
  
  <entry>
    <title>bitcoin-learning-old</title>
    <link href="https://c2ics.com/posts/682a2503d8ba/"/>
    <id>https://c2ics.com/posts/682a2503d8ba/</id>
    <published>2022-12-10T14:29:00.000Z</published>
    <updated>2023-06-01T13:15:29.000Z</updated>
    
    <content type="html"><![CDATA[<div class="tag-plugin colorful note" color="warning"><div class="title"><strong><p>Warning</p></strong></div><div class="body"><p>This article is a total 100% piece of s^_^t that only myself can understand it.</p><p>I kindly request you to close the tab and <strong>refrain from reading more</strong>.</p></div></div><p><a href="https://www.bilibili.com/video/BV1Vt411X7JF">北京大学肖臻老师《区块链技术与应用》公开课</a></p><p><a href="https://www.bilibili.com/video/BV1FL411K7vK">【普林斯顿公开课】比特币与加密货币技术</a></p><p><a href="https://www.youtube.com/playlist?list=PLQIX_E46U4XYE5GR6029FpnaX9aBXbt0B">Youtube <strong>Princeton Bitcoin&#x2F;Blockchain Course</strong></a></p><p>Bitcoin is a blockchain-based cryptocurrency. Block addresses, transaction values, and other information are all made public on the blockchain. Hash and signature are the two cryptographic concepts that Bitcoin primarily uses.</p><h2 id="Hash-function"><a href="#Hash-function" class="headerlink" title="Hash function"></a>Hash function</h2><p>A hash function accepts any string( or bitstream ) as input, and outputs a fixed-length string. It is efficiently computable, thus it can be used extensively.</p><h3 id="Security-properties"><a href="#Security-properties" class="headerlink" title="Security properties"></a>Security properties</h3><p>Each of the hash functions MUST meet these standards:</p><ul><li>Collision-free</li><li>Hiding</li><li>Puzzle-friendly</li></ul><h4 id="Collision-free"><a href="#Collision-free" class="headerlink" title="Collision-free"></a>Collision-free</h4><p>We define a collsion that</p><p>$ a ≠ b\space and\space H(a) &#x3D; H(b) $</p><p>Commonly, collisions can be discovered using the following methods:</p><ol><li>Brute-force: Calculates all potential inputs.</li><li>Identify exploits in hash functions.</li></ol><p>It is unavoidable since a hash function maps inifinite inputs to finite outputs. However, being collision-free does not mean there is no collision. It actually means that no one can <strong>FIND</strong> a collision because it is extremely hard to find it.</p><p>Therefore, we choose to believe it has no collisions</p><p>$H(x)&#x3D;H(y)$, it is safe to assume that $x&#x3D;y$.</p><p>What can hash do?</p><ul><li>Message digest: to check whether or not the message has been altered.</li></ul><h4 id="Hiding"><a href="#Hiding" class="headerlink" title="Hiding"></a>Hiding</h4><p>Given $H(x)$, it is infeasible to find $x$. Hash functions should be one-way.</p><p>The prerequisite is that $x$ must be taken from a fairly wide range in order to guarantee hiding. If not, we must concatenate a $nonce$ from a probability distribution with a <em>high-min entropy</em>, such as a set of 256-bit values, and then perform hash operations like $H(nonce||\space x)$.</p><h3 id="Puzzle-friendly"><a href="#Puzzle-friendly" class="headerlink" title="Puzzle-friendly"></a>Puzzle-friendly</h3><p>For every possible output value $y$, if $k$ is chosen from a distribution with high min-entropy, then it is infeasible to find $x$ such that $H(k\space ||\space x)&#x3D;y$.</p><p>There is no solving strategy that is much better than trying random values of $x$.</p><p>In summary, it have to be arduous to solve, but easy to verify.</p><h3 id="SHA-256"><a href="#SHA-256" class="headerlink" title="SHA-256"></a>SHA-256</h3><p>Secure hash algorithm 256-bit, <em>SHA-256</em>, which the bitcoin uses.</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/sha256.webp" alt="SHA-256 Working Mechanism" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">SHA-256 Working Mechanism</span></div></div><h2 id="Hash-pointers"><a href="#Hash-pointers" class="headerlink" title="Hash pointers"></a>Hash pointers</h2><p>Hash pointers is NOT a pointer, it is a <strong>STRUCT</strong> that contains a pointer to the previous block and a hash of that block.</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/Hash_Pointer.png" alt="Hash Pointer" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">Hash Pointer</span></div></div><h3 id="Blockchain"><a href="#Blockchain" class="headerlink" title="Blockchain"></a>Blockchain</h3><p>Most data structures, including <em>Chained List</em>( for example the Blockchain ), can be constructed using hash pointers.</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/Blockchain.webp" alt="Blockchain" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">Blockchain</span></div></div><p>The initial block produced by the system is known as the <em>Genesis Block</em>, and the most recent block we added, is pointed to by a hash pointer that we should remember and record.</p><h3 id="Tampering-Detection-in-Blockchain"><a href="#Tampering-Detection-in-Blockchain" class="headerlink" title="Tampering Detection in Blockchain"></a>Tampering Detection in Blockchain</h3><p>We can quickly determine whether the entire chain has been modified thanks to the hash pointers.</p><p>Consider the scenario when an attacker changed data in Block 2. However, block 3 contains a hash pointer that points to block 2 and stores a hash of it; since the current hash differs from that stored there, we can infer that the data in block 2 has been altered.<br>Attackers must edit block 3, block 4, all the way to the final block in order to continue the story. The final block, though, is what we remebered and recorded, so attackers cannot modify it!</p><h3 id="Merkle-Tree"><a href="#Merkle-Tree" class="headerlink" title="Merkle Tree"></a>Merkle Tree</h3><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/merkle-tree.webp" alt="Merkle tree" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">Merkle tree</span></div></div><p>A binary tree with hash pointers.</p><p>Advantages:</p><ul><li>It is easier to demonstrate membership in it through $\Theta(\log{}n)$ time and space.</li></ul><p>Variant: Sorted Merkle tree.</p><ul><li>Can verify non-membership in $\Theta(\log{}n)$.</li></ul><h3 id="Not-a-cycle"><a href="#Not-a-cycle" class="headerlink" title="Not a cycle"></a>Not a cycle</h3><p>You can replace plain pointers to hash pointers in any pointer-based data structure <strong>WITHOUT CYCLES</strong>. Because hashes in cycled structure couldn’t match.</p><h2 id="Digital-Signatures"><a href="#Digital-Signatures" class="headerlink" title="Digital Signatures"></a>Digital Signatures</h2><p>What we desire:</p><ul><li>Anyone can verify, but only you can sign.</li><li>A signature is attached to a certain document and cannot be copied and pasted to another.</li></ul><p>Generate a pair – <code>(secret signing key, public verification key)</code>. Use a secret key to sign a message, and returns a signature. Publish your public key to anyone who wants to verify the message, so they can easily verify your message using the public key, message, and signature.</p><p>Requirements:</p><ul><li>Valid signatures verify</li></ul><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">verify(public_key, message, sign(secret_key, message)) == <span class="literal">true</span></span><br></pre></td></tr></table></figure><ul><li>can’t forge signatures</li></ul><p>An adversary who knows the public key and gets to see signatures on messages of his choice can’t produce a verifiable signature on another message. <strong>Attackers can’t forge a message with a valid signature.</strong></p><p>Practical things…</p><ul><li>Algorithms are randomized: If not, the private key might be leaked.</li><li>Limit on message size: fix – Hash(message)</li></ul><h3 id="Sign-a-hash-pointer"><a href="#Sign-a-hash-pointer" class="headerlink" title="Sign a hash pointer"></a>Sign a hash pointer</h3><p>Not to sign the STRUCT, but to sign the whole previous chain.</p><h3 id="ECDSA"><a href="#ECDSA" class="headerlink" title="ECDSA"></a>ECDSA</h3><p>Elliptic Curve Digital Signature Algorithm.</p><p>It is a standard that relies on hairy math and has good randomness.</p><p>Bitcoin uses the ECDSA standard.</p><h3 id="Public-Keys-as-Identities"><a href="#Public-Keys-as-Identities" class="headerlink" title="Public Keys as Identities"></a>Public Keys as Identities</h3><p>If <code>verify(public_key, message, signature) == true</code>, then we can think: public_key says “{message}”. To speak as public_key, you need to know private_key to sign your message.</p><h4 id="How-to-make-a-new-identity"><a href="#How-to-make-a-new-identity" class="headerlink" title="How to make a new identity"></a>How to make a new identity</h4><p>Create a new random key pair <code>(secret_key,public_key)</code>. <code>public_key</code> is your public “name” you can use (usually better to use <code>Hash(public_key)</code>, while <code>secret_key</code> lets you “speak for” the identity.</p><p>Since only you know the <code>secret_key</code>, you are in charge of the identity.</p><h4 id="Decentralized-identity-management"><a href="#Decentralized-identity-management" class="headerlink" title="Decentralized identity management"></a>Decentralized identity management</h4><p>Anybody can create as many different identities as they wish at any moment.</p><p>No central point of control, and no one can control you.</p><p><strong>These identities are called *addresses* in Bitcoin</strong>. The address is a public key or a hash of the public key.</p><h4 id="Privacy"><a href="#Privacy" class="headerlink" title="Privacy"></a>Privacy</h4><p>Addresses are not directly related to a person’s identity in the actual world.<br>But observers can infer your identity by your behavioral pattern over time.</p><h3 id="A-Simple-Cryptocurrency"><a href="#A-Simple-Cryptocurrency" class="headerlink" title="A Simple Cryptocurrency"></a>A Simple Cryptocurrency</h3><h4 id="A-Very-Simple-Coin"><a href="#A-Very-Simple-Coin" class="headerlink" title="A-Very-Simple-Coin"></a>A-Very-Simple-Coin</h4><ul><li>Admin can create new coins. New coins belong to him.</li></ul><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/simple-coin-create.webp" alt="Create" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">Create</span></div></div><ul><li>Coin owners can pay them to someone.</li></ul><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/simple-coin-trade.webp" alt="Trade" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">Trade</span></div></div><h5 id="Double-spending-attack"><a href="#Double-spending-attack" class="headerlink" title="Double-spending attack"></a>Double-spending attack</h5><p>The coin owner can pay one coin to multiple identities without awareness.</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/double-spending.webp" alt="Double-Spending Attack" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">Double-Spending Attack</span></div></div><h4 id="A-Better-Coin"><a href="#A-Better-Coin" class="headerlink" title="A-Better-Coin"></a>A-Better-Coin</h4><p>The admin will publish a history of all transactions by a signed blockchain. Every block is marked with a transaction ID.</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/better-coin-chain.webp" alt="Better coin chain" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">Better coin chain</span></div></div><p>Coins Creation:</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/better-coincreate.webp" alt="Better creation" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">Better creation</span></div></div><p>Trade:</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/better-coin-pay.webp" alt="Better payment" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">Better payment</span></div></div><h4 id="Coins-are-Immutable"><a href="#Coins-are-Immutable" class="headerlink" title="Coins are Immutable"></a>Coins are Immutable</h4><p>Coins can’t be transferred, subdivided, or combined.</p><p>However, you can perform these activities using transactions, like subdividing.</p><p>You can start a new transaction, spend your coin, and pay out <strong>TWO NEW COINS</strong> to yourself since transactions work by consuming old coins and producing new coins with an identical total value.</p><h3 id="Centralized-Problem"><a href="#Centralized-Problem" class="headerlink" title="Centralized Problem"></a>Centralized Problem</h3><p>In these two case, every transaction must be <strong>SIGNED BY THE ADMIN, AND THE ADMIN MUST BE RELIABLE.</strong> If he wants to mess it up, he can simply stop signing or sign the wrong blocks.</p><hr><h2 id="Decentralization"><a href="#Decentralization" class="headerlink" title="Decentralization"></a>Decentralization</h2><p>I want to start by stating that hardly any systems are actually decentralized or centralized.</p><p>For instance, webmail services are centralized, despite the fact that email uses a decentralized protocol (SMTP).</p><p>Aspects of decentralization in Bitcoin:</p><ol><li>Who maintains the ledger?</li><li>Who has authority over which transactions are valid?</li><li>Who creates new bitcoins?</li><li>Who determines how the rules of the system change?</li><li>How do bitcoins acquire exchange value?</li></ol><p>Other centralized things <strong>BEYOND PROTOCOL</strong>: exchanges, wallet software, and service providers.</p><ul><li>P2P: open to anyone, low barrier to entry.</li><li>Mining: open to anyone, but need high costs.</li><li>Updates to software: core developers trusted by the community, have great power.</li></ul><h2 id="Distributed-consensus"><a href="#Distributed-consensus" class="headerlink" title="Distributed consensus"></a>Distributed consensus</h2><p>A distributed system may have a massive amount of nodes. Values in each node have to be the same.</p><h3 id="Bitcoin-is-a-peer-to-peer-system"><a href="#Bitcoin-is-a-peer-to-peer-system" class="headerlink" title="Bitcoin is a peer-to-peer system"></a>Bitcoin is a peer-to-peer system</h3><p>When a person wants to pay another person, he or she broadcasts the transaction to all Bitcoin nodes.</p><p>The one who received Bitcoin doesn’t need to run a Bitcoin node to receive the Bitcoin.</p><h3 id="How-consensus-could-work-in-Bitcoin"><a href="#How-consensus-could-work-in-Bitcoin" class="headerlink" title="How consensus could work in Bitcoin"></a>How consensus could work in Bitcoin</h3><p>At any given time:</p><ul><li>All nodes have a sequence of blocks of transactions they’ve reached a consensus on</li><li>Each node has a set of outstanding transactions it’s heard about.</li></ul><h3 id="Consensus-is-hard"><a href="#Consensus-is-hard" class="headerlink" title="Consensus is hard"></a>Consensus is hard</h3><ul><li>Nodes may be malicious</li><li>Nodes may crash</li><li>Network is imperfect<ul><li>Not all pairs of nodes connected</li><li>Faults in network</li><li><strong>Latency</strong></li></ul></li></ul><p><strong>Impossibility results:</strong></p><ul><li>Byzantine generals problem.</li><li>Fischer-Lynch-Paterson: consensus impossible with a single faulty node.</li></ul><p><strong>Well-known protocols: Paxos</strong></p><p>Paxos never produces an inconsistent result, but can rarely get stuck.</p><p>These results say more about the model than about the problem. The models were developed to study the system of distributive databases. <strong>Bitcoin consensus works better in practice than in theory.</strong></p><p>But theory is important, can help us predict unforeseen attacks.</p><h4 id="Some-things-Bitcoin-does-differently"><a href="#Some-things-Bitcoin-does-differently" class="headerlink" title="Some things Bitcoin does differently"></a>Some things Bitcoin does differently</h4><ul><li>Introduces incentives: possible only because it is a currency.</li><li>Embraces randomness.<ul><li>Does away with the notion of a specific end-point.</li><li>Consensus happens over long time scales – about 1 hour.</li></ul></li></ul><p>The probability of your transactions being merged into the consensus blockchain rises as time goes on, at the end, you won’t say it’s 100%, but the probability of you’re wrong goes to a very small value. This is a kind of guarantee that Bitcoin gives you.</p><h3 id="Consensus-without-identity"><a href="#Consensus-without-identity" class="headerlink" title="Consensus without identity"></a>Consensus without identity</h3><p>Every bitcoin node does not have a long-lasting identity.</p><h4 id="Why-identity"><a href="#Why-identity" class="headerlink" title="Why identity?"></a>Why identity?</h4><ul><li>Pragmatic: some protocols need node IDs.</li><li>Security: assume less than 50% nodes are malicious.</li></ul><h4 id="Why-don’t-Bitcoin-nodes-have-identities"><a href="#Why-don’t-Bitcoin-nodes-have-identities" class="headerlink" title="Why don’t Bitcoin nodes have identities?"></a>Why don’t Bitcoin nodes have identities?</h4><ol><li>Identity is hard in a P2P system — it is decentralized, and no authorities could prove it. (Sybil attack)</li><li>Pseudonymity is the goal of Bitcoin.</li></ol><h3 id="A-simplified-consensus-algorithm"><a href="#A-simplified-consensus-algorithm" class="headerlink" title="A simplified consensus algorithm"></a>A simplified consensus algorithm</h3><ol><li>New transactions are broadcast to all nodes.</li><li>Each node collects new transactions into a block.</li><li>In each round, a <strong>random</strong> node gets to broadcast its block.</li><li>Other nodes accept the block only if all transactions in it are valid (unspent, valid signatures..).</li><li>Nodes express their acceptance of the block silently by including its hash in the next block they create.</li></ol><h4 id="What-can-a-malicious-node-do"><a href="#What-can-a-malicious-node-do" class="headerlink" title="What can a malicious node do?"></a>What can a malicious node do?</h4><p>Double-spending attack.</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/doublesp-attack-of-consensus.webp" alt="double spending attack" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">double spending attack</span></div></div><p><strong>The one that nodes previously got will be preferred</strong>. But we are unsure whether transaction is earlier due to the latency. It is easy to get completely opposite results.</p><p>If the next node proposes to extend the bad block, the longest valid chain will contain the bad block, and the chain that holds the good block will be ignored.</p><h4 id="How-to-solve-it"><a href="#How-to-solve-it" class="headerlink" title="How to solve it?"></a>How to solve it?</h4><p>In this case, the receiver trusts the attacker, he accepts the trade once he hears about the Bitcoin transaction with 0 confirmations.</p><p>He can wait until the following block is suggested. to determine whether the faulty block is exisited or continued.</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/confirmations-to-avoid-doublespending.webp" alt="confirmations to avoid Double spending attacking" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">confirmations to avoid Double spending attacking</span></div></div><p>With more confirmations, there is an exponentially lower chance of double spending. The most common heuristic: wait for 6 confirmations.</p><h2 id="Incentives-and-PoW"><a href="#Incentives-and-PoW" class="headerlink" title="Incentives and PoW"></a>Incentives and PoW</h2><p>Can we penalize the node that created the malicious block? No, because nodes have no identity.</p><p>Can we reward nodes that created honest blocks? Yes, by giving them Bitcoin.</p><h3 id="Incentive-1-block-reward"><a href="#Incentive-1-block-reward" class="headerlink" title="Incentive 1: block reward"></a>Incentive 1: block reward</h3><p>The creator of the block gets to…</p><ul><li>include a special coin-creation transaction in the block</li><li>choose the recipient address of this transaction</li></ul><p>The Block creator gets to collect the reward <strong>only if the block ends up on a long-term consensus branch</strong>.</p><p>Reward value: currently (At 2022) 6.25 BTC, halves every 4 years.</p><p>Therefore, there is a limited supply of bitcoins, 21 million in total.</p><p><strong>This is the only way of Bitcoin creation!</strong></p><h3 id="Incentive-2-transaction-fees"><a href="#Incentive-2-transaction-fees" class="headerlink" title="Incentive 2: transaction fees"></a>Incentive 2: transaction fees</h3><p>The creator of a transaction can choose to make the output value less than the input value. Purely voluntary.</p><h3 id="Proof-of-work-PoW"><a href="#Proof-of-work-PoW" class="headerlink" title="Proof of work(PoW)"></a>Proof of work(PoW)</h3><p>To approximate selecting a random node: select nodes in proportion to a resource that no one can monopolize.</p><ul><li>In proportion to computing power: proof-of-work</li><li>In proportion to ownership: proof-of-stake</li></ul><p>Select nodes in proportion to computing power. Let nodes compete for the right to create a block. And make it moderately hard to create new identities.</p><h4 id="Hash-puzzles"><a href="#Hash-puzzles" class="headerlink" title="Hash puzzles"></a>Hash puzzles</h4><p>To create block, find $nonce$ such that $H(nonce\space ||\space prevHash \space ||\space tx\space ||\space ..\space ||\space tx)$ is very small($&lt;\space target$). Where $tx$ stands for transactions, $target$ is much smaller than 1% of total outputs.</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/hash_puzzles_target.webp" alt="target space in hash puzzles" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">target space in hash puzzles</span></div></div><p>If <code>H()</code> is secure, the only way to succeed is to try enough nonces until you get lucky.<br>Attacks are infeasible if a majority of miners weighted by hash power follow the protocol.</p><h3 id="Pow-property-1-difficult-to-compute"><a href="#Pow-property-1-difficult-to-compute" class="headerlink" title="Pow property 1: difficult to compute"></a>Pow property 1: difficult to compute</h3><p>As of Aug 2014: about $10^{20}$ hashes each block.</p><p>Only some nodes bother to compete — miners.</p><h3 id="Pow-property-2-parameterizable-cost"><a href="#Pow-property-2-parameterizable-cost" class="headerlink" title="Pow property 2: parameterizable cost"></a>Pow property 2: parameterizable cost</h3><p>Nodes automatically re-calculate the $target$ every two weeks.</p><p>Goal: <strong>average</strong> time between blocks &#x3D; 10 min.</p><p>$ Prob(\text{Alice wins next block})\space &#x3D;\space \text{fraction of global hash power she controls} $</p><p>For individual miners:</p><p>$ \text{mean time to find block} \space &#x3D;\space \frac{ \text{10 minutes} }{ \text{fraction of hash power} } $</p><h3 id="Pow-property-3-trivial-to-verify"><a href="#Pow-property-3-trivial-to-verify" class="headerlink" title="Pow property 3: trivial to verify"></a>Pow property 3: trivial to verify</h3><p>$nonce$ must be published as part of the block. Easy for other miners to verify via 1 time Hash function.</p><h2 id="Mining-economics"><a href="#Mining-economics" class="headerlink" title="Mining economics"></a>Mining economics</h2><p>$ \mathop{}_{\text{block reward + Tx fees}}^{\text{mining reward}}\space &lt; \space\text{hardware + electricity cost} \Rightarrow \text{Profit} $</p><h3 id="Bitcoin-has-three-types-of-consensus"><a href="#Bitcoin-has-three-types-of-consensus" class="headerlink" title="Bitcoin has three types of consensus"></a>Bitcoin has three types of consensus</h3><ul><li>Value</li><li>State</li><li>Rules</li></ul><p>Append-only ledger</p><p>Decentralized consenus</p><p>Miners to validate transactions.</p><hr><h2 id="Mechanics-in-Bitcoin"><a href="#Mechanics-in-Bitcoin" class="headerlink" title="Mechanics in Bitcoin"></a>Mechanics in Bitcoin</h2><h3 id="Bitcoin-transactions"><a href="#Bitcoin-transactions" class="headerlink" title="Bitcoin transactions"></a>Bitcoin transactions</h3><p>Account-based ledger is not used in Bitcoin because it is hard to tell the value of an account.</p><p>Alternatively, Bitcoin uses a trasaction-based ledger, where each of the transactions has a unique identifier, an input value, and an output value. You must spend all your Bitcoins in this kind of transactions, even you can’t pay all your Bitcoins to others, in this case you have to pay the Bitcoin you left to your self, and this is known as <code>address changing</code>. How to check if your Bitcoins are enough to pay? Just check the inputs where a pointer points to the previous block which contains your transaction.</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/transaction-ledger-bnew.webp" alt="A transacation-based ledger" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">A transacation-based ledger</span></div></div><p>And yes, you can do multiple to single transactions call joint transaction, it only needs multiple signatures from every payers.</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bitcoin-learning/joint-payments-bnew.webp" alt="Joint transaction" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">Joint transaction</span></div></div><h4 id="An-trasaction-in-JSON-like-text"><a href="#An-trasaction-in-JSON-like-text" class="headerlink" title="An trasaction in JSON-like text"></a>An trasaction in JSON-like text</h4><p>In real case, this will be a compact binary format which couldn’t be understood by human.</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;hash&quot;</span><span class="punctuation">:</span> <span class="string">&quot;5a42590fbe0a90ee8e8747244d6c84f0db1a3a24e8f1b95b10c9e050990b8b6b&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;ver&quot;</span><span class="punctuation">:</span> <span class="number">1</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;vin_sz&quot;</span><span class="punctuation">:</span> <span class="number">2</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;vout_sz&quot;</span><span class="punctuation">:</span> <span class="number">1</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;lock time&quot;</span><span class="punctuation">:</span> <span class="number">0</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;size&quot;</span><span class="punctuation">:</span> <span class="number">404</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;in&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;prev_out&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;hash&quot;</span><span class="punctuation">:</span> <span class="string">&quot;3be4ac9728a0823cf5e2deb2e86fc0bd2aa503a91d307b42ba76117d79280260&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;n&quot;</span><span class="punctuation">:</span> <span class="number">0</span></span><br><span class="line">      <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;scriptSig&quot;</span><span class="punctuation">:</span> <span class="string">&quot;30440....3f3a4ce81&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;prev_out&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span></span><br><span class="line">        <span class="attr">&quot;hash&quot;</span><span class="punctuation">:</span> <span class="string">&quot;7508e6ab259b4df0fd5147bab0c949d81473db4518f81afc5c3f52f91ff6b34e&quot;</span><span class="punctuation">,</span></span><br><span class="line">        <span class="attr">&quot;n&quot;</span><span class="punctuation">:</span> <span class="number">0</span></span><br><span class="line">      <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;scriptSig&quot;</span><span class="punctuation">:</span> <span class="string">&quot;304602210....3f3a4ce81&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;out&quot;</span><span class="punctuation">:</span> <span class="punctuation">[</span></span><br><span class="line">    <span class="punctuation">&#123;</span></span><br><span class="line">      <span class="attr">&quot;value&quot;</span><span class="punctuation">:</span> <span class="string">&quot;10.12287097&quot;</span><span class="punctuation">,</span></span><br><span class="line">      <span class="attr">&quot;scriptPubKey&quot;</span><span class="punctuation">:</span> <span class="string">&quot;OP_DUP OP_HASH160 69e02e18b5705a05dd6b28ed517716c894b3d42e OP_EQUALVERIFY OP CHECKSIG&quot;</span></span><br><span class="line">    <span class="punctuation">&#125;</span></span><br><span class="line">  <span class="punctuation">]</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><ul><li>Metadata<ul><li>hash: unique identifier</li><li>ver, vin_sz, vout_sz, size: housekeeping information</li><li>lock_time: not valid before… (later for details)</li></ul></li><li>Inputs: A list<ul><li>prev_out: previous trasaction</li><li>scriptSig: signature, sign to pay</li></ul></li><li>Outputs: A list<ul><li>value: output value</li><li>scriptPubKey: Bitcoin scripts, recipient address</li></ul></li></ul><h3 id="Bitcoin-Scripts"><a href="#Bitcoin-Scripts" class="headerlink" title="Bitcoin Scripts"></a>Bitcoin Scripts</h3><p>Addresses in both inputs and outputs are all scripts. We concatenate input scripts and output scripts, if it can run with no error, then this transaction is valid.</p><h4 id="Design-Goals"><a href="#Design-Goals" class="headerlink" title="Design Goals"></a>Design Goals</h4><ul><li>Built for Bitcoin.</li><li>Simple, Compact.</li><li>Support for crypotography.</li><li>Stack-based: No variable, easy for data processing.</li><li>Limits on time &#x2F; memory.</li><li>No looping: It is not turing complete, so we can ignore halting problem. So node owners shouldn’t worry about infinite-loop scripts that random users submit.</li></ul><h4 id="Simple-script"><a href="#Simple-script" class="headerlink" title="Simple script"></a>Simple script</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;sig&gt; &lt;pubkey&gt; OP_DUP OP_HASH160 &lt;pubKeyHash?&gt; OP_EQUALVERIFY OP_CHECKSIG</span><br></pre></td></tr></table></figure><ul><li><code>&lt;sig&gt; &lt;pubKey&gt;</code></li><li>OP_DUP: duplicate the top value and push it into top, in this case the <code>&lt;pubKey&gt;</code></li><li>OP_HASH160: take the top value and hash it, in this case it converts <code>&lt;pubKey&gt;</code> to a hash of <code>&lt;pubKey&gt;</code> – <code>&lt;pubKeyHash&gt;</code></li><li><code>&lt;pubKeyHash?&gt;</code>: specified by sender</li><li>OP_EQUALVERIFY: to verify are the two values at top of the stack equal, if not, errors occur, script stop excuting. After the verification, that two values will pop off, in this case only <code>&lt;sig&gt;</code> and that duplicated <code>&lt;pubKey&gt;</code> is on the stack now.</li><li>OP_CHECKSIG: to check if the transaction is signed.</li><li>No error, returns OK, the transaction is being merged into the chain.</li></ul><h3 id="Script-instructions"><a href="#Script-instructions" class="headerlink" title="Script instructions"></a>Script instructions</h3><p>256 opcodes total (15 disabled, 75 reserved).</p><ul><li>Arithmetic</li><li>If&#x2F;then</li><li>Logic&#x2F;data handling</li><li>Crypto<ul><li>Hashes</li><li>Signature verification</li><li>Multi-signature verification: <code>OP_CHECKMULTISIG</code></li></ul></li></ul><h4 id="OP-CHECKMULTISIG"><a href="#OP-CHECKMULTISIG" class="headerlink" title="OP_CHECKMULTISIG"></a>OP_CHECKMULTISIG</h4><ul><li>Built-in support for join signatures</li><li>Specify <code>n</code> public keys</li><li>Specify <code>t</code></li><li>Verification requires <code>t</code> signatures</li></ul><h4 id="IR-as-of-2014"><a href="#IR-as-of-2014" class="headerlink" title="IR as of 2014"></a>IR as of 2014</h4><ul><li>Most nodes whitelist known scripts</li><li>99.9% are simple signature checks</li><li>~0.01% are MULTISIG</li><li>~0.01% are Pay-to-Script-Hash(later discuss)</li><li>Remainder are errors, proof-of-burn</li></ul><h4 id="Proof-of-burn"><a href="#Proof-of-burn" class="headerlink" title="Proof-of-burn"></a>Proof-of-burn</h4><p>Destroy some Bitcoins. just to <code>OP_RETURN &lt;arbitrary data&gt;</code>. program crashed.</p><ol><li>To write arbitrary message into blockchain and store forever.</li></ol><h4 id="P2SH"><a href="#P2SH" class="headerlink" title="P2SH"></a>P2SH</h4><p>Should sender specify scripts?</p><p>No. sender can specify a very simple script like <code>OP_HASH160 &lt;hash of redemption script&gt; OP_EQUAL</code>, and let the reciever to specify correct script.</p><h3 id="to-be-continued…"><a href="#to-be-continued…" class="headerlink" title="to be continued…"></a>to be continued…</h3><!-- flag of hidden posts -->]]></content>
    
    
    <summary type="html">北京大学肖臻老师《区块链技术与应用》公开课、【普林斯顿公开课】比特币与加密货币技术、Youtube Princeton Bitcoin/Blockchain Course</summary>
    
    
    
    <category term="学习" scheme="https://c2ics.com/categories/%E5%AD%A6%E4%B9%A0/"/>
    
    
  </entry>
  
  <entry>
    <title>先审后播环境下如何追番</title>
    <link href="https://c2ics.com/posts/3fcb245db74a/"/>
    <id>https://c2ics.com/posts/3fcb245db74a/</id>
    <published>2022-12-01T11:01:00.000Z</published>
    <updated>2022-12-01T11:01:00.000Z</updated>
    
    <content type="html"><![CDATA[<p>近年来，大陆流媒体版权竞争激烈，用户体验大幅下降。</p><p>蕾皇锐评《无职转生》后，国家对于外来动漫的审查日益严格，「先审后播」的策略使得正常观看几乎不可能。</p><p>以ACG平台哔哩哔哩为例，大会员们即使拥有「抢先看」的特权，也必须等待数天才能观看到删减率达百分之百的正版动画。更不用说为了尽快通过审查而提前提交的「大陆特供」版本。</p><p>正版的受害者。</p><span id="more"></span><p><strong>曾经的优势 —— 弹幕</strong></p><p>弹幕已死。随着 B 站的用户引流、二次元的“破圈”，弹幕的环境变得越来越糟糕。我的B站弹幕屏蔽列表已经写满了50个，仍然无法屏蔽所有无意义、刷屏和不合时宜的弹幕，最多只是减少了一些烂梗。</p><p>基于以上原因，我决定退出在线流媒体平台，寻求自己的一片宁静之地。</p><p><strong>为什么我不推荐去线上盗版站点观看</strong></p><p>一是片源，一些在线站点使用国内正版视频平台的资源，删减情况并未得到改善。</p><p>二是观看体验，网页播放器在快捷键、资源占用、速度和沉浸感方面表现不佳，不如本地播放器。</p><p>三是视频质量，虽然当季作品无法达到理想的画质，但下载的资源通常比在线观看的质量要好。</p><h2 id="基本策略"><a href="#基本策略" class="headerlink" title="基本策略"></a>基本策略</h2><p>回归互联网分享的纯粹形式 —— 种子。</p><p>我通过数个内容聚合站，获取想要作品的种子，下载后本地播放。</p><h2 id="下载"><a href="#下载" class="headerlink" title="下载"></a>下载</h2><p>首先，寻找自己想看的作品。<a href="https://bgm.tv/">Bangumi 番组计划</a> 是一款类似豆瓣的作品评价、记录、讨论平台，拥有完善的索引和评分机制。在这里，你可以找到几乎所有与 ACG 相关的作品。</p><p>然后是资源，推荐前往 <a href="https://nyaa.si/">Nyaa</a>、 <a href="https://mikanani.me/">蜜柑计划</a> 或 <a href="https://bangumi.moe/">萌番组</a> 下载对应作品的<strong>种子</strong>。其中 Nyaa 的资源量大，但资源较为分散，而蜜柑计划更专注于当季新番，提供聚合化、多字幕组的下载链接。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bangumi-at-present/mikani.me.webp" alt="MikanProject" data-fancybox="true"/><a class="image-download blur" style="opacity:0" target="_blank" download="MikanProject" href="/assets/articles/old/bangumi-at-present/mikani.me.webp"><svg class="icon" style="width: 1em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3734"><path d="M561.00682908 685.55838913a111.03077546 111.03077546 0 0 1-106.8895062 0L256.23182837 487.72885783a55.96309219 55.96309219 0 0 1 79.13181253-79.18777574L450.70357448 523.88101491V181.55477937a55.96309219 55.96309219 0 0 1 111.92618438 0v344.06109173l117.07478902-117.07478901a55.96309219 55.96309219 0 0 1 79.13181252 79.18777574zM282.81429711 797.1487951h447.70473912a55.96309219 55.96309219 0 0 1 0 111.92618438H282.81429711a55.96309219 55.96309219 0 0 1 0-111.92618438z" p-id="3735"></path></svg></a></div><div class="image-meta"><span class="image-caption center">MikanProject</span></div></div><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bangumi-at-present/nyaa.si.webp" alt="Nyaa.si" data-fancybox="true"/><a class="image-download blur" style="opacity:0" target="_blank" download="Nyaa.si" href="/assets/articles/old/bangumi-at-present/nyaa.si.webp"><svg class="icon" style="width: 1em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3734"><path d="M561.00682908 685.55838913a111.03077546 111.03077546 0 0 1-106.8895062 0L256.23182837 487.72885783a55.96309219 55.96309219 0 0 1 79.13181253-79.18777574L450.70357448 523.88101491V181.55477937a55.96309219 55.96309219 0 0 1 111.92618438 0v344.06109173l117.07478902-117.07478901a55.96309219 55.96309219 0 0 1 79.13181252 79.18777574zM282.81429711 797.1487951h447.70473912a55.96309219 55.96309219 0 0 1 0 111.92618438H282.81429711a55.96309219 55.96309219 0 0 1 0-111.92618438z" p-id="3735"></path></svg></a></div><div class="image-meta"><span class="image-caption center">Nyaa.si</span></div></div><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/bangumi-at-present/bangumi.moe.webp" alt="Bangumi.moe" data-fancybox="true"/><a class="image-download blur" style="opacity:0" target="_blank" download="Bangumi.moe" href="/assets/articles/old/bangumi-at-present/bangumi.moe.webp"><svg class="icon" style="width: 1em; height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3734"><path d="M561.00682908 685.55838913a111.03077546 111.03077546 0 0 1-106.8895062 0L256.23182837 487.72885783a55.96309219 55.96309219 0 0 1 79.13181253-79.18777574L450.70357448 523.88101491V181.55477937a55.96309219 55.96309219 0 0 1 111.92618438 0v344.06109173l117.07478902-117.07478901a55.96309219 55.96309219 0 0 1 79.13181252 79.18777574zM282.81429711 797.1487951h447.70473912a55.96309219 55.96309219 0 0 1 0 111.92618438H282.81429711a55.96309219 55.96309219 0 0 1 0-111.92618438z" p-id="3735"></path></svg></a></div><div class="image-meta"><span class="image-caption center">Bangumi.moe</span></div></div><p>蜜柑计划的优点是可分字幕组订阅作品。萌番组的优点是支持 <a href="https://bangumi.moe/rss/latest">RSS 订阅</a>，可添加至下载软件列表，跳过访问网站这一步。</p><h3 id="种子和下载软件"><a href="#种子和下载软件" class="headerlink" title="种子和下载软件"></a>种子和下载软件</h3><p>我推荐使用<del>[uTorrent](https://www.utorrent.com/) 下载种子（已弃用，安全问题）</del> <a href="https://www.qbittorrent.org/">qBittorrent</a> 进行下载，为了国内资源分享的环境，请减少使用迅雷等国产软件。</p><p>为什么？种子（BitTorrent&#x2F;BT）是一种 P2P 技术。下载种子时，你未必从文件原发布者的服务器下载，更有可能从其他拥有该资源的用户那里下载。在下载的同时，你也要承担加速别人下载的义务。然而，一些国产软件如迅雷，在吸取其他软件用户的上传速度的同时，只向自己的用户提供加速，我们通常称之为“吸血”。</p><p>这显然违背了互联网的共享精神。</p><p>当期番剧的种子都很热门，用其他下载软件也可以很快！另外，遇到某些死种&#x2F;冷种时，使用迅雷可能有奇效，因为迅雷的中心服务器可能保有文件的副本。有这样一句话：「迅雷都下不动的种子，多半是废了。」</p><h3 id="代理软件"><a href="#代理软件" class="headerlink" title="代理软件"></a>代理软件</h3><p>使用代理软件是没有必要的。况且，P2P 会消耗大量上传流量，所以多数机场已屏蔽 BT 连接。</p><h3 id="自建离线下载"><a href="#自建离线下载" class="headerlink" title="自建离线下载"></a>自建离线下载</h3><p>你可以通过自建VPS离线下载。请注意避免DMCA投诉，并不要在主力主机上搭建。另外，115离线下载永远的神！</p><h2 id="播放"><a href="#播放" class="headerlink" title="播放"></a>播放</h2><p>播放方面，由于当季作品尚未发售 BD 蓝光碟，很难追求最棒的画质和音质，什么播放器都行。推荐Potplayer+LAVFilter+MadVR+XySub 或 Mpv.io 之类的优秀播放器。</p><h2 id="使用-EMBY-管理媒体"><a href="#使用-EMBY-管理媒体" class="headerlink" title="使用 EMBY 管理媒体"></a>使用 EMBY 管理媒体</h2><p>EMBY 是一款现代的媒体平台，我们可以在局域网中搭建它。EMBY 的具体作用和搭建方法我不在此赘述，百度搜索即可，图形化操作一步到位。</p><h2 id="文件命名和常见问题"><a href="#文件命名和常见问题" class="headerlink" title="文件命名和常见问题"></a>文件命名和常见问题</h2><p>在访问譬如 <a href="https://nyaa.si/">Nyaa</a> 这样的站点时，种子的文件名有许多标注，值得我们注意。本文仅解析常见概念，不展开讨论，如有错误，欢迎指正。</p><p>这些是常见的命名方式：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[Lilith-Raws] 斩！赤红之瞳 / Akame ga Kill! [01-24][Baha][WEB-DL][1080p][AVC AAC][CHT][MP4]</span><br><span class="line"></span><br><span class="line">[KTXP&amp;VCB-Studio] 斩·赤红之瞳! / Akame ga Kill! / アカメが斩る! 10-bit 1080p AVC BDRip [Reseed Fin]</span><br><span class="line"></span><br><span class="line">[字幕组/压制组信息] 标题 [集数][来源][分辨率][编码格式][字幕信息]</span><br></pre></td></tr></table></figure><h3 id="字幕组-压制组信息"><a href="#字幕组-压制组信息" class="headerlink" title="字幕组&#x2F;压制组信息"></a>字幕组&#x2F;压制组信息</h3><p>如 [VCB-Studio]、[SNOW-RAWS] 或 [澄空学园字幕组]。</p><p>字幕组：为原视频制作字幕的组织，一般由爱好者组成，为爱发电。</p><p>压制组：尽可能保证高观感的前提下压缩视频大小的组织，不同压制组给出的视频质量可能不一致。</p><h3 id="作品标题"><a href="#作品标题" class="headerlink" title="作品标题"></a>作品标题</h3><p>一般形式：<code>日文 / 罗马转写</code>，还有放在方括号里的，或者以空格作为分隔符的。国内的种子可能会标注中文而不是日文。</p><h3 id="集数标注"><a href="#集数标注" class="headerlink" title="集数标注"></a>集数标注</h3><p>例如<code>[01]</code>表示第一话。</p><p>ACG类作品中很少见但存在的情况：<code>[S01E02]</code>，是第一季、第二集的缩写。</p><p>一般地，直接标注<code>[Sxx]</code>或<code>[01-24]</code>这种的是整季，甚至整部作品多季的合集。</p><h3 id="片源"><a href="#片源" class="headerlink" title="片源"></a>片源</h3><p>从上到下质量依次递减（非绝对，参考制作组水平）。</p><ul><li>BDMV（Bluray.AVC）：蓝光碟原盘文件。</li><li>BDRIP（BluRay.x264&#x2F;x265）：蓝光碟转码，质量略低于 BDMV。</li><li>WebDL：直接从流媒体网站上下载的文件，无重新编码。</li><li>WebRIP：通过特殊软件从流媒体网站上<strong>录制</strong>（转录）的视频，存在二次编码，因此质量略低于 WebDL。</li><li>HDRIP：由 WebDL 或 WebRIP 再次转码，现在很少有这种。</li></ul><p>然而当季番未发售 BD，WebDL 是你能找到的最佳画质。另外，bdmv 的资源体积巨大（一部 13 集的季番大小 20GB 左右），不推荐使用较差 显示器、解码配置、声卡、耳机 &#x2F; 音响 的用户观看，拿来收藏还不错。</p><h3 id="视频分辨率"><a href="#视频分辨率" class="headerlink" title="视频分辨率"></a>视频分辨率</h3><p>HD、FHD、WQHD、UHD</p><p>对应国内视频网站质量，可依次理解为 720p, 1080p, 1440p, 2160p (4K)。高解像度不代表高画质，特别对于当季新番，许多高解像度（分辨率）资源都是 AI 拉上来的，个人不喜欢。现在也很少标注了，当季番基本标配1080p，如果你看的是里番当我没说。</p><h3 id="视频格式（封装）"><a href="#视频格式（封装）" class="headerlink" title="视频格式（封装）"></a>视频格式（封装）</h3><p>MP4、MKV、RMVB等等，这些都是封装格式。简单来说这些文件类似一个包裹，它的后缀则是包裹的包装方式，包裹里面有多个轨道，包含视频（只有画面没有声音!）、音频、字幕等等。**封装格式与质量无关联。**一般地，mkv&gt;mp4（并不绝对！）</p><h3 id="视频格式（编码）"><a href="#视频格式（编码）" class="headerlink" title="视频格式（编码）"></a>视频格式（编码）</h3><p>H.264（AVC&#x2F;X264）、H.265（HEVC&#x2F;X265）与 AV1。</p><p>不同的**视频（此处视频指视频轨道，不包含声音）**的编码方式，对应文件的体积和解码性能压力不同。</p><p>H.264 与 H.265 无需过度关注区别。</p><p>AV1 编码的视频对硬件压力大，但体积小，多见于 WebDL（因为像 Netflix 之类的大型流媒体采用不少 AV1 编码的视频）。</p><h3 id="色彩深度"><a href="#色彩深度" class="headerlink" title="色彩深度"></a>色彩深度</h3><p>8bit与10bit，表示颜色的精细程度。</p><p>即使你的显示器是 8bit，在性能足够的条件下也推荐选 10bit。手机性能较差，不推荐 10bit。</p><h3 id="音频格式"><a href="#音频格式" class="headerlink" title="音频格式"></a>音频格式</h3><p>DTS-HD、FLAC、TrueHD、ALAC，这四个代表声音轨道采用<strong>无损压缩</strong>的编码方式。</p><p>多音轨：例如<code>[flac*2]</code>代表着本视频含有两条以FLAC编码的音频轨道，常见用途是资源存在多国语言配音。</p><p>声道：例如<code>5.1ch</code>、<code>7.1ch</code>，是环绕声，字母 ch 指 Channel。立体声通常不作标记。单声道目前基本不存在。</p><p>还有一种特殊的音频形式，<code>Audio Commentary</code>，常见于剧场版，只有人声没有配乐。</p><h3 id="字幕"><a href="#字幕" class="headerlink" title="字幕"></a>字幕</h3><p>种类：</p><ul><li>内嵌：<strong>硬编码</strong>在视频中，不是文字，而是图像，视频的一部分。无法修改、移除、更换，通常伴有二次压制。优点是开箱即用，无需额外操作，常见于MP4视频中。无法更改位置、样式和大小，不推荐。</li><li>内封：字幕 <strong>封装在</strong> 视频文件 中，一般会封装多种语言的字幕轨道，需要播放器支持。非常方便的一种字幕。</li><li>外挂：视频文件和字幕文件<strong>分离</strong>，需要手动挂载。常见的字幕格式是 <code>ass</code>,<code>ssa</code>，一般来说字幕和视频的文件名称相同，多数支持的播放器可自动挂载。</li></ul><p>语言和文字编码：</p><p>CHS 与 CHT 一般代表字幕的语言。</p><ul><li>CHS（Chinese Simplified）—— 简体中文。</li><li>CHT（Chinese Traditional）—— 繁体中文。</li></ul><p>GB2312 和 BIG5 代表字幕文件的编码，一般来说：</p><ul><li>GB2312—— 简体中文</li><li>BIG5—— 繁体中文</li></ul><p>多语言字幕：</p><p>简日 &#x2F; 繁日：多为双字幕，主字幕为中文、副字幕为日文。（[MultiSub]）</p><h3 id="其他标注"><a href="#其他标注" class="headerlink" title="其他标注"></a>其他标注</h3><ul><li>Uncensored：依表里番决定，无删减<del>或无码</del>。</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;近年来，大陆流媒体版权竞争激烈，用户体验大幅下降。&lt;/p&gt;
&lt;p&gt;蕾皇锐评《无职转生》后，国家对于外来动漫的审查日益严格，「先审后播」的策略使得正常观看几乎不可能。&lt;/p&gt;
&lt;p&gt;以ACG平台哔哩哔哩为例，大会员们即使拥有「抢先看」的特权，也必须等待数天才能观看到删减率达百分之百的正版动画。更不用说为了尽快通过审查而提前提交的「大陆特供」版本。&lt;/p&gt;
&lt;p&gt;正版的受害者。&lt;/p&gt;</summary>
    
    
    
    <category term="ACG" scheme="https://c2ics.com/categories/ACG/"/>
    
    
    <category term="Bangumi" scheme="https://c2ics.com/tags/Bangumi/"/>
    
  </entry>
  
  <entry>
    <title>Windows11无法修改图片默认打开方式</title>
    <link href="https://c2ics.com/posts/7b851f7fd88f/"/>
    <id>https://c2ics.com/posts/7b851f7fd88f/</id>
    <published>2022-11-23T06:57:40.000Z</published>
    <updated>2022-12-03T09:18:40.000Z</updated>
    
    <content type="html"><![CDATA[<p>Windows 11 下，无法修改图片的默认打开方式，只能使用系统默认图像查看器打开图像文件。本文讨论了如何修复此问题，和造成此问题的原因。</p><span id="more"></span><h2 id="问题"><a href="#问题" class="headerlink" title="问题"></a>问题</h2><p>只能使用系统默认图像查看器打开图像文件。</p><p>进入「属性」页面无「打开方式」按钮可供选择，设置中「默认程序」无扩展名关联信息（找不到 <code>*.jpg</code>）；上下文菜单呼出「打开方式」只能「仅一次」，无法设置默认关联。</p><div class="tag-plugin grid" bg="block" style="grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));"><div class="cell" style="">    <div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/windows-default-image-handler/no_openwith.png" alt="无打开方式按钮" data-fancybox="true" style="width:300px;"/></div><div class="image-meta"><span class="image-caption center">无打开方式按钮</span></div></div>    </div>    <div class="cell" style="">    <div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/windows-default-image-handler/no_defaultapp.webp" alt="无法设置为默认" data-fancybox="true" style="width:300px;"/></div><div class="image-meta"><span class="image-caption center">无法设置为默认</span></div></div>    </div>    </div><h2 id="修复"><a href="#修复" class="headerlink" title="修复"></a>修复</h2><p>创建一个<code>.reg</code> 文件，键入以下内容，双击导入。</p><p>或者直接下载文件，<a href="/downloads/修复文件(图像)关联Win11.reg" download>下载</a></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Windows Registry Editor Version 5.00</span><br><span class="line"> </span><br><span class="line">[HKEY_CURRENT_USER\SOFTWARE\Classes\AppXk0g4vb8gvt7b93tg50ybcy892pge6jmt]</span><br><span class="line">&quot;NoOpenWith&quot;=&quot;&quot;</span><br><span class="line">&quot;NoStaticDefaultVerb&quot;=&quot;&quot;</span><br><span class="line"> </span><br><span class="line">[HKEY_CURRENT_USER\SOFTWARE\Classes\AppX43hnxtbyyps62jhe9sqpdzxn1790zetc]</span><br><span class="line">&quot;NoOpenWith&quot;=&quot;&quot;</span><br><span class="line">&quot;NoStaticDefaultVerb&quot;=&quot;&quot;</span><br><span class="line"> </span><br><span class="line">[HKEY_CURRENT_USER\SOFTWARE\Classes\AppX9rkaq77s0jzh1tyccadx9ghba15r6t3h]</span><br><span class="line">&quot;NoOpenWith&quot;=&quot;&quot;</span><br><span class="line">&quot;NoStaticDefaultVerb&quot;=&quot;&quot;</span><br></pre></td></tr></table></figure><h2 id="原因"><a href="#原因" class="headerlink" title="原因"></a>原因</h2><p>使用了 IrfanView 旧关联模式或类似行为的<strong>旧程序</strong>修改注册表 &amp; 微软的流氓操作。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/windows-default-image-handler/irfanview_chanassoc.webp" alt="尝试使用旧方式更改关联，默认勾选(?)" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">尝试使用旧方式更改关联，默认勾选(?)</span></div></div><p><code>计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts</code> 存储扩展名关联设置。如果用户设置了默认打开方式，Windows 会在对应扩展名目录下创建 <code>UserChoice</code>，结构见下图。Windows10 后，微软不允许任何程序修改 <code>UserChoice</code> 注册表，还为 <code>ProgId</code> 键添加了 Hash 验证。用户尝试打开文件时，Windows 验证哈希是否正确，若不正确，直接更改关联为系统默认软件（照片）。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/windows-default-image-handler/regNoOpenWithStructure.png" alt="注册表结构" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">注册表结构</span></div></div><p>IrfanView 已经表明此方法不适用于 Win10 及以上版本，但它是自动勾选的。随后，IFV 尝试强行修改，引发保护机制重置了关联。</p><p>但为什么会找不到「打开方式」呢？对于现代 Windows 应用程序，选项<code>计算机\HKEY_CURRENT_USER\SOFTWARE\Classes\&lt;Application&gt;\NoOpenWith</code> 设置后，选择默认应用的按钮将被隐藏。《反垄断法》呢？救一下啊！</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;Windows 11 下，无法修改图片的默认打开方式，只能使用系统默认图像查看器打开图像文件。本文讨论了如何修复此问题，和造成此问题的原因。&lt;/p&gt;</summary>
    
    
    
    <category term="Tech" scheme="https://c2ics.com/categories/Tech/"/>
    
    
    <category term="Windows" scheme="https://c2ics.com/tags/Windows/"/>
    
  </entry>
  
  <entry>
    <title>删除“此电脑”中的百度网盘图标</title>
    <link href="https://c2ics.com/posts/3c54784dff83/"/>
    <id>https://c2ics.com/posts/3c54784dff83/</id>
    <published>2022-11-20T03:27:07.000Z</published>
    <updated>2023-05-26T09:00:07.000Z</updated>
    
    <content type="html"><![CDATA[<p>安装百度网盘后，资源管理器「此电脑」页面会多出百度网盘产生的垃圾图标。右键发现没有「删除」选项，才发现原来是写在注册表里面了，今天把这恶心的东西拿下！</p><span id="more"></span><h2 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h2><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/remove-baidunetdisk-explorer-ext/baiduwangpan_icon_in_explr_edited.png" alt="百度网盘图标" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">百度网盘图标</span></div></div><p>Win 徽标 + R 键打开 <code>regedit</code>，找到<code>计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace</code>，看到类似于「{679F137C-3162-45da-BE3C-2F9C3D093F64}」的 CLSID，选中并查看默认值是否为「百度网盘」，如果是则删除。删除后重新打开「此电脑」，图标消失。</p><p>按照本方法，理论上可删除所有类似的图标生成。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/remove-baidunetdisk-explorer-ext/the_user_baiduwp_reg.webp" alt="HKCU中的设置" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">HKCU中的设置</span></div></div><hr><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/remove-baidunetdisk-explorer-ext/the_local_machine_reg.webp" alt="HKLM中的设置" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">HKLM中的设置</span></div></div><p>如果你的百度网盘是为所有用户安装（新版本不可能了）的，请移步 <code>\HKEY_LOCAL_MACHINE\</code> 中对应的结构下。但需要注意，此目录下还包含「此电脑」中显示的视频、图片、文档、下载等特殊文件夹，不要错删。例如 <code>&#123;088e3905-0323-4b02-9826-5d99428e115f&#125;</code> 对应「下载」特殊文件夹。</p><div class="tag-plugin image"><div class="image-bg"><img src="/assets/articles/old/remove-baidunetdisk-explorer-ext/the_local_uuid_refers_to.webp" alt="特殊文件夹" data-fancybox="true"/></div><div class="image-meta"><span class="image-caption center">特殊文件夹</span></div></div><!-- flag of hidden posts -->]]></content>
    
    
    <summary type="html">&lt;p&gt;安装百度网盘后，资源管理器「此电脑」页面会多出百度网盘产生的垃圾图标。右键发现没有「删除」选项，才发现原来是写在注册表里面了，今天把这恶心的东西拿下！&lt;/p&gt;</summary>
    
    
    
    <category term="Tech" scheme="https://c2ics.com/categories/Tech/"/>
    
    
    <category term="Windows" scheme="https://c2ics.com/tags/Windows/"/>
    
  </entry>
  
</feed>
