feat: 完成 lec6: C 语言项目实现

1. C 语言语法
2. 编译介绍
3. GNU Make
4. 调试介绍
This commit is contained in:
focused_xy 2024-11-09 16:03:51 +08:00 committed by E1PsyCongroo
parent 3c18dd69e7
commit 77e5a5989a
73 changed files with 1541 additions and 2780 deletions

View File

@ -1,16 +0,0 @@
# Week6 Lecture 大纲
- C 项目的组织
- GNU Make 为例的项目构建
- Git 为例的版本控制
- 多文件的交互
- 头文件
- 函数与变量的声明、作用域、生存期、存储器
- 链接
- 静态链接
- 动态链接
- 测试与调试
- 单元测试
- 断言测试
- Valgrind
- GDB——以 CGDB 为例

View File

@ -0,0 +1,803 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="./static/css/base.css" rel="stylesheet">
<link href="./static/css/tailwind.min.css" rel="stylesheet">
<link href="https://fonts.font.im/css?family=Source+Serif+Pro%7CLato%7CInconsolata" rel="stylesheet"
type="text/css">
<title> lecture6 </title>
<!-- browser favicon -->
<link rel="shortcut icon" href="./static/img/favicon.ico">
<style>
.font-sans {
font-family: 'Lato', 'SimHei', 'STHeiti', 'SimHei', 'Serif';
}
.font-serif {
font-family: 'Source Serif Pro', 'Songti SC', 'SimSun', 'Serif', serif;
}
</style>
<link rel="stylesheet" href="./static/katex/katex.min.css">
<script defer src="./static/katex/katex.min.js"></script>
<script defer src="./static/katex/auto-render.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
renderMathInElement(document.body, {
// customised options
// &#8226; auto-render specific keys, e.g.:
delimiters: [
{ left: '$$', right: '$$', display: true },
{ left: '$', right: '$', display: false },
{ left: '\\(', right: '\\)', display: false },
{ left: '\\[', right: '\\]', display: true }
],
// &#8226; rendering keys, e.g.:
throwOnError: false
});
});
</script>
<link rel="stylesheet" href="./static/reveal/reveal.css">
<link rel="stylesheet" href="./static/reveal/theme/simple.css" id="theme">
<link rel="stylesheet" href="./static/jyy/jyy.css">
</head>
<body class="d-flex flex-column h-100">
<div class="reveal">
<div class="slides">
<section><section><div class="center middle"><div style="width:100%"><div><h1 id="c" class="text-2xl mt-2 font-sans">C 语言项目实现</h1><p class="font-serif my-1">
<include src="Slides_Author">
<div class="py-16">
<p class="font-serif my-1">
<a href="" class=" text-amber-900">
晓阳
</a>
</p>
</div>
<div class="row">
<p class="font-serif my-1"/>
<div class="author-affiliation">
<a href="https://github.com/datawhalechina/cstart" class=" text-amber-900">
<p class="font-serif my-1">
NekoBytes
</p>
<img class="inline-img h-24" src="./static/img/f97e6d415e1a4b25b0d5615817a9b4bb.svg" style="display: inline-block;"/>
</a>
</div>
</div>
</include>
</p></div></div></div></section></section><section><section data-auto-animate><div><h2 id="c" class="text-xl mt-2 pb-2 font-sans">C 语言</h2>
<ul class="list-disc font-serif">
<li class="ml-8">预处理器</li>
<li class="ml-8">控制流<ul class="list-disc font-serif">
<li class="ml-8">if - switch</li>
<li class="ml-8">for - while - do-while</li>
<li class="ml-8">continue - break</li>
<li class="ml-8">goto - return</li>
</ul>
</li>
<li class="ml-8">表达式<ul class="list-disc font-serif">
<li class="ml-8">值类别: 左值、右值、函数指代器</li>
<li class="ml-8">常量及字面量</li>
<li class="ml-8">求值顺序、运算顺序</li>
<li class="ml-8">运算符</li>
</ul>
</li>
<li class="ml-8">未定义行为</li>
</ul></div></section><section data-auto-animate><div><ul class="list-disc font-serif">
<li class="ml-8">对象<ul class="list-disc font-serif">
<li class="ml-8">类型<ul class="list-disc font-serif">
<li class="ml-8">基本类型</li>
<li class="ml-8">函数类型: 声明、定义、可变参数、inline</li>
<li class="ml-8">数组类型: 字符串、多维、隐式指针转换</li>
<li class="ml-8">指针类型: 对象指针、函数指针</li>
<li class="ml-8">枚举类型</li>
<li class="ml-8">自定义类型: 结构体、联合体、位域</li>
</ul>
</li>
<li class="ml-8">存储说明符: typedef, constexpr, auto, register, static, extern, thread_local</li>
<li class="ml-8">类型限定符(cv限定符): const、volatile、restrict、_Atomic</li>
<li class="ml-8">对齐</li>
<li class="ml-8">存储期与链接</li>
<li class="ml-8">生存期</li>
</ul>
</li>
</ul></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans"><a href="https://zh.cppreference.com/w/c/language/eval_order">求值顺序</a>与运算顺序</h2>
<blockquote>
<p class="font-serif my-1">C 语言中没有从左到右或从右到左求值的概念,不要将其与运算符的从左到右或从右到左结合性混淆:</p>
<p class="font-serif my-1">表达式 f1() + f2() + f3() 因为 operator+ 的从左到右结合性而被分析成 (f1() + f2()) + f3()</p>
<p class="font-serif my-1">但运行时对 f3 的函数调用可以最先、最后,或在 f1() 与 f2() 之间求值。</p>
</blockquote>
<p class="font-serif my-1">若在子表达式 E1 和 E2 间存在序列点,则 E1 的值计算和副效应都先序于 E2 的所有值计算和副效应。</p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="cm">/* 未定义行为 */</span>
<span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">++</span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="n">f</span><span class="p">(</span><span class="o">++</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="o">++</span><span class="n">i</span><span class="p">);</span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">-1</span><span class="p">,</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">-1</span><span class="p">);</span>
<span class="n">f</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">);</span><span class="w"> </span><span class="n">a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">;</span>
</code></pre></div></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans"><a href="https://zh.cppreference.com/w/c/language/behavior">未定义行为</a></h2>
<p class="font-serif my-1">因为正确的 C 程序是没有未定义行为的,编译器可以在启用优化的条件下编译确实有 UB 的程序时,生成不期待的结果:</p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="n">有符号溢出</span>
<span class="kt">int</span><span class="w"> </span><span class="n">foo</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="o">+</span><span class="mi">1</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">x</span><span class="p">;</span><span class="w"> </span><span class="c1">// 真或为有符号溢出导致的 UB</span>
<span class="p">}</span>
</code></pre></div>
<p class="font-serif my-1">可以编译成</p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="nl">foo:</span>
<span class="w"> </span><span class="nf">mov</span><span class="w"> </span><span class="no">eax</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span>
<span class="w"> </span><span class="nf">ret</span>
</code></pre></div>
<p class="font-serif my-1">建议开启编译器检查: <code>-fsanitize=undefined</code></p></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans"><a href="https://zh.cppreference.com/w/c/language/variadic">可变参数函数</a></h2>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="kt">int</span><span class="w"> </span><span class="nf">printf</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="kr">restrict</span><span class="w"> </span><span class="n">format</span><span class="p">,</span><span class="w"> </span><span class="p">...);</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">vprintf</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="kr">restrict</span><span class="w"> </span><span class="n">format</span><span class="p">,</span><span class="w"> </span><span class="kt">va_list</span><span class="w"> </span><span class="n">ap</span><span class="p">);</span>
</code></pre></div>
<p class="font-serif my-1">RTFM: <code>man stdarg</code></p>
<ul class="list-disc font-serif">
<li class="ml-8">定义<code>va_list</code>变量</li>
<li class="ml-8">通过<code>va_start</code>获取可变参数列表</li>
<li class="ml-8">通过<code>va_arg</code>获取可变参数</li>
<li class="ml-8">通过<code>va_end</code>销毁资源</li>
<li class="ml-8">通过<code>va_copy</code>拷贝可变参数列表</li>
</ul>
<blockquote>
<p class="font-serif my-1">可变参数的使用类似动态分配,请记得销毁资源和必要时进行<code>va_copy</code>拷贝</p>
</blockquote></div></section><section><div><h2 id="inline" class="text-xl mt-2 pb-2 font-sans"><a href="https://zh.cppreference.com/w/c/language/inline">inline 函数</a></h2>
<p class="font-serif my-1">内联函数: 通过复制代码到函数调用处的方式<strong>减少函数调用</strong>以提高效率</p>
<blockquote>
<p class="font-serif my-1">程序员应该把优化的空间交给编译器,而不是自己做出优化决定!</p>
</blockquote>
<p class="font-serif my-1">如今的 <code>inline</code>: 用于使多个函数定义符合<a href="https://zh.cppreference.com/w/c/language/extern">唯一定义规则</a></p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="cm">/* sum.h</span>
<span class="cm"> * 使用 inline 使得 sum.h 被多个文件 #include 产生的</span>
<span class="cm"> * 多个 sum 函数定义不会违反唯一定义规则</span>
<span class="cm"> */</span>
<span class="kr">inline</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">sum</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">b</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="cm">/* main.c */</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">"sum.h"</span>
<span class="cm">/* test.c */</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">"sum.h"</span>
</code></pre></div></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">函数指针</h2>
<p class="font-serif my-1">指向函数的指针可由函数地址初始化。因为函数到指针存在隐式转换,取址运算符是可选的。</p>
<p class="font-serif my-1">指向函数的指针可以用作函数调用运算符的左操作数;这会调用所指向的函数。</p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdlib.h&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">qsort</span><span class="p">(</span><span class="kt">void</span><span class="w"> </span><span class="n">base</span><span class="p">[.</span><span class="n">size</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">.</span><span class="n">nmemb</span><span class="p">],</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">nmemb</span><span class="p">,</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">size</span><span class="p">,</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">compar</span><span class="p">)(</span><span class="k">const</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="p">[.</span><span class="n">size</span><span class="p">],</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="p">[.</span><span class="n">size</span><span class="p">]));</span>
<span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="nf">bsearch</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">key</span><span class="p">[.</span><span class="n">size</span><span class="p">],</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">base</span><span class="p">[.</span><span class="n">size</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">.</span><span class="n">nmemb</span><span class="p">],</span>
<span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">nmemb</span><span class="p">,</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">size</span><span class="p">,</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">compar</span><span class="p">)(</span><span class="k">const</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="p">[.</span><span class="n">size</span><span class="p">],</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="p">[.</span><span class="n">size</span><span class="p">]));</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">compare_int</span><span class="p">(</span><span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">void</span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="o">*</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span><span class="p">)</span><span class="n">a</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="o">*</span><span class="p">(</span><span class="kt">int</span><span class="o">*</span><span class="p">)</span><span class="n">b</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">compar</span><span class="p">)(</span><span class="k">const</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="kt">void</span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">compare_int</span><span class="p">;</span>
<span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
<span class="n">compare_int</span><span class="p">(</span><span class="o">&amp;</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
<span class="n">compar</span><span class="p">(</span><span class="o">&amp;</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">);</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">compar</span><span class="p">)(</span><span class="o">&amp;</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">);</span>
<span class="n">qsort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span><span class="w"> </span><span class="k">sizeof</span><span class="w"> </span><span class="n">array</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="k">sizeof</span><span class="w"> </span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="k">sizeof</span><span class="w"> </span><span class="n">array</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="n">compar</span><span class="p">);</span>
</code></pre></div></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">指针与数组与函数</h2>
<p class="font-serif my-1">理解定义请参考<a href="https://zh.cppreference.com/w/c/language/operator_precedence">运算符优先级</a></p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="cm">/* 优先级: [] &gt; * &gt; ()</span>
<span class="cm"> * 变量 p 的运算符使用顺序应该是 (* ( p[] ) ) ()</span>
<span class="cm"> * p 首先被取下标 [] -&gt; p 是一个 5 个元素的数组</span>
<span class="cm"> * p[] 可以被解引用 * -&gt; p[] 是一个指针</span>
<span class="cm"> * (*p[]) 可以进行函数调用 () -&gt; *p[] 是一个函数指代器</span>
<span class="cm"> * p 是一个 函数指针 的数组,数组有 5 个元素</span>
<span class="cm"> * 指针指向 int(void) 的函数类型</span>
<span class="cm"> */</span>
<span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">p</span><span class="p">[</span><span class="mi">5</span><span class="p">])(</span><span class="kt">void</span><span class="p">);</span>
<span class="cm">/* 建议使用 typedef 避免复杂类型定义 */</span>
<span class="k">typedef</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">fn_t</span><span class="p">)(</span><span class="kt">void</span><span class="p">);</span><span class="w"> </span><span class="c1">// fn_t 是指向 int(void) 的函数指针</span>
<span class="k">typedef</span><span class="w"> </span><span class="n">fn_t</span><span class="w"> </span><span class="n">fn_arr_t</span><span class="p">[];</span><span class="w"> </span><span class="c1">// fn_arr_t 是 fn_t 的数组</span>
<span class="n">fn_arr_t</span><span class="w"> </span><span class="n">fn_array</span><span class="p">[</span><span class="mi">5</span><span class="p">];</span><span class="w"> </span><span class="c1">// 类型同 p</span>
<span class="cm">/* 比如我们的标准库的信号处理函数指针 */</span>
<span class="k">typedef</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="kt">sighandler_t</span><span class="p">)(</span><span class="kt">int</span><span class="p">);</span>
</code></pre></div></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">结构体与联合体</h2>
<p class="font-serif my-1">结构体是由一序列的成员组成的类型,成员<strong>顺序分配</strong>于内存中</p>
<p class="font-serif my-1">联合体相反,联合体是由一个序列的成员组成的类型,成员<strong>重叠</strong>存储在内存中</p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="k">typedef</span><span class="w"> </span><span class="k">enum</span><span class="w"> </span><span class="n">RetType_t</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">ret_int</span><span class="p">,</span><span class="w"> </span><span class="n">ret_double</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="n">RetType_t</span><span class="p">;</span>
<span class="k">typedef</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">RetType_t</span><span class="w"> </span><span class="n">ret_type</span><span class="p">;</span>
<span class="w"> </span><span class="k">union</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">int_val</span><span class="p">;</span><span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">double_val</span><span class="p">;</span>
<span class="w"> </span><span class="p">};</span><span class="w"> </span><span class="c1">// 匿名联合体</span>
<span class="p">}</span><span class="w"> </span><span class="n">Ret_t</span><span class="p">;</span>
<span class="n">Ret_t</span><span class="w"> </span><span class="nf">f</span><span class="p">(</span><span class="n">RetType_t</span><span class="w"> </span><span class="n">ret_type</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">switch</span><span class="p">(</span><span class="n">ret_type</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="no">ret_int</span><span class="p">:</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="n">Ret_t</span><span class="p">){.</span><span class="n">ret_type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ret_int</span><span class="p">,</span><span class="w"> </span><span class="p">.</span><span class="n">int_val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">};</span>
<span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="no">ret_double</span><span class="p">:</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="n">Ret_t</span><span class="p">){.</span><span class="n">ret_type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ret_double</span><span class="p">,</span><span class="w"> </span><span class="p">.</span><span class="n">double_val</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1.0</span><span class="p">};</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans"><a href="https://zh.cppreference.com/w/c/language/object">对齐要求</a></h2>
<p class="font-serif my-1"><code>alignof(类型名)</code> 运算符可以用于查询类型的对齐要求,表示此类型对象可以分配的相继地址之间的字节数。</p>
<p class="font-serif my-1">结构体和联合体为了同时满足成员和结构体的对齐要求,会导致不同的对象大小和对齐要求。</p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="k">struct</span><span class="w"> </span><span class="nc">S</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w"> </span><span class="c1">// 成员对象大小1对齐1</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">b</span><span class="p">;</span><span class="w"> </span><span class="c1">// 成员对象大小1对齐1</span>
<span class="p">};</span><span class="w"> </span><span class="c1">// 结构体对象大小2对齐1</span>
<span class="cm">/* struct X 的对象必须分配于 4字节边界</span>
<span class="cm"> * 因为 X.n 必须分配于 4 字节边界</span>
<span class="cm"> * 因为 int 的对齐要求(通常)是 4 */</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">X</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="c1">// 成员对象大小4对齐4</span>
<span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="n">c</span><span class="p">;</span><span class="w"> </span><span class="c1">// 成员对象大小1对齐1</span>
<span class="w"> </span><span class="c1">// 剩余的三个字节进行空位填充</span>
<span class="p">};</span><span class="w"> </span><span class="c1">// 结构体对象大小8对齐4</span>
</code></pre></div></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans"><a href="https://zh.cppreference.com/w/c/language/bit_field">位域</a></h2>
<p class="font-serif my-1">声明带有明确宽度的成员,按位数计。相邻的位域成员可能被打包,共享和分散到各个单独的字节。</p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="k">struct</span><span class="w"> </span><span class="nc">S</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// 通常将占用 8 字节</span>
<span class="w"> </span><span class="c1">// 5 位: b1 的值</span>
<span class="w"> </span><span class="c1">// 27 位:未使用</span>
<span class="w"> </span><span class="c1">// 6 位: b2 的值</span>
<span class="w"> </span><span class="c1">// 11 位:未使用</span>
<span class="w"> </span><span class="c1">// 15 位: b3 的值</span>
<span class="w"> </span><span class="kt">unsigned</span><span class="w"> </span><span class="n">b1</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="mi">5</span><span class="p">;</span>
<span class="cm">/* 拥有零 宽度 的特殊无名位域打破填充:</span>
<span class="cm"> * 它指定下个位域在始于下个分配单元的起点 */</span>
<span class="w"> </span><span class="nl">unsigned</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="kt">unsigned</span><span class="w"> </span><span class="n">b2</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="mi">6</span><span class="p">;</span>
<span class="w"> </span><span class="nl">unsigned</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="mi">11</span><span class="p">;</span>
<span class="w"> </span><span class="kt">unsigned</span><span class="w"> </span><span class="n">b3</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="mi">15</span><span class="p">;</span>
<span class="p">};</span>
</code></pre></div></div></section><section data-auto-animate><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">类型限定符</h2>
<ul class="list-disc font-serif">
<li class="ml-8">const: 编译器可以把声明为带 const 限定类型的对象放到只读内存中,并且若程序从来不获取该 const 对象的地址,则可能完全不存储它。<ul class="list-disc font-serif">
<li class="ml-8">对类型被 const 限定的对象的任何修改尝试都导致未定义行为。</li>
</ul>
</li>
<li class="ml-8">volatile: 阻止编译器对带 volatile 限定类型的对象进行优化,确保对对象的操作严格执行。</li>
<li class="ml-8">restrict: 仅用于指向对象类型的指针,用于指示指针是程序中<strong>唯一</strong>直接访问其所指向对象的方式,帮助编译器优化。</li>
<li class="ml-8"><del>_Atomic: 多线程相关</del></li>
</ul>
<p class="font-serif my-1">最佳实践:</p>
<ul class="list-disc font-serif">
<li class="ml-8">仅确保在条件满足时,使用 <code>restrict</code></li>
<li class="ml-8">使用 <code>const</code> 保护不该被修改的对象</li>
</ul></div></section><section data-auto-animate><div><h2 id="const" class="text-xl mt-2 pb-2 font-sans">指针与 const</h2>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
<span class="cm">/* 标明 p1 指针指向 const int</span>
<span class="cm"> * 无法通过 p1 指针修改指向的对象</span>
<span class="cm"> */</span>
<span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="o">*</span><span class="n">p1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="p">;</span>
<span class="cm">/* 标明 p2 指针本身不可修改</span>
<span class="cm"> * 保证 p2 指针始终指向对象 a</span>
<span class="cm"> */</span>
<span class="kt">int</span><span class="w"> </span><span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="n">p2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="p">;</span>
<span class="n">p2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">;</span><span class="w"> </span><span class="c1">// 编译错误</span>
<span class="cm">/* 指针与指向对象均不可修改 */</span>
<span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="n">p3</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="p">;</span>
<span class="cm">/* 危险,可能导致 UB */</span>
<span class="kt">int</span><span class="w"> </span><span class="o">*</span><span class="n">p4</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">;</span>
</code></pre></div></div></section><section data-auto-animate><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans"><a href="https://zh.cppreference.com/w/c/language/storage_duration">生存期、存储期与链接</a></h2>
<p class="font-serif my-1">生存期=对象存储期或临时对象</p>
<ul class="list-disc font-serif">
<li class="ml-8"><del>auto - 自动存储期与无链接</del></li>
<li class="ml-8"><del>register - 自动存储期与无链接;不能取这种对象的地址</del></li>
<li class="ml-8">static - 静态存储期与内部链接(除非在块作用域)</li>
<li class="ml-8">extern - 静态存储期与外部链接(除非已声明带内部链接)</li>
<li class="ml-8"><del>thread_local - 线程存储期</del></li>
</ul>
<p class="font-serif my-1">若不提供存储类说明符,则默认为:</p>
<ul class="list-disc font-serif">
<li class="ml-8">对所有函数为 extern</li>
<li class="ml-8">对在文件作用域的对象为 extern</li>
<li class="ml-8">对在块作用域的对象为 auto</li>
</ul></div></section><section data-auto-animate><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">存储期</h2>
<ul class="list-disc font-serif">
<li class="ml-8">自动存储期。当进入对象所声明于其中的块时分配其存储而当以任何方式goto、return、抵达结尾退出该块时解分配存储。</li>
<li class="ml-8">静态存储期。存储期是整个程序的执行过程,只在 main 函数之前初始化一次存储于对象的值。</li>
<li class="ml-8"><del>线程存储期。</del></li>
<li class="ml-8">分配存储期。按照请求,用动态内存分配函数分配和解分配存储。</li>
</ul>
<p class="font-serif my-1">最佳实践:</p>
<ul class="list-disc font-serif">
<li class="ml-8">使用 <code>static</code> 声明静态存储期,使对象存在整个程序的执行过程。</li>
<li class="ml-8">使用动态内存分配手动管理程序内存。</li>
</ul></div></section><section data-auto-animate><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">链接</h2>
<ul class="list-disc font-serif">
<li class="ml-8">无链接。只能从其所在的作用域指代该标识符。</li>
<li class="ml-8">内部链接。能从当前翻译单元的所有作用域指代该标识符。</li>
<li class="ml-8">外部链接。能从整个程序的任何其他翻译单元指代该标识符。</li>
</ul>
<p class="font-serif my-1">最佳实践:</p>
<ul class="list-disc font-serif">
<li class="ml-8">不要使用全局对象: 静态存储期和外部链接</li>
<li class="ml-8">可以使用静态存储期和内部连接的对象</li>
<li class="ml-8">使用 <code>static</code> 声明不需要暴露到全局的函数</li>
</ul></div></section></section><section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">多文件编译</h2>
<ul class="list-disc font-serif">
<li class="ml-8">头文件:<ul class="list-disc font-serif">
<li class="ml-8">头文件保护</li>
<li class="ml-8">宏定义</li>
<li class="ml-8">类型声明</li>
<li class="ml-8">暴露类型定义</li>
<li class="ml-8">对象声明</li>
<li class="ml-8">函数声明</li>
<li class="ml-8">static/inline 函数定义</li>
</ul>
</li>
<li class="ml-8">源文件:<ul class="list-disc font-serif">
<li class="ml-8">类型定义</li>
<li class="ml-8">对象定义</li>
<li class="ml-8">函数定义</li>
</ul>
</li>
</ul></div></section><section data-auto-animate><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">头文件保护</h2>
<p class="font-serif my-1">考虑下面这种情况:</p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="cm">/* a.h */</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">"b.h"</span>
<span class="k">static</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">sum</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">b</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="cm">/* b.h */</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">"a.h"</span>
<span class="cm">/* main.c */</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">"a.h"</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">"b.h"</span>
</code></pre></div>
<p class="font-serif my-1">其中函数 sum 的定义在 main.c 引入了两次,违反了唯一定义规则,会导致编译错误。</p></div></section><section data-auto-animate><div><p class="font-serif my-1">使用头文件保护确保头文件仅能被同一个源文件<code>#include</code>一次</p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="cp">#ifndef __HEAD_FILENAME_H__</span>
<span class="cp">#define __HEAD_FILENAME_H__</span>
<span class="cm">/* ... */</span>
<span class="cp">#endif</span>
</code></pre></div>
<p class="font-serif my-1"></p>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="cp">#pragma once</span>
</code></pre></div>
<p class="font-serif my-1"><code>#pragma once</code> 是受到绝大多数现代编译器支持的<strong>非标准语用</strong>。当某个头文件中包含它时,指示编译器只对其分析一次,即使它在同一源文件中(直接或间接)被包含了多次也是如此。</p></div></section><section data-auto-animate><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">头文件最佳实践</h2>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="cp">#ifndef __MATH_UTILS_H__</span>
<span class="cp">#define __MATH_UTILS_H__</span>
<span class="c1">// 1. 包含其他头文件</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;stdbool.h&gt;</span>
<span class="c1">// 2. 宏定义</span>
<span class="cp">#define PI 3.14159</span>
<span class="cp">#define MAX(a, b) ((a) &gt; (b) ? (a) : (b))</span>
<span class="c1">// 3. 类型定义</span>
<span class="k">typedef</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">x</span><span class="p">;</span><span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">y</span><span class="p">;</span>
<span class="p">}</span><span class="w"> </span><span class="n">Point</span><span class="p">;</span>
<span class="c1">// 4. 函数声明</span>
<span class="kt">bool</span><span class="w"> </span><span class="nf">double_equal</span><span class="p">(</span><span class="kt">double</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="n">b</span><span class="p">);</span>
<span class="c1">// 5. 内联函数</span>
<span class="kr">inline</span><span class="w"> </span><span class="kt">double</span><span class="w"> </span><span class="nf">square</span><span class="p">(</span><span class="kt">double</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">x</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="cp">#endif </span><span class="c1">// __MATH_UTILS_H__</span>
</code></pre></div></div></section><section data-auto-animate><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">编译器</h2>
<p class="font-serif my-1">RTFM: <a href="https://gcc.gnu.org/onlinedocs/gcc/index.html"><code>man gcc</code></a></p>
<table>
<thead>
<tr>
<th style="text-align: center;">编译选项</th>
<th style="text-align: center;">功能</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;"><code>-E</code></td>
<td style="text-align: center;">对源文件进行预处理</td>
</tr>
<tr>
<td style="text-align: center;"><code>-S</code></td>
<td style="text-align: center;">将源文件编译为汇编代码(C 代码 -&gt; 汇编代码)</td>
</tr>
<tr>
<td style="text-align: center;"><code>-c</code></td>
<td style="text-align: center;">将源文件编译为对象文件(C 代码 -&gt; 机器代码)</td>
</tr>
<tr>
<td style="text-align: center;"><code>-o</code></td>
<td style="text-align: center;">指定输出文件名</td>
</tr>
<tr>
<td style="text-align: center;"><code>-std=...</code></td>
<td style="text-align: center;">选择使用的 C 语言标准规范</td>
</tr>
<tr>
<td style="text-align: center;"><code>-Wall</code></td>
<td style="text-align: center;">开启所有可能的警告(建议开启)</td>
</tr>
<tr>
<td style="text-align: center;"><code>-Werror</code></td>
<td style="text-align: center;">将所有警告视为错误(建议开启)</td>
</tr>
<tr>
<td style="text-align: center;"><code>-g</code></td>
<td style="text-align: center;">生成调试信息(为调试器提供信息)</td>
</tr>
</tbody>
</table></div></section><section data-auto-animate><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">编译器</h2>
<table>
<thead>
<tr>
<th style="text-align: center;">编译选项</th>
<th style="text-align: center;">功能</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;"><code>-O(g/1/2/3/s, ...)</code></td>
<td style="text-align: center;">启用优化(需要调试程序时,建议使用<code>-Og</code>或不优化)</td>
</tr>
<tr>
<td style="text-align: center;"><code>-Idir</code></td>
<td style="text-align: center;">指定头文件搜索路径dir</td>
</tr>
<tr>
<td style="text-align: center;"><code>-Ldir</code></td>
<td style="text-align: center;">指定库文件搜索路径dir</td>
</tr>
<tr>
<td style="text-align: center;"><code>-Dmacro</code></td>
<td style="text-align: center;">定义宏macro = 定义的值)</td>
</tr>
<tr>
<td style="text-align: center;"><code>-llib</code></td>
<td style="text-align: center;">指定连接的库文件</td>
</tr>
<tr>
<td style="text-align: center;"><code>-fsanitize=type</code></td>
<td style="text-align: center;">启用类型相关的问题运行时检测,帮助识别类型不匹配和越界</td>
</tr>
<tr>
<td style="text-align: center;"><code>-v</code></td>
<td style="text-align: center;">输出详细的编译过程信息</td>
</tr>
</tbody>
</table></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">免费的午餐</h2>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="c1"># 开启调试信息</span>
<span class="c1"># 启用严格的编译检查</span>
<span class="c1"># 开启程序运行时检测(地址访问与未定义行为检测)</span>
<span class="c1"># sanitize 建议使用 clanggcc的支持不够好</span>
clang<span class="w"> </span>-g<span class="w"> </span>-Og<span class="w"> </span>-Wall<span class="w"> </span>-Werror<span class="w"> </span>-fsanitize<span class="o">=</span>address<span class="w"> </span><span class="se">\</span>
-fsanitize<span class="o">=</span>undefined<span class="w"> </span>-o<span class="w"> </span>output<span class="w"> </span>input.c
<span class="c1"># 开启 O2 优化,一般很少使用 O3</span>
<span class="c1"># 开启链接时优化</span>
gcc<span class="w"> </span>-O2<span class="w"> </span>-flto<span class="w"> </span>-Wall<span class="w"> </span>-Werror<span class="w"> </span>-o<span class="w"> </span>output<span class="w"> </span>input.c
</code></pre></div>
<blockquote>
<p class="font-serif my-1">熟悉基础设施,可以提高效率!</p>
</blockquote></div></section><section data-auto-animate><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans"><a href="https://zh.cppreference.com/w/c/language/translation_phases">编译详解</a></h2>
<p class="font-serif my-1"><img class="center" src="./static/img/e109692d810a487fae1a2648615b54d6.png"/>
<img class="center" src="./static/img/a1ff3155f35846a5a9dd79e7bf66b781.png"/></p></div></section><section data-auto-animate><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">编译详解</h2>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code>gcc<span class="w"> </span>-v<span class="w"> </span>-Wl,-verbose<span class="w"> </span>-o<span class="w"> </span>output<span class="w"> </span>input.c
</code></pre></div>
<ul class="list-disc font-serif">
<li class="ml-8">预处理阶段: 替换注释为空格、宏文本替换<ul class="list-disc font-serif">
<li class="ml-8"><code>-Idir</code>: <code>#include</code> 的搜索目录</li>
</ul>
</li>
<li class="ml-8">编译阶段: 编译翻译单元为汇编代码</li>
<li class="ml-8">汇编阶段: 编译汇编代码为对象文件</li>
<li class="ml-8">链接阶段: 链接程序运行环境<ul class="list-disc font-serif">
<li class="ml-8"><code>-Ldir</code>: <code>-llib</code> 的搜索目录</li>
<li class="ml-8"><code>-static</code>: 进行静态链接(默认为动态链接)</li>
<li class="ml-8"><code>-llib</code>: 尝试链接 <code>liblib.so</code><code>liblib.a</code> 文件</li>
<li class="ml-8"><code>ldd</code>: 查看程序动态链接的动态库</li>
<li class="ml-8">动态链接: 程序加载时根据路径加载动态链接库</li>
<li class="ml-8">静态链接: 编译链接时将库编译进可执行文件</li>
</ul>
</li>
</ul></div></section></section><section><section><div><h2 id="gnu-make" class="text-xl mt-2 pb-2 font-sans"><a href="https://www.gnu.org/software/make/manual/make.html">GNU Make</a></h2>
<p class="font-serif my-1">GNU Make是一个自动化构建工具用于管理和维护大型程序和项目的构建过程。通过读取定义了一系列规则的“Makefile”文件根据文件修改时间来使用命令重新重新目标。</p>
<ul class="list-disc font-serif">
<li class="ml-8">目标: 通常是Makefile中要生成的文件或要执行的动作<ul class="list-disc font-serif">
<li class="ml-8">写在规则行的最左边。</li>
<li class="ml-8">比如: 可执行文件</li>
</ul>
</li>
<li class="ml-8">依赖: 确定目标如何生成,列出生成目标需要依赖的文件。<ul class="list-disc font-serif">
<li class="ml-8">位于目标后列出的文件或目标。</li>
<li class="ml-8">比如: 源代码和头文件</li>
</ul>
</li>
<li class="ml-8">规则: 描述目标与依赖文件之间的依赖关系 <code>target: dependencies</code></li>
<li class="ml-8">命令: 指定如何编译代码或构建目标。<ul class="list-disc font-serif">
<li class="ml-8">位于规则下方,需要使用<strong>Tab缩进</strong></li>
</ul>
</li>
</ul></div></section><section><div><h2 id="makefile" class="text-xl mt-2 pb-2 font-sans">Makefile 示例</h2>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="c"># 变量定义</span>
<span class="nv">CC</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span>gcc
<span class="nv">CFLAGS</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span>-Wall<span class="w"> </span>-Werror<span class="w"> </span>-g<span class="w"> </span>-Og
<span class="nv">TARGET</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span>program
<span class="nv">SRCS</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span>main.c
<span class="nv">OBJS</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">$(</span>SRCS:.c<span class="o">=</span>.o<span class="k">)</span>
<span class="c"># 首个规则为 make 的默认目标</span>
<span class="nf">all</span><span class="o">:</span><span class="w"> </span><span class="k">$(</span><span class="nv">TARGET</span><span class="k">)</span>
<span class="c"># 链接目标文件</span>
<span class="nf">$(TARGET)</span><span class="o">:</span><span class="w"> </span><span class="k">$(</span><span class="nv">OBJS</span><span class="k">)</span>
<span class="w"> </span><span class="k">$(</span>CC<span class="k">)</span><span class="w"> </span><span class="k">$(</span>CFLAGS<span class="k">)</span><span class="w"> </span>-o<span class="w"> </span><span class="k">$(</span>TARGET<span class="k">)</span><span class="w"> </span><span class="k">$(</span>OBJS<span class="k">)</span>
<span class="c"># 生成对象文件</span>
<span class="nf">%.o</span><span class="o">:</span><span class="w"> </span>%.<span class="n">c</span>
<span class="w"> </span><span class="k">$(</span>CC<span class="k">)</span><span class="w"> </span><span class="k">$(</span>CFLAGS<span class="k">)</span><span class="w"> </span>-c<span class="w"> </span>-o<span class="w"> </span><span class="nv">$@</span><span class="w"> </span>$&lt;
<span class="c"># 清理生成的文件</span>
<span class="nf">clean</span><span class="o">:</span>
<span class="w"> </span>rm<span class="w"> </span>-f<span class="w"> </span><span class="k">$(</span>OBJS<span class="k">)</span><span class="w"> </span><span class="k">$(</span>TARGET<span class="k">)</span>
<span class="c"># 伪目标</span>
<span class="nf">.PHONY</span><span class="o">:</span><span class="w"> </span><span class="n">all</span> <span class="n">clean</span>
</code></pre></div></div></section></section><section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">调试理论</h2>
<p class="font-serif my-1">Code -&gt; Executable file -&gt; Fault -&gt; Error -&gt; Failure</p>
<p class="font-serif my-1">软件工程领域中的三种 “错误”:</p>
<ul class="list-disc font-serif">
<li class="ml-8">Fault - 有bug的代码<ul class="list-disc font-serif">
<li class="ml-8">如数组访问越界, 根据C语言标准, 这是UB</li>
</ul>
</li>
<li class="ml-8">Error - 程序运行时刻的非预期状态<ul class="list-disc font-serif">
<li class="ml-8">如某些内存的值被错误改写</li>
</ul>
</li>
<li class="ml-8">Failure - 可观测的致命结果<ul class="list-disc font-serif">
<li class="ml-8">如输出乱码/assert失败/段错误等</li>
</ul>
</li>
</ul>
<p class="font-serif my-1">调试 = 看着Failure, 找到Fault</p></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">调试过程</h2>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code>Start Fault Failure
+---------------------+------------------+
|------ Error -----|
</code></pre></div>
<p class="font-serif my-1">程序员能做的:</p>
<ul class="list-disc font-serif">
<li class="ml-8">看到Failure, 知道肯定有问题</li>
<li class="ml-8">可以检查程序的某个状态是否正确</li>
</ul>
<p class="font-serif my-1">但检查这件事并不容易</p>
<ul class="list-disc font-serif">
<li class="ml-8">需要程序员来模拟一个应该正确的状态机的转移<ul class="list-disc font-serif">
<li class="ml-8">人肉DiffTest</li>
</ul>
</li>
<li class="ml-8">看上去都 “没什么问题”, 只能慢慢定位</li>
</ul></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans">调试公理</h2>
<h3 id="1">1. <red>机器永远是对的</red></h3>
<blockquote>
<p class="font-serif my-1">程序出错了, 不要怀疑真机的硬件/操作系统/编译器, 先怀疑自己的代码</p>
</blockquote>
<h3 id="2">2. <red>未测试代码永远是错的</red></h3>
<blockquote>
<p class="font-serif my-1">bug往往出现在那些你觉得“应该没问题”的地方</p>
</blockquote>
<h3 id="_2">要解决问题, 先摆正心态</h3></div></section><section><div><h2 id="tracer" class="text-xl mt-2 pb-2 font-sans">Tracer</h2>
<p class="font-serif my-1">输出日志追踪程序状态</p>
<ul class="list-disc font-serif">
<li class="ml-8"><code>__func__</code>: 当前函数</li>
<li class="ml-8"><code>__FILE__</code>: 当前文件名</li>
<li class="ml-8"><code>__LINE__</code>: 当前行号</li>
<li class="ml-8"><code>__VA_ARGS__</code>: 可变参数</li>
</ul>
<div class="codehilite"><pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="cp">#define ANSI_FG_BLUE "\33[1;34m"</span>
<span class="cp">#define ANSI_NONE "\33[0m"</span>
<span class="cp">#define ANSI_FMT(str, fmt) fmt str ANSI_NONE</span>
<span class="cp">#define Log(format, ...) \</span>
<span class="cp"> printf(ANSI_FMT("[%s:%d %s] " format, ANSI_FG_BLUE) "\n", \</span>
<span class="cp"> __FILE__, __LINE__, __func__, ## __VA_ARGS__)</span>
</code></pre></div></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans"><a href="https://zh.cppreference.com/w/c/error">断言</a></h2>
<ul class="list-disc font-serif">
<li class="ml-8">assert - 将预期的正确行为直接写到程序中</li>
<li class="ml-8">保证程序运行中的不变量</li>
<li class="ml-8">免费的午餐: <code>#define NDEBUG</code></li>
</ul>
<p class="font-serif my-1">调试理论层面的意义:</p>
<ul class="list-disc font-serif">
<li class="ml-8">如果捕捉到Error, 通过终止程序马上转变为可观测的Failure</li>
<li class="ml-8">避免Error继续传播, 造成更难理解的Failure</li>
<li class="ml-8">能够大幅提升调试效率</li>
</ul>
<p class="font-serif my-1">一些好的编程习惯:</p>
<ul class="list-disc font-serif">
<li class="ml-8">访问数组前先检查下标assert(idx &lt; ARRAY_SIZE);</li>
<li class="ml-8">指针解引用前先assert(p != NULL);</li>
<li class="ml-8">switch-case不存在默认情况时default: assert(0);</li>
</ul></div></section><section><div><h2 id="_1" class="text-xl mt-2 pb-2 font-sans"><a href="https://zh.wikipedia.org/zh-sg/%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95">单元测试</a></h2>
<p class="font-serif my-1">在计算机编程中,单元测试又称为模块测试 ,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。</p>
<p class="font-serif my-1">写单元测试是份累活:</p>
<ul class="list-disc font-serif">
<li class="ml-8">枚举所有可能的输入情况<ul class="list-disc font-serif">
<li class="ml-8">你不会愿意一个个手写出来的 😂</li>
</ul>
</li>
<li class="ml-8">需要软件工具来辅助我们<ul class="list-disc font-serif">
<li class="ml-8">全遍历测试 - 写个程序/脚本, 生成全排列的测试用例</li>
<li class="ml-8">随机测试 - 随机生成输入情况</li>
</ul>
</li>
<li class="ml-8">对于复杂的设计: 验证空间 vs. 边界情况覆盖率<ul class="list-disc font-serif">
<li class="ml-8">需要更好的规则指导, 这是一个前沿的研究问题</li>
</ul>
</li>
</ul></div></section><section><div><h2 id="lint" class="text-xl mt-2 pb-2 font-sans">免费的午餐: Lint</h2>
<p class="font-serif my-1">通过分析代码(静态程序分析), 提示编译通过但有潜在错误风险的代码</p>
<ul class="list-disc font-serif">
<li class="ml-8">在编译阶段消灭Fault!</li>
<li class="ml-8">虽然无法捕捉所有Fault, 但非常划算</li>
</ul>
<p class="font-serif my-1">编译器一般自带lint工具</p>
<ul class="list-disc font-serif">
<li class="ml-8">gcc中的-Wall, -Werror</li>
<li class="ml-8">clang中的analyzer</li>
</ul>
<p class="font-serif my-1">clangd和clang-tidy</p>
<ul class="list-disc font-serif">
<li class="ml-8">格式化代码: 观察控制流语句的缩进</li>
<li class="ml-8">静态分析: 未初始化的变量,未使用的变量</li>
</ul></div></section><section><div><h2 id="sanitize-valgrind" class="text-xl mt-2 pb-2 font-sans">sanitize 与 valgrind</h2>
<p class="font-serif my-1">sanitize:</p>
<ul class="list-disc font-serif">
<li class="ml-8">让编译器自动插入assert, 拦截常见的非预期行为</li>
<li class="ml-8">AddressSanitizer - 检查指针越界, use-after-free</li>
<li class="ml-8">LeakSanitizer - 检查内存泄漏</li>
<li class="ml-8">UndefinedBehaviorSanitizer - 检查UB</li>
<li class="ml-8">man gcc查看具体用法</li>
</ul>
<p class="font-serif my-1">valgrind:</p>
<ul class="list-disc font-serif">
<li class="ml-8">更加强大的 sanitize</li>
<li class="ml-8">不需要编译时启用</li>
</ul>
<p class="font-serif my-1">使用它们后程序运行效率有所下降</p>
<ul class="list-disc font-serif">
<li class="ml-8">但调试的时候非常值得, 躺着就能让工具帮你找bug</li>
</ul></div></section><section data-auto-animate><div><h2 id="gdb" class="text-xl mt-2 pb-2 font-sans">调试器: <a href="https://sourceware.org/gdb/">GDB</a></h2>
<p class="font-serif my-1">调试器: 可以根据需要暂停程序,并允许观察程序当前状态</p>
<table>
<thead>
<tr>
<th>功能</th>
<th>GDB 命令</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>启动 GDB</td>
<td><code>gdb ./your_program</code></td>
<td>启动 GDB 并加载指定程序</td>
</tr>
<tr>
<td>运行程序</td>
<td><code>run</code></td>
<td>启动并运行程序</td>
</tr>
<tr>
<td>退出 GDB</td>
<td><code>quit</code></td>
<td>退出 GDB</td>
</tr>
<tr>
<td>设置断点</td>
<td><code>break main</code></td>
<td><code>main</code> 函数入口设置断点</td>
</tr>
<tr>
<td/>
<td><code>break 10</code></td>
<td>在第 10 行设置断点</td>
</tr>
<tr>
<td>删除断点</td>
<td><code>delete</code></td>
<td>删除所有断点</td>
</tr>
<tr>
<td/>
<td><code>delete &lt;breakpoint_number&gt;</code></td>
<td>删除特定断点,例如 <code>delete 1</code></td>
</tr>
</tbody>
</table></div></section><section data-auto-animate><div><h2 id="gdb" class="text-xl mt-2 pb-2 font-sans">GDB</h2>
<table>
<thead>
<tr>
<th>功能</th>
<th>GDB 命令</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>查看当前断点</td>
<td><code>info breakpoints</code></td>
<td>显示所有断点信息</td>
</tr>
<tr>
<td>继续执行</td>
<td><code>continue</code></td>
<td>从断点处继续执行程序</td>
</tr>
<tr>
<td>单步执行</td>
<td><code>next</code></td>
<td>单步执行下一行</td>
</tr>
<tr>
<td/>
<td><code>step</code></td>
<td>单步执行,并进入函数调用</td>
</tr>
<tr>
<td>运行到下一断点</td>
<td><code>finish</code></td>
<td>执行当前函数直到返回</td>
</tr>
<tr>
<td>查看当前堆栈</td>
<td><code>where</code></td>
<td>显示当前的堆栈跟踪</td>
</tr>
<tr>
<td>查看变量值</td>
<td><code>print variable_name</code></td>
<td>查看变量值,例如 <code>print a</code></td>
</tr>
<tr>
<td>查看内存值</td>
<td><code>x pointer</code></td>
<td>查看指针指向的内存的值</td>
</tr>
<tr>
<td>查看帮助</td>
<td><code>help</code></td>
<td>显示 GDB 的帮助信息</td>
</tr>
</tbody>
</table></div></section><section><div><h2 id="fault" class="text-xl mt-2 pb-2 font-sans">正确的编程模式: 少写Fault</h2>
<blockquote>
<p class="font-serif my-1">正确的代码 != 好代码</p>
<p class="font-serif my-1">好代码更大概率是正确的</p>
</blockquote>
<p class="font-serif my-1">好代码的两条重要准则:</p>
<ul class="list-disc font-serif">
<li class="ml-8"><strong><green>不言自明</green> - <red>仅看代码就能明白</red>是做什么的(specification)</strong></li>
<li class="ml-8"><strong><green>不言自证</green> - <red>仅看代码就能验证</red>实现是对的(verification)</strong></li>
</ul>
<p class="font-serif my-1">使用正确的编程模式写出好代码:</p>
<ul class="list-disc font-serif">
<li class="ml-8">防御性编程 - 通过assert检查非预期行为</li>
<li class="ml-8">减少代码中的隐含依赖 - 使得 “打破依赖”不会发生<ul class="list-disc font-serif">
<li class="ml-8">头文件 + 源文件</li>
</ul>
</li>
<li class="ml-8">编写可复用的代码 - 不要Copy-Paste</li>
<li class="ml-8">使用合适的语言特性 - 把细节交给语言规范和编译器</li>
</ul></div></section></section>
</div>
</div>
<script src="./static/reveal/reveal.js"></script>
<script>
Reveal.initialize({
width: 1024, height: 768,
slideNumber: 'c/t',
controlsTutorial: false,
progress: false,
hash: true,
center: false,
autoAnimateUnmatched: true,
autoAnimateEasing: 'ease-out',
autoAnimateDuration: 0.3,
transitionSpeed: 'fast'
});
</script>
</body>
</html>

View File

@ -0,0 +1,86 @@
.watermark {
position: fixed;
opacity: 0.1;
font-size: 128px;
width: 100%;
text-align: center;
z-index: 1000;
pointer-events: none;
}
.reveal .katex {
font-size: 100%;
}
red { color: red; }
green { color: green; }
blue { color: blue; }
.codehilite .hll { background-color: #ffffcc }
.codehilite .c { color: #408080; font-style: italic } /* Comment */
.codehilite .err { border: 1px solid #FF0000 } /* Error */
.codehilite .k { color: #008000; font-weight: bold } /* Keyword */
.codehilite .o { color: #666666 } /* Operator */
.codehilite .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */
.codehilite .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */
.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */
.codehilite .gd { color: #A00000 } /* Generic.Deleted */
.codehilite .ge { font-style: italic } /* Generic.Emph */
.codehilite .gr { color: #FF0000 } /* Generic.Error */
.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.codehilite .gi { color: #00A000 } /* Generic.Inserted */
.codehilite .go { color: #888888 } /* Generic.Output */
.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.codehilite .gs { font-weight: bold } /* Generic.Strong */
.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.codehilite .gt { color: #0044DD } /* Generic.Traceback */
.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.codehilite .kp { color: #008000 } /* Keyword.Pseudo */
.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.codehilite .kt { color: #B00040 } /* Keyword.Type */
.codehilite .m { color: #666666 } /* Literal.Number */
.codehilite .s { color: #BA2121 } /* Literal.String */
.codehilite .na { color: #7D9029 } /* Name.Attribute */
.codehilite .nb { color: #008000 } /* Name.Builtin */
.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.codehilite .no { color: #880000 } /* Name.Constant */
.codehilite .nd { color: #AA22FF } /* Name.Decorator */
.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */
.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.codehilite .nf { color: #0000FF } /* Name.Function */
.codehilite .nl { color: #A0A000 } /* Name.Label */
.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
.codehilite .nv { color: #19177C } /* Name.Variable */
.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
.codehilite .mb { color: #666666 } /* Literal.Number.Bin */
.codehilite .mf { color: #666666 } /* Literal.Number.Float */
.codehilite .mh { color: #666666 } /* Literal.Number.Hex */
.codehilite .mi { color: #666666 } /* Literal.Number.Integer */
.codehilite .mo { color: #666666 } /* Literal.Number.Oct */
.codehilite .sa { color: #BA2121 } /* Literal.String.Affix */
.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
.codehilite .sc { color: #BA2121 } /* Literal.String.Char */
.codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */
.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.codehilite .sx { color: #008000 } /* Literal.String.Other */
.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */
.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
.codehilite .ss { color: #19177C } /* Literal.String.Symbol */
.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
.codehilite .fm { color: #0000FF } /* Name.Function.Magic */
.codehilite .vc { color: #19177C } /* Name.Variable.Class */
.codehilite .vg { color: #19177C } /* Name.Variable.Global */
.codehilite .vi { color: #19177C } /* Name.Variable.Instance */
.codehilite .vm { color: #19177C } /* Name.Variable.Magic */
.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,175 @@
.reveal .slide-number {
font-size: 26px;
border-radius: 5px;
background-color: rgba(0, 0, 0, .3);
}
.reveal .slides {
border: 1.5px #ddd solid;
border-radius: 7px;
text-align: left;
font-weight: 300;
}
.reveal h1,
.reveal h2,
.reveal h3,
.reveal h4 {
font-family: 'Lato', 'SimHei', 'STXihei', 'Sans Serif';
font-weight: 400;
}
.reveal p,
.reveal li,
.reveal center {
font-size: 32px;
font-family: 'Lato', 'STHeiti', 'SimHei', 'Sans Serif';
}
.reveal li+li {
margin-top: 10px;
}
.reveal ul {
display: block;
margin-right: 15px;
}
.reveal p,
.reveal h1,
.reveal h2,
.reveal h3,
.reveal h4,
.reveal h5 {
padding: 0 25px 0 25px;
}
.reveal table {
font-size: 32px;
font-family: 'Lato', 'STHeiti', 'SimHei', 'Sans Serif';
margin-top: 15px;
margin-bottom: 15px;
}
.reveal th {
background-color: #eee;
}
.reveal tr:nth-child(even) {
background-color: #efffff;
}
.reveal h1,
.reveal h2,
.reveal h3,
.reveal h4,
.reveal h5,
.reveal h6 {
text-align: left;
margin: 0 0 20px 0;
color: #222;
font-weight: 400;
line-height: 1.2;
letter-spacing: normal;
}
.reveal h1 {
margin: 0 10 0 10;
font-size: 60px;
}
.reveal .middle h1 {
text-align: center;
}
.reveal h2 {
font-size: 48px;
border-bottom: 2px solid rgb(106, 0, 95);
padding-bottom: 5px;
}
.reveal h3 {
font-size: 1.15em;
}
.reveal h4 {
font-size: 1.05em;
}
.reveal .center {
text-align: center;
}
.reveal .middle {
height: 728px;
display: flex;
align-items: center;
width: 100%;
}
.reveal pre {
font-size: 28px;
background-color: #eee;
border-radius: 3mm;
padding: 10px 10px 10px 10px;
}
.reveal pre code {
max-height: none;
}
.reveal code {
font-family: 'Inconsolata', 'STKaiti', 'KaiTi', 'Sans Serif', Monospace;
}
.reveal .middle blockquote {
text-align: center;
color: rgb(106, 0, 95);
background: none;
box-shadow: none;
}
.reveal .middle blockquote a {
color: inherit;
}
.reveal blockquote p,
.reveal blockquote li {
font-family: 'Lato', 'STKaiti', 'KaiTi', 'Sans Serif';
}
section .center {
display: block;
margin-left: auto;
margin-right: auto;
}
.reveal .author-block {
margin: 75px 0 35px 0;
}
.reveal .author-affiliation img {
margin: 15px 0 0 0;
}
.reveal .author-block p,
.reveal .author-affiliation p {
font-family: 'Kaiti', 'STKaiti', 'Serif', 'Times', 'Times New Roman';
margin-block-start: 0em;
margin-block-end: 0em;
}
.reveal .author-affiliation {
display: inline-block;
font-size: 90%;
}
.reveal hr {
border: 10px solid rgba(0, 0, 0, 0);
}
.reveal li {
margin-top: 10px;
}

View File

@ -0,0 +1 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},r={};function n(e){var i=r[e];if(void 0!==i)return i.exports;var a=r[e]={exports:{}};return t[e](a,a.exports,n),a.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var i={};return function(){n.d(i,{default:function(){return s}});var e=n(771),t=n.n(e),r=function(e,t,r){for(var n=r,i=0,a=e.length;n<t.length;){var o=t[n];if(i<=0&&t.slice(n,n+a)===e)return n;"\\"===o?n++:"{"===o?i++:"}"===o&&i--,n++}return-1},a=/^\\begin{/,o=function(e,t){for(var n,i=[],o=new RegExp("("+t.map((function(e){return e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")})).join("|")+")");-1!==(n=e.search(o));){n>0&&(i.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));var l=t.findIndex((function(t){return e.startsWith(t.left)}));if(-1===(n=r(t[l].right,e,t[l].left.length)))break;var d=e.slice(0,n+t[l].right.length),s=a.test(d)?d:e.slice(t[l].left.length,n);i.push({type:"math",data:s,rawData:d,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&i.push({type:"text",data:e}),i},l=function(e,r){var n=o(e,r.delimiters);if(1===n.length&&"text"===n[0].type)return null;for(var i=document.createDocumentFragment(),a=0;a<n.length;a++)if("text"===n[a].type)i.appendChild(document.createTextNode(n[a].data));else{var l=document.createElement("span"),d=n[a].data;r.displayMode=n[a].display;try{r.preProcess&&(d=r.preProcess(d)),t().render(d,l,r)}catch(e){if(!(e instanceof t().ParseError))throw e;r.errorCallback("KaTeX auto-render: Failed to parse `"+n[a].data+"` with ",e),i.appendChild(document.createTextNode(n[a].rawData));continue}i.appendChild(l)}return i},d=function e(t,r){for(var n=0;n<t.childNodes.length;n++){var i=t.childNodes[n];if(3===i.nodeType){for(var a=i.textContent,o=i.nextSibling,d=0;o&&o.nodeType===Node.TEXT_NODE;)a+=o.textContent,o=o.nextSibling,d++;var s=l(a,r);if(s){for(var f=0;f<d;f++)i.nextSibling.remove();n+=s.childNodes.length-1,t.replaceChild(s,i)}else n+=d}else 1===i.nodeType&&function(){var t=" "+i.className+" ";-1===r.ignoredTags.indexOf(i.nodeName.toLowerCase())&&r.ignoredClasses.every((function(e){return-1===t.indexOf(" "+e+" ")}))&&e(i,r)}()}},s=function(e,t){if(!e)throw new Error("No element provided to render");var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],r.ignoredTags=r.ignoredTags||["script","noscript","style","textarea","pre","code","option"],r.ignoredClasses=r.ignoredClasses||[],r.errorCallback=r.errorCallback||console.error,r.macros=r.macros||{},d(e,r)}}(),i=i.default}()}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,285 @@
/**
* A simple theme for reveal.js presentations, similar
* to the default theme. The accent color is darkblue.
*
* This theme is Copyright (C) 2012 Owen Versteeg, https://github.com/StereotypicalApps. It is MIT licensed.
* reveal.js is Copyright (C) 2011-2012 Hakim El Hattab, http://hakim.se
*/
@import url(https://fonts.googleapis.com/css?family=News+Cycle:400,700);
@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic);
section.has-dark-background, section.has-dark-background h1, section.has-dark-background h2, section.has-dark-background h3, section.has-dark-background h4, section.has-dark-background h5, section.has-dark-background h6 {
color: #fff; }
/*********************************************
* GLOBAL STYLES
*********************************************/
:root {
--background-color: #fff;
--main-font: Lato, sans-serif;
--main-font-size: 40px;
--main-color: #000;
--block-margin: 20px;
--heading-margin: 0 0 20px 0;
--heading-font: News Cycle, Impact, sans-serif;
--heading-color: #000;
--heading-line-height: 1.2;
--heading-letter-spacing: normal;
--heading-text-transform: none;
--heading-text-shadow: none;
--heading-font-weight: normal;
--heading1-text-shadow: none;
--heading1-size: 3.77em;
--heading2-size: 2.11em;
--heading3-size: 1.55em;
--heading4-size: 1em;
--code-font: monospace;
--link-color: #00008B;
--link-color-hover: #0000f1;
--selection-background-color: rgba(0, 0, 0, 0.99);
--selection-color: #fff; }
.reveal-viewport {
background: #fff;
background-color: #fff; }
.reveal {
font-family: "Lato", sans-serif;
font-size: 40px;
font-weight: normal;
color: #000; }
.reveal ::selection {
color: #fff;
background: rgba(0, 0, 0, 0.99);
text-shadow: none; }
.reveal ::-moz-selection {
color: #fff;
background: rgba(0, 0, 0, 0.99);
text-shadow: none; }
.reveal .slides section,
.reveal .slides section > section {
line-height: 1.3;
font-weight: inherit; }
/*********************************************
* HEADERS
*********************************************/
.reveal h1,
.reveal h2,
.reveal h3,
.reveal h4,
.reveal h5,
.reveal h6 {
margin: 0 0 20px 0;
color: #000;
font-family: "News Cycle", Impact, sans-serif;
font-weight: normal;
line-height: 1.2;
letter-spacing: normal;
text-transform: none;
text-shadow: none;
word-wrap: break-word; }
.reveal h1 {
font-size: 3.77em; }
.reveal h2 {
font-size: 2.11em; }
.reveal h3 {
font-size: 1.55em; }
.reveal h4 {
font-size: 1em; }
.reveal h1 {
text-shadow: none; }
/*********************************************
* OTHER
*********************************************/
.reveal p {
margin: 20px 0;
line-height: 1.3; }
/* Ensure certain elements are never larger than the slide itself */
.reveal img,
.reveal video,
.reveal iframe {
max-width: 95%;
max-height: 95%; }
.reveal strong,
.reveal b {
font-weight: bold; }
.reveal em {
font-style: italic; }
.reveal ol,
.reveal dl,
.reveal ul {
display: inline-block;
text-align: left;
margin: 0 0 0 1em; }
.reveal ol {
list-style-type: decimal; }
.reveal ul {
list-style-type: disc; }
.reveal ul ul {
list-style-type: square; }
.reveal ul ul ul {
list-style-type: circle; }
.reveal ul ul,
.reveal ul ol,
.reveal ol ol,
.reveal ol ul {
display: block;
margin-left: 10px; }
.reveal dt {
font-weight: bold; }
.reveal dd {
margin-left: 40px; }
.reveal blockquote {
display: block;
position: relative;
width: 90%;
margin: 20px auto;
padding: 5px;
background: rgba(0, 255, 255, 0.05);
border-radius: 10px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
}
.reveal q {
font-style: italic; }
.reveal pre {
display: block;
position: relative;
width: 90%;
margin: 20px auto;
text-align: left;
font-size: 0.55em;
font-family: monospace;
line-height: 1.2em;
word-wrap: break-word;
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15); }
.reveal code {
font-family: monospace;
text-transform: none; }
.reveal pre code {
display: block;
padding: 5px;
overflow: auto;
max-height: 400px;
word-wrap: normal; }
.reveal table {
margin: auto;
border-collapse: collapse;
border-spacing: 0; }
.reveal table th {
font-weight: bold; }
.reveal table th,
.reveal table td {
text-align: left;
padding: 0.2em 0.5em 0.2em 0.5em;
border-bottom: 1px solid; }
.reveal table th[align="center"],
.reveal table td[align="center"] {
text-align: center; }
.reveal table th[align="right"],
.reveal table td[align="right"] {
text-align: right; }
.reveal table tbody tr:last-child th,
.reveal table tbody tr:last-child td {
border-bottom: none; }
.reveal sup {
vertical-align: super;
font-size: smaller; }
.reveal sub {
vertical-align: sub;
font-size: smaller; }
.reveal small {
display: inline-block;
font-size: 0.6em;
line-height: 1.2em;
vertical-align: top; }
.reveal small * {
vertical-align: top; }
.reveal img {
margin: 20px 0; }
/*********************************************
* LINKS
*********************************************/
.reveal a {
color: #00008B;
text-decoration: none;
transition: color .15s ease; }
.reveal a:hover {
color: #0000f1;
text-shadow: none;
border: none; }
.reveal .roll span:after {
color: #fff;
background: #00003f; }
/*********************************************
* Frame helper
*********************************************/
.reveal .r-frame {
border: 4px solid #000;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15); }
.reveal a .r-frame {
transition: all .15s linear; }
.reveal a:hover .r-frame {
border-color: #00008B;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.55); }
/*********************************************
* NAVIGATION CONTROLS
*********************************************/
.reveal .controls {
color: #00008B; }
/*********************************************
* PROGRESS BAR
*********************************************/
.reveal .progress {
background: rgba(0, 0, 0, 0.2);
color: #00008B; }
/*********************************************
* PRINT BACKGROUND
*********************************************/
@media print {
.backgrounds {
background-color: #fff; } }

View File

@ -0,0 +1,23 @@
BUILD_DIR = ./build
CC := clang
LD := clang
CFLAGS := -Wall -Wextra -g -Og -fsanitize=address -fsanitize=undefined
LDFLAGS := $(CFLAGS) -lm
SRCS := $(wildcard *.c)
TARGETS := $(SRCS:%.c=$(BUILD_DIR)/%)
all: $(TARGETS)
$(BUILD_DIR)/%: %.o
@mkdir -p $(dir $@)
$(LD) -o $@ $< $(LDFLAGS)
$(BUILD_DIR)/%.o: %.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c -o $@ $<
clean:
-rm -rf $(BUILD_DIR)
.PHONY: clean all

View File

@ -0,0 +1,20 @@
/* 分别尝试使用
* gcc -o math math.c
* gcc -O2 -o math math.c
* gcc -O2 -DVOLATILE -o math math.c
* gcc -lm -DVOLATILE -o math math.c
*
*/
#include <math.h>
#include <stdio.h>
int main(void) {
double a = 2;
printf("sqrt(a) = %f\n", sqrt(a));
/* */
#ifdef VOLATILE
volatile double b = 2;
printf("sqrt(b) = %f\n", sqrt(b));
#endif
return 0;
}

View File

@ -0,0 +1,9 @@
#include <stdio.h>
int main(void) {
char a[] = "world\n";
char b[5] = "hello";
printf("&a = %p, &b = %p\n", a, b);
printf("%s", b);
return 0;
}

View File

@ -0,0 +1,14 @@
#include <limits.h>
#include <stdio.h>
int foo(int x) {
return x + 1 > x; // 真或为有符号溢出导致的 UB
}
int main(void) {
printf("IMT_MAX + 1 = %d\n", INT_MAX + 1);
printf("INT_MAX = %d\n", INT_MAX);
printf("INT_MAX + 1 > INT_MAX = %d\n", INT_MAX + 1 > INT_MAX);
printf("foo(INT_MAX) = %d\n", foo(INT_MAX));
return 0;
}

View File

@ -0,0 +1,28 @@
#include <assert.h>
#include <stdio.h>
typedef enum RetType_t { ret_int, ret_double } RetType_t;
typedef struct {
RetType_t ret_type;
union {
int int_val;
double double_val;
}; // 匿名联合体
} Ret_t;
Ret_t f(RetType_t ret_type) {
switch (ret_type) {
case ret_int:
return (Ret_t){.ret_type = ret_int, .int_val = 1};
case ret_double:
return (Ret_t){.ret_type = ret_double, .double_val = 1.0};
default:
assert(0);
}
}
int main(void) {
printf("%f\n", f(ret_double).double_val);
printf("%d\n", f(ret_int).int_val);
return 0;
}

View File

@ -1,21 +0,0 @@
# Week6 Note 大纲
- C 项目的组织
- GNU Make 为例的项目构建
- GNU Make 简单语法介绍
- 可供参考的 GNU Make C 项目模板
- Git 为例的版本控制
- Git 简单语法介绍
- 多文件的交互
- 头文件
- 函数与变量的声明、作用域、生存期、存储器
- 链接
- 静态链接
- 动态链接
- 测试与调试
- 单元测试
- 断言
- 调试宏
- 第三方测试框架
- Valgrind
- GDB——以 CGDB 为例

View File

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2017-2019 Richard Littauer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,237 +0,0 @@
# jyyslide-md
❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗
该项目目前有一些亟需优化的地方,我已经有了方案,但是由于工作,暂时没有精力实现,请同好们敬请期待。
1. 支持通过`pip`下载并通过命令使用
>并不是所有人都了解Python、Poetry
2. 命令支持检测文件修改并自动编译(甚至自动刷新浏览器)
>就像前端相关命令一样自然
3. 优化架构,初版开发个人的软件工程水平一般(当前现在也一般但是有一定提高)
4. 拓展**渐变垂直幻灯片**的功能,用户常用渐变实现一张幻灯片的不同部分的先后出现,但是目前需要将不同部分作为多个页,很麻烦
5. 开发VSCode的插件
>就像上面说的,并不是所有人都了解命令行
❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗❗
一款通过简约的Mardown方言生成具有[南大蒋炎岩老师幻灯片](http://jyywiki.cn/OS/2022/slides/1.slides#/)风格的Web幻灯片转换工具
准确的说是一款基于Reveal.js的定制主题Web幻灯片框架类似reveal-md不过定制主题和蒋老师的一样
[Background](#background) | [Install](#install) | [Usage](#usage) | [Grammer](#grammer) | [Example](#example) | [Develop](#develop) | [Acknowledgement](#acknowledgement) | [License](#license)
## Background
>可以从奥卡姆剃刀(如无必要,勿增实体)的角度考虑我开发本项目的发心。
说起幻灯片首先想到的是微软的PowerPointPPT几乎成了幻灯片的代名词。但是在使用过程中我们会发现它提供的很多的功能为了使用这些功能需要很高的学习成本但大多数场景我们用不到这么多功能同时在使用别人的PPT模板是因为我们对功能的不熟练而不能展现模板PPT的全部效果。在幻灯片领域有类似Markdown之于Word的框架嘛
除了能量点这样的制作幻灯片的软件外还有基于Web的幻灯片我基本都[尝试](https://github.com/zweix123/CS-notes/blob/master/Missing-Semester/slide.md)了一下。但是并没有完全满足我的要求的。
[南京大学蒋炎岩老师](https://ics.nju.edu.cn/~jyy)开源了他的[操作系统课程](https://space.bilibili.com/202224425),相信上过他的课的同学除了会被他深入浅出的授课所折服外,也一定对他的幻灯片感兴趣。他的幻灯片是基于[Reveal.js](https://revealjs.com/)这款Web幻灯片框架但不清楚他具体是如何制作的在经过他的同意下我制作了这个将Markdown方言转换成和他一个风格的幻灯片的工具。
对于Markdown扩展语法的设计尽可能简单有些功能不是不能提供但是提供会导致语法没有性价比的扩张所以舍弃。让设计尽可能足够且简约。
## Install
本项目使用Python开发模块管理使用Poetry请确保您的机器上有版本足够的Python**3.10以上**并安装有第三方模块Poetry同时也得益于Python本项目应该可以运行于任何系统上。
>关于Poetry可参考我的[笔记](https://github.com/zweix123/CS-notes/tree/master/Programing-Language/Python#poetry),当然下面会提供足够的用法。
1. 克隆项目到本地并进入:
```bash
git clone https://github.com/zweix123/jyyslide-md.git
cd jyyslide-md
```
2. 利用Poetry下载第三方模块
```bash
poetry install
```
>如果在win机器且出现乱码, 可以尝试下面的方案
>`控制面板` -> `区域` -> `管理` -> `更改系统区域设置` -> 打开`Beta版`
## Usage
>请确保已经[Install](#install)好了
+ 使用Peotry管理的Python有两种运行方式
1. 进入虚拟环境:
```bash
poetry shell
```
之后就可以正常的运行Python代码了
2. 使用前缀在运行Python代码的命令前添加`poetry run`
比如[样例1](#example)中的命令应该是`poetry run python main.py example\jyy\操作系统概述.md`
命令格式如下
```bash
python main.py [Markdown文件]
```
在Markdown文件同级目录会出现一个`dist`文件夹其下有一个index.html文件和一个static文件夹前者即为生成的“Web幻灯片static即为其相关静态文件。网页的title和Markdown文件同名、icon即为`static/img/favicon.png`可通过替换这个文件修改icon。
+ PDF Export: [Manual](https://revealjs.com/pdf-export/)
### Grammer
[教程](https://zweix123.github.io/jyyslide-md/):在这里可以结合效果来说明语法(**推荐**
>这个幻灯片就是用jyyslide-md制作而成的
+ 水平幻灯片使用`\n---\n`(三个)分割
+ 垂直幻灯片使用`\n----\n`(四个)分割
+ 渐变垂直幻灯片使用`\n++++\n`(四个)分割
+ 在同一张幻灯片中依次出现的部分使用`\n--\n`(两个)分割
+ 具体分割方式是从分割符到下一个分隔符或者本张幻灯片末尾的位置
+ 更多样式见[reveal.js官网对Fragments的解释](https://revealjs.com/fragments/)
+ 作者信息使用`\n+++++\n`(五个)和正文分割使用Json格式
这里主要指指的是这部分
<img src="./resource/author.png" width="456">
因为这部分是多个文字、图片、链接为一体如果使用扩展Markdown语法的设置会让语法很凌乱。
实际上这样的页面只在第一页出现,即使不使用这样的语法,使用这样的形式
```
# Title
>author
```
<img src="./resource/example_of_author.png" width="456">
在大多数场景也足够,所以从设计上将这部分从主题抽离出来
这部分的格式如下,
>在[例子](#example)中的jyy中的Markdown文件
```json
{
"author": {
"name": "蒋炎岩",
"url": "https://ics.nju.edu.cn/~jyy/"
},
"departments": [
{
"name": " 南京大学 ",
"url": "https://www.nju.edu.cn/main.htm",
"img": "./img/nju-logo.jpg"
},
{
"name": "计算机科学与技术系",
"url": "https://cs.nju.edu.cn/main.htm",
"img": "./img/njucs-logo.jpg"
},
{
"name": "计算机软件研究所",
"url": "https://www.nju.edu.cn/main.htm",
"img": "./img/ics-logo.png"
}
]
}
```
现也支持YAML格式建议
```yaml
author:
name: 蒋炎岩
url: https://ics.nju.edu.cn/~jyy/
departments:
- name: " 南京大学 "
url: https://www.nju.edu.cn/main.htm,
img: ./img/nju-logo.jpg
- name: 计算机科学与技术系
url: https://cs.nju.edu.cn/main.htm,
img: ./img/njucs-logo.jpg
- name: 计算机软件研究所
url: https://www.nju.edu.cn/main.htm,
img: ./img/ics-logo.png
```
---
+ 对Markdown原生语法适配情况
>这里使用的Markdown语法使用的是**严格**语法。
+ 文字格式:
+ 通过Markdown原生语法支持**加粗**、*斜体*
+ 通过插入html支持<del>删除线</del><mark>高亮</mark><red>标红</red>
+ 支持注释
+ 支持列表
+ 支持代码和代码高亮
>Reveal-md和Slidev支持的代码特定行高亮暂时不支持
+ 支持引用链接和图片图片推荐以插入HTML的方式使用
```html
<img src="图片地址">
```
这里的src支持URL相对地址和绝对地址程序会将其down或者copy到dist下的img中
>这里使用的爬虫是非常简单的爬虫,建议自己下载到本地使用。
+ 图片居中:
```html
<img class="float-right" src="图片地址">
```
+ 图片右对齐:
```html
<img class="float-right" src="图片地址">
```
Markdown中的格式是流的形式即图片是占位的这里默认左对齐和居中的图片都是占位的但是右对齐的图片不占位
其他格式调整SFTW
+ 支持数学公式
+ 支持表格(表格的格式并不好看)
+ 关于Markdown的这个语法大于三个的`-`是分割线`<hr>`,我们发现这和扩展语法冲突,所以这里是大于四个的`-`是分割线且这里的分割线在HTML中是空行的效果
---
+ 调整主题如果您有CSS基础可以调整蒋老师主题主要指字号、字间距、行间距之类的微调关于蒋老师主题的CSS文件在`dist/static/jyy/jyy.css`中。
---
蒋老师有而未设置专门语法的部分
+ 多个幻灯片并列
```
<center>
<img class="inline" ...>
<img class="inline" ...>
<img class="inline" ...>
</center>
```
如果你想你可以直接在Markdown中插入类似上面的代码
+ 插入B站
## Example
+ `example/jyy/操作系统概述.md`即为蒋老师2022年的第一节课
```bash
python main.py example/jyy/操作系统概述.md
```
打开`example\jyy\dist\index.html`即可查看
+ `example/Intro/slide.md`即为本项目介绍的幻灯片
```bash
python main.py example/Intro/slide.md
```
打开`example\Intro\dist\index.html`即可查看
## Develop
+ 根目录下的main.py是项目的入口主体代码在src目录下逻辑核心在converter.py这个过程要维护很多配置信息和全局信息所以我将其放在settings.py下util目录则是些辅助函数
+ 不建议扩展标记converter虽然不长但是写的不是很优雅可维护性低
+ 推荐从`src/util/md_util.py`入手项目将Markdown转换成html的代码在这里可以通过修改markdown模块相关来增加功能
+ 比如slidev的代码特定行高亮这就是后续的开发计划
+ 格式化使用black静态检查使用mypy
+ 依赖库中有很多用于静态检查的模块,如果想最小化本项目,可以重新加载依赖
+ 这个模块`pygments`,没有出现在代码的任何地方,但是在代码高亮中发挥重要作用,如果重新加载依赖,不要忘记它。
## Acknowledgement
+ 感谢[南京大学蒋炎岩老师](https://ics.nju.edu.cn/~jyy/)录制了如此优质的[操作系统课程](https://jyywiki.cn/)
+ 感谢[顾若水](https://github.com/ruoshui255)大佬提供的[思路和大量代码](./src/backup/rouv/ruoshui255.md.py)
+ 感谢[Jungle](https://github.com/Jungle430)对编码问题的提醒
## License
[MIT](LICENSE) © Richard Littauer

View File

@ -1,571 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="./static/css/base.css" rel="stylesheet">
<link href="./static/css/tailwind.min.css" rel="stylesheet">
<link href="https://fonts.font.im/css?family=Source+Serif+Pro%7CLato%7CInconsolata" rel="stylesheet"
type="text/css">
<title> slide </title>
<!-- browser favicon -->
<link rel="shortcut icon" href="./static/img/favicon.ico">
<style>
.font-sans {
font-family: 'Lato', 'SimHei', 'STHeiti', 'SimHei', 'Serif';
}
.font-serif {
font-family: 'Source Serif Pro', 'Songti SC', 'SimSun', 'Serif', serif;
}
</style>
<link rel="stylesheet" href="./static/katex/katex.min.css">
<script defer src="./static/katex/katex.min.js"></script>
<script defer src="./static/katex/auto-render.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
renderMathInElement(document.body, {
// customised options
// &#8226; auto-render specific keys, e.g.:
delimiters: [
{ left: '$$', right: '$$', display: true },
{ left: '$', right: '$', display: false },
{ left: '\\(', right: '\\)', display: false },
{ left: '\\[', right: '\\]', display: true }
],
// &#8226; rendering keys, e.g.:
throwOnError: false
});
});
</script>
<link rel="stylesheet" href="./static/reveal/reveal.css">
<link rel="stylesheet" href="./static/reveal/theme/simple.css" id="theme">
<link rel="stylesheet" href="./static/jyy/jyy.css">
</head>
<body class="d-flex flex-column h-100">
<div class="reveal">
<div class="slides">
<section>
<section>
<div class="center middle">
<div style="width:100%">
<div>
<h1 id="jyyslide-md" class="text-2xl mt-2 font-sans">jyyslide-md</h1>
<hr />
<blockquote>
<p class="font-serif my-1"><a href="https://github.com/zweix123">zweix</a></p>
</blockquote>
</div>
</div>
</div>
</section>
</section>
<section>
<section>
<div class="center middle">
<div style="width:100%">
<div>
<h1 id="_1" class="text-2xl mt-2 font-sans">让我们试试不一样的交互方式</h1>
<hr />
<blockquote>
<p class="font-serif my-1">试试方向键<br />
或者vim的<code>hjkl</code><br />
或者滑动屏幕(移动端) </p>
</blockquote>
</div>
</div>
</div>
</section>
<section>
<div>
<h2 id="revealjsweb" class="text-xl mt-2 pb-2 font-sans">基于Reveal.js框架的Web幻灯片交互方式</h2>
<ul class="list-disc font-serif">
<li class="ml-8">通过方向键或者<code>hjkl</code>切换幻灯片</li>
<li class="ml-8">幻灯片维度更高,除了水平幻灯片还有竖直幻灯片</li>
<li class="ml-8">其他快捷键:<ul class="list-disc font-serif">
<li class="ml-8"><code>o</code><code>esc</code>:总览</li>
<li class="ml-8"><code>b</code>或者<code>v</code>:息屏、亮屏</li>
<li class="ml-8"><code>f</code>:全屏(<code>esc</code>退出全屏)</li>
</ul>
</li>
</ul>
</div>
</section>
</section>
<section>
<section>
<div class="center middle">
<div style="width:100%">
<div>
<h1 id="_1" class="text-2xl mt-2 font-sans">发心</h1>
</div>
</div>
</div>
</section>
<section>
<div>
<h2 id="powerpoint" class="text-xl mt-2 pb-2 font-sans">PowerPoint</h2>
<blockquote>
<p class="font-serif my-1">可以从奥卡姆剃刀的角度考虑</p>
</blockquote>
<p class="font-serif my-1">能量点的功能非常丰富,但是功能多意味着学习成本大,但实际上我只需要很小部分的功能就能完成大部分的事情。<br />
由于这种复杂性我们在借鉴别人的PPT模板时也由于对PPT本身不熟悉而不能发挥模板的全部效果</p>
</div>
</section>
<section>
<div>
<h2 id="web" class="text-xl mt-2 pb-2 font-sans">基于Web的幻灯片</h2>
<table>
<thead>
<tr>
<th style="text-align: center;">框架</th>
<th style="text-align: center;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">Reveal.js</td>
<td style="text-align: center;">功能多,难度大</td>
</tr>
<tr>
<td style="text-align: center;">revael-md</td>
<td style="text-align: center;">Reveal.js的前端定制主题困难</td>
</tr>
<tr>
<td style="text-align: center;">Slidev</td>
<td style="text-align: center;">完备的软件,不支持垂直幻灯片</td>
</tr>
<tr>
<td style="text-align: center;">VSCode插件、Obsidian默认插件</td>
<td style="text-align: center;">功能少</td>
</tr>
</tbody>
</table>
<hr />
<p class="font-serif my-1">并没有完全满足我的要求的框架</p>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans"><a
href="http://jyywiki.cn/OS/2022/slides/1.slides#/">南京大学蒋炎岩老师幻灯片</a></h2>
<p class="font-serif my-1">蒋老师的幻灯片就很有意思源码可以直接看从代码上看大概也是使用了Reveal.js但是自己定制了主题。<br />
在得到蒋老师的同意后我通过类比老师的HTML源码开发出了这个将Markdown扩展语法转换成蒋老师幻灯片风格的工具。</p>
</div>
</section>
</section>
<section>
<section>
<div class="center middle">
<div style="width:100%">
<div>
<h1 id="_1" class="text-2xl mt-2 font-sans">扩展语法的介绍</h1>
<blockquote>
<p class="font-serif my-1">解析不是编译过程,<br />
而且简单的split<br />
所以关键字不能用于正文</p>
</blockquote>
</div>
</div>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">作者信息</h2>
<p class="font-serif my-1">我们观察蒋老师幻灯片的这部分
<img class="center" src="./static/img/01c2c61129ca41ba9c49b27cd6938202.png" width="500px" />
文字和图片对应且都是外链想通过Markdown扩展语法实现会破坏语法的简约所以我选择在Markdown的开头设置文件信息。
</p>
<ul class="list-disc font-serif">
<li class="ml-8">使用标记<code>\n+++++\n</code>和正文分割其格式使用Json</li>
</ul>
<p class="font-serif my-1"><a
href="https://github.com/zweix123/jyyslide-md/blob/master/example/jyy/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%A6%82%E8%BF%B0.md">这个样例</a>就是上图效果。
</p>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">水平幻灯片和垂直幻灯片</h2>
<p class="font-serif my-1">您已经体验过水平和垂直的幻灯片</p>
<ul class="list-disc font-serif">
<li class="ml-8">使用<code>\n---\n</code>(三个减号的单独行)来划分水平幻灯片</li>
<li class="ml-8">使用<code>\n----\n</code>(四个减号的单独行)来幻灯水平幻灯片</li>
</ul>
<blockquote>
<p class="font-serif my-1">更多的减号就是Markdwon的分隔符<code>&lt;hr&gt;</code></p>
<blockquote>
<p class="font-serif my-1"><code>&lt;hr&gt;</code>在幻灯片中的渲染不是分隔符而是空行</p>
</blockquote>
</blockquote>
</div>
</section>
<section>
<div class="center middle">
<div style="width:100%">
<div>
<h1 id="_1" class="text-2xl mt-2 font-sans">渐变幻灯片</h1>
<blockquote>
<p class="font-serif my-1">下面展示一下典型应用</p>
</blockquote>
</div>
</div>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/e31cb6ff1c3d4ae09fcd5ebe7bf1db26.png" /></p>
<hr />
<blockquote>
<p class="font-serif my-1">每张渐变幻灯片的格式规则和普通幻灯片是一样的</p>
</blockquote>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/70a2a1e5d7ee4ff698ecdf2d709e2441.png" /></p>
<hr />
<ul class="list-disc font-serif">
<li class="ml-8">使用关键字<code>\n++++\n</code>来划分</li>
</ul>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/0e3d523d743b401194b7dce4c28559b2.png" /></p>
<hr />
<p class="font-serif my-1">这里展示了渐变幻灯片的典型应用:展示变化的过程</p>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/c8030b852f8c43499b848d356ffc0803.png" /></p>
<hr />
<p class="font-serif my-1">它不会像默认的主题那样使用切换的方式而突兀</p>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/2ee0fd5c3d824767bbf3c75eb537089a.png" /></p>
<hr />
<p class="font-serif my-1">上面展示的就是广度优先搜索的过程</p>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/dc8cb20d5d44433a9aac59f4acfc44b7.png" /></p>
<p class="font-serif my-1">这是最后倒数第七张</p>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/68f09159f31d4d92a43f61752d14999b.png" /></p>
<p class="font-serif my-1">这是最后倒数第六张</p>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/a3b6d4fa237240f5a714559be1c8a84e.png" /></p>
<p class="font-serif my-1">这是最后倒数第五张</p>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/f06295a5cf20468c8eda980e4c085dd8.png" /></p>
<p class="font-serif my-1">这是最后倒数第四张</p>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/c7ba81a333e34266bd5f7fd23a305e54.png" /></p>
<p class="font-serif my-1">这是最后倒数第三张</p>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/77564618dc974b8caa7359ecad692e45.png" /></p>
<p class="font-serif my-1">这是最后倒数第二张</p>
</div>
</section>
<section data-auto-animate>
<div>
<p class="font-serif my-1"><img class="center"
src="./static/img/616b4aaf0ecd49f9bae25173b97ec259.png" /></p>
<p class="font-serif my-1">这是最后一张</p>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">每张幻灯片依次出现的部分</h2>
<div class="fragment" data-fragment-index="1">
<ul class="list-disc font-serif">
<li class="ml-8">本质是Reveal.js的<a href="https://revealjs.com/fragments/">fragments</a>
</li>
</ul>
</div>
<div class="fragment" data-fragment-index="2">
<ul class="list-disc font-serif">
<li class="ml-8">使用关键字<code>\n--\n</code>划分</li>
</ul>
</div>
<div class="fragment" data-fragment-index="3">
<div class="codehilite">
<pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code>它划分的是从标记一下到下一个标记或者当前幻灯片末尾的部分
</code></pre>
</div>
</div>
</div>
</section>
</section>
<section>
<section>
<div class="center middle">
<div style="width:100%">
<div>
<h1 id="markdown" class="text-2xl mt-2 font-sans">对Markdown原生语法的适配</h1>
</div>
</div>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">文本格式</h2>
<ul class="list-disc font-serif">
<li class="ml-8">通过Markdown原生语法支持<strong>加粗</strong><em>斜体</em></li>
</ul>
<div class="codehilite">
<pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code>+ 通过Markdown原生语法支持**加粗**和*斜体*
</code></pre>
</div>
<ul class="list-disc font-serif">
<li class="ml-8">通过插入HTML支持<del>删除线</del><mark>高亮</mark><red>标红</red>
</li>
</ul>
<div class="codehilite">
<pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code>+<span class="w"> </span>通过插入HTML支持<span class="nt">&lt;del&gt;</span>删除线<span class="nt">&lt;/del&gt;</span><span class="nt">&lt;mark&gt;</span>高亮<span class="nt">&lt;/mark&gt;</span><span class="nt">&lt;red&gt;</span>标红<span class="nt">&lt;/red&gt;</span>
</code></pre>
</div>
<ul class="list-disc font-serif">
<li class="ml-8">Markdown语法<code>大于三个-的行</code><br />
在Markdown这语法是分割线<code>&lt;hr&gt;</code>,但是和我定义的扩展语法冲突,所以这里是大于四个的<code>-</code>才是,另外对转换后的<code>&lt;hr&gt;</code>,作用是空行而不是分割线。
</li>
</ul>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">注释</h2>
<blockquote>
<p class="font-serif my-1">这是注释</p>
</blockquote>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">列表</h2>
<ul class="list-disc font-serif">
<li class="ml-8">这是无序列表</li>
<li class="ml-8">这是无序列表</li>
<li class="ml-8">这是无序列表</li>
</ul>
<hr />
<ol>
<li class="ml-8">这是有序列表</li>
<li class="ml-8">这是有序列表</li>
<li class="ml-8">这是有序列表</li>
</ol>
<hr />
<ul class="list-disc font-serif">
<li class="ml-8">这是嵌套列表<ol>
<li class="ml-8">1</li>
<li class="ml-8">2</li>
<li class="ml-8">3</li>
</ol>
</li>
</ul>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">代码高亮</h2>
<div class="codehilite">
<pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;iostream&gt;</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">"Hello World!"</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre>
</div>
<blockquote>
<p class="font-serif my-1">Reveal-md和Slidev支持的代码特定行高亮暂时不支持</p>
</blockquote>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">数学公式</h2>
<p class="font-serif my-1">$$\overbrace{1+2+\cdots+n}^{n个} \qquad
\underbrace{a+b+\cdots+z}_{26}$$</p>
<div class="codehilite">
<pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="p">$$</span>\<span class="nv">overbrace</span><span class="p">{</span><span class="mi">1</span><span class="o">+</span><span class="mi">2</span><span class="o">+</span>\<span class="nv">cdots</span><span class="o">+</span><span class="nv">n</span><span class="p">}</span><span class="o">^</span><span class="p">{</span><span class="nv">n个</span><span class="p">}</span><span class="w"> </span>\<span class="nv">qquad</span><span class="w"> </span>\<span class="no">und</span><span class="nv">erbrace</span><span class="p">{</span><span class="nv">a</span><span class="o">+</span><span class="nv">b</span><span class="o">+</span>\<span class="nv">cdots</span><span class="o">+</span><span class="nv">z</span><span class="p">}</span><span class="nv">_</span><span class="p">{</span><span class="mi">26</span><span class="p">}$$</span>
</code></pre>
</div>
<hr />
<p class="font-serif my-1">$$\lim_{x \to \infty} x^2_{22} - \int_{1}^{5}x\mathrm{d}x +
\sum_{n=1}^{20} n^{2} = \prod_{j=1}^{3} y_{j} + \lim_{x \to -2} \frac{x-2}{x}$$</p>
<div class="codehilite">
<pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="p">$$</span>\<span class="nv">lim_</span><span class="p">{</span><span class="nv">x</span><span class="w"> </span>\<span class="k">to</span><span class="w"> </span>\<span class="no">inf</span><span class="nv">ty</span><span class="p">}</span><span class="w"> </span><span class="nv">x</span><span class="o">^</span><span class="mi">2</span><span class="nv">_</span><span class="p">{</span><span class="mi">22</span><span class="p">}</span><span class="w"> </span><span class="o">-</span><span class="w"> </span>\<span class="nv">int_</span><span class="p">{</span><span class="mi">1</span><span class="p">}</span><span class="o">^</span><span class="p">{</span><span class="mi">5</span><span class="p">}</span><span class="nv">x</span>\<span class="nv">mathrm</span><span class="p">{</span><span class="nv">d</span><span class="p">}</span><span class="nv">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span>\<span class="nv">sum_</span><span class="p">{</span><span class="nv">n</span><span class="o">=</span><span class="mi">1</span><span class="p">}</span><span class="o">^</span><span class="p">{</span><span class="mi">20</span><span class="p">}</span><span class="w"> </span><span class="nv">n</span><span class="o">^</span><span class="p">{</span><span class="mi">2</span><span class="p">}</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>\<span class="nv">prod_</span><span class="p">{</span><span class="nv">j</span><span class="o">=</span><span class="mi">1</span><span class="p">}</span><span class="o">^</span><span class="p">{</span><span class="mi">3</span><span class="p">}</span><span class="w"> </span><span class="nv">y_</span><span class="p">{</span><span class="nv">j</span><span class="p">}</span><span class="w"> </span><span class="o">+</span><span class="w"> </span>\<span class="nv">lim_</span><span class="p">{</span><span class="nv">x</span><span class="w"> </span>\<span class="k">to</span><span class="w"> </span><span class="o">-</span><span class="mi">2</span><span class="p">}</span><span class="w"> </span>\<span class="nv">frac</span><span class="p">{</span><span class="nv">x</span><span class="o">-</span><span class="mi">2</span><span class="p">}{</span><span class="nv">x</span><span class="p">}$$</span>
</code></pre>
</div>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">引用:普通引用</h2>
<p class="font-serif my-1"><a href="https://github.com/opencurve/curve">分布式存储系统Curve</a></p>
<div class="codehilite">
<pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code>[分布式存储系统Curve](https://github.com/opencurve/curve)
</code></pre>
</div>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">引用:图片</h2>
<blockquote>
<p class="font-serif my-1">支持Markdown原生图片引用语法<br />
<code>![图片失效显示的文字](图片的路径或者网址)</code>
</p>
</blockquote>
<p class="font-serif my-1">建议使用插入HTML的方式</p>
<div class="codehilite">
<pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="p">&lt;</span><span class="nt">img</span> <span class="na">alt</span><span class="o">=</span><span class="s">"图片失效显示的文字"</span> <span class="na">src</span><span class="o">=</span><span class="s">"图片的路径或者网址"</span><span class="p">&gt;</span>
</code></pre>
</div>
<p class="font-serif my-1">这里<code>alt</code>并不是必须的</p>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">图片格式</h2>
<ul class="list-disc font-serif">
<li class="ml-8">图片居中</li>
</ul>
<div class="codehilite">
<pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="p">&lt;</span><span class="nt">img</span> <span class="na">alt</span><span class="o">=</span><span class="s">...</span> <span class="na">class</span><span class="o">=</span><span class="s">"center"</span> <span class="na">src</span><span class="o">=</span><span class="s">...</span><span class="p">&gt;</span>
</code></pre>
</div>
<blockquote>
<p class="font-serif my-1">顺序不关键</p>
</blockquote>
<ul class="list-disc font-serif">
<li class="ml-8">右对齐</li>
</ul>
<div class="codehilite">
<pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="p">&lt;</span><span class="nt">img</span> <span class="na">alt</span><span class="o">=</span><span class="s">...</span> <span class="na">class</span><span class="o">=</span><span class="s">"float-right"</span> <span class="na">src</span><span class="o">=</span><span class="s">...</span><span class="p">&gt;</span>
</code></pre>
</div>
<blockquote>
<p class="font-serif my-1">Markdown是流的形式即图片是占位的但是这里右对齐的图片不占位</p>
</blockquote>
<ul class="list-disc font-serif">
<li class="ml-8">大小</li>
</ul>
<div class="codehilite">
<pre class="bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2"><span/><code><span class="p">&lt;</span><span class="nt">img</span> <span class="err">...</span> <span class="na">src</span><span class="o">=</span><span class="s">...</span> <span class="na">width</span><span class="o">=</span><span class="s">"678px"</span><span class="p">&gt;</span>
</code></pre>
</div>
</div>
</section>
<section>
<div>
<h2 id="_1" class="text-xl mt-2 pb-2 font-sans">其他</h2>
<ul class="list-disc font-serif">
<li class="ml-8">关于自定义(需要前端知识)</li>
</ul>
<blockquote>
<p class="font-serif my-1">
自定义在本框架中是不推荐的,因为“像蒋炎岩”是项目的第一目的,其他的是次要,比如您需要自定义,要么您需要重构您的幻灯片,要么这个框架不适合您。</p>
</blockquote>
<p class="font-serif my-1">
蒋老师的主题样式都在静态文件下<code>jyy/jyy.css</code>文件中,网页的主体都在<code>.reveal .slides</code>在这里修改即可全局修改推荐只修改诸如字体、字间距、行间距这样的属性zweix的前端也不好不知道其他修改会发生什么
</p>
</div>
</section>
</section>
<section>
<section>
<div class="center middle">
<div style="width:100%">
<div>
<h1 id="_1" class="text-2xl mt-2 font-sans">谢谢</h1>
<blockquote>
<p class="font-serif my-1">希望本工具能提高您的效率</p>
</blockquote>
</div>
</div>
</div>
</section>
</section>
</div>
</div>
<script src="./static/reveal/reveal.js"></script>
<script>
Reveal.initialize({
width: 1024, height: 768,
slideNumber: 'c/t',
controlsTutorial: false,
progress: false,
hash: true,
center: false,
autoAnimateUnmatched: true,
autoAnimateEasing: 'ease-out',
autoAnimateDuration: 0.3,
transitionSpeed: 'fast'
});
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

View File

@ -1,342 +0,0 @@
# jyyslide-md
<hr>
>[zweix](https://github.com/zweix123)
---
# 让我们试试不一样的交互方式
<hr>
>试试方向键
>或者vim的`hjkl`
>或者滑动屏幕(移动端)
----
## 基于Reveal.js框架的Web幻灯片交互方式
+ 通过方向键或者`hjkl`切换幻灯片
+ 幻灯片维度更高,除了水平幻灯片还有竖直幻灯片
+ 其他快捷键:
+ `o`或`esc`:总览
+ `b`或者`v`:息屏、亮屏
+ `f`:全屏(`esc`退出全屏)
---
# 发心
----
## PowerPoint
> 可以从奥卡姆剃刀的角度考虑
能量点的功能非常丰富,但是功能多意味着学习成本大,但实际上我只需要很小部分的功能就能完成大部分的事情。
由于这种复杂性我们在借鉴别人的PPT模板时也由于对PPT本身不熟悉而不能发挥模板的全部效果
----
## 基于Web的幻灯片
| 框架 | 说明 |
| :--------------------------: | :---------------------------: |
| Reveal.js | 功能多,难度大 |
| revael-md | Reveal.js的前端定制主题困难 |
| Slidev | 完备的软件,不支持垂直幻灯片 |
| VSCode插件、Obsidian默认插件 | 功能少 |
<hr>
并没有完全满足我的要求的框架
----
## [南京大学蒋炎岩老师幻灯片](http://jyywiki.cn/OS/2022/slides/1.slides#/)
蒋老师的幻灯片就很有意思源码可以直接看从代码上看大概也是使用了Reveal.js但是自己定制了主题。
在得到蒋老师的同意后我通过类比老师的HTML源码开发出了这个将Markdown扩展语法转换成蒋老师幻灯片风格的工具。
---
# 扩展语法的介绍
>解析不是编译过程,
>而且简单的split
>所以关键字不能用于正文
----
## 作者信息
我们观察蒋老师幻灯片的这部分
<img class="center" src="./img/author.png" width="500px">
文字和图片对应且都是外链想通过Markdown扩展语法实现会破坏语法的简约所以我选择在Markdown的开头设置文件信息。
+ 使用标记`\n+++++\n`和正文分割其格式使用Json
[这个样例](https://github.com/zweix123/jyyslide-md/blob/master/example/jyy/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E6%A6%82%E8%BF%B0.md)就是上图效果。
----
## 水平幻灯片和垂直幻灯片
您已经体验过水平和垂直的幻灯片
+ 使用`\n---\n`(三个减号的单独行)来划分水平幻灯片
+ 使用`\n----\n`(四个减号的单独行)来幻灯水平幻灯片
>更多的减号就是Markdwon的分隔符`<hr>`
>>`<hr>`在幻灯片中的渲染不是分隔符而是空行
----
# 渐变幻灯片
>下面展示一下典型应用
----
<img class="center" src="./img/step1.png">
<hr>
>每张渐变幻灯片的格式规则和普通幻灯片是一样的
++++
<img class="center" src="./img/step2.png">
<hr>
+ 使用关键字`\n++++\n`来划分
++++
<img class="center" src="./img/step3.png">
<hr>
这里展示了渐变幻灯片的典型应用:展示变化的过程
++++
<img class="center" src="./img/step4.png">
<hr>
它不会像默认的主题那样使用切换的方式而突兀
++++
<img class="center" src="./img/step5.png">
<hr>
上面展示的就是广度优先搜索的过程
++++
<img class="center" src="./img/step6.png">
这是最后倒数第七张
++++
<img class="center" src="./img/step7.png">
这是最后倒数第六张
++++
<img class="center" src="./img/step8.png">
这是最后倒数第五张
++++
<img class="center" src="./img/step9.png">
这是最后倒数第四张
++++
<img class="center" src="./img/step10.png">
这是最后倒数第三张
++++
<img class="center" src="./img/step11.png">
这是最后倒数第二张
++++
<img class="center" src="./img/step12.png">
这是最后一张
----
## 每张幻灯片依次出现的部分
--
+ 本质是Reveal.js的[fragments](https://revealjs.com/fragments/)
--
+ 使用关键字`\n--\n`划分
--
它划分的是从标记一下到下一个标记或者当前幻灯片末尾的部分
---
# 对Markdown原生语法的适配
----
## 文本格式
+ 通过Markdown原生语法支持**加粗**和*斜体*
```
+ 通过Markdown原生语法支持**加粗**和*斜体*
```
+ 通过插入HTML支持<del>删除线</del><mark>高亮</mark><red>标红</red>
```
+ 通过插入HTML支持<del>删除线</del><mark>高亮</mark><red>标红</red>
```
+ Markdown语法`大于三个-的行`
在Markdown这语法是分割线`<hr>`,但是和我定义的扩展语法冲突,所以这里是大于四个的`-`才是,另外对转换后的`<hr>`,作用是空行而不是分割线。
----
## 注释
>这是注释
----
## 列表
+ 这是无序列表
+ 这是无序列表
+ 这是无序列表
<hr>
1. 这是有序列表
2. 这是有序列表
3. 这是有序列表
<hr>
+ 这是嵌套列表
1. 1
2. 2
3. 3
----
## 代码高亮
```c++
#include <iostream>
int main() {
std::cout << "Hello World!" << std::endl;
return 0;
}
```
>Reveal-md和Slidev支持的代码特定行高亮暂时不支持
----
## 数学公式
$$\overbrace{1+2+\cdots+n}^{n个} \qquad \underbrace{a+b+\cdots+z}_{26}$$
```
$$\overbrace{1+2+\cdots+n}^{n个} \qquad \underbrace{a+b+\cdots+z}_{26}$$
```
<hr>
$$\lim_{x \to \infty} x^2_{22} - \int_{1}^{5}x\mathrm{d}x + \sum_{n=1}^{20} n^{2} = \prod_{j=1}^{3} y_{j} + \lim_{x \to -2} \frac{x-2}{x}$$
```
$$\lim_{x \to \infty} x^2_{22} - \int_{1}^{5}x\mathrm{d}x + \sum_{n=1}^{20} n^{2} = \prod_{j=1}^{3} y_{j} + \lim_{x \to -2} \frac{x-2}{x}$$
```
----
## 引用:普通引用
[分布式存储系统Curve](https://github.com/opencurve/curve)
```
[分布式存储系统Curve](https://github.com/opencurve/curve)
```
----
## 引用:图片
>支持Markdown原生图片引用语法
>```
>![图片失效显示的文字](图片的路径或者网址)
>```
建议使用插入HTML的方式
```html
<img alt="图片失效显示的文字" src="图片的路径或者网址">
```
这里`alt`并不是必须的
----
## 图片格式
+ 图片居中
```html
<img alt=... class="center" src=...>
```
>顺序不关键
+ 右对齐
```html
<img alt=... class="float-right" src=...>
```
>Markdown是流的形式即图片是占位的但是这里右对齐的图片不占位
+ 大小
```html
<img ... src=... width="678px">
```
----
## 其他
+ 关于自定义(需要前端知识)
>自定义在本框架中是不推荐的,因为“像蒋炎岩”是项目的第一目的,其他的是次要,比如您需要自定义,要么您需要重构您的幻灯片,要么这个框架不适合您。
蒋老师的主题样式都在静态文件下`jyy/jyy.css`文件中,网页的主体都在`.reveal .slides`下在这里修改即可全局修改推荐只修改诸如字体、字间距、行间距这样的属性zweix的前端也不好不知道其他修改会发生什么
---
# 谢谢
>希望本工具能提高您的效率

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 487 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 888 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -1,335 +0,0 @@
author:
name: 蒋炎岩
url: https://ics.nju.edu.cn/~jyy/
departments:
- name: " 南京大学 "
url: https://www.nju.edu.cn/main.htm,
img: ./img/nju-logo.jpg
- name: 计算机科学与技术系
url: https://cs.nju.edu.cn/main.htm,
img: ./img/njucs-logo.jpg
- name: 计算机软件研究所
url: https://www.nju.edu.cn/main.htm,
img: ./img/ics-logo.png
+++++
# 操作系统概述
----
## Overview
本次课回答的问题
+ **Q1** (Why): 为什么要学操作系统?
+ **Q2** (What): 到底什么是操作系统?
+ **Q3** (How): 怎么学操作系统?
<hr>
本次课主要内容
+ 前导知识概述
+ 操作系统的历史/宏观概述
---
# 个人/课程简介
----
## 我是谁?
<img class="float-right" src="./img/frog-head.jpg" width="250px">
<del>努力成为卷王的临时工✖️</del> ([计算机软件研究所](https://cs.nju.edu.cn/ics/index.htm)✔)
+ “软件自动化”:测试/分析;代码合成
+ Two ACM SIGSOFT Distinguished Paper
Awards; Best Paper Award @ ICSE'21
<hr>
Co-Founder of Project-N
+ 在 bare-metal 上实现完整计算机系统
<hr>
JSOI/<del>南京大学 ICPC 集训队</del>教练
+ CCF NOI/NOIP 系列赛江苏赛区技术负责人
+ ICPC World Finals 49th Place (2009, team leader)
+ ICPC World Finals 13th Place (2019, co-coach)
----
## 课程信息与成绩构成
>所有课程信息都在[课程主页](http://jyywiki.cn/OS/2022/)发布 (请 RTFM)
成绩构成
+ 期末考试 40% + 随堂期中测验 10%
+ 大实验 25% + 小实验 25%
+ soft + hard deadlines
+ <red>不要对编程抱有任何侥幸心理</red>
+ 无论你基础如何,都相信自己能做到
<hr>
不强制要求到课
+ 努力上传视频,但不保证设备不会翻车
----
## 学术诚信 (Academic Integrity)
[Academic integrity](https://integrity.mit.edu/) 不是底线,而是 “自发的要求”
+ 对 “不应该做的事情” 有清楚的认识
+ **<red>不将代码上传到互联网</red>**
+ **<red>主动不参考别人完成的实验代码</red>**
+ **<red>不使用他人测试用例</red>** (depends)
+ 有些行为可能使你**得到分数**,但**失去应有的训练**
<hr>
只在 “绝对可以求助” 的时候才寻求帮助
+ 在全民内卷、不劳而获很容易的时代很难
+ 但坚持下来的人会变得很不一样
----
## 四周目反思
四周目表现平稳
+ 增加了更多的代码课和代码示例
+ 非递归汉诺塔
+ `.dl` 二进制文件格式与动态加载器
+ model checker (本周目将得到大幅改进)
<hr>
第五周目
+ 工具现代化 + 新手友好
+ 绝大部分代码示例都在 Windows 应用商店安装的 Ubuntu
+ 更多的 xv6 (大家有 RISC-V 的基础了)
+ 逐渐重构 Online Judge
+ 更新一部分实验 (如果可以的话,有一个 POSIX subsystem)
---
# Q1: 为什么要学操作系统?
----
## 为什么要学操作系统?
<img class="float-right" src="./img/mariner.jpg" width="300px">
为什么要学操作系统呢?
+ 为什么要学微积分/离散数学/XXXX/……?
+ 长辈/学长:<del>擦干泪不要问为什么</del>
<hr>
微积分 “被混起来” 的几件事
+ Newton 时代的微积分 (启蒙与应用)
+ 现代方法Mathematica, [sympy](https://docs.sympy.org/latest/tutorial/index.html), [sage](http://sagemath.org/)
+ 这也是为什么我主张第一门语言学 Python
+ Cauchy 时代的微积分 (严格化与公理化)
+ 以及之后各种卡出的 bug (Weierstrass 函数、Peano 曲线……)
+ 微积分的现代应用
+ 优化、有限元、PID……
----
## 学习操作系统的目的
<red>你体内的 “编程力量” 尚未完全觉醒</red>
+ 每天都在用的东西,你还没搞明白
+ 窗口是怎么创建的?[为什么 Ctrl-C 有时不能退出程序?](https://stackoverflow.blog/2017/05/23/stack-overflow-helping-one-million-developers-exit-vim/)
+ 组里的服务器有 128 个处理器,但你的程序却只能用一个 😂
+ 你每天都在用的东西,你却实现不出来
+ 浏览器、编译器、IDE、游戏/外挂、任务管理器、杀毒软件、病毒……
<hr>
<red>《操作系统》给你有关 “编程” 的全部</red>
+ 悟性好:学完课程就在系统方向 “毕业”
+ 具有编写一切 “能写出来” 程序的能力 (具备阅读论文的能力)
+ 悟性差:内力大增
+ 可能工作中的某一天想起上课提及的内容
----
## 学习操作系统的目的
>充满热情而且相当聪明的学生...早就听说过物理学如何有趣...相对论、量子力学……但是,当他们学完两年以前那种课程后,许多人就泄气了……学的还是斜面、静电这样的内容
>
>——《The Feynman Lectures on Physics, 1963》
我学《操作系统》的时候 (2009),大家都说操作系统很难教
+ 使用<del>豆瓣评分高达 5.7/10</del> 的 “全国优秀教材”
+ 没有正经的实验 (写一些 16-bit code)
+ 完全错误的 toolchain调试全靠蛮力和猜
+ 为了一点微不足道的分数内卷、沾沾自喜、失去 integrity
+ 这么玩,<red>脖子都要被美国人掐断了</red>
+ 这门课的另一个意义:<red>告诉你可以去变得更强、真正的强</red>
---
# Q2: 到底什么是操作系统?
----
## 什么是操作系统?
>Operating System: A body of software, in fact, that is responsible for *making it easy to run programs* (even allowing you to seemingly run many at the same time), allowing programs to share memory, enabling programs to interact with devices, and other fun stuff like that. (OSTEP)
<hr>
--
很多疑点
+ “programs” 就完了?那么多复杂的程序呢!
+ “shared memory, interact with devices, ...”?
----
## 什么是操作系统? (cont'd)
“管理软/硬件资源、为程序提供服务” 的程序?
<img class="center" src="./img/os-classify.jpg" width="768px">
----
## 理解操作系统
“精准” 的定义毫无意义
+ 问出正确的问题:操作系统如何从一开始变成现在这样的?
+ 三个重要的线索
+ 计算机 (硬件)
+ 程序 (软件)
+ 操作系统 (管理软件的软件)
<hr>
本课程讨论<red>狭义的操作系统</red>
+ 对单一计算机硬件系统作出抽象、支撑程序执行的软件系统
+ 学术界谈论 “操作系统” 是更广义的 “System” (例子OSDI/SOSP)
----
## 1940s 的计算机
跨时代、非凡的天才设计,但很简单 (还不如我们数电实验课做的 CPU 复杂呢)
+ 计算机系统 = 状态机 (ICS 课程的 takeaway message)
+ 标准的 Mealy 型数字电路
+ ENIAC (1946.2.14;请在这个特殊的节日多陪陪你的电脑)
<img class="center" src="./img/eniacrun.jpg" width="650px">
----
## 1940s 的计算机 (cont'd)
电子计算机的实现
+ 逻辑门:[真空电子管](https://www.bilibili.com/video/av59005720/?vd_source=4ee99d4ebd507c7277fa312ed28dbdda)
+ 存储器:延迟线 (delay lines)
+ 输入/输出:打孔纸带/指示灯
<center>
<img class="inline" src="./img/vaccum-tube.gif" width="250px">
<img class="inline" src="./img/throw-ball.gif" width="300px">
<img class="inline" src="./img/delay-memory-fig2-s.gif" width="400px">
</center>
----
## 1940s 的程序
ENIAC 程序是用物理线路 “hard-wire” 的
+ 重编程需要重新接线
+ [ENIAC Simulator; sieve.e](https://www.cs.drexel.edu/~bls96/eniac/)
<hr>
最早成功运行的一系列程序:打印平方数、素数表、计算弹道……
+ 大家还在和真正的 “bugs” 战斗
<img class="center" src="./img/first-bug.webp" width="400px">
----
## 1940s 的操作系统
>没有操作系统。
能把程序放上去就很了不起了
+ 程序直接用指令操作硬件
+ 不需要画蛇添足的程序来管理它
----
## 1950s 的计算机
更快更小的逻辑门 (晶体管)、更大的内存 (磁芯)、丰富的 I/O 设备
+ I/O 设备的速度已经严重低于处理器的速度,中断机制出现 (1953)
<img class="center" src="./img/ERA-1101.jpg" width="360px">
----
## 1950s 的程序
可以执行更复杂的任务,包括通用的计算任务
+ 希望使用计算机的人越来越多;希望调用 API 而不是直接访问设备
+ Fortran 诞生 (1957)
```
C---- THIS PROGRAM READS INPUT FROM THE CARD READER,
C---- 3 INTEGERS IN EACH CARD, CALCULATE AND OUTPUT
C---- THE SUM OF THEM.
100 READ(5,10) I1, I2, I3
10 FORMAT(3I5)
IF (I1.EQ.0 .AND. I2.EQ.0 .AND. I3.EQ.0) GOTO 200
ISUM = I1 + I2 + I3
WRITE(6,20) I1, I2, I3, ISUM
20 FORMAT(7HSUM OF , I5, 2H, , I5, 5H AND , I5,
* 4H IS , I6)
GOTO 100
200 STOP
END
```
----
# 省略
---
# 省略

View File

@ -1,9 +0,0 @@
import argparse
from src.converter import converter
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("filepath", help="select a Markdown file to convert", type=str)
args = parser.parse_args()
converter(args.filepath)

View File

@ -1,698 +0,0 @@
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
[[package]]
name = "black"
version = "23.1.0"
description = "The uncompromising code formatter."
optional = false
python-versions = ">=3.7"
files = [
{file = "black-23.1.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:b6a92a41ee34b883b359998f0c8e6eb8e99803aa8bf3123bf2b2e6fec505a221"},
{file = "black-23.1.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:57c18c5165c1dbe291d5306e53fb3988122890e57bd9b3dcb75f967f13411a26"},
{file = "black-23.1.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:9880d7d419bb7e709b37e28deb5e68a49227713b623c72b2b931028ea65f619b"},
{file = "black-23.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e6663f91b6feca5d06f2ccd49a10f254f9298cc1f7f49c46e498a0771b507104"},
{file = "black-23.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:9afd3f493666a0cd8f8df9a0200c6359ac53940cbde049dcb1a7eb6ee2dd7074"},
{file = "black-23.1.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:bfffba28dc52a58f04492181392ee380e95262af14ee01d4bc7bb1b1c6ca8d27"},
{file = "black-23.1.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c1c476bc7b7d021321e7d93dc2cbd78ce103b84d5a4cf97ed535fbc0d6660648"},
{file = "black-23.1.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:382998821f58e5c8238d3166c492139573325287820963d2f7de4d518bd76958"},
{file = "black-23.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bf649fda611c8550ca9d7592b69f0637218c2369b7744694c5e4902873b2f3a"},
{file = "black-23.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:121ca7f10b4a01fd99951234abdbd97728e1240be89fde18480ffac16503d481"},
{file = "black-23.1.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:a8471939da5e824b891b25751955be52ee7f8a30a916d570a5ba8e0f2eb2ecad"},
{file = "black-23.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8178318cb74f98bc571eef19068f6ab5613b3e59d4f47771582f04e175570ed8"},
{file = "black-23.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a436e7881d33acaf2536c46a454bb964a50eff59b21b51c6ccf5a40601fbef24"},
{file = "black-23.1.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:a59db0a2094d2259c554676403fa2fac3473ccf1354c1c63eccf7ae65aac8ab6"},
{file = "black-23.1.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:0052dba51dec07ed029ed61b18183942043e00008ec65d5028814afaab9a22fd"},
{file = "black-23.1.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:49f7b39e30f326a34b5c9a4213213a6b221d7ae9d58ec70df1c4a307cf2a1580"},
{file = "black-23.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:162e37d49e93bd6eb6f1afc3e17a3d23a823042530c37c3c42eeeaf026f38468"},
{file = "black-23.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b70eb40a78dfac24842458476135f9b99ab952dd3f2dab738c1881a9b38b753"},
{file = "black-23.1.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:a29650759a6a0944e7cca036674655c2f0f63806ddecc45ed40b7b8aa314b651"},
{file = "black-23.1.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:bb460c8561c8c1bec7824ecbc3ce085eb50005883a6203dcfb0122e95797ee06"},
{file = "black-23.1.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c91dfc2c2a4e50df0026f88d2215e166616e0c80e86004d0003ece0488db2739"},
{file = "black-23.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2a951cc83ab535d248c89f300eccbd625e80ab880fbcfb5ac8afb5f01a258ac9"},
{file = "black-23.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:0680d4380db3719ebcfb2613f34e86c8e6d15ffeabcf8ec59355c5e7b85bb555"},
{file = "black-23.1.0-py3-none-any.whl", hash = "sha256:7a0f701d314cfa0896b9001df70a530eb2472babb76086344e688829efd97d32"},
{file = "black-23.1.0.tar.gz", hash = "sha256:b0bd97bea8903f5a2ba7219257a44e3f1f9d00073d6cc1add68f0beec69692ac"},
]
[package.dependencies]
click = ">=8.0.0"
mypy-extensions = ">=0.4.3"
packaging = ">=22.0"
pathspec = ">=0.9.0"
platformdirs = ">=2"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
[package.extras]
colorama = ["colorama (>=0.4.3)"]
d = ["aiohttp (>=3.7.4)"]
jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "certifi"
version = "2022.12.7"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.6"
files = [
{file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
{file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
]
[[package]]
name = "charset-normalizer"
version = "3.0.1"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
optional = false
python-versions = "*"
files = [
{file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"},
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"},
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"},
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"},
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"},
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"},
{file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"},
{file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"},
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"},
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"},
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"},
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"},
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"},
{file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"},
{file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"},
{file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"},
{file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"},
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"},
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"},
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"},
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"},
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"},
{file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"},
{file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"},
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"},
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"},
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"},
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"},
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"},
{file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"},
{file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"},
{file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"},
]
[[package]]
name = "click"
version = "8.1.3"
description = "Composable command line interface toolkit"
optional = false
python-versions = ">=3.7"
files = [
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]]
name = "cssselect"
version = "1.2.0"
description = "cssselect parses CSS3 Selectors and translates them to XPath 1.0"
optional = false
python-versions = ">=3.7"
files = [
{file = "cssselect-1.2.0-py2.py3-none-any.whl", hash = "sha256:da1885f0c10b60c03ed5eccbb6b68d6eff248d91976fcde348f395d54c9fd35e"},
{file = "cssselect-1.2.0.tar.gz", hash = "sha256:666b19839cfaddb9ce9d36bfe4c969132c647b92fc9088c4e23f786b30f1b3dc"},
]
[[package]]
name = "idna"
version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.5"
files = [
{file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
]
[[package]]
name = "jinja2"
version = "3.1.2"
description = "A very fast and expressive template engine."
optional = false
python-versions = ">=3.7"
files = [
{file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
{file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
]
[package.dependencies]
MarkupSafe = ">=2.0"
[package.extras]
i18n = ["Babel (>=2.7)"]
[[package]]
name = "lxml"
version = "4.9.4"
description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*"
files = [
{file = "lxml-4.9.4-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e214025e23db238805a600f1f37bf9f9a15413c7bf5f9d6ae194f84980c78722"},
{file = "lxml-4.9.4-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec53a09aee61d45e7dbe7e91252ff0491b6b5fee3d85b2d45b173d8ab453efc1"},
{file = "lxml-4.9.4-cp27-cp27m-win32.whl", hash = "sha256:7d1d6c9e74c70ddf524e3c09d9dc0522aba9370708c2cb58680ea40174800013"},
{file = "lxml-4.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:cb53669442895763e61df5c995f0e8361b61662f26c1b04ee82899c2789c8f69"},
{file = "lxml-4.9.4-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:647bfe88b1997d7ae8d45dabc7c868d8cb0c8412a6e730a7651050b8c7289cf2"},
{file = "lxml-4.9.4-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:4d973729ce04784906a19108054e1fd476bc85279a403ea1a72fdb051c76fa48"},
{file = "lxml-4.9.4-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:056a17eaaf3da87a05523472ae84246f87ac2f29a53306466c22e60282e54ff8"},
{file = "lxml-4.9.4-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:aaa5c173a26960fe67daa69aa93d6d6a1cd714a6eb13802d4e4bd1d24a530644"},
{file = "lxml-4.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:647459b23594f370c1c01768edaa0ba0959afc39caeeb793b43158bb9bb6a663"},
{file = "lxml-4.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:bdd9abccd0927673cffe601d2c6cdad1c9321bf3437a2f507d6b037ef91ea307"},
{file = "lxml-4.9.4-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:00e91573183ad273e242db5585b52670eddf92bacad095ce25c1e682da14ed91"},
{file = "lxml-4.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a602ed9bd2c7d85bd58592c28e101bd9ff9c718fbde06545a70945ffd5d11868"},
{file = "lxml-4.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:de362ac8bc962408ad8fae28f3967ce1a262b5d63ab8cefb42662566737f1dc7"},
{file = "lxml-4.9.4-cp310-cp310-win32.whl", hash = "sha256:33714fcf5af4ff7e70a49731a7cc8fd9ce910b9ac194f66eaa18c3cc0a4c02be"},
{file = "lxml-4.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:d3caa09e613ece43ac292fbed513a4bce170681a447d25ffcbc1b647d45a39c5"},
{file = "lxml-4.9.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:359a8b09d712df27849e0bcb62c6a3404e780b274b0b7e4c39a88826d1926c28"},
{file = "lxml-4.9.4-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:43498ea734ccdfb92e1886dfedaebeb81178a241d39a79d5351ba2b671bff2b2"},
{file = "lxml-4.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4855161013dfb2b762e02b3f4d4a21cc7c6aec13c69e3bffbf5022b3e708dd97"},
{file = "lxml-4.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c71b5b860c5215fdbaa56f715bc218e45a98477f816b46cfde4a84d25b13274e"},
{file = "lxml-4.9.4-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9a2b5915c333e4364367140443b59f09feae42184459b913f0f41b9fed55794a"},
{file = "lxml-4.9.4-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d82411dbf4d3127b6cde7da0f9373e37ad3a43e89ef374965465928f01c2b979"},
{file = "lxml-4.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:273473d34462ae6e97c0f4e517bd1bf9588aa67a1d47d93f760a1282640e24ac"},
{file = "lxml-4.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:389d2b2e543b27962990ab529ac6720c3dded588cc6d0f6557eec153305a3622"},
{file = "lxml-4.9.4-cp311-cp311-win32.whl", hash = "sha256:8aecb5a7f6f7f8fe9cac0bcadd39efaca8bbf8d1bf242e9f175cbe4c925116c3"},
{file = "lxml-4.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:c7721a3ef41591341388bb2265395ce522aba52f969d33dacd822da8f018aff8"},
{file = "lxml-4.9.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:dbcb2dc07308453db428a95a4d03259bd8caea97d7f0776842299f2d00c72fc8"},
{file = "lxml-4.9.4-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:01bf1df1db327e748dcb152d17389cf6d0a8c5d533ef9bab781e9d5037619229"},
{file = "lxml-4.9.4-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:e8f9f93a23634cfafbad6e46ad7d09e0f4a25a2400e4a64b1b7b7c0fbaa06d9d"},
{file = "lxml-4.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3f3f00a9061605725df1816f5713d10cd94636347ed651abdbc75828df302b20"},
{file = "lxml-4.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:953dd5481bd6252bd480d6ec431f61d7d87fdcbbb71b0d2bdcfc6ae00bb6fb10"},
{file = "lxml-4.9.4-cp312-cp312-win32.whl", hash = "sha256:266f655d1baff9c47b52f529b5f6bec33f66042f65f7c56adde3fcf2ed62ae8b"},
{file = "lxml-4.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:f1faee2a831fe249e1bae9cbc68d3cd8a30f7e37851deee4d7962b17c410dd56"},
{file = "lxml-4.9.4-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:23d891e5bdc12e2e506e7d225d6aa929e0a0368c9916c1fddefab88166e98b20"},
{file = "lxml-4.9.4-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:e96a1788f24d03e8d61679f9881a883ecdf9c445a38f9ae3f3f193ab6c591c66"},
{file = "lxml-4.9.4-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:5557461f83bb7cc718bc9ee1f7156d50e31747e5b38d79cf40f79ab1447afd2d"},
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:fdb325b7fba1e2c40b9b1db407f85642e32404131c08480dd652110fc908561b"},
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d74d4a3c4b8f7a1f676cedf8e84bcc57705a6d7925e6daef7a1e54ae543a197"},
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ac7674d1638df129d9cb4503d20ffc3922bd463c865ef3cb412f2c926108e9a4"},
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:ddd92e18b783aeb86ad2132d84a4b795fc5ec612e3545c1b687e7747e66e2b53"},
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2bd9ac6e44f2db368ef8986f3989a4cad3de4cd55dbdda536e253000c801bcc7"},
{file = "lxml-4.9.4-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:bc354b1393dce46026ab13075f77b30e40b61b1a53e852e99d3cc5dd1af4bc85"},
{file = "lxml-4.9.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:f836f39678cb47c9541f04d8ed4545719dc31ad850bf1832d6b4171e30d65d23"},
{file = "lxml-4.9.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:9c131447768ed7bc05a02553d939e7f0e807e533441901dd504e217b76307745"},
{file = "lxml-4.9.4-cp36-cp36m-win32.whl", hash = "sha256:bafa65e3acae612a7799ada439bd202403414ebe23f52e5b17f6ffc2eb98c2be"},
{file = "lxml-4.9.4-cp36-cp36m-win_amd64.whl", hash = "sha256:6197c3f3c0b960ad033b9b7d611db11285bb461fc6b802c1dd50d04ad715c225"},
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:7b378847a09d6bd46047f5f3599cdc64fcb4cc5a5a2dd0a2af610361fbe77b16"},
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:1343df4e2e6e51182aad12162b23b0a4b3fd77f17527a78c53f0f23573663545"},
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6dbdacf5752fbd78ccdb434698230c4f0f95df7dd956d5f205b5ed6911a1367c"},
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:506becdf2ecaebaf7f7995f776394fcc8bd8a78022772de66677c84fb02dd33d"},
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca8e44b5ba3edb682ea4e6185b49661fc22b230cf811b9c13963c9f982d1d964"},
{file = "lxml-4.9.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9d9d5726474cbbef279fd709008f91a49c4f758bec9c062dfbba88eab00e3ff9"},
{file = "lxml-4.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:bbdd69e20fe2943b51e2841fc1e6a3c1de460d630f65bde12452d8c97209464d"},
{file = "lxml-4.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8671622256a0859f5089cbe0ce4693c2af407bc053dcc99aadff7f5310b4aa02"},
{file = "lxml-4.9.4-cp37-cp37m-win32.whl", hash = "sha256:dd4fda67f5faaef4f9ee5383435048ee3e11ad996901225ad7615bc92245bc8e"},
{file = "lxml-4.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6bee9c2e501d835f91460b2c904bc359f8433e96799f5c2ff20feebd9bb1e590"},
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:1f10f250430a4caf84115b1e0f23f3615566ca2369d1962f82bef40dd99cd81a"},
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:3b505f2bbff50d261176e67be24e8909e54b5d9d08b12d4946344066d66b3e43"},
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:1449f9451cd53e0fd0a7ec2ff5ede4686add13ac7a7bfa6988ff6d75cff3ebe2"},
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:4ece9cca4cd1c8ba889bfa67eae7f21d0d1a2e715b4d5045395113361e8c533d"},
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59bb5979f9941c61e907ee571732219fa4774d5a18f3fa5ff2df963f5dfaa6bc"},
{file = "lxml-4.9.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b1980dbcaad634fe78e710c8587383e6e3f61dbe146bcbfd13a9c8ab2d7b1192"},
{file = "lxml-4.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9ae6c3363261021144121427b1552b29e7b59de9d6a75bf51e03bc072efb3c37"},
{file = "lxml-4.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bcee502c649fa6351b44bb014b98c09cb00982a475a1912a9881ca28ab4f9cd9"},
{file = "lxml-4.9.4-cp38-cp38-win32.whl", hash = "sha256:a8edae5253efa75c2fc79a90068fe540b197d1c7ab5803b800fccfe240eed33c"},
{file = "lxml-4.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:701847a7aaefef121c5c0d855b2affa5f9bd45196ef00266724a80e439220e46"},
{file = "lxml-4.9.4-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:f610d980e3fccf4394ab3806de6065682982f3d27c12d4ce3ee46a8183d64a6a"},
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:aa9b5abd07f71b081a33115d9758ef6077924082055005808f68feccb27616bd"},
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:365005e8b0718ea6d64b374423e870648ab47c3a905356ab6e5a5ff03962b9a9"},
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:16b9ec51cc2feab009e800f2c6327338d6ee4e752c76e95a35c4465e80390ccd"},
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:a905affe76f1802edcac554e3ccf68188bea16546071d7583fb1b693f9cf756b"},
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fd814847901df6e8de13ce69b84c31fc9b3fb591224d6762d0b256d510cbf382"},
{file = "lxml-4.9.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:91bbf398ac8bb7d65a5a52127407c05f75a18d7015a270fdd94bbcb04e65d573"},
{file = "lxml-4.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f99768232f036b4776ce419d3244a04fe83784bce871b16d2c2e984c7fcea847"},
{file = "lxml-4.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bb5bd6212eb0edfd1e8f254585290ea1dadc3687dd8fd5e2fd9a87c31915cdab"},
{file = "lxml-4.9.4-cp39-cp39-win32.whl", hash = "sha256:88f7c383071981c74ec1998ba9b437659e4fd02a3c4a4d3efc16774eb108d0ec"},
{file = "lxml-4.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:936e8880cc00f839aa4173f94466a8406a96ddce814651075f95837316369899"},
{file = "lxml-4.9.4-pp310-pypy310_pp73-macosx_11_0_x86_64.whl", hash = "sha256:f6c35b2f87c004270fa2e703b872fcc984d714d430b305145c39d53074e1ffe0"},
{file = "lxml-4.9.4-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:606d445feeb0856c2b424405236a01c71af7c97e5fe42fbc778634faef2b47e4"},
{file = "lxml-4.9.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1bdcbebd4e13446a14de4dd1825f1e778e099f17f79718b4aeaf2403624b0f7"},
{file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0a08c89b23117049ba171bf51d2f9c5f3abf507d65d016d6e0fa2f37e18c0fc5"},
{file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:232fd30903d3123be4c435fb5159938c6225ee8607b635a4d3fca847003134ba"},
{file = "lxml-4.9.4-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:231142459d32779b209aa4b4d460b175cadd604fed856f25c1571a9d78114771"},
{file = "lxml-4.9.4-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:520486f27f1d4ce9654154b4494cf9307b495527f3a2908ad4cb48e4f7ed7ef7"},
{file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:562778586949be7e0d7435fcb24aca4810913771f845d99145a6cee64d5b67ca"},
{file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a9e7c6d89c77bb2770c9491d988f26a4b161d05c8ca58f63fb1f1b6b9a74be45"},
{file = "lxml-4.9.4-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:786d6b57026e7e04d184313c1359ac3d68002c33e4b1042ca58c362f1d09ff58"},
{file = "lxml-4.9.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95ae6c5a196e2f239150aa4a479967351df7f44800c93e5a975ec726fef005e2"},
{file = "lxml-4.9.4-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:9b556596c49fa1232b0fff4b0e69b9d4083a502e60e404b44341e2f8fb7187f5"},
{file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:cc02c06e9e320869d7d1bd323df6dd4281e78ac2e7f8526835d3d48c69060683"},
{file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:857d6565f9aa3464764c2cb6a2e3c2e75e1970e877c188f4aeae45954a314e0c"},
{file = "lxml-4.9.4-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c42ae7e010d7d6bc51875d768110c10e8a59494855c3d4c348b068f5fb81fdcd"},
{file = "lxml-4.9.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f10250bb190fb0742e3e1958dd5c100524c2cc5096c67c8da51233f7448dc137"},
{file = "lxml-4.9.4.tar.gz", hash = "sha256:b1541e50b78e15fa06a2670157a1962ef06591d4c998b998047fff5e3236880e"},
]
[package.extras]
cssselect = ["cssselect (>=0.7)"]
html5 = ["html5lib"]
htmlsoup = ["BeautifulSoup4"]
source = ["Cython (==0.29.37)"]
[[package]]
name = "markdown"
version = "3.4.1"
description = "Python implementation of Markdown."
optional = false
python-versions = ">=3.7"
files = [
{file = "Markdown-3.4.1-py3-none-any.whl", hash = "sha256:08fb8465cffd03d10b9dd34a5c3fea908e20391a2a90b88d66362cb05beed186"},
{file = "Markdown-3.4.1.tar.gz", hash = "sha256:3b809086bb6efad416156e00a0da66fe47618a5d6918dd688f53f40c8e4cfeff"},
]
[package.extras]
testing = ["coverage", "pyyaml"]
[[package]]
name = "markupsafe"
version = "2.1.2"
description = "Safely add untrusted strings to HTML/XML markup."
optional = false
python-versions = ">=3.7"
files = [
{file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"},
{file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"},
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"},
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"},
{file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"},
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"},
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"},
{file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"},
{file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"},
{file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"},
{file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"},
{file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"},
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"},
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"},
{file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"},
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"},
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"},
{file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"},
{file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"},
{file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"},
{file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"},
{file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"},
{file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"},
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"},
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"},
{file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"},
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"},
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"},
{file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"},
{file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"},
{file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"},
{file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"},
{file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"},
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"},
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"},
{file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"},
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"},
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"},
{file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"},
{file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"},
{file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"},
{file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
]
[[package]]
name = "mypy"
version = "1.1.1"
description = "Optional static typing for Python"
optional = false
python-versions = ">=3.7"
files = [
{file = "mypy-1.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39c7119335be05630611ee798cc982623b9e8f0cff04a0b48dfc26100e0b97af"},
{file = "mypy-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61bf08362e93b6b12fad3eab68c4ea903a077b87c90ac06c11e3d7a09b56b9c1"},
{file = "mypy-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbb19c9f662e41e474e0cff502b7064a7edc6764f5262b6cd91d698163196799"},
{file = "mypy-1.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:315ac73cc1cce4771c27d426b7ea558fb4e2836f89cb0296cbe056894e3a1f78"},
{file = "mypy-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:5cb14ff9919b7df3538590fc4d4c49a0f84392237cbf5f7a816b4161c061829e"},
{file = "mypy-1.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:26cdd6a22b9b40b2fd71881a8a4f34b4d7914c679f154f43385ca878a8297389"},
{file = "mypy-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b5f81b40d94c785f288948c16e1f2da37203c6006546c5d947aab6f90aefef2"},
{file = "mypy-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b437be1c02712a605591e1ed1d858aba681757a1e55fe678a15c2244cd68a5"},
{file = "mypy-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d809f88734f44a0d44959d795b1e6f64b2bbe0ea4d9cc4776aa588bb4229fc1c"},
{file = "mypy-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:a380c041db500e1410bb5b16b3c1c35e61e773a5c3517926b81dfdab7582be54"},
{file = "mypy-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b7c7b708fe9a871a96626d61912e3f4ddd365bf7f39128362bc50cbd74a634d5"},
{file = "mypy-1.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1c10fa12df1232c936830839e2e935d090fc9ee315744ac33b8a32216b93707"},
{file = "mypy-1.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0a28a76785bf57655a8ea5eb0540a15b0e781c807b5aa798bd463779988fa1d5"},
{file = "mypy-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ef6a01e563ec6a4940784c574d33f6ac1943864634517984471642908b30b6f7"},
{file = "mypy-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d64c28e03ce40d5303450f547e07418c64c241669ab20610f273c9e6290b4b0b"},
{file = "mypy-1.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:64cc3afb3e9e71a79d06e3ed24bb508a6d66f782aff7e56f628bf35ba2e0ba51"},
{file = "mypy-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce61663faf7a8e5ec6f456857bfbcec2901fbdb3ad958b778403f63b9e606a1b"},
{file = "mypy-1.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2b0c373d071593deefbcdd87ec8db91ea13bd8f1328d44947e88beae21e8d5e9"},
{file = "mypy-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:2888ce4fe5aae5a673386fa232473014056967f3904f5abfcf6367b5af1f612a"},
{file = "mypy-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:19ba15f9627a5723e522d007fe708007bae52b93faab00f95d72f03e1afa9598"},
{file = "mypy-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:59bbd71e5c58eed2e992ce6523180e03c221dcd92b52f0e792f291d67b15a71c"},
{file = "mypy-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9401e33814cec6aec8c03a9548e9385e0e228fc1b8b0a37b9ea21038e64cdd8a"},
{file = "mypy-1.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b398d8b1f4fba0e3c6463e02f8ad3346f71956b92287af22c9b12c3ec965a9f"},
{file = "mypy-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:69b35d1dcb5707382810765ed34da9db47e7f95b3528334a3c999b0c90fe523f"},
{file = "mypy-1.1.1-py3-none-any.whl", hash = "sha256:4e4e8b362cdf99ba00c2b218036002bdcdf1e0de085cdb296a49df03fb31dfc4"},
{file = "mypy-1.1.1.tar.gz", hash = "sha256:ae9ceae0f5b9059f33dbc62dea087e942c0ccab4b7a003719cb70f9b8abfa32f"},
]
[package.dependencies]
mypy-extensions = ">=1.0.0"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
typing-extensions = ">=3.10"
[package.extras]
dmypy = ["psutil (>=4.0)"]
install-types = ["pip"]
python2 = ["typed-ast (>=1.4.0,<2)"]
reports = ["lxml"]
[[package]]
name = "mypy-extensions"
version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
optional = false
python-versions = ">=3.5"
files = [
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
]
[[package]]
name = "packaging"
version = "23.0"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.7"
files = [
{file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"},
{file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"},
]
[[package]]
name = "pathspec"
version = "0.11.0"
description = "Utility library for gitignore style pattern matching of file paths."
optional = false
python-versions = ">=3.7"
files = [
{file = "pathspec-0.11.0-py3-none-any.whl", hash = "sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229"},
{file = "pathspec-0.11.0.tar.gz", hash = "sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc"},
]
[[package]]
name = "platformdirs"
version = "3.1.0"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
optional = false
python-versions = ">=3.7"
files = [
{file = "platformdirs-3.1.0-py3-none-any.whl", hash = "sha256:13b08a53ed71021350c9e300d4ea8668438fb0046ab3937ac9a29913a1a1350a"},
{file = "platformdirs-3.1.0.tar.gz", hash = "sha256:accc3665857288317f32c7bebb5a8e482ba717b474f3fc1d18ca7f9214be0cef"},
]
[package.extras]
docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"]
test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
[[package]]
name = "pygments"
version = "2.14.0"
description = "Pygments is a syntax highlighting package written in Python."
optional = false
python-versions = ">=3.6"
files = [
{file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"},
{file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"},
]
[package.extras]
plugins = ["importlib-metadata"]
[[package]]
name = "pyquery"
version = "2.0.0"
description = "A jquery-like library for python"
optional = false
python-versions = "*"
files = [
{file = "pyquery-2.0.0-py3-none-any.whl", hash = "sha256:8dfc9b4b7c5f877d619bbae74b1898d5743f6ca248cfd5d72b504dd614da312f"},
{file = "pyquery-2.0.0.tar.gz", hash = "sha256:963e8d4e90262ff6d8dec072ea97285dc374a2f69cad7776f4082abcf6a1d8ae"},
]
[package.dependencies]
cssselect = ">=1.2.0"
lxml = ">=2.1"
[package.extras]
test = ["pytest", "pytest-cov", "requests", "webob", "webtest"]
[[package]]
name = "pyyaml"
version = "6.0.1"
description = "YAML parser and emitter for Python"
optional = false
python-versions = ">=3.6"
files = [
{file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
{file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
{file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
{file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
{file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
{file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
{file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
{file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
{file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
{file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
{file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
{file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
]
[[package]]
name = "requests"
version = "2.28.2"
description = "Python HTTP for Humans."
optional = false
python-versions = ">=3.7, <4"
files = [
{file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"},
{file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"},
]
[package.dependencies]
certifi = ">=2017.4.17"
charset-normalizer = ">=2,<4"
idna = ">=2.5,<4"
urllib3 = ">=1.21.1,<1.27"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
optional = false
python-versions = ">=3.7"
files = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
[[package]]
name = "types-markdown"
version = "3.4.2.6"
description = "Typing stubs for Markdown"
optional = false
python-versions = "*"
files = [
{file = "types-Markdown-3.4.2.6.tar.gz", hash = "sha256:8c6a834f207c621dbdc3aac5728006ae1b1d2ffea0b9f877b8ef26f4c10f4fc4"},
{file = "types_Markdown-3.4.2.6-py3-none-any.whl", hash = "sha256:00d7105ea9cdff57432494a7e4bf760a56a9ba8073bc5a9a4766844caa1094e2"},
]
[[package]]
name = "types-pyyaml"
version = "6.0.12.12"
description = "Typing stubs for PyYAML"
optional = false
python-versions = "*"
files = [
{file = "types-PyYAML-6.0.12.12.tar.gz", hash = "sha256:334373d392fde0fdf95af5c3f1661885fa10c52167b14593eb856289e1855062"},
{file = "types_PyYAML-6.0.12.12-py3-none-any.whl", hash = "sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24"},
]
[[package]]
name = "types-requests"
version = "2.28.11.17"
description = "Typing stubs for requests"
optional = false
python-versions = "*"
files = [
{file = "types-requests-2.28.11.17.tar.gz", hash = "sha256:0d580652ce903f643f8c3b494dd01d29367ea57cea0c7ad7f65cf3169092edb0"},
{file = "types_requests-2.28.11.17-py3-none-any.whl", hash = "sha256:cc1aba862575019306b2ed134eb1ea994cab1c887a22e18d3383e6dd42e9789b"},
]
[package.dependencies]
types-urllib3 = "<1.27"
[[package]]
name = "types-urllib3"
version = "1.26.25.10"
description = "Typing stubs for urllib3"
optional = false
python-versions = "*"
files = [
{file = "types-urllib3-1.26.25.10.tar.gz", hash = "sha256:c44881cde9fc8256d05ad6b21f50c4681eb20092552351570ab0a8a0653286d6"},
{file = "types_urllib3-1.26.25.10-py3-none-any.whl", hash = "sha256:12c744609d588340a07e45d333bf870069fc8793bcf96bae7a96d4712a42591d"},
]
[[package]]
name = "typing-extensions"
version = "4.5.0"
description = "Backported and Experimental Type Hints for Python 3.7+"
optional = false
python-versions = ">=3.7"
files = [
{file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
{file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
]
[[package]]
name = "urllib3"
version = "1.26.14"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
{file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"},
{file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"},
]
[package.extras]
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "45e7bbf0d4892d1876fc168359f6c7a9f524eecbb3628b333e6737ffa56299e9"

View File

@ -1,29 +0,0 @@
[tool.poetry]
name = "jyyslide-md"
version = "0.1.0"
description = ""
authors = ["zweix123 <1979803044@qq.com>"]
readme = "README.md"
packages = [{include = "jyyslide_md"}]
[tool.poetry.dependencies]
python = "^3.10"
requests = "^2.28.2"
jinja2 = "^3.1.2"
markdown = "^3.4.1"
pyquery = "^2.0.0"
pygments = "^2.14.0"
lxml = "^4.9.4"
pyyaml = "^6.0.1"
types-markdown = "^3.4.2.6"
types-requests = "^2.28.11.17"
types-pyyaml = "^6.0.12.12"
[tool.poetry.group.dev.dependencies]
black = "^23.1.0"
mypy = "^1.1.1"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -1,200 +0,0 @@
import json
import os
import shutil
import yaml
from jinja2 import Template
from pyquery import PyQuery # type: ignore
from src.util import *
from . import settings as st
def process_html_elements(before_html):
temp_html = "<html><body>{}</body></html>".format(before_html)
page = PyQuery(temp_html)
e = page
for item in e("h1").parent():
t = PyQuery(item)
t.wrap("<div style='width:100%'>")
t.wrap("<div class='center middle'>")
class_data = {
"ul": "list-disc font-serif",
"li": "ml-8",
"h2": "text-xl mt-2 pb-2 font-sans",
"h1": "text-2xl mt-2 font-sans",
"p": "font-serif my-1",
"pre": "bg-gray-100 overflow-x-auto rounded p-2 mb-2 mt-2",
# "img": "center", # 设置图片是否默认居中
}
for k, v in class_data.items():
for item in e(k):
t = PyQuery(item)
t.add_class(v)
page = e
items = page("body").children()
return "".join([str(PyQuery(e)) for e in items])
def process_terminal(semi_html):
semi_html += st.author_template
st.author_template = ""
temp = "<div>" + semi_html + "</div>"
semi_html = process_html_elements(temp)
return semi_html
def vertical_to_fragment(vertical: str) -> str:
fragments = vertical.split(st.op_index_fragment)
fragment_list = [md_util.md_to_html(fragments[0])]
template = "<div class='fragment' data-fragment-index='{}'>{}</div>"
for i in range(1, len(fragments)):
fragment_list.append(template.format(i, md_util.md_to_html(fragments[i])))
return "".join(fragment_list)
def vertical_to_animate(vertical: str) -> str:
animates = vertical.split(st.op_animate_section)
animate_list = list()
template = "{}"
for i in range(len(animates)):
animate_list.append(template.format(md_util.md_to_html(animates[i])))
return "".join(animate_list)
def horizontal_to_vertical(horizontal: str) -> str:
verticals_divided_by_second = horizontal.split(st.op_second_section)
sections = list()
template_second = "<section>{}</section>"
for vertical_divided_by_second in verticals_divided_by_second:
if vertical_divided_by_second.isspace():
continue
if st.op_animate_section in vertical_divided_by_second:
verticals_divided_by_animate = vertical_divided_by_second.split(
st.op_animate_section
)
template_animate = "<section data-auto-animate>{}</section>"
for vertical_divided_by_animate in verticals_divided_by_animate:
if vertical_divided_by_animate.isspace():
continue
sections.append(
template_animate.format(
process_terminal(
vertical_to_animate(vertical_divided_by_animate)
)
)
)
elif st.op_index_fragment in vertical_divided_by_second:
sections.append(
template_second.format(
process_terminal(vertical_to_fragment(vertical_divided_by_second))
)
)
else:
sections.append(
template_second.format(
process_terminal(md_util.md_to_html(vertical_divided_by_second))
)
)
return "".join(sections)
def md_divide_to_horizontal(content: str):
horizontals = content.split(st.op_first_section)
sections = list()
template = "<section>{}</section>"
for horizontal in horizontals:
if horizontal.isspace():
continue
html_second_sections = horizontal_to_vertical(horizontal)
html = template.format(html_second_sections)
sections.append(html)
return "".join(sections)
def get_body(content):
html_first_sections = md_divide_to_horizontal(content)
return html_first_sections
def process_image_link():
def func(link):
new_name, err = file_util.get_image_to_target(
link, st.filepath, st.images_foldpath
)
return (
os.path.join(".", "static", st.images_foldname, new_name)
if err is False
else ""
), err
st.content = md_util.process_images(st.content, func)
def process_front_matter():
if st.op_front_matter not in st.content:
st.author_template = ""
return
parts = st.content.split(st.op_front_matter)
front_matter = parts[0]
st.content = "".join(parts[1:])
try:
data = json.loads(front_matter)
except Exception as e:
data = yaml.load(front_matter, Loader=yaml.SafeLoader)
for department in data["departments"]:
new_name, err = file_util.get_image_to_target(
department["img"], st.filepath, st.images_foldpath
)
if err is False:
department["img"] = os.path.join(
".", "static", st.images_foldname, new_name
)
department["name"] = department["name"].replace(" ", "&#12288;")
st.author_template = st.author_template.render(author=data["author"], departments=data["departments"]) # type: ignore
def process_static():
if os.path.exists(st.output_foldpath) is True:
shutil.rmtree(st.output_foldpath)
os.mkdir(st.output_foldpath)
shutil.copytree(st.static_path, st.static_foldpath)
def converter(MDfilepath):
st.Init(MDfilepath)
process_static()
st.template = Template(file_util.read(st.template_from))
st.author_template = Template(file_util.read(st.authortemp_from))
st.content = file_util.read(st.filepath)
process_front_matter() # 解析markdown中的front_matter and render author_template(will change content)
process_image_link() # 处理Markdown文本中的图片链接, 将它们get到静态文件, 同时修改content
st.title = "".join(st.filename.split(".")[:-1])
st.body = get_body(st.content)
st.template = st.template.render(title=st.title, body=st.body)
file_util.write(st.output_filepath, st.template)

View File

@ -1,47 +0,0 @@
import os
from jinja2 import Template
settings_abspath = os.path.split(os.path.realpath(__file__))[0]
projects_abspath = os.path.abspath(os.path.join(settings_abspath, ".."))
static_path = os.path.join(projects_abspath, "src", "static")
template_from = os.path.join(projects_abspath, "template", "basetemp.html")
authortemp_from = os.path.join(projects_abspath, "template", "authortemp.html")
op_first_section = "\n---\n"
op_second_section = "\n----\n"
op_animate_section = "\n++++\n"
op_index_fragment = "\n--\n"
op_front_matter = "\n+++++\n"
# 文件信息
filename = str()
filepath = str()
output_foldname = "dist"
output_filename = "index.html"
output_foldpath = str()
output_filepath = str()
static_foldpath = str()
images_foldname = "img" # 如果要修改还要修炼static下的img文件名template中icon的文件路径
images_foldpath = str()
content = str() # MD内容
template: str | Template = str() # HTML内容
title = str()
body = str()
# 作者信息相关
author_template: str | Template = str()
def Init(target_filepath):
global filename, filepath, output_foldname, output_filename, output_foldpath, output_filepath, static_foldpath, images_foldpath
filename = os.path.basename(target_filepath)
filepath = os.path.abspath(target_filepath)
output_foldpath = os.path.join(filepath.split(filename)[0], output_foldname)
output_filepath = os.path.join(output_foldpath, output_filename)
static_foldpath = os.path.join(output_foldpath, "static")
images_foldpath = os.path.join(static_foldpath, images_foldname)

View File

@ -1 +0,0 @@
from . import file_util, net_util, str_util, md_util

View File

@ -1,60 +0,0 @@
import os, shutil, uuid
from typing import Optional, Tuple
from . import str_util, net_util
def get_files_under_folder(
folerpath: str, suffix_name: Optional[str] = None
) -> list[str]:
"""返回目录folderpath下后缀名为suffix_name的所有文件的绝对路径列表"""
return [
os.path.abspath(os.path.join(dirpath, filename))
for dirpath, dirnames, filenames in os.walk(folerpath)
for filename in filenames
if suffix_name is None or str(filename).endswith("." + suffix_name)
]
def read(filepath: str) -> str: # 读取文本文件内容
if os.path.exists(filepath) is False:
raise Exception("The path {} is not exists".format(filepath))
with open(filepath, "r", encoding="utf-8") as f:
return str(f.read())
def write(filepath: str, data: str) -> None: # 向文件(覆)写内容
dirpath = os.path.dirname(filepath)
if os.path.exists(dirpath) is False:
os.makedirs(dirpath)
with open(filepath, "w", encoding="utf-8") as f:
f.write(data)
def get_abspath(basefile: str, filepath: str) -> str: # 从绝对路径变化成相对路径且符合当前的操作系统
return os.path.normpath(os.path.join(os.path.dirname(basefile), filepath))
def get_image_to_target(
link: str, from_filepath: str, target_foldpath: str
) -> Tuple[str, bool]:
# 对于from_filepath(请使用其绝对地址)中的图床链接link, 它可能是url、绝对地址或相对地址, 我们会get它然后重命名并放到target_foldpath下, 并返回重命名后的名字
# 这里对图片类型的判断是通过link的后缀名, 有些图片的url的末尾不是类型名, 就会有bug
name = uuid.uuid4().hex + "." + link.split(".")[-1]
if str_util.is_url(link):
pass
else:
if os.path.isabs(link) is True:
pass
else:
link = get_abspath(from_filepath, link)
pass
if str_util.is_url(link):
net_util.down_image(link, os.path.join(target_foldpath, name))
else:
if os.path.exists(link) is False:
print("The path is not exists: ", link)
return "", True
shutil.copyfile(link, os.path.join(target_foldpath, name))
return name, False

View File

@ -1,70 +0,0 @@
import re
from typing import List, Union
def process_images(content, func):
"""处理Markdown类型字符串中的图片链接, 返回处理过图片链接部分的Markdown字符串
Args:
content (_type_): Markdown类型字符串
func (_type_): 处理图片链接的函数, 该函数接受图片链接字符串, 返回一个(有关图片链接的新串, 是否有错误)的元组
"""
def modify(match):
# 下面是黑盒魔法
tar = match.group()
pre, mid, suf = str(), str(), str()
if tar[-1] == ")":
pre = tar[: tar.index("(") + 1]
mid = tar[tar.index("(") + 1 : -1]
suf = tar[-1]
else:
mid = re.search(r'src="([^"]*)"', tar).group(1)
pre, suf = tar.split(mid)
link = mid
# 黑盒魔法结束
new_name, err = func(link)
return pre + (new_name if err is False else link) + suf
patten = r"!\[.*?\]\((.*?)\)|<img.*?src=[\'\"](.*?)[\'\"].*?>"
return re.sub(patten, modify, content)
###
from markdown import markdown
from markdown import Extension
from markdown.blockprocessors import BlockProcessor
import xml.etree.ElementTree as etree
def md_to_html(md: str) -> str:
class BoxBlockProcessor(BlockProcessor):
first = True
def run(self, parent, blocks):
if self.first:
self.first = False
e = etree.SubElement(parent, "div")
self.parser.parseBlocks(e, blocks)
for _ in range(0, len(blocks)):
blocks.pop(0)
return True
return False
class BoxExtension(Extension):
def extendMarkdown(self, md):
md.parser.blockprocessors.register(BoxBlockProcessor(md.parser), "box", 175)
extensions: List[Union[str, BoxExtension]] = [
BoxExtension(),
"meta",
"fenced_code",
"codehilite",
"extra",
"attr_list",
"tables",
"toc",
]
return markdown(md, extensions=extensions)

View File

@ -1,7 +0,0 @@
import requests
def down_image(img_url, save_file_path):
resp = requests.get(img_url)
with open(save_file_path, "wb") as f:
f.write(resp.content)

View File

@ -1,13 +0,0 @@
from urllib.parse import urlparse
# 分辨URL和路径: 判断一个字符串是否为URL
def is_url(string):
result = urlparse(string)
return all([result.scheme, result.netloc])
# 分辨URL和路径: 判断一个字符串是否为路径
def is_path(string):
result = urlparse(string)
return not all([result.scheme, result.netloc])

View File

@ -1,24 +0,0 @@
<p class=" font-serif my-1">
<include src="Slides_Author">
<div class="py-16">
<p class=" font-serif my-1">
<a href="{{ author.url }}" class=" text-amber-900">
{{ author.name }}
</a>
</p>
</div>
<div class="row">
<p class=" font-serif my-1"></p>
{% for department in departments %}
<div class="author-affiliation">
<a href="{{ department.url }}" class=" text-amber-900">
<p class=" font-serif my-1">
{{ department.name }}
</p>
<img class="inline-img h-24" src="{{ department.img }}" style="display: inline-block;">
</a>
</div>
{% endfor %}
</div>
</include>
</p>

View File

@ -1,79 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="./static/css/base.css" rel="stylesheet">
<link href="./static/css/tailwind.min.css" rel="stylesheet">
<link href="https://fonts.font.im/css?family=Source+Serif+Pro%7CLato%7CInconsolata" rel="stylesheet"
type="text/css">
<title> {{ title }} </title>
<!-- browser favicon -->
<link rel="shortcut icon" href="./static/img/favicon.ico">
<style>
.font-sans {
font-family: 'Lato', 'SimHei', 'STHeiti', 'SimHei', 'Serif';
}
.font-serif {
font-family: 'Source Serif Pro', 'Songti SC', 'SimSun', 'Serif', serif;
}
</style>
<link rel="stylesheet" href="./static/katex/katex.min.css">
<script defer src="./static/katex/katex.min.js"></script>
<script defer src="./static/katex/auto-render.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
renderMathInElement(document.body, {
// customised options
// &#8226; auto-render specific keys, e.g.:
delimiters: [
{ left: '$$', right: '$$', display: true },
{ left: '$', right: '$', display: false },
{ left: '\\(', right: '\\)', display: false },
{ left: '\\[', right: '\\]', display: true }
],
// &#8226; rendering keys, e.g.:
throwOnError: false
});
});
</script>
<link rel="stylesheet" href="./static/reveal/reveal.css">
<link rel="stylesheet" href="./static/reveal/theme/simple.css" id="theme">
<link rel="stylesheet" href="./static/jyy/jyy.css">
</head>
<body class="d-flex flex-column h-100">
<div class="reveal">
<div class="slides">
{{ body }}
</div>
</div>
<script src="./static/reveal/reveal.js"></script>
<script>
Reveal.initialize({
width: 1024, height: 768,
slideNumber: 'c/t',
controlsTutorial: false,
progress: false,
hash: true,
center: false,
autoAnimateUnmatched: true,
autoAnimateEasing: 'ease-out',
autoAnimateDuration: 0.3,
transitionSpeed: 'fast'
});
</script>
</body>
</html>