diff options
| author | yingyu5658 <i@yingyu5658.me> | 2025-12-13 08:33:08 +0800 |
|---|---|---|
| committer | yingyu5658 <i@yingyu5658.me> | 2025-12-13 08:33:08 +0800 |
| commit | 1e5f8eb33bc41cb59faf059e83701152785cabea (patch) | |
| tree | 45867273ac2178285be840764f7962d2b55556c6 | |
| download | blog-1e5f8eb33bc41cb59faf059e83701152785cabea.tar.gz blog-1e5f8eb33bc41cb59faf059e83701152785cabea.zip | |
Initial commit
174 files changed, 12578 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..73ab876 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +public/ +resources/ diff --git a/.hugo_build.lock b/.hugo_build.lock new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/.hugo_build.lock @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5e9d66e --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# 映屿 (GlowIsle) + +[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) +[](https://creativecommons.org/licenses/by-nc-sa/4.0/) + + + +- 详情: [关于页面](https://www.glowisle.me/about)。 + +- Telegram频道: [🌊 央山常量池](https://t.me/glowisle/) + +--- + +博客源码使用 GPL-2.0 协议授权 | 文章内容使用 CC BY-NC-SA 4.0 协议授权 diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..2f61dae --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,10 @@ +--- +date: '{{ .Date }}' +draft: true +title: '{{ replace .File.ContentBaseName "-" " " | title }}' +slug: '' +categories: + - +tags: + - +--- diff --git a/content/_index.md b/content/_index.md new file mode 100644 index 0000000..0865506 --- /dev/null +++ b/content/_index.md @@ -0,0 +1,19 @@ +--- +title: "映屿" +--- + + + + +你好,这里是 映屿 (GlowIsle). 你可以叫我 Verdant 或 五葉地錦。 + +我会在这里写写生活随笔、读书感悟、技术实践和幼稚观点。 + +我的理念是**不花里胡哨、不迎合大众、不随波逐流、不投放广告**,专注自己想写的内容。 + +--- + + +## 最近更新 + +{{< recent-posts >}} diff --git a/content/about.md b/content/about.md new file mode 100644 index 0000000..f5214f8 --- /dev/null +++ b/content/about.md @@ -0,0 +1,59 @@ +--- +date: 2025-02-26T20:31:14+08:00 +title: 关于 +type: no-comments +--- +> 📌 如果想获得最新动态,可以加入本博客的Telegram频道[「🌊 央山常量池」](https://t.me/glowisle/),有博客选题、观察思考,还有我的碎碎念。 +> +> 若不方便使用Telegram,也可以访问 [网页版的央山常量池](https://channel.glowisle.me/)。 + +## 我是谁 + +- 11 年出生,天津人,目前初中在读。 +- 执着于文字、排版、设计传递的「感觉」。 +- 尝试热爱数理化但被反复虐杀。 +- 有一定智商情商。 +- 现实存在感微弱。 + +我用过很多网名,比如:银鱼、反犬孔、**五葉地錦**。在英文网站使用的 id 为:yingyu5658, **Verdant**. + +最大的爱好是**自己待着**做各种事: +- [**喜欢看书**](https://www.glowisle.me/readings)。最爱文学,正在犹豫要不要尝试哲学。 +- **喜欢音乐**。最爱J-Pop。東京事変、椎名林檎 …… 贝斯新手。 +- **被迫写作**。不写会憋死,假装会写几个字。 +- **写点代码**。目前在研究 Go,瞎写着玩,也想学Rust。 + +## 关于这里 + +~~全站都是听歌听嗨了写的车轱辘话。~~ + +这里是记录日常观察、技术实践、阅读思考与个人成长的网络日志。不花里胡哨、不迎合大众、不随波逐流、不投放广告,专注自己想写的内容。 + +- 博客内容承诺均**非AI创作**。 +- 所有文章内容使用[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/)协议授权。 +- 目前文章字数:{{< word-count "posts" >}} + +## 这个博客是如何搭建的 + +本博客使用快速、易用的静态博客生成程序 [Hugo](https://gohugo.io/),在 [hugo-bearneo](https://github.com/rokcso/hugo-bearneo) 主题的基础上进行修改,静态文件托管在Github Pages,图床使用Cloudflare R2对象存储。我使用 Emacs 撰写文章,并推送到远程仓库构建部署。 + +## 在哪找到我 + +- Email: [i@glowisle.me](mailto:i@glowisle.me/) +- 即时通讯: [Verdant](https://t.me/VerdantIO/)(Telegram) +- Mastodon: [c7.io/@Verdant](https://c7.io/@Verdant/) +- Github: [Verdant](https://github.com/yingyu5658/) + +## 订阅 + +如果你喜欢我的文字,可以用以下链接订阅: + +``` +https://www.glowisle.me/atom.xml/ +``` + +订阅Telegram频道的消息: + +``` +https://channel.glowisle.me/rss.xml/ +``` diff --git a/content/archives.md b/content/archives.md new file mode 100644 index 0000000..8e8196d --- /dev/null +++ b/content/archives.md @@ -0,0 +1,4 @@ +--- +title: "归档" +type: "archives" +--- diff --git a/content/categories.md b/content/categories.md new file mode 100644 index 0000000..cdb715b --- /dev/null +++ b/content/categories.md @@ -0,0 +1,27 @@ +--- +type: no-comments +title: 分类 +--- +### [💭 随笔](/categories/随笔) + +记录事情 | 抒发观点 | 发表议论 + +### [📚 读书](/categories/读书/) + +撰写书评 | 撰写读后感 | 书籍推荐 | 读书总结 + +在 [这里](/readings/) 查看我读过的书。 + +### [🎥 观影](/categories/读书/) + +撰写影评 | 撰写观后感 | 电影推荐 | 观影总结 + +### [💻 技术](/categories/技术/) + +技术实践 | 技术观点 + +--- + +##### [~~🧻 往昔~~](/categories/往昔) + +###### ~~早期不成熟的文章合集 | 包含偏激观点 | 冒犯性用语 | 不建议阅读~~ diff --git a/content/links.md b/content/links.md new file mode 100644 index 0000000..929a60b --- /dev/null +++ b/content/links.md @@ -0,0 +1,44 @@ +--- +date: "2025-06-07T13:08:07+08:00" +title: 友人 +type: no-comments +--- +| Link | Description | +| -------------------------------------------- | -------------------------------------------------- | +| [MRZHU的小站](https://www.sifangbazhu.tech/) | 向着计算物理出发吧! | +| [RhoPaperの小站](https://rhopaper.top/) | 纸 至 执 | +| [177](https://177.plus/) | 行胜于言 | +| [PRIN BLOG](https://printempw.github.io/) | 半吊子全栈开发者的日常 | +| [Web Teleporter](https://webteleporter.top) | - | +| [搬砖日记](https://banzhuanriji.com/) | - | +| [彬红茶日记](https://note.redcha.cn) | 我的个人笔记📒 | +| [轻风blog](https://www.qingfengnb.cn) | 茫茫人海,多么幸运才能遇见你! | +| [成烁BLOG](https://blog.chengshuo.top) | 致一锦程 探索不停 | +| [Jame](https://jame.work) | 随笔 | +| [白熊阿丸的小屋](https://blog.bxaw.name) | 在这里可以看到一个真实的我,我会在这里书写我的一切 | +| [Mayx的博客](https://mabbs.github.io) | Mayx’s Home Page | +| [龙场茶室](https://blog.peterchen97.cn/) | - | +| [太隐](https://wangyurui.com/) | 一个人的思想发育史就是他的阅读史 | +| [辛未羊的网络日志](https://panqiincs.me/) | 记录生活和学习 | + +<!-- + + +交换友链、链接变更等请**发邮件**:i@glowisle.me + +## 交换友链要求 + +1. 独立博客(非影视、聚合、搬运类); +2. 文章不少于30篇; +3. 原创内容占比至少80%; + +## 本站信息 + +``` +名称:映屿 +简介:关于互联网、书籍、生活琐事以及那些一闪而过的念头。 +链接:https://www.glowisle.me/ +订阅:https://www.glowisle.me/atom.xml +``` + +--> diff --git a/content/posts/2025普鲁斯特问卷.md b/content/posts/2025普鲁斯特问卷.md new file mode 100644 index 0000000..9004d5c --- /dev/null +++ b/content/posts/2025普鲁斯特问卷.md @@ -0,0 +1,202 @@ +--- +date: '2025-12-11T20:18:45+08:00' +draft: true +title: '2025普鲁斯特问卷' +slug: '2025-proust-questionnaire' +categories: + - 随笔 +tags: + - 普鲁斯特问卷 +--- +## 01 What is your idea of perfect happiness? +你认为最完美的幸福是怎样的? + +我理想中的幸福,是类似日语中「幸せ(しあわせ)」的概念: + +有着自己的时间和空间,能干自己喜欢的事,**不会有人突然闯进来**。 + +为什么是日语?这个词给我的印象就是一种温暖、朦胧的幸福和自在,不是宏大而抽象的幸福。有时候在汉语「幸福」这个词,我也会联想到「阖家欢乐」的场面。 + +## 02 What is your greatest fear? +你最大的恐惧是什么? + +失败。虽然没有人会否定我,但我会做我的仇人,疯狂指指点点,在一次次对自己的审问里又陷入到Q3的状态。 + +## 03 What is the trait you most deplore in yourself? +你最痛恨自己的哪些特质? + +间歇性认为自己独一无二,遭受一点挫折就全盘否定自己,在踌躇满志和意志消沉之间来回挣扎却不作出改变的懦弱、愤世嫉俗的尖锐、无休止的内省。 + +04 What is the trait you most deplore in others? +你最痛恨别人的什么特点? + +自信、自大;充满向上的活力,乐观到仿佛失败没有存在过;无端的快乐;吵吵闹闹的友情。 + +05 Which living person do you most admire? +还在世的人中你最欣赏的是谁? + +没有特别欣赏的某一个人,但非常欣赏能坚持自己热爱的事的人。 + +06 What is your greatest extravagance? +你最大的奢侈品是什么? + +喝着可乐,听着歌,坐在电脑前打打字。 + +07 What is your current state of mind? +你目前的心境怎样? + +在平静和沮丧之间微妙的平衡。 + +08 What do you consider the most overrated virtue? +你认为哪种美德是被过高评价的? + +个人的勤奋。 + +09 On what occasion do you lie? +什么情况下你会撒谎? + +当事态发展到不撒谎就对我自身不利时。 + +10 What do you most dislike about your appearance? +你对自己的外表哪一点不满意? + +矮。 + +11 Which living person do you most despise? +还在世的人中你最鄙视谁? + +拾人牙慧,自以为是的他人观点的转述机器。 + +12 What is the quality you most like in a man? +你最喜欢男性身上的什么品质? + +力量、蓬勃的生命力、理性主导。 + +13 What is the quality you most like in a woman? +你最喜欢女性身上的什么品质? + +善于**发现快乐**和**感受快乐**。 + +14 Which words or phrases do you most overuse? +你最常使用的单词或短语是什么? + +除了「我」和某些不堪入耳的脏话以外,应该就是「死」了,对别人的,对自己的。 + +15 What or who is the greatest love of your life? +你这一生中最伟大的爱是谁/什么? + +寻找中。 + +16 When and where were you happiest? +何时何地让你感觉到最快乐? + +不被人打扰,做自己的事,做成功于否评判标准模糊的事,这会让我的自尊心获得官能性的快感。 + +17 Which talent would you most like to have? +你最想拥有哪种才能? + +理科能力。 + +18 If you could change one thing about yourself, what would it be? +如果你能够改变自己的一件事,那会是什么? + +减少熬夜。 + +19 What do you consider your greatest achievement? +你认为自己最大的成就是什么? + +尽管没人看,但还是唧唧歪歪词不达意水平低下地羞耻地在博客写了十几万字。 + +20 If you were to die and come back as a person or a thing, what would it be? +如果有转世,你希望成为什么样的人或物? + +狗、猫。 + +21 Where would you most like to live? +你最想住在哪里? + +长江之南 | 日本京都 | 某个高维度地区的乡村。 + +22 What is your most treasured possession? +你最珍贵的财产是什么? + +我14岁的年龄。我在这个阶段发表什么观点都会被看作「早慧」,如果认知水平的增长速度不能走在年龄增长速度的前面,那我将失去我最值得骄傲的特质。 + +23 What do you regard as the lowest depth of misery? +你认为程度最浅的痛苦是什么? + +身体上的痛苦。 + +24 What is your favorite occupation? +你最喜欢的职业是什么? + +程序员、作家、画家。 + +25 What is your most marked characteristic? +你最显著的特点是什么? + +至少朋友对我的评价是有点阴暗。 + +26 What do you most value in your friends? +你最看重朋友的什么特点? + +真诚、谦虚。 + +27 Who are your favorite writers? +你最喜欢的作家是谁? + +三岛由纪夫。 + +这是真正的男人,知行合一的艺术家。他是我写作的老师,思考的老师,尤其是对死亡观的懵懂的构建上。 + +在除了写作的方面,他是自强、清醒、对自己极高标准的人,是掌控生活,掌控生命的成功者。 + +28 Who is your hero of fiction? +谁是你心目中小说里的英雄? + +我自己那部未发布的小说里的主人公,窝窝囊囊、惨惨戚戚,拧巴的人。 + +灵感来源于我自己,正因此,我写的时候,看的时候会陷入「独一无二」的自豪感,然后陷入Q3的状态。 + +29 Which historical figure do you most identify with? +你最认同哪位历史人物? + +项羽。 + +30 Who are your heroes in real life? +谁是你现实生活中的英雄? + +一男一女。 + +31 What are your favorite names? +你最喜欢的名字是什么? + +所在、 + +32 What is it that you most dislike? +你最不喜欢什么? + +写作文。写歌舞升平的盛世,写失败后努力就取得成功的励志,写自信强大积极的处世态度。不这么写就不会获得高分。 + +33 What is your greatest regret? +你最大的遗憾是什么? + +信了政治课本的鬼话:这个阶段的感情不是真正的爱情。 + +到底什么是他妈的真正的爱情啊?老子的爱情需要你课本来定义吗? + +没有在初中阶段尝试谈恋爱,以后再也不能遇到懵懂纯洁的爱情了。 + +34 How would you like to die? +你想以何种方式死去? + +失败之后,死在温暖的热带、缤纷的花海、金黄的麦田里。 + +我有时候在想,既然某个国家政治上的言论封锁都那么严厉,那更何况一个世界呢?按照宗教的说法,基督教有天堂和地狱,佛教也有类似的概念,中国传统民俗里则是「地府」这种概念。 + +万一那些是假的呢?万一他们构建的地狱的概念根本不存在,或者说这里就是死后的世界,就是地狱呢?既然按照他们的说法,死后会下地狱,去地府,如果这是假的,他们在骗人,那是不是意味着,在这个世界死掉就会进入「活着」的世界?万一这里是痛苦的尽头呢? + +35 What is your motto? +你的座右铭是什么? + +mujou、 diff --git a/content/posts/4Key音游段位单曲成绩计算的程序实现.md b/content/posts/4Key音游段位单曲成绩计算的程序实现.md new file mode 100644 index 0000000..ca76751 --- /dev/null +++ b/content/posts/4Key音游段位单曲成绩计算的程序实现.md @@ -0,0 +1,327 @@ +--- +abbrlink: 594023371 +categories: +- 往昔 +date: "2025-06-07 13:08:07" +tags: +- Malody +- osu +- 数据结构与算法 +title: 4Key音游段位单曲成绩计算的程序实现 +--- +## 前言 + +其实这个坑我很早以前就想开了,在我刚开始学编程那会就一直想写一个这个东西。但苦于数学进度没达到,要用到加权平均数,这东西我前两天才学到,之前对数学也一直是懒得学的状态,要不然几乎是看不懂那个算法的。 + +我手头有一个[Special-Week](https://github.com/Special-Week)写的网页版的单曲成绩计算器,就以这个为研究样本吧。以下简称原作者为sw(如有冒犯请联系修改) + +## 数据结构设计 + +```js + // 基础的4k类 + class Dan4k { + constructor(key1, key2, key3, key4, danName) { + this.m_key1 = key1; + this.m_key2 = key2; + this.m_key3 = key3; + this.m_key4 = key4; + this.m_danName = danName; + } + } + +``` + +每一个段(LN、Om),sw都单独写了一个内部类,继承Dan4k。 + +```js + // lnDan类 + class LnDan extends Dan4k { + constructor(key1, lnKey1, key2, lnKey2, key3, lnKey3, key4, lnKey4, danName) { + super(key1, key2, key3, key4, danName); + this.m_lnKey1 = lnKey1; + this.m_lnKey2 = lnKey2; + this.m_lnKey3 = lnKey3; + this.m_lnKey4 = lnKey4; + } + } + // ma段 + class MaDan extends Dan4k { + constructor(key1, key2, key3, key4, name1, name2, name3, name4, danName) { + super(key1, key2, key3, key4, danName); + this.m_name1 = name1; + this.m_name2 = name2; + this.m_name3 = name3; + this.m_name4 = name4; + } + } + // reform段 + class ReformDan extends Dan4k { + constructor(key1, key2, key3, key4, name1, name2, name3, name4, danName) { + super(key1, key2, key3, key4, danName); + this.m_name1 = name1; + this.m_name2 = name2; + this.m_name3 = name3; + this.m_name4 = name4; + } + + } + // om段 + class OmDan extends Dan4k { + constructor(key1, key2, key3, key4, danName) { + super(key1, key2, key3, key4, danName); + } + } +``` + +我打算重写的程序不带LN玩了,我自己也没玩过LN,不清楚是什么机制。那就来看看剩下的几个类。 + +`Dan4k`类定义了一个段位的基础属性,但是这个参数key1-4是用来做什么在当前上下文暂且不清楚,是第n首歌的物量吧。 + +那么由此可以推断,这些类都描述了一个谱面的基本属性: +- 物量 +- 歌曲名称 +- 段位名称 +然后分支匹配数据并计算。我也用C语言实现一个。 + +```c +// 整个段位信息 +typedef struct Dan { + // 段位名字 + char* dan_name; + // 四首歌的名字,用于匹配数据 + char* song1_name; + char* song2_name; + char* song3_name; + char* song4_name; + // 四首歌的物量 + int song1_key; + int song2_key; + int song3_key; + int song4_key; +}Dan; +``` + +来看看网页版中数据是如何存储的 + +```js + // MaDan数据 + let MaArr = [ + new MaDan(813, 955, 907, 654, "Glitch Nerds", "Borealis", "Niflheim", "Moon", "1dan"), + new MaDan(1152, 850, 950, 969, "Follow Tomorrow", "Bronze Coffin", "Keigan no Zettaireido", "SakuraMirage", "2dan"), + new MaDan(1169, 1143, 974, 1347, "Quon", "Genkyoku o Kirikizamu", "Gin no Kaze", "Adjudicatorz-Danzai-", "3dan"), + new MaDan(1400, 1402, 1685, 1599, "Tenkuu no Yoake", "VALLISTA", "Crystal World ~Fracture~", "Zenithalize", "4dan"), + new MaDan(1953, 2250, 2166, 1667, "Ten Thousand Tons of Anonymous Letters", "Chips of Notes", "Despair of Elferia", "Kamigami no Asobi", "5dan"), + new MaDan(1487, 1424, 1381, 1587, "Sweet Cherry X", "Akasagarbha", "HELLO EveryOne", "DataErr0r", "6dan"), + new MaDan(1909, 1814, 1777, 2681, "Fairy Stage", "Xross Infection", "Wave", "Blue Zenith", "7dan"), + new MaDan(1962, 1067, 2388, 1772, "The Lost Dedicated", "The Party We Have Never Seen", "Finixe", "Ultimate Dream", "8dan"), + new MaDan(1799, 2023, 2283, 1787, "Dusk", "Panic Popn Picnic", "Kick-ass Kung-Fu Carnival", "Yakusoku no kimi", "9dan"), + new MaDan(2606, 2188, 2194, 2187, "Chaser", "Loli Fantasy", "Daydream", "Moon Gate", "10dan"), + new MaDan(2160, 1952, 1821, 3249, "Border of Life", "Scorpion Dance", "The Island of Albatross", "beautiful loli thing", "ex1"), + new MaDan(2871, 2024, 1871, 2452, "Hitsune no youmeiri", "紫阳花-AZISAI-", "love&justice", "message", "ex2"), + new MaDan(2327, 1593, 2166, 2200, "Jumble Rumble", "End Time", "++", "Crow Solace", "ex3"), + new MaDan(2731, 2653, 2033, 2761, "EDM Jumpers", "line-epsilon", "Contrapasso -paradiso-", "YELL!", "ex4"), + new MaDan(3229, 2731, 2561, 2109, "Satori de Pon!", "Legend of Seeker", "Crystal World -Fracture-", "Wizdomiot", "ex5"), + new MaDan(1766, 1861, 3171, 1680, "Sepia", "Nopea", "Satori Trisis", "Death", "ex6"), + new MaDan(2339, 2461, 2511, 2177, "Paranoia", "Boulafacet", "Paraclete -Miracle-", "Yumemi no Shonen", "ex7"), + new MaDan(1929, 2380, 2710, 4675, "Martail Arts", "Gene Disruption", "Paradigm Shift", "Death Melody", "ex8"), + new MaDan(3468, 3335, 3698, 5061, "Only my railgun", "-Purgatorium-", "Blue Zenith", "Inner Universe", "exfin"), + + new MaDan(492, 529, 595, 681, "Ikitoshi Ikerumono", "Rambling Pleat", "Yi Meng Qian Xiao", "White Eternity", "0danv3"), + new MaDan(695, 621, 718, 1279, "Rex Incoqnito", "Koiseyo Otome!", "Break", "KING", "1danv3"), + new MaDan(1397, 1090, 805, 1212, "Stargazer", "Seyana", "Love Emotion", "Mermaid Girl", "2danv3"), + new MaDan(1055, 1489, 1288, 1789, "Koi Kou Enishi", "Onegai!Kon Kon Oinari-sama", "The Last page", "Hoshi ga Furanai Machi", "3danv3"), + new MaDan(1865, 1434, 1284, 1839, "Umiyuri Kaiteitan", "Fire in the sky", "Icyxis", "The Crimson Empire", "4danv3"), + new MaDan(1282, 1706, 1473, 1939, "Platinum Disco", "Cute na Kanojo", "Reimei Sketchbook", "Joker", "5danv3"), + new MaDan(1694, 1636, 1803, 2115, "Chocolate Disco", "Call Me, Beep Me (If You Wanna Reap Me)", "DIE IN THE SEA", "unhappy century", "6danv3"), + new MaDan(1701, 1799, 2132, 1899, "Don't Stop The Music", "Six Acid Strings", "Arkadia [Illusion]", "Valkyrie Revolutia", "7danv3"), + new MaDan(2237, 2081, 2280, 2000, "Don't let you down", "Yoru ni Kakeru", "Snow Veil -Shoujo to Kemono no Mori-", "Positive Dance Time", "8danv3"), + new MaDan(2374, 1899, 2142, 1810, "Kikai Shoujo Gensou", "Cold Planet", "Stray Star", "Unleashed World", "9danv3"), + new MaDan(2034, 1740, 2270, 2166, "Hiensou", "Rocky Buinne", "Yue Ai Yue Ye", "Spin Eternally", "10danv3"), + new MaDan(1952, 2013, 1953, 2111, "Scorpion Dance", "Tailin no Soul", "Eiya no Parade", "Onsoku Uchuu Ryokou", "ex1v3"), + new MaDan(2107, 1953, 2386, 2674, "Moments", "Towards the Horizon", "Torikago", "Frontier Explorer", "ex2v3"), + new MaDan(2518, 2636, 2326, 2511, "Edison", "INTERNET OVERDOSE", "Euthanasia", "Fin.ArcDeaR", "ex3v3"), + new MaDan(2634, 2212, 2336, 2602, "ZENITHALIZE", "Asymmetrical Grooves", "Pure Ruby", "EVERLASTING HAPPiNESS", "ex4v3"), + new MaDan(2734, 2417, 3089, 2974, "Bring Our Ignition Back", "Unsan-musho", "Electric Angel", "Kegare Naki Bara Juuji", "ex5v3"), + new MaDan(2483, 2276, 2921, 3194, "Defeat awaken battle ship", "Extraction", "Pastel Subliminal", "Synthesized Fortress", "ex6v3"), + new MaDan(2846, 2260, 2333, 3347, "LiFE Garden", "Alpha", "Stay Alive", "Heaven's Fall", "ex7v3"), + new MaDan(3789, 3663, 2424, 3255, "Hayabusa", "Shuu no hazama", "Amatsukami", "CRIMSON FIGHTER", "ex8v3"), + new MaDan(3888, 3030, 3581, 3700, "crazy_tek (DJ Noriken Remix)", "Nhelv", "Shuuten", "Deadly force - Put an end", "ex9v3"), + new MaDan(2828, 3362, 3393, 5100, "Infinity Heaven", "NEURO-CLOUD-9", "Kizuato", "Runengon", "exfinv3"), + ] +``` + +可以看到,简单地调用构造函数新建对象。继续实现: +我们可以写一个`init`函数,根据需要创建结构体变量。 +```c +Dan* dan_data_init(Dan*, int* songs_key); +``` + +第二个参数是存放物量的数组,这样就实现了代码复用,减少重复代码的编写,定义一次所有物量即可。 + +```c +// 常规段 +int mld_1dan_total_keys[] = {813, 955, 907, 654}; +int mld_2dan_total_keys[] = {1152, 850, 950, 969}; +int mld_3dan_total_keys[] = {1169, 1143, 974, 1347}; +int mld_4dan_total_keys[] = {1400, 1402, 1685, 1599}; +int mld_5dan_total_keys[] = {1953, 2250, 2166, 1667}; +int mld_6dan_total_keys[] = {1487, 1424, 1381, 1587}; +int mld_7dan_total_keys[] = {1909, 1814, 1777, 2681}; +int mld_8dan_total_keys[] = {1962, 1067, 2388, 1772}; +int mld_9dan_total_keys[] = {1799, 2023, 2283, 1787}; +int mld_10dan_total_keys[] = {2606, 2188, 2194, 2187}; +``` + +这里目前把常规段都录入了,那要怎么按需匹配创建结构体变量呢?可以通过一个指针数组保存这些数据数组的地址,然后根据用户输入的数字直接作为索引,创建结构体变量并进行初始化赋值。 + +优点:避免if/switch分支判断逐个比较,时间复杂度为常数阶。 + +```c +int* dan_total_keys_index[] = {mld_1dan_total_keys, mld_2dan_total_keys, mld_3dan_total_keys, mld_4dan_total_keys, mld_5dan_total_keys, mld_6dan_total_keys, mld_7dan_total_keys, mld_8dan_total_keys, mld_9dan_total_keys, mld_10dan_total_keys}; +``` + +后续接着往这个数组里面装指针即可。 + +基本的数据结构实现了,就可以开始研究一下算法,后续再录入数据吧。 + +## 算法实现 + +曾经听群友讲过这个东西核心理念是加权平均数,最近才学到,那就来看看怎么做这个平均数吧。 + +直接看原作者是怎么实现的 + +```js + function normal_calculation(accArr, noteArr) { + let score1 = accArr[0] + let temp1 = (noteArr[0] + noteArr[1]) * accArr[1] - noteArr[0] * accArr[0] + let score2 = temp1 / (noteArr[1]) + let temp2 = (noteArr[0] + noteArr[1] + noteArr[2]) * accArr[2] - (noteArr[0] + noteArr[1]) * accArr[1] + let score3 = temp2 / (noteArr[2]) + let temp3 = (noteArr[0] + noteArr[1] + noteArr[2] + noteArr[3]) * accArr[3] - (noteArr[0] + noteArr[1] + noteArr[2]) * accArr[2] + let score4 = temp3 / (noteArr[3]) + return [score1, score2, score3, score4] + } +``` + +第一首的ACC不变,这个不说了。 + +这个temp算的是什么??? + +刚刚去看了一下引用,accArr存放着四首的玩家成绩Acc,noteArr存着这四首歌的Note总数量。 + +还是没搞明白这个temp在干什么,看这段代码是真想骂街啊。 + +用1dan举例子,Note和ACC: +``` +813, 955, 907, 654 +99 98 96 94 +``` +~~叠批来了~~ + +Malody的每一个判定都有不同的权重,都有对应不同的Acc衰减,所以每一首歌曲结束后都是一个加权平均数。程序要做的事情就是逆推出原本的Acc。 + +所以`accArr`是一个累计加权平均值数组。 +`noteArr`是每批数据的权重。 +目标:计算每批数据的**独立加权平均值**。 + +### 数学逻辑 + +**第一批数据:** +```js +let score1 = accArr[0] +``` +直接使用第一个累计平均值a1,此时只有第一批数据。 + +**第二批数据:** +```js +let temp1 = (noteArr[0] + noteArr[1]) * accArr[1] - noteArr[0] * accArr[0] +let score2 = temp1 / noteArr[1] +``` + +- 累计平均值`a2 = (n1s1 +n2s2) / (n1 + n2)` +- 解得`s2`:`(n1 +n2)a2 - n1s1 / n2` +...... + +额...这一顿推导,给我也整不会了。我数学奇烂,那就用一个简明易懂的例子来理解吧。 + +### 人话 + +假设参加了4次考试 + +- 第一次考了80分(score1) +- 第二次的平均分是93.3(accArr[1]) +- 第三次的平均分是95(accArr[2]) +- 第四次的平均分是97.5(accArr[3]) + +但是你忘了每次考试的重要程度(权重): +- 第一次考试占10(noteArr[0] = 10) +- 第二次 20(noteArr[1] = 20) +- 第三次 30(noteArr[2] = 30) +- 第四次 40(noteArr[3] = 40) + +你想知道每次考试单独的平均分是多少 + +1. 第一次考试: + 直接用平均分(因为只有一次考试) +2. 第二次考试: + 先算总分:`前两次总分 = (10+20)*93.3 = 2800` + 减去第一次的分数:`第二次分数 = 2800 - 10 * 80 = 2000` + 第二次平均分: ``score2 = 2000 / 20 = 100`` +3. 第三次考试: + 总分:`(10 + 20 + 30 )*95 = 5700` + 减去前两次:`第三次分数 = 5700 - 2800` + 平均分:`score3 = 2900 / 30 ≈ 96.7` +4. 第四次考试 + 总分:`(10+20+30+40)*97.5 = 9750` + 减去前3次:`第四次分数 = 9750 - 5700 = 4050` + 平均分:`score4 = 4050 / 40 = 101.25` + +写着写着突然发现 +```c +typedef struct Dan +{ + // 四首歌的物量 + int* songs_total_keys; +} Dan; +``` +这个数据结构只需要一个数组。 + +人话说完了,该说说计算机的话了。 + +### 实现 + +```c +double *common_calc(int *total_keys, double *player_acc) +{ + // 权重:total_keys + // 分数:player_acc + // 返回的数组,保存计算完成的Acc + double *result = (double *)malloc(sizeof(double) * 4); + if (result == NULL) + { + printf("[ERROR] 内存分配失败!"); + return NULL; + } + + double song1_acc, song2_acc, song3_acc, song4_acc; + + // 第一首歌:直接取第一个累积平均值 + result[0] = player_acc[0]; + + // 第二首歌:((n0 + n1)*a1 - n0*a0) / n1 + double sum2 = total_keys[0] + total_keys[1]; + result[1] = (sum2 * player_acc[1] - total_keys[0] * player_acc[0]) / total_keys[1]; + + // 第三首歌:((n0 + n1 + n2)*a2 - (n0 + n1)*a1) / n2 + double sum3 = sum2 + total_keys[2]; + result[2] = (sum3 * player_acc[2] - sum2 * player_acc[1]) / total_keys[2]; + + // 第四首歌:((n0 + n1 + n2 + n3)*a3 - (n0 + n1 + n2)*a2) / n3 + double sum4 = sum3 + total_keys[3]; + result[3] = (sum4 * player_acc[3] - sum3 * player_acc[2]) / total_keys[3]; + + return result; +} +``` + +然后就是主函数处理用户输入了,没什么含金量,不水了。 diff --git a/content/posts/AI是现代自媒体的开塞露.md b/content/posts/AI是现代自媒体的开塞露.md new file mode 100644 index 0000000..086ec6c --- /dev/null +++ b/content/posts/AI是现代自媒体的开塞露.md @@ -0,0 +1,88 @@ +--- +date: '2025-11-22T21:06:49+08:00' +draft: false +title: '「创作者」们,用AI当开塞露' +slug: 'stop-pooping-with-ai' +categories: + - 随笔 +tags: + - AI + - 人工智能 + - 自媒体 + - 内容创作 +--- +AI是一个躲都躲不掉的话题,无论在哪里都能看到。我个人对这个话题兴趣不大,但最近发生了一件让我很不舒服的事,就借着这次机会谈谈AI创作的事。 + +--- +今天下午,我和我父亲聊天。他最近一直在看AI和自媒体有关的内容。比如Claude, 提示词优化等方面,想运营一个短视频帐号,用AI大量制作暴款视频带货盈利(主要聚焦个人成长、社交等方面)。这事跟我说主要是想找我提供所谓的「技术支持」,让我帮他部署模型、调试和维护。但有了今天这篇文章,就代表了我压根不想干。 + +虽然从理论上这么赚钱并非不可行,甚至已经有很多比较成熟的方案,你只要会打字,有一台能联网的设备就行。但仔细想想,还是能找出几个值得掰扯的点。 + +## 你能想到的为什么别人想不到? + +AI大规模普及后,写作、编程、绘画、甚至是作曲的门槛已经变得相当低,只要有语言组织能力,或许加上一点点财力,就能轻松用人工智能帮你完成「创作」。而这种「创作」的流程又进一步优化,已经有了很多基于AI的「创作」工作流,教你调教各种AI,优化提示词、写文章、写代码…… + +上次让某些领域有颠覆性改变的发明还是社交媒体,让每一个人都可以轻松发表自己的看法。而AI的出现让每一个人都能「创作」。 + + + + +**既然每一个人都能做,为什么商单会找上你**?千篇一律的文案风格、视频风格,甚至难以分辨彼此。内容同质化、低质化、模板化的大背景下怎样才能做到脱颖而出?内卷是永远不会停止的,借助AI做自媒体的门槛看似谁都能轻而易举地踏过去,实际上相当困难。 + +## 观众的被欺骗感 + +试着想象一下:你刷到的每一个视频背后,都是葛优躺在显示器前,复制粘贴大模型生成的文本,机械、重复、麻木地完成工作的那类人在制作,并且他们只需要两三分钟就可以生产出十分钟甚至更长的,看起来人模狗样的视频,而你要花费你宝贵的生命在大模型从互联网各处和语料拾来的牙慧上,你作何感受? + +无论是二十分钟甚至更长的科普视频,还是用手机和烂梗素材拼贴的短视频,背后都有**创作者**付出了时间和精力。无论质量的高低,**创作者**的**真心**是可触摸到的。每一字每一句,都闪耀着作者思想的光辉,而AI生成的文本,只是在数学上计算了每个字可能出现的概率,在用词里对用户加以谄媚,在结果上空有其表。他究竟代表着谁?你想让他代表谁,他就可以代表谁。一篇高中生的习作可以被AI捧到提名诺奖,而真正诺奖得主的作品,又可以被批判得一文不值。 + +使用AI批量生产内容,不仅是对观众的欺骗,更是对创作这一行为本身的背叛。AI背后的到底是作者,还是冷冰冰的数学与统计学程序?创作,最后不要沦为收手工「匠心费」的只能看,不能摸的工艺品了。 + +## 思考深度和逻辑能力缺失 + +在搜集资料时,我发现了这样的观点: + +>>从自身出发,更科学、更理性地对待AI创作时代,树立对自我创作的价值的全新认识。 +>> +>> 比如,从“我写的”转向“我发现的”。 +>> +>>比如,从“内容生产者”转型“内容想象者”。 +>> +>>比如,“表达自我”升级成“激发共鸣”。 +>> +>>…… +>> +>> **第三种,我把它称作“伪人性崇拜”,它其实是一种人类社会长久依赖就存在的反智倾向。** +>> +>>但是他们却忘了:海明威用打字机写作,并坚称打字机比用笔书写更凝练、更高效,也被同时代用钢笔、甚至羽毛笔创作的同行和文艺界人士们,揶揄、嘲讽,甚至批评,说他的作品充满机械的臭味,批判他从根本上是一个作风粗野,毫无历史上伟大作家们那种深邃的精神格调,也毫无优雅气质的“文痞”。 +>> +>>当电脑出现后,这种对机器创作的偏见就更明显了,“键盘的机械触感隔断人类灵魂的流淌,完全比不上笔在纸上的流畅书写的情感自然深刻”,类似这样的言论在当时老一批作家和读者中,流行了很长时间。 +>> +>>其实,今天当我们在星巴克用MacBook甚至是智能手机码字时,当我们随时通过搜索引擎,大大摆脱对个人知识储备和数据资料积累的依赖时,对以前的人们来说,何尝不是另一种“技术作弊”? +> +> —— [《为什么中国很多人见别人用AI的就崩了?AI写作歧视症:这个时代最挣扎的文化偏见》](https://zhuanlan.zhihu.com/p/28802794985)(后文简称《偏见》)[^1] + +郑永年认为短视频的崛起让中国进入了全民弱智的时代,那么AI的崛起,无疑是给这种形势火上浇油。如果短视频真的使全民弱智,那么滥用AI进行「创作」,并主张「树立对自我创作价值的全新认知」,就是让本就难以沉静的心更加浮躁:输入提示词、等待模型「思考」、获得输出。这个过程,从创作者自身的角度出发思考,他们得到了什么?打字速度和准确度的提升? + +《偏见》中探讨的「我发现的」与「我写的」实际上是一种包含关系:我发现 => 我写 => 我有收获。而不是:我发现 => AI想、AI写 => 我坐享其成。 + +第二条也同理,想象 => 设计 => 实践。这是生产的大过程。 + +而「表达自我」与「激发共鸣」,一定是「升级」的关系吗?甚至无法从中找到逻辑联系。两者可以共存,而且没有谁高谁低。 + +在引用《偏见》的第二段文本中,讨论了创作工具的偏见:纸笔、打字机、电脑。不管使用何种工具,「创作」的过程都是作者独立思考、独立撰写。而不是让他「人」代替创作者思考与撰写。 + +在我看来,AI的「深度思考」功能最具讽刺意味。主动放弃深度思考的权利、丧失深度思考的能力、当指挥AI思考的皇帝。这正是走向自我堕落的道路。 + +郑的观点可以再一次得到验证:谣言、仇恨、戾气的生产会更加易如反掌;长期滥用AI,思考和逻辑能力的缺失让它们更能猖獗释放。 + +## 滥用AI与善用AI + +既然如此,用AI就有罪么?技术本身是中性的,问题的根源在于使用技术的人和目的。 + +AI是搜索引擎的新形式,它有着人手无法匹敌的爬取信息能力;AI是学识渊博的良师,从文学问到物理,从心理学问到古汉语,在已经有丰富研究的非前沿领域有着强大的知识储备。将AI作为真正意义上的工具使用,而不是免费的外包员工,是有利于创作和创作者的明智行为。 + +例如,使用AI寻找灵感,讨论话题切入点、如何优化作品表现的手法。甚至写文章时,将AI作为对话式的词典使用、探讨几个近义词在同一语境下的表现效果;纠打字错误、校对文本等。所以,合理地使用AI能提高创作效率和质量,同时也能促进自己能力的提升,而非沦为八手文本的搬运工,在变现的利益诱惑下丧失了创作的本心。 + +使用技术的方式有很多种,但完全使用AI进行「创作」,还美其名曰「创作者」,究竟是当还是立,请自行明辩吧! + +[^1]: 这篇文章从手法上说,存在来源不明的数据和案例、不当类比、偷换概念等诡辩行为,如「某平台数据显示」、「72%的人会优先批判AI生成的文章」、「来自AI研究机构的最新数据表明」、02中谬误2的两个案例、谬误3 偷换AI本身情感与给人带来的情感波动的概念等。 diff --git a/content/posts/CSS鼠标指针操作.md b/content/posts/CSS鼠标指针操作.md new file mode 100644 index 0000000..f651111 --- /dev/null +++ b/content/posts/CSS鼠标指针操作.md @@ -0,0 +1,32 @@ +--- +abbrlink: 3385388897 +categories: + - 往昔 +cover: ./cover.jpg +date: "2025-03-04 10:13:10" +tags: +- 前端 +title: CSS鼠标指针操作 +--- + +今天在上网冲浪的时候,看到Github上有一个明日方舟风格的[主题](https://github.com/Yue-plus/hexo-theme-arknights),这个主题让我感到新鲜的一点是网页中的鼠标指针特效 + +这么舒服的动画效果我必须也要做一个,说干就干,新建个HTML文档。 + +```css +* { + cursor: pointer; +} +``` + +这样,我们整个网页的鼠标指针样式就都变成了小手指的样式,不过这样还是太丑,我们仿照arknights主题的样式,打开PS,画一个指针图标出来看看 + +使用url()属性可以替换自己的素材图片 + +```css +* { + cursor: url("./source/cu.ico"), auto; +} +``` + +这样鼠标指针的效果就做好了(因为我的截图软件要用鼠标指针选区,所以截不到图) diff --git a/content/posts/C语言下的二进制文件IO.md b/content/posts/C语言下的二进制文件IO.md new file mode 100644 index 0000000..b63cc7e --- /dev/null +++ b/content/posts/C语言下的二进制文件IO.md @@ -0,0 +1,69 @@ +--- +date: "2025-07-12T00:26:59+08:00" +draft: false +categories: +- 往昔 +slug: "" +title: C语言下的二进制文件IO踩坑 +--- + +C语言下的二进制文件读写有个坑,就是一定要按存储的顺序读取。例: +```c +typedef struct player { + int id; + double XP; + double MP; +}player; +``` + +这里有一个玩家的数据结构,我们创建变量并初始化。 + +```c +int b_i[32] = {1, 233, 2453, 5432, 21 ,43 ,297, 752, 643}; +player yingyu5658; +yingyu5658.MP = 100; +yingyu5658.XP = 100; +yingyu5658.id = 114514; +``` + +对文件进行存储时,按照MP=>XP=>ID的顺序存储 +```c +pd = fopen("./data", "wb"); +fwrite(&yingyu5658.MP, sizeof(double), 1, pd); +fwrite(&yingyu5658.XP, sizeof(double), 1, pd); +fwrite(&yingyu5658.id, sizeof(int), 1, pd); +``` + +读取的时候一定要按照这个顺序,否则读取出来的内容是无效的。 + +```c +int id; +double XP, MP; +pd = fopen("./data", "rb"); +fread(&MP, sizeof(double), 1, pd); +fread(&XP, sizeof(double), 1, pd); +fread(&id, sizeof(int), 1, pd); +player new_player; +new_player.id = id; +new_player.XP = XP; +new_player.MP = MP; +printf("id: %d\n", new_player.id); +printf("XP: %f\n", new_player.XP); +printf("MP: %f\n", new_player.MP); +``` + +运行结果: +``` +写入了id: 114514 +写入了XP: 100.000000 +写入了MP: 100.000000 + +id: 114514 +XP: 100.000000 +MP: 100.000000 +``` + +使用完也要关闭流,否则资源泄漏 +```c +fclose(pd); // 必须显式关闭 +``` diff --git a/content/posts/C语言实现简易Shell.md b/content/posts/C语言实现简易Shell.md new file mode 100644 index 0000000..30b8a07 --- /dev/null +++ b/content/posts/C语言实现简易Shell.md @@ -0,0 +1,83 @@ +--- +categories: +- 往昔 +date: "2025-07-10T00:09:36+08:00" +draft: false +title: C语言实现简易Shell +--- + +实现一个Shell,需要的功能有: +- 循环读取用户输入 +- 输出提示符 +- 创建子进程执行命令 +- 等待回收子进程 + +shell中的大多数命令都是通过创建子进程来执行的,可以使用`fork()`创建子进程,然后替换主进程执行命令。 +创建 +常用函数原型 +```c +pid_t fork(void); // pid_t是int类型 +pid_t get_pid(); // 获取当前进程pid +pid_ getppid(); // 获取当前进程的父进程值 +``` + + +`fork()`用于创建创建一个进程,所阐明的进程复制父进程的代码段/数据段/BSS段/等所有用户空间信息,在内和中操作系统重新为其申请了一个PCB,并使用父进程的PCB初始化。 + +实现fork()子进程替换为命令子进程, 最佳的进程替换的接口是`exevp()` + +在创建子进程前,我们需要解析传递给shell的参数 + +使用`strtok()`对command以空格进行分割,所以显而易见地,得到的结果数组中,第0位是命令名称,后面全部都是选项。 + +使用`waitpid()`等待子进程,`fork()`获取的子进程id可以用于制定回收子进程。 + +```c +#include <pwd.h> +#include <sys/wait.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <unistd.h> + +#define MAX_COMMAND_SIZE 256 + +int main() +{ + char *command_argv[MAX_COMMAND_SIZE]; + char command[MAX_COMMAND_SIZE]; + memset(command, '\n', MAX_COMMAND_SIZE); + const char* user_name = getlogin(); + while(1) + { + printf("[%s@EazyShell]$ ", user_name); + fgets(command, MAX_COMMAND_SIZE, stdin); + command[strcspn(command, "\n")] = '\0'; // 去掉末尾的换行符 + // 分割命令行,一个空格为一项子命令或参数 + command_argv[0] = strtok(command," "); + int index = 1; + while(command_argv[index++] = strtok(NULL, " ")); + + // 创建子进程,并进程替换 + pid_t id = fork(); + if(id == 0) + { + // 进程替换 + execvp(command_argv[0], command_argv); + return -1; // 失败则退出-1 + } + + // 父进程回收子进程 + int status = 0; + pid_t ret = waitpid(id, &status, 0); + if (ret = 0) + { + printf("父进程成功回收子进程, exit_code: %d, exit_sig: %d\n", WEXITSTATUS(status), WTERMSIG(status)); + } + } + + return 0; +} +``` + +这个程序的健壮性和内存布局还有待优化,但只是一个简易的shell,用于理解它的工作原理,这就够了。 diff --git a/content/posts/C语言的可变参数.md b/content/posts/C语言的可变参数.md new file mode 100644 index 0000000..636ec4f --- /dev/null +++ b/content/posts/C语言的可变参数.md @@ -0,0 +1,121 @@ +--- +abbrlink: 188975074 +categories: +- 往昔 +date: "2025-07-05 18:32:52" +tags: +- C语言 +- 编程 +title: C语言的可变参数 +--- + +## 介绍 + +C语言中,`printf()`和`scanf()`函数就是典型的变参函数,其优点是灵活处理参数。 + +想要创建变参函数需引入头文件`stdarg.h`,它有一些宏: + +``` +va_list 指向整个可变参数列表的指针 +原型:typedef char* va_list; + +va_start 指向可变参数列表前的参数(...前的参数) +原型:void va_start(va_list ap, paramN); + +va_arg 可变参数列表 +原型:typedef va_arg(va_list ap, type) + +va_end 结束对可变参数列表的访问,并释放资源 +原型:void va_end(va_list ap); +``` + +## 使用例 + +```c +#include <stdio.h> +#include <stdarg.h> + + +// 定义一个使用省略号的函数原型 +void function(int argument, ...) +{ + // 声明一个va_list类型的变量ap,这是可变参数列表 + va_list ap; + + // 使用va_start把变量ap初始化为参数列表 + va_start(ap, argument); + + // 第二个参数表明本函数期望传入一个int类型 + // 但是编译器不会检查到底输入了什么。 + int output = va_arg(ap, int); + + printf("可变参数:%d\n", output); + + va_end(ap); +} + + +int main() +{ + function(1, 109); +} +``` + +输出: + +``` +可变参数:109 +``` + +函数起了作用,但是如果我们需要接受多个参数,应该如何获取呢? + +```c +#include <stdio.h> +#include <stdarg.h> + + +// 定义一个使用省略号的函数原型 +void function(int argument, ...) +{ + // 声明一个va_list类型的变量ap,这是可变参数列表 + va_list ap; + + // 使用va_start把变量ap初始化为参数列表,此处的第二个参数是最后一个固定参数 + va_start(ap, argument); + + // 第二个参数表明本函数期望传入一个int类型 + // 但是编译器不会检查到底输入了什么。 + + int arguments_list[4]; + + for(int i = 0; i < 4; i++) { + arguments_list[i] = va_arg(ap, int); // 按int类型提取参数 + } + + va_end(ap); + + // 遍历参数列表并打印 + for (int i = 0; i < 4; i++) { + printf("可变参数%d:%d\n", i + 1, arguments_list[i]); + } + +} + + +int main() +{ + function(1, 10, 12, 2, 111); +} +``` + + + +## 扩展:`va_start`的第二个参数的工作原理 + +`va_start`的第二个参数用于定位可变参数列表的起始位置,具体而言,它指向函数参数列表中最后一个固定参数(即省略号前的参数),通过该参数的地址计算出第一个可变参数在内存中的位置。 + +C函数的参数按从右至左顺序入栈(栈底高地址,栈顶低地址) + +`va_start`的第二个参数作为基准点,其地址加上自身大小后,即指向第一个可变参数的起始地址。 + +所以`...`前至少要有一个固定参数用于寻址。 diff --git a/content/posts/C语言的头文件与OOP范式的抽象类、接口的异同点.md b/content/posts/C语言的头文件与OOP范式的抽象类、接口的异同点.md new file mode 100644 index 0000000..f0c212b --- /dev/null +++ b/content/posts/C语言的头文件与OOP范式的抽象类、接口的异同点.md @@ -0,0 +1,46 @@ +--- +abbrlink: 3508058237 +categories: +- 往昔 +date: "2025-06-06 20:16:56" +tags: +- C语言 +title: C语言的头文件与OOP范式的抽象类、接口的异同点 +--- +## 引言 + +说真的,从去年十一月份开始接触编程,到现在也好几个月了,自认为进步速度较快,但速度快也就导致了深度浅,走马观花式的学习,现在还是有很多理解不深刻的点,今天来仔细研究一下这个问题。我也是先入为主,第一门编程语言学的是Java,所以再接触C,一些概念就混淆了。 + +## C语言模块化设计的核心 + +头文件本质是对外提供的接口**契约**,包含函数声明、宏定义、结构体类型声明。例如: +```c +// math_utils.h +#ifndef MATH_UTILS_H +#define MATH_UTILS_H +int add(int a, int b); // 函数声明 +#endif +``` + +- 编译隔离:通过头文件守卫(#ifndef)实现模块之间的编译隔离。 +- 虽然头文件可以实现函数,但这会破坏模块化。 + +### 模块化实现规范 + +- 源文件承载具体实现,通过包含对应头文件实现联系 +- 模块间通过`extern`关键字声明共享全局变量(谨慎使用) + +## 面向对象中的抽象机制 + +抽象类可以包含部分实现,它的目的是:**描述一个公共基类,有共同的特征,有部分方法实现,但另一部分依赖子类自行实现**。 + +接口是一系列方法的声明,一个接口就是在描述一种能力。 + +设计目标上,抽象类为了代码复用+多台,而接口是行为契约。 + +## 设计范式对比 + +### C模块化 vs OOP抽象 + +- 抽象粒度:C模块关注功能单元(做什么),而OOP抽象关注对象行为契约(是谁做什么) +- 扩展方式:C通过函数指针传递上下文,OOP通过继承、实现扩展。 diff --git a/content/posts/Electron-CommonJS-require踩坑.md b/content/posts/Electron-CommonJS-require踩坑.md new file mode 100644 index 0000000..de0388f --- /dev/null +++ b/content/posts/Electron-CommonJS-require踩坑.md @@ -0,0 +1,53 @@ +--- +abbrlink: 472869193 +categories: +- 往昔 +date: "2025-05-31T09:07:36+08:00" +tags: +- 前端 +- Electron +title: Electron CommonJS require踩坑 +--- +最近在开发一个Electron项目,在导入类的时候有以下报错: +``` +node:internal/modules/cjs/loader:1411 Uncaught Error: Cannot find module './File' +Require stack: +- E:\Develop\markdown-editor\src\html\index.html + at Module._resolveFilename (node:internal/modules/cjs/loader:1408:15) + at a._resolveFilename (node:electron/js2c/renderer_init:2:2643) + at defaultResolveImpl (node:internal/modules/cjs/loader:1064:19) + at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1069:22) + at Module._load (node:internal/modules/cjs/loader:1218:37) + at c._load (node:electron/js2c/node_init:2:17950) + at s._load (node:electron/js2c/renderer_init:2:31718) + at TracingChannel.traceSync (node:diagnostics_channel:322:14) + at wrapModuleLoad (node:internal/modules/cjs/loader:242:24) + at Module.require (node:internal/modules/cjs/loader:1494:12) +``` +提示找不到模块。 + +Electron中,使用require语句导入,都是默认从项目跟目录开始查找,所以要拼接完整路径。使用绝对路径也是不行的,在IDE里可以跳转,但是一运行就是找不到模块 +`const File = require("src/js/File")` + +``` +Uncaught Error: Cannot find module 'src/js/File' +Require stack: +- E:\Develop\markdown-editor\src\html\index.html + at Module._resolveFilename (node:internal/modules/cjs/loader:1408:15) + at a._resolveFilename (node:electron/js2c/renderer_init:2:2643) + at defaultResolveImpl (node:internal/modules/cjs/loader:1064:19) + at resolveForCJSWithHooks (node:internal/modules/cjs/loader:1069:22) + at Module._load (node:internal/modules/cjs/loader:1218:37) + at c._load (node:electron/js2c/node_init:2:17950) + at s._load (node:electron/js2c/renderer_init:2:31718) + at TracingChannel.traceSync (node:diagnostics_channel:322:14) + at wrapModuleLoad (node:internal/modules/cjs/loader:242:24) + at Module.require (node:internal/modules/cjs/loader:1494:12) +``` + +## 解决方法 +使用path.join拼接完整路径 +```js +const File = require(path.join(__dirname, "../js/File.js")); +``` +经过测试,只能用这种方法导入,太怪了 diff --git a/content/posts/Emacs-EAF插件打开浏览器只显示opening-http-xxx-xxx的解决方法.md b/content/posts/Emacs-EAF插件打开浏览器只显示opening-http-xxx-xxx的解决方法.md new file mode 100644 index 0000000..e3dfb40 --- /dev/null +++ b/content/posts/Emacs-EAF插件打开浏览器只显示opening-http-xxx-xxx的解决方法.md @@ -0,0 +1,21 @@ +--- +abbrlink: 717508352 +categories: +- 往昔 +date: "2025-04-29 10:02:49" +tags: +- Emacs +- Linux +title: Emacs EAF插件打开浏览器只显示opening http://xxx.xxx的解决方法 +--- +检查是否安装全部依赖,如yay、pip等。我这里是由于没有安装pip导致的。 + +`sudo pacman -S python-pip` + +安装好后,进入eaf安装目录 + +`cd ~/.emacs.d/site-lisp/emacs-application-framework && ./install-eaf.py` + +重新安装eaf。等待脚本运行完成,打开emacs,输入`M-x eaf-install-and-update`,等待执行完成。 + +重新输入`M-x eaf-open-browser`,输入网址,即可正常访问网页。 diff --git a/content/posts/Emacs配置记录-2——C-C++环境配置.md b/content/posts/Emacs配置记录-2——C-C++环境配置.md new file mode 100644 index 0000000..2d5b855 --- /dev/null +++ b/content/posts/Emacs配置记录-2——C-C++环境配置.md @@ -0,0 +1,116 @@ +--- +abbrlink: 24667834 +categories: +- 往昔 +date: "2025-06-04 18:58:37" +tags: +- Emacs +- Linux +title: Emacs配置记录 2——C/C++环境配置 +--- +## 前言 + +经过[上一篇]()的简单调教,Emacs已经勉强变成了一个温顺的文本编辑器,但是离写代码这个宏大的目标还是有一段距离的,今天来解决主要问题:代码补全。由于我要写一点简单的C代码,那么重点就先放到C/CPP环境搭建中。 + +站在巨人的肩膀上,在Emacs中的代码补全使用巨硬的LSP协议。 + +## Spacemacs + +经过考虑,我还是决定使用Spacemacs,比起原版Emacs,它更适合新手,也更能快速投入开发。避免配置陷阱,过多把时间花在刀把上。唉,也就是说,昨天大部分都白干了。算了,生命的意义就在于折腾,怕折腾我也不会玩Emacs了。来吧! + +先来安装一下Spacemacs。 +`git clone https://github.com/syl20bnr/spacemacs ~/.emacs.d` + +重启Emacs,让他下载一下自带的包。 + +上次没清理干净Spacemacs,不知道存在哪的备份还在,算是免去了一些折腾吧。来看看现在的Emacs都配置了什么。 +```lisp + dotspacemacs-configuration-layers + '(yaml + markdown + javascript + (auto-completion :variables + auto-completion-idle-delay 0.01 ; 降低补全延迟 + auto-completion-minimum-prefix-length 1) + (prettier :variables + prettier-always-enable t) ; 保存时自动格式化 + (javascript :variables + javascript-backend 'lsp ; 启用LSP后端 + javascript-fmt-tool 'prettier) ; 格式化工具选Prettier + (c-c++ :variables + c-c++-backend 'lsp-clangd) ; C/C++使用Clangd后端 + (vue :variables + vue-backend 'lsp) ; Vue使用LSP后端 + (html) ; HTML/CSS支持 + (lsp) ; 必须的LSP核心支持层 + (auto-completion) ; 自动补全 + (syntax-checking) ; 语法检查 + ;; ---------------------------------------------------------------- + ;; Example of useful layers you may want to use right away. + ;; Uncomment some layer names and press `SPC f e R' (Vim style) or + ;; `M-m f e R' (Emacs style) to install them. + ;; ---------------------------------------------------------------- + ;; auto-completion + ;; better-defaults + emacs-lisp + treemacs + ;; git + helm + lsp + ;; markdown + multiple-cursors + ;; org + ;; (shell :variables + ;; shell-default-height 30 + ;; shell-default-position 'bottom) + ;; spell-checking + ;; syntax-checking + ;; version-control + treemacs) +``` +emmm,还是有点有用的。比如C/C++这里,就启用了LSP。还有一些之前搞的前端配置。就是不知道为啥,JavaScript的补全不太好使。 + +## 语法检查 + +语法检查,选择当前比较成熟的flycheck,在Spacemacs中对应`syntax-checking`,在.spacemacs中的`dotspacemacs-configuration-layers`写入`(configuration-layer/declare-layer 'syntax-checking)` + 该层会自动集成Flycheck及其常见语言的后端支持。 + +C/C++要安装`clang-tidy`或`cppcheck`。 + +### 进阶配置 + +```lisp + (with-eval-after-load 'flycheck + (setq flycheck-check-syntax-automatically '(save mode-enabled) ;; 保存时检查 + flycheck-display-errors-delay 0.5 ;; 错误显示延迟 + flycheck-indication-mode 'right-fringe)) ;; 错误标记位置 +``` + + +## [.spacemacs 文件基本介绍](https://liuzhijun-source.github.io/spacemacs-14-days/#/Week01/Day05/day05_spacemacs%E7%9A%84%E8%BF%9B%E9%98%B6%E9%85%8D%E7%BD%AE_%E4%B8%8A?id=spacemacs-%e6%96%87%e4%bb%b6%e5%9f%ba%e6%9c%ac%e4%bb%8b%e7%bb%8d) + +.spacemacs 文件一般会自动生成在主目录下,这个文件是配置 Spacemacs 的入口,有关于 Spacemacs 本身的配置基本都能在里面进行修改,用户设置同样在这个文件中修改。 + +.spacemacs 中,内容一般被分为以下几个部分,每个部分都封装在一个函数中: + +- `dotspacemacs/layers` + +在这里可以声明一些 layer,以及删除、增添一些包,在这里还可以调整 Spacemacs 加载时的一些行为 + +- `dotspacemacs/init` + +Spacemacs 绝大部分的配置都位于此,你可以在此修改配置中可选的选项,但绝对不能将自己的用户配置代码添加在这里 + +- `dotspacemacs/user-init` + +这里的内容会在 Emacs 启动前开始加载,一般在这里设置你需要使用的 elpa 源,你应该尽量把用户配置放在 `dotspacemacs/user-config` 中 + +- `dotspacemacs/user-config` + +在这里可以添加你的用户配置代码,你自己的定义的大部分配置一般都在这里完成 + +- `dotspacemacs/emacs-custom-settings` + +Spacemacs 自己生成的配置,同样不建议自己去修改 + +> 摘自[Spacemaccs 14 Days](https://liuzhijun-source.github.io/spacemacs-14-days/#/Week01/Day05/day05_spacemacs%E7%9A%84%E8%BF%9B%E9%98%B6%E9%85%8D%E7%BD%AE_%E4%B8%8A) diff --git a/content/posts/Emacs,我又回来了!.md b/content/posts/Emacs,我又回来了!.md new file mode 100644 index 0000000..a3c8076 --- /dev/null +++ b/content/posts/Emacs,我又回来了!.md @@ -0,0 +1,77 @@ +--- +date: '2025-11-01T12:01:12+08:00' +draft: false +title: 'Emacs,我又回来了!' +slug: 'emacs-i-am-back' +categories: + - 往昔 +tags: + - Emacs + - GNU/Linux +--- +## 前言 + +这大概已经是我第四次尝试入门 Emacs 了。 + +前几次尝试过自己重新配置 Emacs、Spacemacs。自己配置简直是在堆屎山, Spacemacs 的机制搞不明白而且很卡,听说[Doom Emacs](https://github.com/doomemacs/doomemacs) 对 Vi/Vim 用户很友好,那就尝试一下吧! + +虽然我不能算是个老 Vimer,但是也深受 Vim 操作模式的荼毒,只想用 HJKL 走天下。之前也想玩 Obsidian 。但是**它的 Vim mode 实在是太简陋了!!!** C-d不是向下翻页,而是把整行都删掉! + +不过手机上的 Ob 还是可以一用,比如 Banyan 插件,用来随时随地写一些碎碎念很方便。至于其他的功能,还是配 Emacs 更好玩吧。 + +## 安装 + +根据官方仓库的文档,使用以下命令安装: + +```bash +git clone --depth 1 https://github.com/doomemacs/doomemacs ~/.config/emacs +~/.config/emacs/bin/doom install +``` + +速度比我想象中的要快得多,而且是交互式操作,感觉比 Spacemacs 友好一点?~~这个脚本的输出有一股 Cargo 味……~~ + +安装结束后给了一点提示: + +``` +But before you doom yourself, here are some things you should know: + +1. Don't forget to run 'doom sync' and restart Emacs after modifying init.el or + packages.el in ~/.config/doom. This is never necessary for config.el. + +2. If something goes wrong, run `doom doctor` to diagnose common issues with + your environment, setup, and config. + +3. Use 'doom upgrade' to update Doom. Doing it any other way will require + additional steps (see 'doom help upgrade'). + +4. Access Doom's documentation from within Emacs via 'SPC h d h' or 'C-h d h' + (or 'M-x doom/help'). + +Have fun! +``` + +其中提到了一个叫**doom**的命令,这是一个在`~/.emacs.d/bin/`下的二进制文件,可以做个链接到`/usr/bin`以便在任何地方使用。 + +```bash +sudo ln -s ~/.emacs.d/bin/doom /usr/bin/doom +``` + +## 配置 + +启动时全屏: + +```elisp +(add-hook 'window-setup-hook #'toggle-frame-maximized) +``` + +安装 [Eaf](https://github.com/emacs-eaf/emacs-application-framework) 插件: + +``` +git clone --depth=1 -b master https://github.com/emacs-eaf/emacs-application-framework.git ~/.emacs.d/site-lisp/emacs-application-framework/ + +cd emacs-application-framework +chmod +x ./install-eaf.py +./install-eaf.py +``` + +用用看吧,后续有什么需求再折腾。 diff --git a/content/posts/Java小程序之两数计算器.md b/content/posts/Java小程序之两数计算器.md new file mode 100644 index 0000000..2e7c415 --- /dev/null +++ b/content/posts/Java小程序之两数计算器.md @@ -0,0 +1,112 @@ +--- +abbrlink: 3073696125 +author: yingyu5658 +categories: +- 往昔 +cid: 90 +cover: images\2024\12\2743265221.jpg +customSummary: null +date: "2024-11-30 18:51:07" +layout: post +mathjax: auto +noThumbInfoEmoji: null +noThumbInfoStyle: default +outdatedNotice: false +parseWay: auto +reprint: standard +slug: 90 +status: publish +tags: +- Java +thumb: null +thumbChoice: default +thumbDesc: null +thumbSmall: null +thumbStyle: default +title: Java小程序之两数计算器 +--- + + +这个案例是我练习方法的使用时做的,应该能有更好的方式实现这个功能。 +代码如下 +```java + +import org.w3c.dom.ls.LSOutput; + +import java.util.Scanner; + +public class Basic { + public static void main(String[] args) { + for (; ; ) { + + + System.out.println("欢迎使用!"); + System.out.println("按键1 2 3 4分别为加 减 乘 除,输入后请回车"); + Scanner startSc = new Scanner(System.in); + int selectNumber = startSc.nextInt(); + if(selectNumber >4) { + System.out.println("请输入正确的数字以选择!"); + } + //以下为加法 + if (selectNumber == 1) { + System.out.println("请输入您要计算的第一个数字"); + Scanner jiafaSc = new Scanner(System.in); + int jiafa1 = jiafaSc.nextInt(); + System.out.println("请输入您要计算的第二个数字"); + int jiafa2 = jiafaSc.nextInt(); + jiafa(jiafa1, jiafa2); + } + //以下为减法 + if (selectNumber == 2) { + System.out.println("请输入您要计算的第一个数字"); + Scanner jianfaSc = new Scanner(System.in); + int jianfa1 = jianfaSc.nextInt(); + System.out.println("请输入您要计算的第二个数字"); + int jianfa2 = jianfaSc.nextInt(); + jianfa(jianfa1, jianfa2); + } + //以下为乘法 + if (selectNumber == 3) { + System.out.println("请输入您要计算的第一个数字"); + Scanner chengfaSc = new Scanner(System.in); + int chengfa1 = chengfaSc.nextInt(); + System.out.println("请输入您要计算的第二个数字"); + int chengfa2 = chengfaSc.nextInt(); + chengfa(chengfa1, chengfa2); + } + if (selectNumber == 4) { + System.out.println("请输入您要计算的第一个数字"); + Scanner chufaSc = new Scanner(System.in); + int chufa1 = chufaSc.nextInt(); + System.out.println("请输入您要计算的第二个数字"); + int chufa2 = chufaSc.nextInt(); + chufa(chufa1, chufa2); + } + System.out.println("-----------------------------------------"); + } + } + //加减乘除各项功能的方法,上面直接调用 + public static int jiafa(int a, int b) { + int jieguo = a + b; + System.out.println(jieguo); + return a + b; + } + + public static int jianfa(int a, int b) { + int jieguo = a - b; + System.out.println(jieguo); + return a - b; + } + + public static int chengfa(int a, int b) { + int jieguo = a * b; + System.out.println(jieguo); + return a * b; + } + + public static int chufa(int a, int b) { + int jieguo = a / b; + System.out.println(jieguo); + return a / b; + } +} diff --git a/content/posts/Java方法的传参原理.md b/content/posts/Java方法的传参原理.md new file mode 100644 index 0000000..98824ce --- /dev/null +++ b/content/posts/Java方法的传参原理.md @@ -0,0 +1,102 @@ +--- +abbrlink: 1642973481 +author: yingyu5658 +categories: +- 往昔 +cid: 95 +cover: images\2024\12\2743265221.jpg +customSummary: null +date: "2024-11-30 20:14:00" +layout: post +mathjax: auto +noThumbInfoEmoji: null +noThumbInfoStyle: code +outdatedNotice: false +parseWay: auto +reprint: standard +slug: 95 +status: publish +tags: +- Java +thumb: null +thumbChoice: default +thumbDesc: null +thumbSmall: null +thumbStyle: default +title: Java方法的传参原理 +updated: 2024/12/07 10:56:51 +--- + + +## Java方法的参数传递机制-基本类型 +值传递 +### 值传递是什么 +在传输实参给方法的形参的时候,**传输的是实参变量中存储的副本** +说人话,把实参里面的东西赋值了一部分扔了给形参 +## 值传递具体理解案例 +```java +public class prameter { + public static void main(String[] args) { + int a = 10; //定义一个int变量a赋值为10 + change(a); //调用change方法 + System.out.println("main" + a); //打印mian a中的值 + } + +//这里开始写方法 + public static void change(int a){ + System.out.println("change1" + a); //打印方法中a的值 + a = 20; + System.out.println("change2"a); //打印赋值后a的值 + } +} +``` +我们运行以后,控制台输出的结果为 +``` +change1 10 +change2 20 +main 10 +``` +## 为什么main中打印的不是赋值后的20? +这就要提到刚才的概念:**值传递** +我们定义了一个变量``a = 10;``,在方法中``public static void change(int a)`` +由于**值传递**,也就是把值复制了一分传给方法,所以我们方法里用的值永远都是刚刚定义的``int a = 10;``,所以``change(a); = change(10);`` +我们后面再赋值,打印出来的结果还是10,除非你把变量定义的代码改了,否则方法里的值不会变。 + + +## 引用类型的参数传递 +引用类型的参数传递也满足值传递,但代码中会有不同的地方。 +示例代码 +```java + public static void main(String[] args) { + int[] arrs = new int[]{10,20,30}; + change(arrs); + System.out.println("main" + arrs[1]); + } + public static void change(int[] arrs) { + System.out.println("方法内1" + arrs[1]); + arrs[1] = 222; + System.out.println("方法内2" + arrs[1]); + } +``` +结果: +``` +方法内1:20 +方法内2:222 +main:222 +``` +上一篇文章提到了栈内存的执行顺序,根据上一篇所讲,代码执行顺序如下: +1.先执行 +```java + public static void change(int[] arrs) { + System.out.println("方法内1" + arrs[1]); + arrs[1] = 222; + System.out.println("方法内2" + arrs[1]); + } +``` +2.再回到main方法 +```java + System.out.println("main" + arrs[1]); +``` +在1时进行打印,结果得到数组内第二个位置存储的20. +代码继续向下执行,第二个位置被赋值为222,此时再打印它,结果得到222. +这时候change方法执行完,它在栈内存中会被清除,然后回到main方法,由于刚才change方法中对arr[1]进行了赋值,所以我们再打印,结果得到的还是它赋值出来的222. diff --git a/content/posts/Java方法的基本使用.md b/content/posts/Java方法的基本使用.md new file mode 100644 index 0000000..1aab77a --- /dev/null +++ b/content/posts/Java方法的基本使用.md @@ -0,0 +1,80 @@ +--- +abbrlink: 3033809787 +author: yingyu5658 +categories: +- 往昔 +cid: 89 +cover: images\2024\12\2743265221.jpg +customSummary: null +date: "2024-11-29T20:45:20+08:00" +layout: post +mathjax: auto +noThumbInfoEmoji: null +noThumbInfoStyle: default +outdatedNotice: "no" +parseWay: auto +reprint: standard +slug: 89 +status: publish +tags: +- Java +thumb: null +thumbChoice: default +thumbDesc: null +thumbSmall: null +thumbStyle: default +title: Java方法的基本使用 +updated: 2024/11/29 20:46:17 +--- + + + + +# 方法是什么 + +方法是一种语法结构,它可以把代码封装成一段功能,以便重复调用。 + +方法的完整格式: + +例子:数字求和 + +```java + public static int sum(int a,int b){ + int c = a + b; + return c; + } +``` + +方法的调用: + +```java + int rs= sum(10,20); +``` + +## 方法使用的注意点: + +方法申明了具体的返回值类型,内部必须使用return返回对应类型的数据。 + +形参列表可以有多个,甚至可没有;如果有多个形参,必须用英文逗号隔开,且不能给初始化值 + +## 使用方法的好处 + +- 提高代码的复用性,提高了开发效率 +- 让程序逻辑性更清晰 + +## 方法的其他定义形式 + +```java + public static void printHelloWorld(int n) { + for (int i = 1; i <=n; i++) { + System.out.println("Hello World"); + } + } +//打印三行helloworld(使用方法) +``` + + + +- 如果方法不需要返回数据,返回类型必须申明成``void``此时方法内部可以不使用return返回数据。 +- 方法如果不需要接收数据,则不需要定义形参,调用方法时也不可以传数据给方法了。 +- 没有参数,且没有返回类型(void)申明的方法,称为**无参数、无返回值的方法** diff --git a/content/posts/Java面向对象编程——多态、抽象类、接口.md b/content/posts/Java面向对象编程——多态、抽象类、接口.md new file mode 100644 index 0000000..1581584 --- /dev/null +++ b/content/posts/Java面向对象编程——多态、抽象类、接口.md @@ -0,0 +1,79 @@ +--- +CopyRight: true +NoCover: true +ShowReward: false +ShowToc: show +abbrlink: 2251989209 +author: yingyu5658 +categories: +- 往昔 +cid: 186 +cover: images\2024\12\2743265221.jpg +date: "2025-01-10 15:05:00" +desc: null +keywords: null +layout: post +showTimeWarning: true +slug: 186 +status: publish +summaryContent: null +tags: +- Java +thumb: null +title: Java面向对象编程——多态、抽象类、接口 +updated: 2025/01/10 15:06:08 +--- + + +## 什么是多态 +- 在继承/实现情况下的一种现象,表现为:对象多态、行为多态。 +### 多态的前提 +- 有**继承/实**现关系;存在父类引用子类对象;**存在方法重写** +- ## 多态的注意事项 +- 多态是对象、行为的多态,成员变量不体现多态。 + +<!--more--> + +## 使用多态的好处 +- 在多态形式下,右边的对象是解耦合的,更便于拓展和维护。 +- 定义方法时,使用父类类型的形参,可以接收一切子类对象,扩展性更强、更便利。 +## 多态下产生的一个问题 +- 多态下不能使用子类的独有功能。 +### 多态下的类型转换 +- 自动类型转换:`父类 变量名 = new 子类();` +- 强制类型转换: `子类 变量名 = (子类)父类变量` +### 强制类型转换的注意事项 +- 存在继承/实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错。 +- 运行时,如果发现对象的真实类型与强转后的类型不同,就会报类型转换异常(ClassCastException) +#### 强转前,Java建议: +- 使用instanceof关键字,判断当前对象的真是类型,再进行强制类型转换。 + +## final +- final关键字的中文是最终的意思,可以修饰类、方法、变量 + - 修饰类:该类被称为最终类,特点是不能被继承了。 + - 修饰方法:该方法被称为最终方法,特点是不能被重写了。 + - 修饰变量:该变量只能被赋值一次。 +## 常量 +- 使用了static final 修饰的成员变量就被称为常量; +- 作用:通常用于记录系统的配置信息。 +- **注意:常量的命名规范:使用大写英文单词,多个单词使用下划线连接起来。** +### 视同常量记录系统配置信息的优势、执行原理 +- 代码可读性更好、可维护性也更好。 +- 程序编译后,常量会被宏替换:出现常量的地方全部会被替换成其记住的字面量,这样可以保证使用常量和直接用字面量的性能是一样的。 + +## 抽象类 +### 什么是抽象类 +- Java中有个关键字叫abstract,他就是抽象的意思,可以用来修饰类、成员方法 +- abstract修饰类,这个就是抽象类,修饰成员方法同理。 +### 抽象类的注意事项、特点 +- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类。 +- 类该有的成员(成员变量、方法、构造器)抽象类都可以有。 +- **抽象类最主要的特点:** 抽象类不能创建对象,仅作为一种特殊的父类,让子类继承并实现。 +- 一个类继承抽象类,必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。 +### 抽象类的使用场景和好处 +- 父类知道每个子类都要做某个行为,但每个子类做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,我们设计这样的抽象类,就是为了更好的支持多态。~~爸爸画饼儿子烙饼~~ +## 接口 +### 接口概述 +- Java提供了一个关键字interface,用这个关键字我们可以定义出一个特殊的结构:接口。 +- 注意:接口不能创建对象;接口是用来被类实现(implements)的,实现接口的类被称为实现类。 +- 一个类可以实现多个接口,实现类实现多个接口必须重写完全部接口的全部抽象方法,否则实现类需要定义成抽象类。 diff --git a/content/posts/Java面向对象编程——继承.md b/content/posts/Java面向对象编程——继承.md new file mode 100644 index 0000000..04fae6c --- /dev/null +++ b/content/posts/Java面向对象编程——继承.md @@ -0,0 +1,86 @@ +--- +CopyRight: true +NoCover: true +ShowReward: false +ShowToc: show +abbrlink: 850254895 +author: yingyu5658 +categories: +- 往昔 +cid: 185 +cover: images\2024\12\2743265221.jpg +date: "2025-01-10 13:19:11" +desc: null +keywords: null +layout: post +showTimeWarning: true +slug: 185 +status: publish +summaryContent: null +tags: +- Java +thumb: null +title: Java面向对象编程——继承 +updated: 2025/01/10 13:19:11 +--- + + +## 什么是继承 +- Java中提供了一个关键字``extends``,用这个关键字,可以让一个类和另一个类建立起父子关系。 +### 继承的特点 +- 子类能继承父类的非私有成员变量和成员方法。 +### 继承后对象的创建 +- 子类的对象是由子类、父类共同完成的。 + +<!--more--> + +## 继承相关的注意事项 + +### 权限修饰符 + +#### 什么是权限修饰符? +- 用来限制类中的成员(成员变量、成员方法、构造器、代码块...)能够被访问的范围 +### 权限修饰符有几种与各自的作用 + +| 修饰符 | 在本类中 | 同一个包下的其他类 | 任意包下的子类 | 任意包下的任意类 | +| --------- | ---- | --------- | ------- | -------- | +| private | √ | | | | +| 缺省 | √ | √ | | | +| protected | √ | √ | √ | | +| public | √ | √ | √ | √ | +provate < 缺省 < protected < public +## 单继承 + +Java是**继承**的,Java中的类**不支持多继承**,但是支持**多层继承**。 +## Object类 + +- Ojbect类是所有Java类的父类,任何类都是Object的子类。 +## 方法重写 + +### 什么是方法重写 + +- 当子类发现父类中的方法无法满足自己的需求时,**子类可以重写一个方法名称、参数列表一样的方法**去覆盖父类的这个方法,这就是方法重写。 +- 注意:方法重写后,方法的访问遵循**就近原则**。 +### 方法重写的注意事项 +- 重写时使用**Override注解**,他可以指定Java编译器,检查我们方法重写的格式是否正确,代码可读性也会更好。 +- 子类重写父类方法时,访问权限必须大于或等于父类该方法的权限(**public > protected > 缺省**)。 +- 重写的方法返回值类型,必须与被重写方法的返回值类型一样,或者范围更小。 +- 私有方法、静态方法不能被重写,如果重写会报错。 +### 方法重写在开发中的常见应用场景 +- 子类重写Object类的toString()方法,以便返回对象的内容。 +## 子类中访问其他成员的特点 + +1. 在子类方法中访问其他成员是按照就近原则的。 + - 先子类局部范围找。 + - 然后子类成员范围找。 + - 然后父类成员找 + - 然后父类成员范围找,如果父类范围还没有找到则报错。 + +2. 如果子父类中,出现了重名的成员,会优先使用子类的,如果此时一定要在子类中使用父类的方法怎么办? + - 可以通过`super`关键字,指定访问父类的成员:``super.父类成员变量/父类成员方法`` +## 子类构造器的特点 +- 子类的全部构造器,都会先调用父类的构造器,再执行自己。 + +### 子类构造器是如何实现调用父类构造器的: +- 默认情况下,子类全部构造器的第一行代码是`super();`(写不写都有),他会调用父类的无参数构造器。 +- 如果父类没有无参数构造器,我们必须在子类构造器的第一行手写`super();`,指定去调用父类的构造器。 diff --git a/content/posts/Java面向对象编程快速入门.md b/content/posts/Java面向对象编程快速入门.md new file mode 100644 index 0000000..33f35df --- /dev/null +++ b/content/posts/Java面向对象编程快速入门.md @@ -0,0 +1,73 @@ +--- +abbrlink: 1091767210 +author: yingyu5658 +categories: +- 往昔 +cid: 98 +customSummary: null +date: "2024-12-01 13:05:00" +layout: post +mathjax: auto +noThumbInfoEmoji: null +noThumbInfoStyle: default +outdatedNotice: false +parseWay: auto +reprint: standard +slug: 98 +status: publish +tags: +- Java +thumb: null +thumbChoice: default +thumbDesc: null +thumbSmall: null +thumbStyle: default +title: Java面向对象编程快速入门 +updated: 2024/12/07 10:56:43 +--- + + +# 什么是面向对象编程 +通俗易懂的说,就是把一坨一坨的数据放到一起存储 +比如要存储一个学生的语文成绩和数学成绩 +新建一个类 +```java +public class Student { + String name;//名字 + double chinese;//语文成绩 + double math;//数学成绩 + + public void printTotalScore() { + System.out.println(name + "的总成绩是" + (chinese + math)); + } + + public void printAverageScore() { + System.out.println(name + "的平均成绩是" + (chinese + math) / 2.0); + } +} +``` +这样学生的模板就创建好了,但是这个模板还没有指向学生的每一个个体。我们可以再同一个包下再新建一个类。 +```java +public class Test { + public static void main(String[] args) { + //1.创建宇哥学生对象来封装学生a的数据 + Student s1 = new Student(); + s1.name = "学生a"; + s1.chinese = 100; + s1.math = 100; + s1.printTotalScore(); + s1.printAverageScore(); + + //2.再创建一个学生对象,封装学生b的数据 + Student s2 = new Student(); + s2.name = "学生b"; + s2.chinese = 100; + s2.math = 59; + s2.printTotalScore(); + s2.printAverageScore(); + } +} +``` +用以上代码新建一个学生类并且调用我们之前写好的功能 + +- 开发一个一个的对象,把数据交给对象,再用调用对象的方法来完成对数据的处理,这种方法叫**面向对象编程**。 diff --git a/content/posts/KDE桌面环境无法在Konsole切换中文输入法的解决方案.md b/content/posts/KDE桌面环境无法在Konsole切换中文输入法的解决方案.md new file mode 100644 index 0000000..4fc93c7 --- /dev/null +++ b/content/posts/KDE桌面环境无法在Konsole切换中文输入法的解决方案.md @@ -0,0 +1,19 @@ +--- +abbrlink: 3134572074 +categories: +- 往昔 +date: "2025-03-08 22:07:58" +tags: +- Linux +title: KDE桌面环境无法在Konsole切换中文输入法的解决方案 +--- + +### 原因 + +KDE默认使用Wayland会话,而fcitx4不支持Wayland,需升级到fcitx5。若无法升级到fcitx5或升级后仍然无法切换中文输入法,**安装fcitx-qt6** + +```bash +sudo pacman -S fcitx-qt6 +``` + +安装后执行`sudo reboot now`进行重启,问题解决。 diff --git a/content/posts/Kitty终端美化记录.md b/content/posts/Kitty终端美化记录.md new file mode 100644 index 0000000..bee79b4 --- /dev/null +++ b/content/posts/Kitty终端美化记录.md @@ -0,0 +1,62 @@ +--- +abbrlink: 2218331126 +categories: +- 往昔 +date: "2025-03-09 12:41:10" +tags: +- Linux +title: Kitty终端美化记录 +--- + +Kitty这个终端可谓是兼顾了性能与美观,虽然默认设置很简陋,但是经过一番折腾后也能变得很漂亮。 + +## 选择配色 + +运行`kitty + kitten themes`后会弹出一个选择配色的界面 + +令我感到非常高兴的是,这个界面支持vim的hjkl键位,也可以用/来搜索。 +选好后,回车按m,command + ^ + ,重载配置文件。 + +## 配置字体 + +打开kitty的配置文件`nvim ~/.config/kitty/kitty.conf`,把字号改到12 +`font_size 12` +输入`kitty list-fonts --psnames`来列出系统安装好的所有等宽字体。 + +## 设置窗口风格 + +进入配置文件 + +``` +#window +# 不显示窗口标题栏 保留窗口圆角 +hide_window_decorations titlebar-only +# 边距 +window_padding_width 5 +# 不透明度 +background_opacity 0.8 +# 毛玻璃效果 +background_blur 30 +``` + +## 设置标签栏风格 + +``` +#tab bar +tab_bar_edge top +tab_bar_style powerline +tab_powerline_style slanted +``` + +## 安装终端文件管理器 + +`yay -S yazi` +推荐yazi的原因,就是能用vim快捷键啊!hjkl好文明! +而且它还能直接在终端预览图片 + + +## 最终效果预览 + + + + diff --git a/content/posts/Nodejs环境下控制台拼接字符串输出有undefind.md b/content/posts/Nodejs环境下控制台拼接字符串输出有undefind.md new file mode 100644 index 0000000..07605e6 --- /dev/null +++ b/content/posts/Nodejs环境下控制台拼接字符串输出有undefind.md @@ -0,0 +1,59 @@ +--- +abbrlink: 2367638025 +categories: +- 往昔 +date: "2025-03-22 18:56:33" +tags: +- JavaScript +- NodeJS +title: Nodejs环境下控制台拼接字符串输出有undefind +--- + +今天在Nodejs环境下搓小工具,控制台输出拼接字符串时,发现有`undefind`,代码如下: + +```javascript +const date = new Date(); +const year = date.getFullYear(); +const month = date.getMonth(); +const day = date.getDate(); +const hour = date.getHours(); +const minute = date.getMinutes(); +const second = date.getSeconds(); +const logTime = `[${year}-${month}-${day} ${hour}:${minute}:${second}] `; + +class GenerateLog { + static log() { + process.stdout.write(logTime); + } +} + +console.log(GenerateLog.log() + "log output on the console"); +``` + +输出确是这样: + +``` +[2025-3-22 18:56:33] undefindlog output on the console +``` + +原因 +:`GenerateLog.log()`方法没有返回值,所以输出`undefind`,解决方法如下: + +```javascript +// 让log方法返回logTime +class GenerateLog { + static log() { + return logTime; // 返回字符串 + } +} + +console.log(GenerateLog.log() + "log output on the console"); +``` + +关键总结: +Javascript中,如果方法没有返回值,那么输出的就是`undefind` + +#### 扩展 + +为什么 console.log() 本身会返回 undefined? +在 REPL 环境(如 Node.js 命令行或浏览器控制台)中,每条语句的执行结果会被隐式打印。由于 console.log() 函数本身没有返回值(即返回 undefined),因此会显示 undefined。但在脚本执行时,这一行为不会发生,因为脚本模式不自动打印返回值 diff --git a/content/posts/Spigot服务端控制台中文乱码解决方案.md b/content/posts/Spigot服务端控制台中文乱码解决方案.md new file mode 100644 index 0000000..f0bc53c --- /dev/null +++ b/content/posts/Spigot服务端控制台中文乱码解决方案.md @@ -0,0 +1,34 @@ +--- +CopyRight: true +NoCover: true +ShowReward: false +ShowToc: show +abbrlink: 4161445720 +author: yingyu5658 +categories: +- 往昔 +cid: 181 +cover: images\2024\12\2743265221.jpg +date: "2025-01-04 08:35:00" +desc: null +keywords: null +layout: post +showTimeWarning: true +slug: 181 +status: publish +summaryContent: null +tags: +- Java +- 服务器 +- Minecraft +thumb: null +title: Spigot服务端控制台中文乱码解决方案 +updated: 2025/01/04 08:35:54 +--- +1. 把``-Dfile.encoding=UTF-8``加在开服脚本文件的``-jar``前即可。 +2. 在启动脚本第一行加上`chcp 65001` +我的启动脚本如下: +```bash +chcp 65001 +java -Dfile.encoding=UTF-8 -jar spigot-1.21.jar +``` diff --git a/content/posts/String的注意事项.md b/content/posts/String的注意事项.md new file mode 100644 index 0000000..f44a781 --- /dev/null +++ b/content/posts/String的注意事项.md @@ -0,0 +1,83 @@ +--- +CopyRight: true +NoCover: true +ShowReward: false +ShowToc: show +abbrlink: 1413738899 +author: yingyu5658 +categories: +- 往昔 +cid: 171 +cover: images\2024\12\2743265221.jpg +date: "2024-12-19 22:28:15" +desc: null +keywords: null +layout: post +showTimeWarning: true +slug: 171 +status: publish +summaryContent: null +tags: +- Java +thumb: null +title: String的注意事项 +updated: 2024/12/19 22:28:15 +--- + + +# String的注意事项 +- 1. String对象的内容不可改变, 被称为不可变字符串对象。 +- 2. 只要是以“...”的方式写出的字符串,都会存储到字符串常量池,且相同的字符串只存储一份; +- 但通过new方式创建字符串对象,每new一次都会产生一个新的对象放在堆内存中。 +# 不可变字符串对象 +不可变?它肯定可变啊,比如 +```java +package string; + +public class StringDemo3 { + public static void main(String[] args) { + String name = "yingyu5658"; + name += ".me"; + name += "域名"; + System.out.println(name); + + } +} +``` +这时候把name打印出来不就是``yingyu5658.me域名``了吗? +**每次试图改变字符串对象实际上是新产生可字符串对象,变量每次都与指向了新的字符串对象,之前字符串对象的内容确实是没有改变的,因此说String的对象都是不可变的。** + +# 第二点注意事项 + +示例代码: +```java +package string; + +public class StringDemo3 { + public static void main(String[] args) { + String s1 = "abc"; + String s2 = "abc"; + System.out.println(s1 == s2); + //true + } +} +``` +这里使用双等来判断两个变量的地址是否相同,返回结果为``true``,也就是说,地址是相同的。 +原理:上文提到,双引号包裹住的字符串,会被保存到字符串常量池中,**且相同的字符串只存储一份**。这里我们声明了两个内容为abc的String类型变量。Java是很聪明的,当我们把s2声明,它要存到字符串常量池时,看到内容一样,就不再存了,而是把**s2也指向abc**,因此s1地址和s2地址是一样的。 + +## new +示例代码: +```java +package string; + +public class StringDemo3 { + public static void main(String[] args) { + char[] chars = {'a','b','c'}; + String a1 = new String(chars); + String a2 = new String(chars); + System.out.println(a1 == a2); + //false + } +} +``` +上文提到,每new一次就会创建一个新的对象,所以此时再比较两者地址,返回false,是不同的。 diff --git a/content/posts/Tmux配置记录.md b/content/posts/Tmux配置记录.md new file mode 100644 index 0000000..d4b4c01 --- /dev/null +++ b/content/posts/Tmux配置记录.md @@ -0,0 +1,84 @@ +--- +abbrlink: 1389132829 +categories: +- 往昔 +date: "2025-06-21 14:19:36" +tags: +- Linux +title: Tmux配置记录 +--- +TMux 是终端复用神器,让你在一个终端窗口管理多个会话、窗口和窗格。 + +基础操作:启动Tmux +```shell +tmux +``` + +所以我选择在`~/.bashrc`里加上这句,每次打开终端都会自动进入tmux。 + +**需要掌握的概念**: +- 会话(Session):长期运行的终端环境。 +- 窗口(Window):会话中的标签页。 +- 窗格(Pane):窗口中的分屏。 + +**默认快捷键:** + +| 操作 | 快捷键 | 说明 | +| -------- | ------------ | --------- | +| **会话管理** | | | +| 脱离会话 | `Ctrl+b d` | 后台运行会话 | +| 查看会话列表 | `Ctrl+b s` | 方向键选择并进入 | +| 重命名当前会话 | `Ctrl+b $` | | +| **窗口管理** | | | +| 新建窗口 | `Ctrl+b c` | | +| 关闭当前窗口 | `Ctrl+b &` | | +| 切换窗口 | `Ctrl+b 0~9` | 切换到指定编号窗口 | +| 窗口列表 | `Ctrl+b w` | 可视化选择窗口 | +| **窗格管理** | | | +| 水平分割窗格 | `Ctrl+b "` | | +| 垂直分割窗格 | `Ctrl+b %` | | +| 切换窗格 | `Ctrl+b 方向键` | | +| 关闭当前窗格 | `Ctrl+b x` | | +| 最大化/恢复窗格 | `Ctrl+b z` | 临时全屏当前窗格 | + +**配置自定义(~/.tmux.conf)**: +```conf +set-option -g default-shell /bin/bash # 强制使用 Bash +set-option -g default-command /bin/bash # 确保新会话/Pane 也使用 Bash + +unbind H # 移除 H 的绑定 +unbind L # 移除 L 的绑定 +# 启用鼠标支持 +set -g mouse on + +# 键 +set -g prefix C-w +unbind C-b + +bind -r Left previous-window # 前缀键+←:左移窗口 +bind -r Right next-window # 前缀键+→:右移窗口 +# 屏幕分割 +bind v split-window -h # 前缀键+v垂直分割 +bind -n C-Left resize-pane -L 5 # Ctrl+←:向左扩大窗格 5 单位 +bind -n C-Right resize-pane -R 5 # Ctrl+→:向右扩大窗格 5 单位 +``` + +``` + ________________ +< fuck you tmux! > + ---------------- + \ ^__^ + \ (oo)\_______ + (__)\ )\/\ + ||----w | + || || +``` + + + + + + + + + diff --git a/content/posts/Typecho不要用阿里云系统镜像.md b/content/posts/Typecho不要用阿里云系统镜像.md new file mode 100644 index 0000000..3dbd0b2 --- /dev/null +++ b/content/posts/Typecho不要用阿里云系统镜像.md @@ -0,0 +1,37 @@ +--- +abbrlink: 3097784315 +author: yingyu5658 +categories: +- 往昔 +cid: 156 +customSummary: null +date: "2024-12-15 21:45:47" +layout: post +mathjax: auto +noThumbInfoEmoji: null +noThumbInfoStyle: default +outdatedNotice: false +parseWay: auto +reprint: standard +slug: 156 +status: publish +tags: +- Typecho +- 阿里云 +thumb: null +thumbChoice: default +thumbDesc: null +thumbSmall: null +thumbStyle: default +title: Typecho不要用阿里云系统镜像 +updated: 2024/12/15 21:49:46 +--- + + +不要用阿里云的系统镜像,那个是1.1版本的。。。很多插件都没办法正常用。。。比如这两个插件就会这样 + + + +还有很多主题和插件都犯这样的毛病,在此不多提,我会想办法升级版本的(又挖了个坑) + +难受 diff --git a/content/posts/Valine评论系统踩坑记录.md b/content/posts/Valine评论系统踩坑记录.md new file mode 100644 index 0000000..5ddf1da --- /dev/null +++ b/content/posts/Valine评论系统踩坑记录.md @@ -0,0 +1,31 @@ +--- +abbrlink: 955127510 +categories: +- 往昔 +date: "2025-04-23 21:54:03" +tags: +- 博客 +title: Valine评论系统踩坑记录 +--- + +我个人很早以前就惦记着换上这个评论系统,曾经使用Butterfly主题的时候就有折腾过Valine,当时是浏览器缓存策略和CORS跨域拦截的问题。网上能找到的教程都比较老,几年以前的情况不再适用于现在了,所以现在去折腾的话,大概率要踩非常多的坑。本文主要讲述我个人踩到的坑和解决方法。 + +本文内容是我自己试错出来的,不要问为什么要这么做,我也不清楚,但是这么做可以正常使用! + +首先你要有一个自己的域名,不要用.github.io。LeanCloud中设置-域名绑定-API访问域名要绑定你自己的二级域。 + + + +这里一定一定要做DNS解析,非常重要。 + +然后就是安全中心里面的Web安全域名,LeanCloud默认放行localhost,但是127.0.0.1我这边测试是不行的,如果有需求要自己填写。Web安全域名要填写https、http两种协议保险。 + +主题配置文件中,以我这个主题为例,serverURLs要填写自己的二级域名 + +```yaml + serverURLs: https://comment.yingyu5658.me +``` + +一定要加协议头,否则将会在你的博客域名下构建请求,比如我的`www.yingyu5658.me/comment.yingyu5658.me/`,这将导致报错。即使你使用国际版也要填写这一项!Leancloud请求不到。 + +现在Valine的教程都有过时,遇到问题还需结合具体情况分析。我看LeanCloud的各种API结构变更还挺多的,太久远的教程就不建议看了。 diff --git a/content/posts/Vim基础操作快速入门.md b/content/posts/Vim基础操作快速入门.md new file mode 100644 index 0000000..7585f53 --- /dev/null +++ b/content/posts/Vim基础操作快速入门.md @@ -0,0 +1,112 @@ +--- +abbrlink: 2074174141 +author: yingyu5658 +categories: +- 往昔 +cid: 147 +cover: ../../images/2024/12/4041053621.jpg +customSummary: null +date: "2024-12-13 16:13:36" +layout: post +mathjax: auto +noThumbInfoEmoji: null +noThumbInfoStyle: default +outdatedNotice: "no" +parseWay: auto +reprint: standard +slug: 147 +status: publish +tags: +- Vim +thumb: null +thumbChoice: default +thumbDesc: null +thumbSmall: null +thumbStyle: default +title: Vim基础操作快速入门 +updated: 2024/12/13 16:15:07 +--- + +# 前言 + +各种鼠标操作让我有点抓狂,vim或许是一个很适合我的东西,全键盘操作听起来就很方便快捷,除了上手难度有点高以外,vim看起来似乎没有任何的缺点。在下载安装好了vim后,我开始学习了快捷键。~~然后我们就可以直接把鼠标扔了。~~ + + +**记住要先把输入法切换成英文模式** + +# 普通模式 + +## 退出 + +很多人第一次用vim,最难受的事情绝对是不知道怎么退出。 +退出:`:q!` + +## 移动光标 + +`h` `j` `k` `l` 这四个按键分别对应左 下 上 右 + +> 这个比较难适应,不过也比把手移动到右下方用箭头键舒服了 + +### 大范围移动 + +行数 + `h`/ `j`/ `k`/ `l` +比如,想要向下移动三行,就是3`j`,向左移动四格,就是3`h` +`gg` 跳转到文档的最上方 +`G` 跳转到文档的最下方 + +### 按照单词跳转 + +`w`,也就是“word”的首字母。就可以跳转到下一个单词的开头。 +`b` beginning就跳转到前一个单词的开头 +`f` find 查找单词。比如要把光标移动到离你最近的b,就可以输入`fb` + +### 翻页 + +`Ctrl + u`向上翻页。u理解为up首字母。 +`Ctrl + d`向下翻页。d理解为down首字母。 + +## 复制粘贴 + +在普通模式下,输入`y` (yank),复制整个单词:`yaw` “aw'“为~~阿伟~~ all word +`p` 即paste,粘贴。 + +## 删除 + +普通模式下,`d` 也就是delete,直接删除当前行和下一行的内容 +还可以跟上文的`hjkl`结合起来,比如d8j就是向下删除八行 + +## 撤销 + +`u` 也就是undo。 + +> 这些快捷键很灵活,都可以互相结合使用 + +# 输入模式 + +## 进入输入模式 + +在普通模式下,输入`i` 也就是insert,就可以进入输入模式了。 + +1. `i`是在当前光标的前一个字母开始输入。 +2. 使用`a`也就是append,就可以在当前光标之后输入。 +3. 使用`I`就会从这一行的开头进入输入模式。 +4. 使用`A`就会从这一行的末尾进入输入模式。 + 完成编辑后,使用`ESC` 就可以退出编辑模式,回到普通模式了。 + +# 命令模式 + +在普通模式下输入`:`就可以进入命令模式,按下`ESC`就会退出命令模式。 +在下方的命令行中,可以输入命令 +`q`也就是quit就可以退出 +保存`w` +保存并退出`wq` + +# 可视模式 + +普通模式下按下`v`就可以进入可视模式。 + +# 配置文件 + +vim中修改键位,安装主题全都是用一个配置文件来完成的。 +原版vim的配置文件叫做.vimrc +关于修改键位,我的看法是不要改,因为你适应之后上服务器就会很难受,什么都不适应。 diff --git a/content/posts/WSL-Arch-Linux-ZSH输入中文乱码解决方法.md b/content/posts/WSL-Arch-Linux-ZSH输入中文乱码解决方法.md new file mode 100644 index 0000000..0e2aa27 --- /dev/null +++ b/content/posts/WSL-Arch-Linux-ZSH输入中文乱码解决方法.md @@ -0,0 +1,22 @@ +--- +abbrlink: 570074617 +categories: +- 往昔 +date: "2025-04-29 10:31:26" +description: 乱码是由于没有安装字体造成的,安装字体即可 +tags: +- Linux +title: WSL Arch Linux ZSH输入中文输入法乱码解决方法 +--- + +没有进行配置的情况下输入中文,一般会显示<0xffffffff>,这是由于没有安装字体造成的。 + +```bash +sudo pacman -S noto-fonts-cjk # 安装中文字体 +sudo vi /etc/locale.gen # 取消注释 zh_CN.UTF-8 +sudo locale-gen # 生成语言环境 +echo "export LANG=zh_CN.UTF-8" >> ~/.zshrc # 设置默认中文环境 +source ~/.zshrc +``` + +source后,再次尝试输入中文,无异常。 diff --git a/content/posts/osu-APIv1请求示例.md b/content/posts/osu-APIv1请求示例.md new file mode 100644 index 0000000..0d51968 --- /dev/null +++ b/content/posts/osu-APIv1请求示例.md @@ -0,0 +1,83 @@ +--- +abbrlink: 3260068752 +categories: +- 往昔 +date: "2025-04-11 22:29:23" +tags: +- JavaScript +- NodeJS +title: osu!APIv1请求示例 +--- + +## 前言 + +本文章使用Nodejs环境做演示。请求用户数据。代码中的APIKEY要在[osu官网](https://osu.ppy.sh/home/account/edit)申请。 + +```js +const API_URL = "osu.ppy.sh"; +const init = { + k: "YOUR_API_KEY", + type: "string", + u: "kyzzz5658", +}; + +const https = require("https"); + +// 将参数序列化为查询字符串 +const query = new URLSearchParams(init); +const options = { + hostname: API_URL, + method: "GET", + path: `/api/get_user?${query}` // 附加参数 +}; + +const req = https.request(options, (res) => { + let data = ''; + res.on('data', (chunk) => data += chunk); + res.on('end', () => { + try { + console.log(JSON.parse(data[0].username)); + } catch (e) { + console.error('JSON 解析失败:', e); + } + }); +}); + +// 错误处理 +req.on('error', (err) => { + console.error('请求失败:', err.code); +}); +``` + +输出: + +``` +[ + { + user_id: '33932276', + username: 'Kyzzz5658', + join_date: '2023-06-24 08:48:13', + count300: '2139', + count100: '609', + count50: '194', + playcount: '44', + ranked_score: '1917044', + total_score: '3095639', + pp_rank: '1968010', + level: '8.0115', + pp_raw: '43.5449', + accuracy: '81.70417785644531', + count_rank_ss: '0', + count_rank_ssh: '0', + count_rank_s: '0', + count_rank_sh: '0', + count_rank_a: '1', + country: 'CN', + total_seconds_played: '2259', + pp_country_rank: '38721', + events: [] + } +] +``` + + [首页 ·ppy/osu-api 维基](https://github.com/ppy/osu-api/wiki) diff --git a/content/posts/x86-64汇编学习笔记.md b/content/posts/x86-64汇编学习笔记.md new file mode 100644 index 0000000..9ff3d35 --- /dev/null +++ b/content/posts/x86-64汇编学习笔记.md @@ -0,0 +1,180 @@ +--- +abbrlink: 2938437705 +categories: +- 往昔 +date: "2025-04-29 13:44:13" +tags: +- 汇编 +title: x86-64汇编学习笔记 +--- + +## 机器指令和机器语言 + +机器指令,二进制数字,机器语言全局机器指令的集合,CPU通过执行一系列的机器指令完成计算工作。 + +汇编语言就是为了代替机器指令,使人类能够更加简单地编写程序而诞生的。汇编语言就是机器码的助记符。 + +编译器将汇编代码再编译为真正的机器码。 + +## 内存与硬盘 + +内存指内存条,即RAM,临时存储,读写快容量小。 + +硬盘长期存储,读写慢但容量大。 + +**ROM并非硬盘**,ROM**只读存储器**(Read Only Memory),其内容在写入后就不能更改。 + +## 存储单元 + +物理内存被划分为很多个存储单元,一个存储单元能存储8bit内容,也就是1字节。 + +**内存的最小单元是字节,不是位。** + +- 1B = 8bit + +- 1KB = 1024B + +- 1MB = 1024KB + + ...... + +每一个存储单元都有相应的编号,也就是内存地址。运行程序时,操作系统会把程序载入内存中,随后CPU读取和写入程序中的某些数据并执行代码。 + +无论是读取还是写入、执行,这些都是需要通过CPU总线进行的。 + +总线分为数据线、地址总线、控制总线 + +简而言之,地址总线负责寻址,控制总线负责发出控制指令,如读写,数据总线负责各个组件之间的数据传输。 + +## CPU的寻址能力 + +CPU的寻址能力是由地址总线的位数决定的。 + +通常认为32位系统有32位的寻址能力,64位同理,但不绝对。 + +## 虚拟内存 + +物理内存即真实存在的内存,虚拟内存是建立在页表的基础上,由操作系统实现的。 + +## 寄存器 + +基本的程序执行寄存器分为以下四类 + +1. 通用目的寄存器 +2. 段寄存器 +3. 标志寄存器 +4. 指令指针寄存器 + +### 16位通用寄存器中的高位和低位 + +16位通用寄存器中,ax,bx,cx,dx可以只使用其高8位或低8位。 + +高8位用字符`h`表示,低8位用字母`l`表示。 + +### 32位通用目的寄存器 + +将16位通用寄存器扩展到32位,就得到了以下寄存器。 + +- EAX +- EBX +- EDX +- ESI +- EDI +- ESP +- EBP + +### 64位通用目的寄存器 + +将32扩展到64位,就得到了以下寄存器 + +- RAX +- RBX +- RCX +- RDX +- RSI +- RDI +- RSP +- RDP + +R是通用前缀,取自单词Register。 + +此外还有R8-R15。 + +### 同名寄存器之间的关系 + +同名寄存器之间并不是许多个相互独立的寄存器,而是共同属于一个寄存器。 + +以RAX为例: + +RAX是整个64位寄存器,EAX指的是RAX的低32位,AX指的是RAX的0-15位。AH指的是RAX的8-15位,AL指的是RAX的0-7位。 + +1 word = 2 byte + +1 double word = 4 byte + +## 段寄存器 + +段寄存器CS、DS、SS、ES、FS、GS都保存着16位段选择子。用于标识内存中特定的段。 + +CS指向代码段,SS指向栈段,DS、ES、FS、GS指向数据段。 + +内存可以被分为不同的段,访问内存时通过段基址+偏移的方式来访问。 + +注意:物理内存本身是连续的,并没有被分隔开,分段是CPU的寻址方式。 + +到了64位,段的概念被进一步弱化。 + +内存变成平坦模型,即无分段式内存。所有对内存的访问都在同一个地址空间内进行。 + +此外,对于段的保护也被弱化,64位更强调对页的保护。 + +> 看来段寄存器没什么用了啊 + +段寄存器最初的存在目的是辅助寻址,在32位下基本不再用于寻址,而是用于保护,而64位中其保护作用进一步被削弱。 + +## 标志寄存器 + +标准寄存器存储了机组标志,分别是状态标志、控制标志、系统标志。 + + + +简单地来说,系统中的某些状态与指令的执行结果会存在这个寄存器当中。 + +标志寄存器在32位和64位中分别叫**EFLAGS**和**RFLAGS** + +RFLAGS的高32位是保留为,低32位与EFLAGS相同。 + +## 指令指针寄存器 + +简而言之,他存储的是CPU即将执行的下一条指令的地址,通常用ip/eip/rip替代 (16,32,64位) + +## 进制 + +简单来说,n进制就是逢n进一。计算机当中,除了10进制,还有2进制和6进制。 + +## 小端序和大端序 + +小端序是指低字节在低地址,高字节在高地址。 + +优点:字节高低位与地址高低位序列相同。 + +缺点:不符合人类阅读顺序。 + +如:64 00 00 00 + +大端序与之相反。 + +如 00 00 00 64 + +## MOV指令 + +MOV取自英文单词move,移动。 + +例: + +``` +MOV RAX, RCX +``` + +意思是,把RCX寄存器的值赋值给RAX + diff --git a/content/posts/《伊豆的舞女》读后感.md b/content/posts/《伊豆的舞女》读后感.md new file mode 100644 index 0000000..4e75434 --- /dev/null +++ b/content/posts/《伊豆的舞女》读后感.md @@ -0,0 +1,45 @@ +--- +categories: +- 读书 +date: "2025-08-21T20:37:54+08:00" +draft: false +slug: izu-no-odoriko +tags: +- 伊豆的舞女 +- 川端康成 +- 日本文学 +title: 《伊豆的舞女》读后感 +--- +我读的这本《伊豆的舞女》是一页文库出品的川端康成短篇小说集,共选入十篇。依照顺序分别为:《伊豆的舞女》、《油》、《篝火》、《春景色》、《温泉旅馆》、《抒情歌》、《禽兽》、《母亲的初恋》、《朝云》、《「燕」号列车上的女孩》。还有作者自序和三岛由纪夫作的序。 + +《伊豆的舞女》这一篇的内容是一位高中生为排遣心中难以言喻的苦闷,来到伊豆旅行,遇到江湖艺人,并对其中的舞女产生了恋慕之情。采用川端康成擅长,也是风格的日常碎片拼接的手法,用一件件小事体现出「我」对舞女的爱恋,一直到最后离别的过程。 + +这篇故事从头到尾都流露着一股淡淡的阴郁和忧愁,而文章末尾写道的眼泪流尽后品尝到的「甘美的快乐」,我认为是文章的中心和精华,通过日常小事到离别,体现出日本文学中「物哀」的精髓,也就是对世间生命、感情无常的深度共情与审美升华。 + +由对舞女的感情和离别,引申出一系列复杂的情感体验。途中,薰子一句“您真是好人啊”的纯真评价,让他首次感受到被接纳的温暖,脱离出孤儿身份的长期忧郁,结尾的泪水冲刷了长期积累的沉重的阴霾,代之以甘美的轻盈。与熏子因阶级、年龄差异注定无果的恋慕之情,本应导向沉重的痛苦,却被升华为短暂而珍贵的体验,是物哀美学的核心体现。 + +话虽然是这么说,但我们尊重不同的观点,豆瓣上有些读者认为这个故事充满「男凝」,我表示不理解,拳师特有的观点吧。草木皆兵,一切都是父权社会男性对女性的压迫!她们看《温泉旅馆》,不会又觉得物化女性吧? + +其中《温泉旅馆》写当时社会底层女性奔波辗转的劳苦命运,《油》深入剖析「我」对丧失父母之爱情在油上的转移和投射,但这几个故事里我印象最深刻的是《朝云》,故事讲述了一个女子学校的学生对一位女性老师产生崇拜的唯美故事,说它是百合也不为过了。我在一个日语网站看到对这个故事有这样的评价,应该是出版商的标语之类的: + +> 恋はあまりにも、幻影だった。 +> +>日本文学史上、最も純潔なる青春少女小説!! + +大意是:爱恋太过于幻影了。日本文学史上,最纯洁的青春少女小说!! + +恋这个字在日语中特指 恋爱之情、爱慕之心,尤其强调 情感萌动阶段的心动、憧憬或单相思,比中文“爱”更轻盈,带有青春期的纯粹性与虚幻感。这正是我喜欢这个故事的原因。作者把一颗懵懂的、纯粹的,对美好向往的心写活了,一个含蓄多思的少女形象跃然纸上。 + +而纯洁,就在于没有到肉体层面,对美好的向往和肉欲是完全不同的两个方向,节选两段可以感受一下: + +> 当时她似乎也是打宿舍出来,我**低头**和她擦肩而过,因为她并不了解我的心事。其实我根本不用低着头,想看就看好了,尽管这么想着,但我到底**没敢**抬起头来。然而,她那穿着毛衣的**可爱身姿**使人感到她仿佛是个同我们年龄相差不大的姑娘,我因这一浙大的发现震惊不已,看来,自己内心的**某些东西觉醒**了,那就是所谓的**青春**吗?我也逐渐成为**和她一样**的“姑娘”了,我心中充满**喜悦**,一双眼睛**贪婪地偷偷**瞅着她,同时又看看自己,在她的诱惑下,我迅速成熟了。 + +尤其是最后一小段:贪婪、偷偷,这种色彩的词语在当前的语境下,能传达出一种热烈又真切的爱慕与向往,向往到什么程度呢?想「成为」爱慕的对象,这是对理想自我的精神投射,承载着自我认同的焦虑。 + +能从节选片段中感受到川端康成的语言特点:细腻、情感丰富,善于用各种细节和心里描写塑造人物的真实的性格。细腻到像主人公,一个少女站在读者面前,摊开自己的日记,把各种大事小事无一例外地仔细展示给读者,就差亲口朗读了。 + +而在毕业典礼上,菊井老师在逃避后又写下的「祝你幸福」,以及对幸福究竟是什么这个问题的解答更是耐人寻味,解读空间很大。 + +「我不认为幸福是各种各样的。」 + +真正的幸福究竟是什么样的?
\ No newline at end of file diff --git a/content/posts/《奔马》书评:刀刃突入腹部的瞬间,红日在眼睑内冉冉升起.md b/content/posts/《奔马》书评:刀刃突入腹部的瞬间,红日在眼睑内冉冉升起.md new file mode 100644 index 0000000..d5b378d --- /dev/null +++ b/content/posts/《奔马》书评:刀刃突入腹部的瞬间,红日在眼睑内冉冉升起.md @@ -0,0 +1,46 @@ +--- +date: 2025-10-05T11:35:41+08:00 +draft: false +title: 《奔马》书评:刀刃突入腹部的瞬间,红日在眼睑内冉冉升起 +slug: honba-mishima-yukio +categories: + - 读书 +tags: + - 三岛由纪夫 + - 丰饶之海 + - 日本文学 + - 文学 + - 读书笔记 + - 奔马 + - 书评 +description: 「我为幻想而生,以幻想为目标而行动,也因幻想受惩罚……我多想得到不是幻想的东西啊。」 +--- +今日凌晨读完了丰饶之海的第二卷:《奔马》,这是四部曲中最暴烈的一部。全书围绕着上一部的主人公松枝清显的转世 —— 饭沼勋的行动展开。讲述了一个阳刚强健的少年,因不忍政治腐败,天皇的实权丧失,忧国之心驱使他组织刺杀政府企业巨头,失败后,他雄心未泯,最终刺杀了藏原再切腹自尽的故事。重点展现了作者对武士道中「忠」与「勇」的极致追求。 + +本部书与上一部《春雪》比起来,又是另一个极端。上一部的主人公松枝清显沉溺在幻想中,优柔寡断;而转生后的饭沼勋则成了一个行动者。如果说松枝清显是作者孱弱一面的投射,那么饭沼勋则是作者暴烈极端的一面和其政治诉求的投射。清显沉溺幻想的虚无,饭沼勋用行动对抗虚无。作者塑造了一个让人印象深刻的少年形象:冲动的、理想的、认知是非黑即白的、尖锐的少年形象。 + +这股少年气是饭沼勋最闪耀的优点,也是他走向悲剧的重要原因之一。他受《神风连史话》的影响,组织成立了昭和神风连。而这是一个几乎注定失败的行为,其中贯穿全书的对自杀的理性规划与向往,让人不禁怀疑,他究竟是想要救国,还是想悲壮地自杀? + +<!--more--> + +对于这一部分的不理解,主要源于文化差异,在日本文化,以及武士道文化中,自杀不被认为是消极的、逃避性质的寻死,而是一种以肉体的毁灭与极度痛苦,验证其精神纯洁性(如忠心、承担失败、洗刷侮辱)的最高**仪式**。**死是一个手段,而不是目的。** 三岛一直有美化死亡、自杀的倾向,但在全书围绕展开的「日本精神」中,又是正常的。 + +而勋对天皇的病态的执着敬仰,也要结合文化背景来理解。日本的天皇在第二次世界大战结束前,不单单是一个政治上的领袖,而是日本神话体系中最高权威神的人间体,他是一种**纯粹的权威和信仰** ,这源于其宗教信仰上对民众思想的控制和洗脑。 + +因此也就可以理解为什么勋对天皇有如此病态的情感。书中,勋自述了对天皇的忠义的认识: + +> “是。所谓忠义,对于我来说,就是手握滚烫的米饭做饭团,只顾一心一意做好饭团,献给陛下。其结果,要是陛下不饿,立即退了回来,或者说:‘这种难吃的东西,也敢呈献上来?’说着就把饭团砸到我的脸上。要是这样,我就会满脸粘着饭粒退下,怀着感动立即切腹。假如陛下饿了,高兴地吃了我的饭团,我也立即退下,怀着感动立即切腹。为什么呢?因为陛下吃了草莽小民做的饭团,这本来就罪该万死。要是做了饭团不献上来,一直捧在手上,又会怎样呢?饭团肯定会腐烂,这也不合忠义,我将此称作无勇之忠义。所谓有勇之忠义,就是冒死将一心一意做的饭团敬献上去。” + +那么,回到最初的问题,他究竟是想要救国,还是想要自杀?可以给出一个明确的回答:切腹是目的,也是手段。这是一个矛盾点。 + +他口口声声为了天皇与国家,但其行动逻辑却一步步指向了自我毁灭的必然结局。这不是勋的逻辑故障,而是三岛由纪夫「行动哲学」与「死亡美学」的内在缺陷。三岛追求的并非现实世界的改变,而是一种**美学的、象征性的姿态**。意义不在于**救赎**,而在于**献祭**。改变国家和震撼人心,重在后者。所以这种自杀是带有表演性质的,呼应其美学思想的行为,同时是目的也是手段。这是一种互相催生,又互相遏制生长的矛盾状态。但**死亡是唯一确定的、必须发生的终点**,行动只是为这个终点提供理由和仪式感。全书结尾,也是高潮的一句话,最能佐证此观点: + +> 刀刃突入腹部的瞬间,红日在眼睑内冉冉升起。 + +切腹时极度的肉体痛苦被转化为精神上的快感体验,举事是否成功,对饭沼勋来说已经不重要了,红日的最核心的象征就是**天皇、日本国体、纯粹的日本民族精神**。这是勋毕生追求的终极信仰对象。 + +但同样需要思考的是,勋的自杀,除了在他个人的精神意义上的高潮,对外在的世界,对国家的影响又如何呢?如此极端的行动,执着和病态,又有什么意义呢?杀死了藏原(或其他暗杀名单中的人),国家就真的复兴了吗?军国主义和天皇掌权的失败已经证明了其荒谬和不可行性。因此勋的自杀,以及藏原之死,都如同从奔腾的洪流中取走一滴水,在宏观历史进程中的影响微乎其微。 + +饭沼勋的少年气,是对世界理想化、对动机单纯化、对结果美学化的自我陶醉的品质。他一生所追求的,正是这种「纯粹」。在勋眼中,现实世界已被污染,任何妥协或苟活都意味着对理想的背叛,是对「纯粹性」的玷污。只有通过**壮烈的、仪式性的死亡**(尤其是切腹),才能**保持精神的绝对纯洁**,避免被污浊的现实世界所腐蚀。死亡成为守卫纯粹精神的最后堡垒和唯一途径。所以从这个角度看作者本身,三岛的自杀并不能单纯定性为政治表演,也是一次知行合一的为美学殉教的实践。 + +本书虽尽显武士道精神的极端、对个体生命的漠视,以及日本军国主义和天皇绝对权威下的偏执与疯狂,但其文学和美学上的暴烈和阳刚的价值不可忽视,作者将日本文化中最纤美的一面在上一部发展到极致再毁灭,又在本部书中将日本文化中最刚烈的一面推向巅峰再毁灭,由衷钦佩作者笔下波谲云诡的文字氛围,期待下一卷《晓寺》带来的震撼。 diff --git a/content/posts/《春雪》书评:任何美梦都会有结束的时候,没有什么永恒的东西.md b/content/posts/《春雪》书评:任何美梦都会有结束的时候,没有什么永恒的东西.md new file mode 100644 index 0000000..e9def1c --- /dev/null +++ b/content/posts/《春雪》书评:任何美梦都会有结束的时候,没有什么永恒的东西.md @@ -0,0 +1,35 @@ +--- +date: 2025-09-28T21:18:43+08:00 +draft: false +title: 《春雪》书评:任何美梦都会有结束的时候,没有什么永恒的东西 +slug: spring-snow-mishima-yukio +categories: + - 读书 +tags: + - 三岛由纪夫 + - 春雪 + - 丰饶之海 + - 日本文学 + - 读后感 +--- +于今日正式结束了三岛由纪夫的绝笔之作《丰饶之海》四部曲的第一卷 —— 《春雪》的阅读。刚开始读,它给我一种「很不三岛」的感觉,语言风格细腻柔美,甚至有几分古典韵味,对景物的描写细致入微,但处处洋溢着一丝哀愁,我还以为自己在阅读川端康成的作品。可以理解为三岛对恩师的致敬吧? + +故事围绕着松枝清显与绫仓聪子的爱情悲剧展开,互为对方青梅竹马的两人试探猜忌,始终没有发展。聪子始终深爱着清显,但清显一直维护着他的孤傲,给人一种非常「拧巴」的感觉。直到聪子与治典亲王订婚,清显才意识到自己的确深爱着聪子,于是一场短暂禁忌之恋开始,最终聪子怀孕,被迫堕胎后,面对皇室和家族的巨大压力,她削发为尼,遁入空门。清显相思成疾,因肺病夭折,令人哀惋。 + +<!--more--> + +令我感受最深的,还是聪子这个角色的遭遇。被迫堕胎,清显和她爱情的结晶被彻底的物理意义上的抹除,也没有任何回头路留给聪子,她才走投无路做了尼姑,世俗已经没有任何可以让她留恋的东西了,而在事情刚刚发生的时候,松枝和绫仓两家还在商量如何瞒天过海,提出了一个佩戴假发参加纳彩的主意。 + +> 纳彩时要戴垂形假发,而平时要戴束形假发。人眼无处不在,聪子即使入浴也不可随意摘掉。 + +> 人人心里都在描绘着聪子应该佩戴的假发,它比真发还要光洁、流丽,如射干果一般乌黑闪亮。它就是强加授予的王权。 + +聪子已经不是一个有着自我的「人」,而是一个与家族兴衰荣誉直接绑定的「物」,家族一手操办着婚事,丝毫不考虑聪子的感受。而那讽刺的假发,便成了一具假面,聪子要时时刻刻戴着假面生活,完全压抑隐藏自己。但聪子真的得到解脱了吗?还是进入了另一层禁锢? + +而小说中纯粹的美的化身 —— 清显,又是纯粹的情绪的化身,感性的化身,他近乎自虐式回味着感情,反复咀嚼品尝痛苦,而且有着强烈的自我美化倾向,又极度渴望悲剧,而这种思想最终将他导向了毁灭,他是一个唯美主义的殉道者,他爱着的也许不是聪子,而是他心目中聪子的幻影,现实中的聪子只是幻想的承载和投射。 + +另一个让我非常震撼,也钦佩的点是本书的名字:「春雪」、「春の雪」。春天落下的雪。不合时宜,短暂易逝,是对主角二人爱情的完美隐喻,同时也体现日本文学的风格:对短暂之美的细腻感受,哀而不伤,以及对不完美的接纳甚至美化,而本书确实是一本将唯美推向巅峰之作,也是将三岛心目中对柔弱纤美风格追求的毁灭之作。也对日本文学中力图传达的美学意识 —— 物哀 、幽玄 、侘寂三者融合达到巅峰,读完却怅然若失,如同自己亲身经历了一场凄美的爱情。 + +而「春雪」与「丰饶之海」这两个词,都有一种虚无的意境美,想起「丰饶之海」这个词取自月球上的「丰富海」,并且作者解释有讽刺意味,是「干枯的谎言之海」,震撼之情难以言表,深入想想一种恐惧感袭上心头,又一股颤栗般的感动将它冲散,却余韵悠长。 + +> 任何美梦都会有结束的时候,没有什么永恒的东西。
\ No newline at end of file diff --git a/content/posts/【数据结构与算法】二叉树.md b/content/posts/【数据结构与算法】二叉树.md new file mode 100644 index 0000000..2e58426 --- /dev/null +++ b/content/posts/【数据结构与算法】二叉树.md @@ -0,0 +1,78 @@ +--- +abbrlink: 1421131593 +categories: +- 往昔 +date: "2025-05-25 18:46:37" +tags: +- 数据结构与算法 +title: 【数据结构与算法】二叉树 +--- +## 定义 + +二叉树(binary tree)是指树中节点的度不大于2的有序树,它是一种最简单且最重要的树。二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。 + +## 实现 + +### 结构定义 + +~~尝试了一下C语言,各种指针乱指,各种bug,暂时放自己一马,跟自己和解一下用js写写吧。~~ + +```js +class TreeNode { + constructor(data) { + this.data = data; + this.left = null; // 左节点 + this.right = null; // 右边节点 + } +} +``` + +### 创建对象并绑定节点 + +```js +// 手动绑定节点 +let root = new TreeNode(1) +root.left = new TreeNode(2) +root.right = new TreeNode(3) +root.left.left = new TreeNode(4) +root.right.right = new TreeNode(5) +``` + +此时树的结构: +``` + 1 + / \ + 2 3 + / \ \ + 4 5 6 +``` + +### 遍历二叉树 + +#### 前序遍历(DFS) + +```js +function preOrder(node) { + if(node) { + console.log(node.data) + preOrder(node.left) + preOrder(node.right) + } +} +``` +这里用递归调用,遍历到左右元素 + +#### 层序遍历(BFS) + +```js +function levelOrder(root) { + const queue = []; + queue.push(root); + while (queue.length) { + const node = queue.shift(); + console.log(node.data); + if (node.left) queue.push(node.left); + if (node.right) queue.push(node.right); + } +} +``` diff --git a/content/posts/【数据结构与算法】众数、中位数.md b/content/posts/【数据结构与算法】众数、中位数.md new file mode 100644 index 0000000..83e1ed8 --- /dev/null +++ b/content/posts/【数据结构与算法】众数、中位数.md @@ -0,0 +1,137 @@ +--- +abbrlink: 2344272299 +categories: +- 往昔 +date: "2025-05-27 19:41:53" +tags: +- 数据结构与算法 +title: 【数据结构与算法】众数、中位数 +--- +今天学这个东西的时候,看到这种线性的数据结构加上排序步骤,很难不想写个程序来跑跑。 + +先来说说中位数,这个比较有思路。 + +## 中位数 + +具体的操作步骤应该是:**排序 => 获得数据元素个数n => 是奇数 ? (n+1) / 2 : n / 2** + + +那么排序就用之前学的冒泡排序,这种题目大概不会完全倒序给数据,编写sort函数: + +```c +void sort(int arr[], int n) +{ + for (int i = 0; i < n - 1; i++) { + for (int j = 0; j < n - i - 1; j++) { + if (arr[j] > arr[j + 1]) { + int temp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = temp; + } + } + } +} +``` + +接下来是判断奇偶,奇偶的判断非常简单,对取模运算的值比对就可以,编写is_even函数,判断奇偶性。 +```c +int is_even(int data) +{ + if (data % 2 == 0) { + return true; + } else { + return false; + } +} +``` + +完成了奇偶判断,下一步就可以正式进行中位数的运算,编写get_median函数。 +```c +double get_median(int arr[], int length) +{ + // 获取索引 + double result = 0; + sort(arr, length); + if (is_even(length)) { + int median_index_1 = arr[(length / 2) - 1]; + int median_index_2 = arr[length / 2]; + // 计算数据 + result = (median_index_1 + median_index_2) / 2.0; + } else { + result = arr[length / 2]; + } + + return result; +} +``` + +这个函数首先计算了中位数在数组的哪个索引,然后进行了计算。 + + +## 众数 + +众数(Mode)是指在[统计分布](https://baike.baidu.com/item/%E7%BB%9F%E8%AE%A1%E5%88%86%E5%B8%83/8478867?fromModule=lemma_inlink)上具有明显集中趋势点的[数值](https://baike.baidu.com/item/%E6%95%B0%E5%80%BC/2013853?fromModule=lemma_inlink),代表[数据](https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE/33305?fromModule=lemma_inlink)的一般水平。 也是一组数据中出现次数最多的数值,有时众数在一组数中有好几个。用M表示。 + +那么,在程序中,想要计算一个值出现的次数并比对,可拆分为两步。 + +1. 计算出每一个数据出现的次数 +2. 结果排序比对 +3. 找出最大值 + +我没学过什么高级的数据结构,就用这个复制数组的笨办法吧。 + +```c +int get_mode(int arr[], int length) +{ + int *copy_arr = malloc(length * sizeof(int)); + memcpy(copy_arr, arr, length * sizeof(int)); + sort(copy_arr, length); + + int max_count = 0; + int current_count = 1; + int mode = copy_arr[0]; + + for (int i = 1; i < length; i++) { + if (copy_arr[i] == copy_arr[i - 1]) { + current_count++; + } else { + if (current_count > max_count) { + max_count = current_count; + mode = copy_arr[i - 1]; + } + current_count = 1; + } + } + + if (current_count > max_count) { + mode = copy_arr[length - 1]; + } + + free(copy_arr); + return mode; +} +``` + +这个函数干了以下几件事: +- 复制数组 +- 排序复制好的数组 +- 对比数组元素,如果array[i] == array[i - 1],出现次数+1 +- 如果遇到新元素,检查是否需要更新最大值 +- 动态更新众数值 + +测试跑一把,输出如下 +```c +int main() +{ + int arr[] = {1, 1, 1, 1, 2, 2, 4, 5, 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2}; + int length = sizeof(arr) / sizeof(arr[0]); + int result = get_mode(arr, length); + printf("result = %d\n", result); +} +``` + +``` +result = 4 +``` + +~~这个办法实在是有点蠢,找时间仔细学学哈希表,应该能更快。~~ diff --git a/content/posts/【数据结构与算法】冒泡排序.md b/content/posts/【数据结构与算法】冒泡排序.md new file mode 100644 index 0000000..f0f08d9 --- /dev/null +++ b/content/posts/【数据结构与算法】冒泡排序.md @@ -0,0 +1,109 @@ +--- +abbrlink: 403994443 +categories: +- 往昔 +date: "2025-05-10 20:06:05" +tags: +- 数据结构与算法 +title: 【数据结构与算法】冒泡排序 +--- + +## 核心思想 + +通过相邻元素的两两比较,将较大的元素逐步“冒泡”到数组末尾,每轮排序确定一个最大元素的最终位置。 + +## 代码实现 + +```c +void bubble_sort(int arr[], int n) { + // 最外层控制循环轮数 n-1轮 + for (int i = 0; i < n - 1; i++) { + // 内层循环处理相邻元素比较和交换 + for(int j = 0; j < n-i-1; j++) { + if (arr[j] > arr[j+1]) { + int temp = arr[j]; + arr[j] = arr[j+1]; + arr[j+1] = temp; + } + } + } +} + +// 调用 +void print_array(int arr[], int size) { + for (int i = 0; i < size; i++) { + printf("%d,", arr[i]); + } + printf("\n"); +} + +int main() { + int arr[] = {23, 232, 55, 2, 7, 0, 576, 342}; + int n = sizeof(arr) / sizeof(arr[0]); + + printf("排序前:"); + print_array(arr, n); + bubble_sort(arr, n); + + printf("排序后"); + print_array(arr, n); +} +``` + + + +## 原理分析 + +### 外层循环的 i < n - 1 + +- n个元素的数组最多需要n-1轮冒泡,如5元素数组需要4轮排序 +- **数学依据**:每轮将一个最大值“沉底”,当完成n-1轮时,最后一个元素必然有序 + +示例验证: + +``` +原始数组:[3, 1, 4, 2] +第一轮:[1, 3, 2, 4] (确定最大值4) +第二轮:[1, 2, 3, 4] +``` + +用文字解释上面的函数,原理就是在循环中对比数组第i个元素和i+1(即后一位)元素的大小,若i > i +1 则把两者交换位置,随着循环的进行,数组就会被排序。 + +### 内层循环的 j < n - i - 1 + +- 动态缩小范围:每轮结束后末尾i个元素已有序 +- 比较次数:第i轮需要比较(n-1)-i次相邻元素 + +想象一下数组的线性结构,实际上就是在计算排序后的一位的前一位,这样就不会处理已经排序好的元素,进入下一轮循环时可正常排序。 + +### 数组长度n的计算机制 + +在main函数中,对于n的计算,采用了`sizeof(arr) / sizeof(arr[0])`的方式。可以这么理解。 + +```c +int arr[] = {6,4,8,2}; +假设int占用4字节,计算整个数组的内存占用 +sizeof(arr) = 5 * 4 = 20 +sizeof(arr[0]) = 4 +n = 20 / 4 = 5 +``` + +计算出数组的总占用,再除以单个占用,就可以得到元素个数了。 + +### 参数n的作用 + +- 循环控制:确定外层循环次数n-1次 +- 边界保护,防止越界 +- 效率优化:避免无效比较,如j<n-i-1 + +## 最坏情况 + +冒泡排序的最坏情况发生在**输入数组完全逆序情况下**,此时算法需要进行最大次数的比较和交换操作,时间复杂度达到最高。 + +当待排序数组的初始状态为完全逆序,如[5,4,3,2,1],每一轮外层循环都要将当前为排序部分的最大元素冒泡到正确位置,而且每次比较都会发生交换,此时: + +- **比较次数**: 共需要进行*(n - 1) + (n - 2) + ...*(等差数列求和)。 +- **交换次数**: 每次比较均需要交换,总交换次数也为上式结果。 + + + diff --git a/content/posts/【数据结构与算法】哈希表.md b/content/posts/【数据结构与算法】哈希表.md new file mode 100644 index 0000000..3b78524 --- /dev/null +++ b/content/posts/【数据结构与算法】哈希表.md @@ -0,0 +1,130 @@ +--- +abbrlink: 971437699 +categories: +- 往昔 +date: "2025-05-28 21:44:28" +tags: +- 数据结构与算法 +title: 【数据结构与算法】哈希表 +--- +哈希表(Hash Table)是一种基于键(Key)直接访问数据的高效数据结构,其核心思想是通过哈希函数将键映射到数组的特定位置,从而实现平均时间复杂度为 O(1)O(1) 的插入、查找和删除操作。 + +## 结构定义 +```c +// 哈希表节点 +typedef struct HashNode { + int key; + int value; + struct Hashcode* next; +} HashNode; + +// 哈希表 +typedef struct { + int size; + HashNode** buckets; +} HashTable; +``` + +## 初始化 +创建HashTable结构体变量,进行初始化赋值,分配桶的内存。 +```c +// 初始化哈希表 +HashTable *creat_hash_table(int size) +{ + HashTable* table = (HashTable*)malloc(sizeof(HashTable)); + table->size = size; + table->buckets = (HashNode**)malloc(size * sizeof(HashNode*)); + for(int i = 0; i < size; i++) + { + table->buckets[i] = NULL; + } + return table; +} +``` + +## 哈希函数 +```c +// 哈希函数 +int hash(int key, int size) +{ + return key % size; +} +``` + +通过简单取模运算获得哈希值 + +## 插入 +```c +// 插入 +void insert(HashTable *table, int key, int value) +{ + int index = hash(key, table->size); + HashNode *newNode = (HashNode *)malloc(sizeof(HashNode)); + newNode->key = key; + newNode->value = value; + newNode->next = NULL; + + // 插入链表头部,避免遍历链表 + if (table->buckets[index] == NULL) + { + table->buckets[index] = newNode; + } + else + { + newNode->next = table->buckets[index]; + table->buckets[index] = newNode; + } +} +``` +头插法无需遍历到尾部。 + +## 查找 +```c +// 查找 + +int search(HashTable *table, int key) +{ + int index = hash(key, table->size); + HashNode *current = table->buckets[index]; + while (current != NULL) + { + if (current->key == key) + { + return current->value; + } + current = current->next; + } + return -1; +} +``` + +## 删除 +```c +void deleate(HashTable* table, int key) +{ + int index = hash(key, table->size); + HashNode* current = table->buckets[index]; + HashNode* prev = NULL; + + while(current != NULL) + { + if(current->key == key) + { + if(prev == NULL) + { + table->buckets[index] = current->next; + } + else + { + prev->next = current->next; + } + + free(current); + return; + } + prev = current; + current = current->next; + } +} + +``` diff --git a/content/posts/【数据结构与算法】栈.md b/content/posts/【数据结构与算法】栈.md new file mode 100644 index 0000000..b41b715 --- /dev/null +++ b/content/posts/【数据结构与算法】栈.md @@ -0,0 +1,107 @@ +--- +abbrlink: 3557841346 +categories: +- 往昔 +date: "2025-05-11 10:09:21" +tags: +- 数据结构与算法 +title: 【数据结构与算法】栈 +--- + +## 基本概念 + +栈(Stack)是一种后进先出(LIFO)原则的线性数据结构。核心操作包括: + +- 压栈(Push):将元素添加到栈顶 +- 出栈(Pop):移除并返回栈顶元素 +- 查看栈顶(Check)获取但移除栈顶元素 +- 判空(is_empty)检查栈是否为空 + +## 结构定义 + +使用动态数组实现栈,包含三个核心属性: + +```c +typedef struct Stack { + int* data; // 存储元素的数组 + int top; // 栈顶指针(当前元素位置) + int capacity; // 栈的最大容量 +} +``` + +- `data`:动态分配的数组指针 +- `top`:初始值为-1,表示空栈,压栈时递增,出栈时递减 +- `capacity`:栈的容量上限 + +## 功能实现 + +### 初始化 + +```c +// 初始化栈 +void init_stack(Stack *s, int capacity) { + // 计算最大容量 + s -> data = (int*)malloc(sizeof(int) * capacity) + if(!s -> data) { + printf("内存分配失败!\n"); + exit(1); + } + // 初始化栈顶为-1,表空 + s -> top = -1; + // 把当前计算的最大容量赋值给传进来的栈 + s -> capacity = capacity; +} +``` + +这个函数中进行了动态分配内存计算最大容量,初始化赋值和异常处理。 + +### 压栈(Push) + +```c +// 压栈(Push) +void push(Stack *s, int value) { + if (s -> top = s -> capacity -1) { + printf("栈已满!\n"); + return; + } + s -> data[++s->top] = value; +} +``` + +检查栈是否已满,先递增指针再存入数据 + +### 出栈(Pop) + +```c +// 出栈(Pop) +int pop(Stack *s) { + if(is_empty(s)) { + printf("栈为空!\n"); + return -1; + } + return s->data[s->top--]; +} +``` + +检查栈是否为空,返回当前栈顶元素后移动指针 + +### 辅助功能 + +```c +// 判空 +int is_empty(Stack *s) { + return s-> top == -1 +} + +// 查看栈顶元素 +int peek(Stack *s) { + return is_empty(s) ? -1 : s->data[s->top]; +} + +// 销毁 +void destory_stack(Stack *S) { + free(s->data); + s -> top = -1; + s -> capacity = 0; +} +``` diff --git a/content/posts/【无废话】全网最简单的Hexo+Obsidian图片解决方案.md b/content/posts/【无废话】全网最简单的Hexo+Obsidian图片解决方案.md new file mode 100644 index 0000000..4b9091f --- /dev/null +++ b/content/posts/【无废话】全网最简单的Hexo+Obsidian图片解决方案.md @@ -0,0 +1,23 @@ +--- +abbrlink: 1008281873 +categories: +- 往昔 +date: "2025-03-05 21:17:42" +tags: +- Hexo +- Obsidain +- 博客 +title: 【无废话】全网最简单的Hexo+Obsidian图片解决方案 +--- + +把Hexo博客根目录用黑曜石打开,如果已经打开了仓库 + +在弹出的窗口中选第二个。 + +在source目录下新建images文件夹用于存放图片 +设置 => 文件与链接 => 附件默认存放路径:选择指定的附件文件夹。路径填写刚刚创建的image文件夹的相对路径 +取消使用Wiki链接 +注意。由于我的文件结构是这样的所以这么填写,要**根据自己的文件结构填写相对路径**。 + +搞定,同时可以在本地编辑环境和博客网站中显示。 + diff --git a/content/posts/【星落】关于我对命运既定的想法.md b/content/posts/【星落】关于我对命运既定的想法.md new file mode 100644 index 0000000..d5ac2b8 --- /dev/null +++ b/content/posts/【星落】关于我对命运既定的想法.md @@ -0,0 +1,41 @@ +--- +abbrlink: 2888969971 +categories: +- 往昔 +date: "2025-06-03 20:47:13" +tags: [] +title: 【投稿】关于我对命运既定的想法 +--- +> 本文作者:[星が落ちる](https://space.bilibili.com/1920354618) +> 本文观点仅代表作者个人观点,不代表任何除作者外的个人或组织的立场。 + +我的观点或许和强决定论很相似,我认为人类存在本质上是一种“预置框架”下的时间性展开,所谓自由意志与命运抗争,都是框架内既定的程序脚本 + +## 存在的结构性预设 + +宇宙并非混沌的随机,而是一个蕴含精密内在逻辑与因果的拓扑结构。人类个体,是其中的特定节点,生命轨迹并非无中生有,而是被预编于这个宏观框架之中,此框架并非物理牢笼,而是一套时间-事件-可能性的完备集合。它规定了每个个体生命中所有的经历、选择、结果。我们个体看似无穷的可能性,实则严格限定于框架所划定的可能性空间之内 + +## 时间的预分配性与行为的伪自由 + +我们做任何事并非源于主体的绝对自由,而是对框架内预设时间槽的填充。我们在特定时刻产生做某事的冲动、做出某个决定、采取某项行动——这些看似自主的瞬间,实则是框架内预设的触发点被激活。早与晚的差异,体现为个体在框架内遍历其预设事件序列的不同速率或路径选择。事件的必然性及其在人生中的结构性位置已被既定。 +既定的事必定会发生。 + +## 框架内的元叙事 + +许多人说只要自强不息努力奋斗就可以战胜命运、主宰命运,而事实真的如此吗? +我认为人类引以为傲的战胜命运的壮举,其本身即为框架剧本中不可或缺的高潮篇章,在面对预设的逆境、挑战或命运枷锁时,所迸发的反抗意志、运用的智慧策略、付出的艰辛努力,以及最终取得的胜利——这一切情感、思考与行动的总和,都是框架预先设定的核心情节要素。 +所谓打破枷锁的快感与成就感,本质上是框架赋予个体体验其预设角色的情感反馈机制。人类在抗争中所依赖的勇气、毅力、才智等品质,同样是框架赋予该角色的属性配置。因此,战胜命运非但不是对框架的逃脱,反而是对其叙事张力与复杂性的完美演绎,是框架维持其动态平衡与戏剧性的自洽设计。 + +## 存在的意义 + +我的这种观点可能超越了机械的因果,指向一种蕴含复杂可能性、个体体验丰富性甚至伪自由模拟的结构性宿命论。我的观点不同于宗教宿命论,不诉诸人格化神明,而诉诸一个抽象的、自洽的、包罗万象的存在逻辑系统。 +在框架下,存在的意义不在于创造命运,而在于深度体验与理解自身角色。 +框架内预设的体验序列对每个个体而言是独一无二且不可替代的。即使意识到框架的存在,这种感觉本身也是框架赋予的一种深刻体验,是角色复杂性的体现。 +如同盆景展现自然之美,个体在命运框架的既定中,依然可以追求情感、智慧、创造力的内在充盈与表达,这种绽放同样是框架预设的珍贵可能性。 + +宇宙如同一个编写了所有可能世界线的超级程序,而人类意识则是运行于此程序中的、具有自我叙事功能的独特进程。 +我们的自由选择,是对程序分支的遍历命运的枷锁,在此视角下,人生并非一场开放的冒险,而是一场在既定剧本中力求深刻演绎、并从中获得独特存在性领悟的庄严旅程。框架是牢笼,亦是舞台;是限制,亦是成全。 +在必然性的重压下,我们或许可以寻找到一种深刻的宁静与对生命本身更谦卑的敬畏。 + +我们能做的就是尽可能在框架下演绎精彩的人生。 + diff --git a/content/posts/【未解决】Windows-WSL报错:Error-0x80080005.md b/content/posts/【未解决】Windows-WSL报错:Error-0x80080005.md new file mode 100644 index 0000000..4bec069 --- /dev/null +++ b/content/posts/【未解决】Windows-WSL报错:Error-0x80080005.md @@ -0,0 +1,245 @@ +--- +abbrlink: 1348465439 +categories: +- 往昔 +date: "2025-03-04 20:58:30" +tags: +- Windows +- Linux +title: '【未解决】Windows WSL报错:Error: 0x80080005 ???????' +--- + +设备环境: +``` +操作系统:Windows 10 +安装系统:Arch Linux +错误日志: +Installing, this may take a few minutes... +WslRegisterDistribution failed with error: 0x80080005 +Error: 0x80080005 ??????? + +Press any key to continue... +``` + +网上有一篇[文章](https://ask.csdn.net/questions/7625716)提到这个错误,下面的评论回复以管理员权限运行命令提示符并执行`sc stop LxssManager`和`sc start LxssManager` +出现如下报错: + + +``` +C:\Windows\system32>sc stop LxssManager +[SC] OpenService 失败 1060: + +指定的服务未安装。 +``` + +顺藤摸瓜,在网上寻找`LxssManager`这个服务要如何安装。 +网上暂时还没有找到相关文章能够解决这个问题,但是CSDN的一篇文章引起了我的注意 +[[SC] OpenService 失败:1060指定的服务未安装_[sc] openservice 失败 1060: 指定的服务未安装。-CSDN博客](https://blog.csdn.net/renwudao24/article/details/52061906) +文章中提到了“服务”,在开始菜单中搜索服务,进入应用找到了一个名为WSL Service的服务。点左上角启动。 +提取关键信息:**1058、被禁用、关联的设备没有启动**。 +检查功能是否开启:按下 `Win+S` 搜索 **启用或关闭Windows功能** +勾选`适用于Linux的Windows子系统`和`虚拟机平台`这两项,点击确定 +重启电脑。 +回来以后,用管理员身份运行powershell,强制重置WSL服务,依次执行: + +```bash +wsl --shutdown +wsl --unregister Arch # 替换为你的发行版名称 +wsl --install -d Arch # 重新注册发行版 +``` + +如果提示内核缺失,在这里下<https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi> + +如果有以下输出: + +``` +zcz system32 ♥ 21:32 wsl --shutdown +此应用程序需要适用于 Linux 的 Windows 子系统可选组件。 +通过运行安装它: wsl.exe --install --no-distribution +可能需要重新启动系统才能使更改生效。 +错误代码: Wsl/WSL_E_WSL_OPTIONAL_COMPONENT_REQUIRED +``` + +两种可能: + +1. 没有安装WSL服务 +2. **服务被禁用** + 后者比较棘手,我们先做第一种尝试 + **强制安装WSL组件** + **以管理员身份运行 PowerShell**,执行以下命令: + +```bash +# 安装WSL核心组件(会自动启用虚拟化功能) +wsl --install +``` + +输出: + +``` +zcz system32 ♥ 21:34 wsl --install +正在安装 Windows 可选组件: Microsoft-Windows-Subsystem-Linux + +Deployment Image Servicing and Management tool +Version: 10.0.19041.3636 + +Image Version: 10.0.19045.5487 + +启用一个或多个功能 +[==========================100.0%==========================] +The operation completed successfully. +正在安装 Windows 可选组件: VirtualMachinePlatform + +Deployment Image Servicing and Management tool +Version: 10.0.19041.3636 + +Image Version: 10.0.19045.5487 + +启用一个或多个功能 +[==========================100.0%==========================] +The operation completed successfully. +请求的操作成功。直到重新启动系统前更改将不会生效。 +``` + +再次进行重启。 +`Restart-Computer` +开机加载界面显示:我们无法完成更新,正在撤销更改。。 +尝试过的方法:进入安全模式,尝试重启更新,失败。 +安全模式仍然失败,选择临时禁用WSL服务 +管理员cmd执行 + +```powershell +sc config LxssManager start= disabled +shutdown /r /t 0 +``` + +输出: + +``` +C:\Windows\system32>sc config LxssManager start= disabled&& shutdown /r /t 0 +[SC] OpenService 失败 1060: + +指定的服务未安装。 +``` + +唉,老朋友,又见面了。只能祭出来我的终极大杀器。 + +### **彻底重装WSL** + +```powershell +# 卸载所有发行版 +wsl --unregister * +# 删除残留配置 +Remove-Item -Path "$env:USERPROFILE\AppData\Local\Packages\*Linux*" -Recurse -Force +``` + +输出: + +``` +zcz system32 ♥ 22:04 # 卸载所有发行版 +> wsl --unregister * +> # 删除残留配置 +> Remove-Item -Path "$env:USERPROFILE\AppData\Local\Packages\*Linux*" -Recurse -Force +正在注销。 +此应用程序需要适用于 Linux 的 Windows 子系统可选组件。 +通过运行安装它: wsl.exe --install --no-distribution +可能需要重新启动系统才能使更改生效。 +错误代码: Wsl/WSL_E_WSL_OPTIONAL_COMPONENT_REQUIRED +``` + +输入`wsl.exe --install --no-distribution` +输出: + +``` +zcz system32 ♥ 22:09 wsl.exe --install --no-distribution +正在安装 Windows 可选组件: Microsoft-Windows-Subsystem-Linux + +Deployment Image Servicing and Management tool +Version: 10.0.19041.3636 + +Image Version: 10.0.19045.5487 + +启用一个或多个功能 +[==========================100.0%==========================] +The operation completed successfully. +正在安装 Windows 可选组件: VirtualMachinePlatform + +Deployment Image Servicing and Management tool +Version: 10.0.19041.3636 + +Image Version: 10.0.19045.5487 + +启用一个或多个功能 +[==========================100.0%==========================] +The operation completed successfully. +请求的操作成功。直到重新启动系统前更改将不会生效。 +``` + +继续重启,显示“我们无法完成更新,正在撤销更改。” + +**以管理员身份打开CMD**: +按下 `Win+S` → 输入 `cmd` → 右键选择 **“以管理员身份运行”** **执行以下命令(注意语法)**: + +```cmd +sc config LxssManager start= auto +sc config vmcompute start= auto +net start LxssManager +net start vmcompute +``` + +仍然1085,管理员cmd执行 + +``` +dism /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart + +dism /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart +``` + +尝试重装WSL,出现 +![[_posts\Windows-WSL报错:Error-0x80080005\Pasted image 20250304222548.png]] + +研究了一阵子,**`vmcompute`**(虚拟机核心服务)和 **`LxssManager`**(WSL管理服务)均未注册,导致WSL安装向导崩溃。 + +```Powershell +# 以管理员身份运行 +dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart +dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart +dism.exe /online /enable-feature /featurename:HypervisorPlatform /all /norestart +``` + +重启,“我们无法完成更新,正在撤销更改。” +。。。。。、、、、 +尽力了。现在看来,是系统层面的硬伤了。可能行得通的有重装系统和保留文件重置系统两个选择。不过我还是会和这个问题死磕一下,我就不信我干不成这个事。明天还要苦逼上学,先睡了。 +2025.3.4 22:57 + +———————————————————————————— + +2025.3.5 + +尝试**强制修复系统核心组件** + +``` +# 以管理员身份运行 PowerShell +sfc /scannow +DISM /Online /Cleanup-Image /RestoreHealth +``` + +**重置 Windows Update 组件** + +``` +# 管理员cmd执行 net stop wuauserv +net stop cryptSvc +net stop bits +net stop msiserver +rmdir C:\Windows\SoftwareDistribution /S /Q +net start wuauserv +net start cryptSvc +net start bits +net start msiserver +# 强制重建WSL核心服务 +sc create vmcompute binPath= "C:\Windows\System32\vmcompute.exe" start= auto type= kernel +sc create LxssManager binPath= "C:\Windows\System32\lxss\LxssManager.dll" start= auto type= own +net start vmcompute +net start LxssManager +``` + +仍然无法启动。使用wsl偶遇神秘怪异bug拼尽全力无法战胜。我都已经浪费这么长时间来研究这个问题,为什么我不直接装个Linux系统呢。周末就把这傻卵系统换成Arch! diff --git a/content/posts/一文不值的疑云.md b/content/posts/一文不值的疑云.md new file mode 100644 index 0000000..2e5b3c2 --- /dev/null +++ b/content/posts/一文不值的疑云.md @@ -0,0 +1,71 @@ +--- +date: 2025-09-27T13:15:25+08:00 +draft: false +title: 一文不值的疑云 +slug: the-unfounded-cloud +categories: + - 随笔 +tags: + - 散文 + - 记事 + - 学校 +--- +周三,老师提醒我们,明天有一个测评,需要记住自己的身份证号。放学后又在班级群发了一条通知提醒,看来是很重要的事。 + +转天上午的一个大课间,班主任要带我们去参加那个测评了,正当我准备起身去楼道里站队,老师跟我说: + +「你妈说你不参加,你在屋里待着就行了。」 + +我有点懵了,旁边几个人围着我问为什么我不参加,我有什么心理问题吗?到这时候我才知道,原来是上面安排的心理测试。那些问题我只能回答不知道,我真的什么都不知道。那些问题凝成了厚厚的疑云悬挂在我胸口。庆幸和不安缠绕在那团云里。 + +<!--more--> + +一方面,我庆幸于不用参加这种活动,可以自己一个人在教室里安安静静地,沉浸在自己的思绪里;另一方面,我不安于全班,甚至全校只有我一个人没有参加这个活动,以及,母亲为什么没有让我参加?难道我真有什么问题吗?种种猜想和预测占据了我的脑海,那些可恶的不安已经把所有原本打算考虑的问题,全部挤压出去了。 + +我低着头,烦躁地翻动一本课外书,那书本劣质的墨水和纸张,导致翻开之后就有一股工业的恶臭弥漫开,又和我周身流露出来的不安的恶臭混合在一起。门外其他班级也站好队走了,吵闹终于结束了,楼道里如冬日般寂静,使我更能沉浸在不安里。 + +是父母想到了什么,深思熟虑的结果,让我不参加吗?是他们的问题,还是我的问题呢?如果是他们的问题,他们为什么认为我不应该参加这次心理测试呢?如果是母亲的问题,难道她又诉诸玄学了?如果是我的问题,我到底需不需要参加这次测试?是因为他们觉得我心理有问题才不让我参加,还是因为他们断定我就是一个健康向上,热爱学习的好学生,才不让我参加那种活动? + +不安和沮丧之间需要一架精妙的桥梁,我的永不停歇思考和猜测,正是最贴合河水两岸缺口的桥,那条河流奔腾着绝望,在思考的独木桥上一不小心就会跌入河流,在绝望的冲刷下被河床的石头磕得头破血流。但这样的结果,说到底还是自己走独木桥的技艺不精。 + +无尽的猜忌的折磨,像鬼打墙一样,必须有一个外人进来才能打破。第一个回来教室的人成了这个角色。我从初一开始就很讨厌他,他总是看着我的脸在偷笑,说我严肃的表情很滑稽,但那就是我最日常的表情,我不是故作严肃。只是每当我开始思考一些问题,最终感受都会导向痛苦,那表情只是大脑内痛苦的外在显现。他又看到了自己最喜欢的那个表情,摇着尾巴朝我跑过来,我坐在座位上,他用手搂住我的脖颈,用他的额头紧紧贴着我的额头,在我面前憋笑。他离我太近了,我能感受到他轻浮的吐息,和身上浅薄的气味。这就是肢体接触带来的几乎让我呕吐的感觉。我不理解为什么这个人每天都能那么开心,每天的精力和活力像用不完一样,以及为什么和很多女同学都有勾搭。他又问出我最想得到答案的那个问题: + +「你为什么没去?你有心理问题吗?」 + +我只能尴尬地回应:我也不知道为什么。 + +得不到答案,胸口这云就永远也不会消散,越是思考,想得出答案,那团云就越是厚重,越压得我喘不过气。我也无心听课和默写,化学默得一塌糊涂,重新默写的几道题也几乎全错,直到今天还没解决,我也无力去解决了。那个问题始终在我心头,到底为什么我不去? + +所有人都陆续回来了,开始上课后,我的思绪更没有寄存之地了,它就像一根点燃的火柴,马上就要烧到我的手,点燃全身了,火势已经不可控制,只有得到问题的答案才能扑灭这团火,但不放学找到母亲,永远也得不到这个问题的答案。我就这样被烈火反复舔舐着,一场凄美的自焚在教室里开始了,他只会慢慢烧焦我的皮肤,永远无法灼伤我的内脏,给我一个彻底的解脱。 + +熬过了一节课,我就趴在桌子上继续想,我向来下课都喜欢趴在桌子上装睡,这样是最安全的方式,但我得不到答案。 + +下午开始了运动会列队彩排。这种出狱即赴死般的囚犯的活动,在整齐的队列里喊着力量迸发的口号的活动,在我眼里一直有着悲戚色彩,但我又不能不参加。上次体育课训练,我发现我被围在队伍中间,队伍被围在学校篮球场中间,篮球场被围在学校高高的围墙中间。 + +我们站在阴凉地。前面同学浓烈的体臭让我的眉头紧皱,但他的心地善良,看到我那样的表情,说: + +「怎么老愁眉苦脸的,多想想让自己开心的事吧。」 + +让我难过的事,就在我眼前。无论是他的体臭,还是问题的答案,都近在咫尺,又远在天边。只要屏住呼吸就闻不到了,只要停止思考就不难过了。 + +在初一的时候,好像没有节目,今年有三个同学组织了一个舞蹈节目,我们剩下的同学要手里拿着一把小扇子作为背景板配合她们的演出。我看着手里的折扇,再徐徐将它展开,大红背景色的扇面,一支白色的梅花占了三分之一,再展开就什么都没有了,只有一片红。这把扇子给人一种不调和的丑陋感。我这三年就像这把扇子,已经展开了三分之二,但在一支凄美的梅花之后,什么也没有。从侧面看这把扇子,褶皱跌宕起伏,其中一根扇骨还裂开了,扇子可以折起来再甩开,但这处裂痕永远也回不到先前的样子了。开扇的那一过程,如果不达到尽头,就绝对不可能停下来吧? + +我又沉浸在自己悲情的幻想里,感官被屏蔽了,等到队伍走起来,穿过操场围栏大门,从一片阴翳之中到阳光普照的操场,我瞬间以为自己在梦中,但热辣的阳光照得我皮肤刺痛,为什么这样都不会醒来呢? + +主席台上站着一个女生,手里拿着话筒,用尖细的声音读着学生提交上去的介绍词,最常出现的词汇就是青春、汗水、胜利......我向来厌恶这种充满力量感的词,但我对这场运动会没有任何贡献,有什么资格评价呢?我跟着队伍行走完全交给下意识的本能,大脑完全沉浸在幻想中了。 + +本能,真伟大啊,帮我暂时运行身体,应付那些琐事,好让我能沉浸在自己的思绪里,彩排结束回到教室的过程中,我看见了跑道上的地漏,我觉得那简直就是为了让扇子掉下去拿不上来而生的,如果我手里的扇子不存在,那么这里所有的地漏都没有了存在的意义。 + +在猜忌的痛苦里熬过了剩下的几个小时,终于放学,给母亲发了条消息。 + +「为什么不让我参加那个测评啊?」 + +「你不参加的是心理测试的那个。」 + +「为什么不参加?」 + +「老师早晨说不参加的尽快私信,我以为可以不参加。我也以为没什么用,就想着赶紧告诉她。」 + +我能说我的母亲愚蠢吗?我舍不得,我也不敢埋怨她。她早上确实非常忙碌,没有时间细看消息。但我如此复杂剧烈的情感,原因竟是母亲的「我以为」导致的,一切痛苦和挣扎都是徒劳吗?她也许察觉到了我的难过,就跟我说,之前参加的比赛,获奖证书到了,明天给我拿去。 + +于是,本应该是荣誉的事,在此刻被彻底玷污了。
\ No newline at end of file diff --git a/content/posts/一次对Webmention的探索.md b/content/posts/一次对Webmention的探索.md new file mode 100644 index 0000000..7870fe7 --- /dev/null +++ b/content/posts/一次对Webmention的探索.md @@ -0,0 +1,82 @@ +--- +date: '2025-12-05T17:22:22+08:00' +draft: false +title: '一次对Webmention的探索' +slug: 'exploring-webmention' +categories: + - 技术 +tags: + - Webmention + - 去中心化 + - 博客 +--- +> Webmention is a simple way to notify any URL when you link to it from your site. +> +> It is an open web standard (W3C Recommendation) for conversations and interactions across the web, a powerful building block used for a growing distributed network of peer-to-peer comments, likes, reposts, and other responses across the web. + +Webmention 是一种开放网络标准(W3C推荐标准),用于在链接到某个网址时,自动向该网址发送通知。它是构成分布式网络的基础组件,支持跨网站的点对点评论、点赞、转发等多种互动。 + +在 [上一篇文章](https://www.glowisle.me/posts/tear-hypocrisy-apart/) 写完后,我开始寻找更合适的评论方案。Webmention这个看起来古老,但又超前的形式很快引起了我的兴趣。「去中心化」这个词貌似对我有什么魔力,就比如Mastodon,比Twitter更吸引我。 + +我很想试试用Go手搓一套收发系统,但时间并不充裕,正巧[webmention.io](https://webmention.io)提供现成的服务和[详细的文档](https://indielogin.com/setup),那就跟着文档配置吧。 + +## 验证与接收 + +教程提供了多种验证方案,这里使用最简便的Github. 只要在网站的首页挂上一个链接,指向用户档案页: + +```html +<a href="https://github.com/example" rel="me">github.com/example</a> +``` + +如果不想让它可见,也可以设置为一个`<link>: + +```html +<link href="https://github.com/example" rel="me"> +``` + + + +这里我部署后回退了一下网页就弹出来Github APP 认证请求了,大概需要刷新网页或打开Github? + +这样,访问之后页面中提供的链接,就可以看到别人发送的Webmention了。 + +## 渲染 + +在网页中添加link + +```html +<link rel="webmention" href="https://webmention.io/你的用户名/webmention" /> +``` + +我使用[webmention.js](https://github.com/PlaidWeb/webmention.js),根据说明文档,可以复制仓库中的`/static/webmention.min.js`到博客的`/static/js/webmention.min.js`. + +在评论框下方提供一个容器`<div id="webmentions"></div>`,并引用脚本 + +```html +<div id="webmentions"></div> +<script src="/js/webmention.min.js" + data-id="webmentions" // 与容器id匹配 + data-page-url="https://yourdomain.com/当前文章永久链接" // 建议使用 + data-max-webmentions="50" // 最多显示数量 + data-wordcount="30" // 回复预览最大字数 + data-sort-by="published" // 按照发布时间排序 + data-sort-dir="up" // 时间升序 + async> +</script> +``` + +Hugo用户在永久链接上可以使用: + +```html +data-page-url="https://yourdomain.com{{ .RelPermalink }}" +``` + +为了本地测试,使用相对链接的变量拼接。脚本会对API发送请求,如果拿到的数据是空的,则会把最终的HTML输出为一个空字符串,所以刚开始看不到输出是正常的。大概写点CSS就可以正常投入使用了。 + +## 对Webmention的看法 + +我认为Webmention是一种很像友情链接的互惠模式,优于在评论区下方留下链接的形式。续上上一篇文章的话题,这样不仅促成高质量的互动,也能丰富自己的写作素材,分量应该重于评论区链接的手段。就像上一篇文章的结尾所说,利人利己,何乐而不为呢? + +虽然这种模式的普及程度不高,但我相信去中心化会称为互联网的新趋势。开放、互联才能称为「互联网」。 + +我通过一些Webmention,一条一条顺藤摸瓜也找到了很多有趣的博客。我准备有时间优化渲染格式,可能也会研究一点桥接的功能,不过还是要保持博客一贯的简洁风格。当然,要先有人回应才有数据拿来渲染,欢迎大家使用Webmention参与互动! diff --git a/content/posts/万能必胜沟通法.md b/content/posts/万能必胜沟通法.md new file mode 100644 index 0000000..e0edee3 --- /dev/null +++ b/content/posts/万能必胜沟通法.md @@ -0,0 +1,25 @@ +--- +categories: +- 往昔 +date: "2025-07-21T19:04:43+08:00" +draft: false +slug: "" +tags: +- 小品 +- 沟通 +title: 万能必胜沟通法 +--- + +我有问题,你指出 = 你在犟嘴。 + +我要输出情绪:你在犟嘴。 + +我不想解决问题 = 你在犟嘴,并且我不理你。 + + +精神胜利大法万岁! + +不容置疑的皇权万岁!! + +至高无上的皇权万岁!!! + diff --git a/content/posts/三岛由纪夫——文化和时代背景塑造的矛盾体.md b/content/posts/三岛由纪夫——文化和时代背景塑造的矛盾体.md new file mode 100644 index 0000000..1aff483 --- /dev/null +++ b/content/posts/三岛由纪夫——文化和时代背景塑造的矛盾体.md @@ -0,0 +1,42 @@ +--- +date: '2025-09-06T17:32:44+08:00' +draft: false +title: '三岛由纪夫 —— 文化和时代背景塑造的矛盾体' +description: "三岛由纪夫,一个伟大的小说家、一个迷恋死亡的疯子、一个狂热的右翼分子。" +slug: 'yukio-mishima' +categories: + - 读书 +tags: + - 三岛由纪夫 + - 日本文学 +--- + + +三岛由纪夫,一个伟大的小说家、一个迷恋死亡的疯子、一个狂热的右翼分子。 + +这个月四日,在《丰饶之海》四部曲后,我收到了这本由约翰·内森编撰的《三岛由纪夫传》。当时我的心情是无比激动的,因为我马上就要触摸到这位伟大作家的人生一角,一个鲜活而丰满的三岛即将展现在我眼前。 + +今日九点至十六点,在之前阅读《金阁寺》、《潮骚》、《仲夏之死》等作品所催生出的崇拜感、以及对他人生的极度好奇心和窥探欲的驱使下,一口气读完了这本书。读完后,刚拿到书的那种激动荡然无存,取而代之的是一股怅然若失,一股意犹未尽...... + +三岛由纪夫,本名平冈公威。其童年经历奠定了他情感丰富的内心,强势的祖母对他的控制欲使他受尽压抑,催生出一幅「假面性格」。为了减少母亲的焦虑,在母亲面前极力隐藏真情实感;为逃避现实的苦痛,投身于幻想和文学中;环境造就的早熟,让他在文学界崭露头角 —— 这是我个人对三岛童年时期的概括。他对鲜血、暴力等元素的追求和逃避现实的幻想,让我想起《金阁寺》中,沟口的心里活动: + +> 倘使我是个结巴而寡言的暴君,那么家属们窥见我的脸色,就会终日战战兢兢地生活。我没有必要用明确而流畅的语言来使我的残暴正当化,因为只要我寡言就可以使一切残暴正当化。这样,我总乐于幻想把平日藐视我的教师和同学一个个地处以刑罚。我还乐于幻想我成为内心世界的国王,成为冷静观察的大艺术家。尽管我表面很贫穷,可精神世界却比谁都富有。 + +此处的心里活动定是三岛童年时期的写照,也符合三岛自己所言:「我不会描写自己没见过的事物。」 + +公威的祖母夏子对他的管控是极其病态的,从小只允许他与稍年长于他的女性玩耍,禁止一切带有危险性的或可能发出噪音的玩具出现,以及禁止公威出门,这一切都在潜移默化地塑造着他的「女性气质」。而童年时期异性过度的陪伴、对希腊古典美学的痴迷,也是影响三岛对男性健硕肉体的向往的重要因素。 + +三岛的人生可以分为前中后期三个阶段。在出生及《假面的告白》发表前,可以作为前期,这个阶段他表现出文学方面的天赋。而同《告白》可认为是其半自传体作品的《镜子之家》,作为中期和后期的分界,《镜子之家》已经表现出令人不安的对死亡的美化和向往,为《忧国》等风格近似的作品奠定了基础。中期的《金阁寺》也是日本文学中浓厚艳丽的一笔。 + +他是时代和文化背景造就的政治疯子,但无论哪个时期的三岛,在文学上所表现出的能力及建树,是绝对成功且伟大的。三岛是战后日本青年信仰崩塌影响的极端化,其童年家庭环境,以及当时三岛学习成绩优异,考试排名榜首,天皇亲自为他颁发银手表,都在为其后来的闹剧扇风点火。 + +三岛自杀的真正原因众说纷纭,我认为这是多方因素共同影响造成的。文学界,三岛多次翘首盼望诺贝尔文学奖颁给自己,他太想要这个奖了,而导师川端康成先获诺奖,这或许让他感到绝望,在汽车里沮丧地说「他们未来十年也不可能颁奖给日本了」也可以作为此观点的有力证明。 + +政治方面,三岛所崇尚的「武士精神」,和「为天皇赴死的光荣」高度重合。曾多次试图加入军队的经历可以看出他野心的流露,但日本战败、丧失军事主权的现实让他一度陷入绝望和挣扎中。所以他召集和他同样有野心的右翼军国主义残余,组织了私人武装,整日演练与假想敌,也就是可能危及天皇安全的左翼发动的暴乱的战斗。最终还是做起了日本右翼至今矢志不渝的修宪大梦[^1],发动兵变,最终上演切腹自尽的闹剧,实现了一直所幻想的「英雄式的死亡」,完成了一场荒诞的政治表演。除「盾会」活动外,三岛还发表了著名论著《文化防卫论》,其中观点可粗略概括为「天皇是日本文化的源头以及守护者」,体现其拥护天皇的思想。 + +在文学方面,他无疑是非常成功的。华美的词藻几乎穷尽人类语言能够表达的全部,而政治方面,其在文学上流露出的对死亡的美化、迷恋、向往成为了三岛通向兵变之路的最后一块砖。我为如此杰出的文学家死得竟这样荒谬而感到惋惜! + +读完此书,曾经的一个完美、伟岸的三岛在我内心崩塌了,而一个更加丰满立体,具有多面性的三岛形象又在我内心被建立起来。优雅的、自律的、伟大的才子;极端的、荒谬的、病态的疯子......三岛啊!你的生命被自己迸发的才华之火燃尽了吗! + +[^1]:第九条【放弃战争,否认军备及交战权】<br>1.日本国民衷心谋求基于正义与秩序的国际和平,永远放弃以国权发动的战争、武力威胁或武力行使作为解决国际争端的手段。<br> +2.为达到前项目的,不保持陆海空军及其他战争力量。不承认国家的交战权 <br> ——[《日本国宪法(暂译)》](https://www.cn.emb-japan.go.jp/itpr_zh/kenpo_zh.html) diff --git a/content/posts/上帝类是什么?该如何避免上帝类?.md b/content/posts/上帝类是什么?该如何避免上帝类?.md new file mode 100644 index 0000000..2a48f0b --- /dev/null +++ b/content/posts/上帝类是什么?该如何避免上帝类?.md @@ -0,0 +1,30 @@ +--- +abbrlink: 964047394 +categories: +- 往昔 +date: "2025-03-30 10:47:35" +tags: +- 软件开发 +title: 上帝类是什么?该如何避免上帝类? +--- +## 什么是上帝类 +所谓的上帝类,就是指**一个类承担了过多的职能**,变得过于**臃肿**和**复杂**、**难以维护**。没有遵守单一职责原则。像上帝一样什么都能干,每个功能高度耦合,牵一发而动全身,不利于业务的拓展。 + +## 上帝类是如何产生的 +上帝类的产生,通常是由于需要快速实现功能而做出的妥协,长期积累就变成繁重的技术债务。或是缺乏规划经验,功能不断地被加到类中。依旧长期积累,上帝类产生了。 + +## 上帝类的优缺点 +上帝类虽然在上文被冠以臃肿、难维护的帽子,但并不代表他没有优点,要辨证地看待。 + +- 优点:上帝类适用于一些较小的、逻辑简单的任务或工具类,逻辑不复杂,也不需要长时间维护,即拿即用。不用过多地考虑职责和颗粒度的划分,也能提高开发效率 +- 缺点:即上文中所提到的。臃肿、复杂、难以维护、测试麻烦、缺乏可读性、耦合度高,不可拓展同时违反SRP和OCP原则 + +## 上帝类的判定 +- 代码行数判定法:代码行数很多的有可能是上帝类,注意是有可能。如果是上帝类,应当进行适当重构 +- 依赖关系判定法:通过分析类的依赖关系来判定其是否与其他类高度关联,如果是,他有可能是上帝类。 +- 职责判定法:如果一个类承担了过多的职责,他该干的也干了,不该干的也干了,那么毫无疑问,他是上帝类。 +- 测试覆盖率判定法: 如果一个类难以单元测试,或覆盖率低或总是出现奇奇怪怪的不可预测的问题,那么他有可能是上帝类。 + + +## 如何避免上帝类 +所以,要如何避免上帝类,这个问题的答案已经显而易见了。和上一段相反着做即可。遵守单一职责原则。规划好代码架构。比如,要处理一个压缩包解析和数据展示功能,首先就要拆分职责为不同的类。类中再去写相对应的函数。我们可以把这个功能拆分为解压、读取、展示信息三个类,类中分别编写相应的代码,这样就能做到避免上帝类的产生,从而提高代码的可维护性和可拓展性。 diff --git a/content/posts/不喊口号,不搞煽情:《南京照相馆》才是抗日题材该有的样子.md b/content/posts/不喊口号,不搞煽情:《南京照相馆》才是抗日题材该有的样子.md new file mode 100644 index 0000000..4f6092b --- /dev/null +++ b/content/posts/不喊口号,不搞煽情:《南京照相馆》才是抗日题材该有的样子.md @@ -0,0 +1,77 @@ +--- +date: '2025-11-30T20:36:51+08:00' +draft: false +title: '不喊口号,不搞煽情:《南京照相馆》才是抗日题材该有的样子' +slug: 'dead-to-rights' +categories: + - 观影 +tags: + - 《南京照相馆》 + - 电影 +--- + +学校里每周一次的美术课在升入初三后,改为放电影,我在学校看完了一大半的《南京照相馆》,今天在家看完了剩余部分。 + +先说结论,《南京照相馆》无疑是一部艺术水平、教育意义极高、角色塑造饱满、讽刺控诉手法辛辣的非常成功的电影。 + +## 为什么《南京照相馆》更出彩 + +《南京照相馆》比同类型影片更出彩的原因是,它以平民的视角,揭露了抗日战争时期日寇在南京城泯灭人性的暴行,让战争的残酷更能落地。电影没有以上帝视角带着必胜的信念,泛泛而谈战争,而是用平民百姓在战争中受到的伤害、屈辱、苦难、屠杀,把战时普通老百姓的无助和绝望展现给观众。这就让历史看得见、摸得着,感受得到。而且没有宏大的英雄主义叙事,没有无所不能的超人式的人物,而是聚焦在小人物的挣扎。 + +其表现手法精湛之处数不胜数,举几个让我印象深刻的例子: + + + + + +> 「保护那个人的生命,那是仁。」 +> +> 「在照相馆挂上了安全的牌子,那是义。」 +> +> 「向他们提供食物和药品,那是礼。」 +> +> 「借刀杀人,那是智。」 +> +> 「遵守诺言,给他们通行证,那是信。」 +> +> 「我的理解,没有错吧?」 + +那个军官一边用毛笔写着歪歪扭扭的汉字,一边自信地说着。每写一个字都穿插平民百姓被虐待凌辱杀害的镜头。 + +仁义礼智信,一个也不沾。 + +有一个小细节,图一的台词中,中英字幕的表述都是「那个人 / 那个男人」,而日语的台词中使用「もの」,意思是「物、东西」。这也回答了林毓秀问王广海的那个问题:「日本人会把我们当人看吗?」 + +人性都泯灭了,如何理解人权? + +--- + + + +在电影结尾,苏柳昌对伊藤用日语说出的强有力的「私たちは友達じゃない。絶対。」(我们不是朋友,绝对不是。)把这条从苏给伊藤洗照片开始的虚伪的「朋友」暗线推向高潮。 + +选用对方的语言,不是因为认可,而是确保对方能明确自己的态度。这句话不仅是对伊藤说的,也是说给今天的观众听的。它扯碎了美化或淡化历史的人给罪行扣上的面具,更是对当今日本的军国主义残余势力说的,振聋发聩。 + +从角色塑造上,以王广海为例,能看到一条清晰的成长轨迹。 + +在最初,王是一个麻木、圆滑、对日军抱有不切实际的期望且极尽谄媚的汉奸形象,经典言论是:「日本人主持南京,我们的好日子就来了。」 + +但在拍照片时日军把婴儿(华华)摔死后、在现场亲眼目睹屠杀后,对日军的态度慢慢发生改变,在自己的妻子快要被日军羞辱后彻底觉醒反抗,但也死在了大梦初醒的恍惚时分,被伊藤枪杀。 + +王广海和伊藤都是电影中层次感塑造非常好的角色,前者从麻木中觉醒人性和反抗精神,后者则一步步泯灭人性,显现出野蛮的本质,尽显侵华日军的虚伪、狡诈、残忍。 + +## 应当这样落实爱国主义教育 + +谈起抗日题材的影视作品,「爱国」是不得不说的一环。《南京照相馆》证明了,大家并不是讨厌以爱国为主旋律的电影,只是反感低水平的卖弄爱国情怀,以圈钱为目的烂片炒作和道德绑架。 + +我作为一个学生,向来对所谓「爱国主义教育」嗤之以鼻,因为它是烈日炎炎下空洞枯燥的演讲,是手抄报,是观后感、读后感,是一项任务,一个形式,是考试的标准答案,是政治正确。如上的所谓「爱国主义教育」倒不如说成「形式主义驯服」和「仇恨教育」。 + +而看了《南京照相馆》,切实体会到历史伤疤的疼痛和战争的残酷,是一种更高级更有效的教育,能让人更深刻认识到「国」是如何来的、为什么要爱国,以及和平的珍贵。 + +当今中日关系形式紧张,由于最近国内的发展状况,反日情绪高涨,高市早苗屡次冒犯,反复在台湾问题上试探底线,在九三阅兵后,不少人对可能会发生的战争持乐观甚至戏谑轻敌的态度,而教员早就在抗日战争刚刚拉开帷幕时撰写《论持久战》批驳了速胜论和速亡论两种错误的观点,其精神内核在今天仍旧有指导意义,即使敌我实力差距悬殊,过度乐观和轻敌都不是好的信号。 + +我们不仅要防日本军国主义复辟,更要防极端民族主义思潮的侵袭。针对日本平民的复仇思想,希望南京的惨剧在东京重演,也是不切实际且残忍的想法。应当正视并铭记历史而不是延续仇恨,关心身边为祖国做出贡献的底层人民和劳动者而不是空喊爱国口号。爱「国」这个抽象的符号,一定要落到具体的人。 + +虽然这部电影在艺术上取得了成功,但在技术上仍有不足之处[^1]、且结尾直接进入审判略显仓促,但总体来说是一部非常成功的电影,是一部很干净纯粹的电影,价值观导向正确、拍摄手法和思路水平高,反映真实的历史。它没有卖弄爱国情怀,也没有让侵略者怜悯的情节,而是用受害者的一腔悲愤和不屈为战争大背景下的小人物立碑作传。在惨烈的战争后,我们更应该珍爱和平,电影落幕后,窗外的安定与幸福就是最好的彩蛋。愿我们这一代人铭记历史,革命先烈安息,祖国繁荣昌盛,世界和平安定! + +[^1]: 1:22:26演员双手没有被捆至背后,在被杀害后手从身后挣扎开倒地;1:22:26伊藤翻开的抽屉中有左至右书写的简体字「档案袋」,下方有拼音「DANG AN DAI」。 diff --git a/content/posts/个人博客凭什么为你提供价值?.md b/content/posts/个人博客凭什么为你提供价值?.md new file mode 100644 index 0000000..2603bc3 --- /dev/null +++ b/content/posts/个人博客凭什么为你提供价值?.md @@ -0,0 +1,135 @@ +--- +date: 2025-09-30T22:25:35+08:00 +draft: false +title: 个人博客凭什么为你提供价值? +slug: the-value-of-blog +categories: + - 随笔 +tags: + - 杂文 + - 博客 + - 价值 + - 写作 + - 互联网 +--- +今天我在网上冲浪的时候,看见了一个收录博客的网站。收录的所有网站都是手动整理而来,并且对所谓博客的「价值」颇有一番见解,断章取义地引用了一段[知乎用户的回答](https://www.zhihu.com/question/19990156/answer/206653231)。原问题是回应关于个人博客的前途的,其中对博客的价值作出了一些判断。以下是原回答: + +<!--more--> + +<details> + + +<summary>点击查看详细内容</summary> + +我想来分析一下为什么很多个人博客 + +无疾而终,没“前途”。 + +## 对博客价值的根本性认识错误 + +以为个人博客是用来抒发“个人情感和认识”的,这是最常见的认识错误。这是我的博客,我写什么都可以,而且还假设自己写了东西别人就会来看。 + +没人在乎你情绪化的感情抒发,这对他们没多少用处。 + +个人博客更好的定义,是你以个人的名义发表对别人有价值的内容。所以个人博客内容创作的出发点不是让别人来关注自己,而是让自己为别人服务。 + +用博客内容为别人服务并不复杂,比如你写偏文章,介绍最近哪个店东西打折,只要你能把时间,地点,主体对象,促销力度等信息介绍清楚,就是一篇很有价值的博文。因为它对不少人有实际价值。 + +相反,你洋洋洒洒写一通美文,说得尽是些神神叨叨自怨自艾的个人情绪,除了你妈爱看以外,对别人没多少价值。你想开个博客靠抒发个人情感而不为别人的生活增值,却盘算着博客能有前途,这是无知,自以为是的痴人说梦。 + +## 没有质量的更新 + +很多个人博主的注意力,只有更新,不断更新,最好每天更新。只要能“保持更新”,就无所不用其极,完全失去内容建设。 + +需要的耐心。写文章就是随便胡诌两句,不用心,还让读者“随便看看,不喜勿爱”,甚至复制黏贴,采集抄袭,玩的都是些下三滥的手段。却还指望博客能有前途,真是消化[^1]。 + +更新是重要的,但有比更新更重要的事。是“价值”。 + +你写一篇优质的文章,哪怕是夏天室内防暑省电技巧大全,也会永远地存在于搜索引擎,会不断地有人访问,这篇文章会成为你的网站一个优质的lead。为你创造潜在的知名度,关注度,甚至带来物质利益。 + +中国的博主相对国外的博主,最大的缺点就是没有耐心,没有耐心,什么都做不成。除非你相信一个个人博客可以短时间内成功,不用积累。 + +## 不懂营销 + +酒香也怕巷子深,况且你真有好酒,为什么不多做一点,让更多人知道你有好酒? + +太多博主以为自己写了东西,花了力气,回报自然回来。有的时候确实是这样,比如你写的东西正好是别人不怎么写的一个特别的领域,也就是说,竞争小,或者运气好,干脆就是一片蓝海。 + +但这种机缘哪是人人都有?大部分人写的话题,都是很多人反复了不知道多少遍的,你写同一个主题的优势,无非是那是你自己独特的角度和构思,或者你的文字比别人用得好,讲故事有自己的风格,文章的结构超过他们,内容超过他们。 + +但仅有这些是不够的。 + +你得发现可能对你写的东西感兴趣的人群,把他们吸引过来,给他们一个机会理解你,也给你自己一个机会更好更快地走向成功。你得把营销看成一件正经事来做,不是让你去骗人,而是把好东西告诉需要知道的人。 + + +我举一个例子, 这是我自己的一个教别人学Javascript编程核心概念的小网站:[http://itlr.cc](https://link.zhihu.com/?target=http%3A//itlr.cc)。我确实花了一点时间去准备内容,主要是视频的,到目前卖了大概人民币4000块,几个月时间,其他收入加起来大概8000。这是不是很多钱,当然不是! + +我是不是在每天更新?没有,其实很久不更新了,但是微信上几乎每天都有人加。这网站有前途吗,有的,虽然谈不上大前途,但是发挥点工作外余热,自己也能学到东西。 + +你也可以,但要用点心,真把它当件事情来做,要学习不骗人的营销。 + +你会发现让一个网站有前途,是一件并不是很难的事。如果你没有耐心,是不会成功的。 + +</details> + +--- +我今天挖一七年的坟,评判一下关于价值的观点。 + +## 对博客价值的根本性认识错误 + +我们来看看百度百科怎么描述「博客」: + +> 许多博客专注在特定的课题上提供评论或新闻,其他则被作为个人性的日记。一个典型的博客结合了文字、图像、其他博客或网站的链接及其它与主题相关的媒体,能够让读者以互动的方式留下意见,是许多博客的重要要素。大部分的博客内容以文字为主,但仍有一些博客专注在艺术、摄影、视频、音乐、播客等各种主题 +> +> …… +> +> 简言之,Blog就是以网络作为载体,简易迅速便捷地发布**自己的心得**,及时有效轻松地与他人进行交流,再集丰富多彩的个性化展示于一体的综合性平台。 +> +> …… +> +> 它可以是**个人**纯粹的想法和心得,包括对时事新闻、国家大事的**个人看法**,或者对一日三餐、服饰打扮的精心料理等 +> +> 它**绝不仅仅**是纯粹个人思想的表达和日常琐事的记录,它所提供的内容可以用来进行交流**和**为他人提供帮助,是可以包容整个互联网的,具有极高的共享精神和价值。 +> +> …… +> +> **日记、照片、诗歌、散文,甚至科幻小说的发表或张贴都有**。 + + + +以此可以证明,博客的创作题材非常自由。 + +再来看回答的观点: + +> 个人博客更好的定义,是你以个人的名义发表对别人有价值的内容。所以个人博客内容创作的出发点不是让别人来关注自己,而是让自己为别人服务。 +> …… +> 相反,你洋洋洒洒写一通美文,说得尽是些神神叨叨自怨自艾的个人情绪,除了你妈爱看以外,对别人没多少价值。你想开个博客靠抒发个人情感而不为别人的生活增值,却盘算着博客能有前途,这是无知,自以为是的痴人说梦。 + +认为个人博客**只能为别人服务**,**无法帮助他人的内容就是无价值**。这是一个非常幽默的逻辑。**个人**博客为什么要着力于为**他人**提供价值? + +那么谁有权定义价值?流量数据?工具性?创作者的主体性?你定义的价值,是情感价值还是存在价值?既然其存在,为什么会无价值? + +按照博客导航站点的逻辑:「只收藏有价值的优秀博客」,其收录了以下这些情感类、个人生活类的博客,其观点就不攻自破了。 + +- [头痛一个月 - 小陈故事](https://www.chener.net/archives/headacheinAugust/) +- [别了,那些人,再见,那些记忆 - 生活的左上角](https://bwskyer.com/bye-man-bye-memory.html) + +如果用知乎回答的观点:「谁想知道你头怎么样?谁想知道你跟虾米音乐有什么故事?**除了你妈爱看以外,对别人没多少价值。**」 + +这显然功利无情,完全背离了博客的初衷,将博客完全定义成为他人服务的工具,拒绝了自身需要的情感表达,否认了生活类以及情感类博客的意义,偏激不可取。 + +## 情感类博客没有价值? + +只有实用价值才配被称作价值吗?显然不可能。 + +所有人的声音都值得被听见,在博客这样一个如此纯粹的表达空间里,依然被所谓的价值捆绑,如果所谓的价值、前途就是「钱途」,那你大可去写那一种微信公众号——图文版抖音、吸引眼球博流量、话说一半的标题党、图文无关的封面党,并且在文章头部、正文里、结尾,甚至评论区都挂上广告,当「流量主」,稳定获取收益。 + +写一篇实用性的文章帮助读者,是作者和读者的双向链接,而写情感类文章找到共鸣者,同样是双向链接,且比前者更牢固。这就好比你家厕所水管漏水,在外面找了一个修水管的工人,他干完活拿钱走人,过两天你会记得他吗?你只会记得你家厕所冲水真顺畅。这是实用价值。 + +但如果当时你给他接了杯水,递了根烟,扯闲天的时候发现大家都是大老远从家跑过来,在外打拼的苦人,甚至有可能是老乡或同好,你们留了联系方式,卖命之余能一起抱怨身边的烂人烂事。共鸣共鸣,频率相同才有共鸣 —— 这就是情感共鸣带来的链接的牢固性,能让你觉得:「哦,原来不止我一个人这样。」这是情感价值。这也是除了「夏天室内防暑省电技巧大全」以外,有质量的更新。 + +我从早期结构一盘散沙的各种文章,到如今结构极其松散的各种文章;从痛恨Linux,到向往Linux,到沉迷Linux,对各种事物理解的转变……改变不大,但那是自己坚实的脚印,看到自我成长,这是博客的自我价值。 + +所以,不要被所谓的价值禁锢了,想写就写,不要不敢写。更不需要强行营销,重要的是保持博客的纯粹性。打这种功利主义者的脸,最好的方法就是**坚持写下去,顽强地写下去**,写他们认为没有价值的东西,笔耕不辍,生生不息。 + +[^1]: 未修改原文用词。可能是「笑话」。 diff --git a/content/posts/为什么我选择Github-issues,而不是朋友圈.md b/content/posts/为什么我选择Github-issues,而不是朋友圈.md new file mode 100644 index 0000000..4eb8fdf --- /dev/null +++ b/content/posts/为什么我选择Github-issues,而不是朋友圈.md @@ -0,0 +1,39 @@ +--- +abbrlink: 3029910242 +categories: +- 往昔 +date: "2025-07-05 09:09:48" +tags: +- 社交 +title: 为什么我选择Github issues,而不是朋友圈 +--- + +> 本页面内容来自[Moments](https://github.com/yingyu5658/Moments/edit/main/README.md) + +## 概述 + +把GitHub issues当朋友圈发。 + +我厌倦朋友圈浓重的装逼气味和虚假社交属性,打造一个纸糊的人设并不好玩,专门发出来某些东西给某人看也非常恶心,所以我选择逃避。 + +## 为什么要用issues,而不是朋友圈? + +- 访问受限,门槛较高 && 过滤傻逼 +- 有更方便管理的标签和查找 +- 易于二次开发 +- Markdown格式写作 +- 清净,不用一点开就吃别人拉出来的屎 +- 能相对敞亮地说话 + +综上,使用issues是更好的。 + +## 为什么叫Moments? + +这是微信英文界面对朋友圈的翻译,我觉得这个翻译像是十几年前微信朋友圈这个功能刚出来时做的。刹那、瞬间,重在记录,而现在朋友圈的发展越来越妖魔化,已经变成一些虚伪的人从各个角度试图营销自己的垃圾场,也变成了意义不明、只放一个二维码要求扩列的赛博妓院。朋友圈的内容总给人虚假感,因为微信是一个社交平台,和你的人设高度绑定,大部分人到死前都会经历毫无尊严的一段时光,想到这里,那些虚假的人设、别人的看法也就没那么重要了。 + +## 个人原因 + +我从发布了第一条[私密朋友圈](https://www.yingyu5658.me/post/707697709/)开始,就一直在探索利用间隙碎片时间释放表达欲与分享欲的途径,,为了远离那些恶心的卖弄人设行为且能专心用私密朋友圈记录,我屏蔽了所有好友的朋友圈,但微信朋友圈不易于管理和查找,没一阵就被pass掉。 + +除了朋友圈,我大部分释放前两种欲望的途径是和群里的网友聊天,但是随着[网络死亡计划](https://www.yingyu5658.me/post/2631380338/)对群聊的筛选,我活动的群聊变得很少,有些还留着的群是因为加的时间很长,但基本没人理我。后来[信息节食](https://www.yingyu5658.me/post/3628666444/)的实行,我也不会再浪费太多时间在群里吹水,总憋着容易溢出,于是Moments诞生了。 + diff --git a/content/posts/人生中第一次大考.md b/content/posts/人生中第一次大考.md new file mode 100644 index 0000000..1e3f877 --- /dev/null +++ b/content/posts/人生中第一次大考.md @@ -0,0 +1,26 @@ +--- +abbrlink: 2367861242 +categories: +- 往昔 +date: "2025-06-23 20:18:10" +tags: +- 考试 +title: 人生中第一次大考 +--- +会考是我人生中经历的第一次大考,不难,考试前一两周也写了不下三四十套卷子。具体考试日期就在中考最后一天的下午。打这段字的时候,我正在开向考点的车上。 + +考前两天我几乎没复习任何东西,对了一张地理卷子的答案,94/100,看着网上初一地理的课,做了些复习笔记。遗憾的是,那篇笔记我忘记了push到博客上,所以我才有时间在这里写字。那两天完全无心复习 。唯一留作业的历史和数学两科中,只有数学勉勉强强写了一张卷子,今天考完回来开始写作业吧。 + +每次各种略微重要的考试前,总有一群大脑发育不完全的懒猪在朋友圈、QQ空间转各种迷信性质的图片。我也发了一个说说。 + +我认为我说的非常有道理。 + +有些生理意义上的头疼,前一晚做了些梦,很乱,没睡好。早上六点家里的幼畜例行吵闹,两个小时的睡眠空缺又让我的精神雪上加霜,起床后眼睛肿了,可能又碰到什么过敏物质。 + +出发前去买矿泉水,为了节省时间,抬起脚跑了几步,突然发现自己已经很长时间没跑过了。平常在学校只有上学、放学、打饭、领卷子会起身,其余时间都是坐着,下课就睡觉。 + +--- + +现在这段文字是从考点出来后写下的。 + +考点学校比我念书的学校环境好多了,教室宽敞明亮,楼道也很干净,桌椅看起来都是新的。生物有一道种植大棚里二氧化碳发生器的作用的题,和一道肾单位尿液再吸收的题,前者超纲,后者没复习到。无论怎样,考完了。 diff --git a/content/posts/从0开始搭建自己的终端开发环境.md b/content/posts/从0开始搭建自己的终端开发环境.md new file mode 100644 index 0000000..14009c9 --- /dev/null +++ b/content/posts/从0开始搭建自己的终端开发环境.md @@ -0,0 +1,355 @@ +--- +abbrlink: 2799171278 +categories: +- 往昔 +date: "2025-04-15 21:15:24" +tags: +- 终端 +- Neovim +title: 从0开始搭建自己的终端开发环境 + +--- + +**系统**:WSL Arch + +### 主折腾点 + +**代码编辑器**:Vim(Neovim) + +**终端体验优化**:tmux + +**文件管理器**:yazi + +## 代码编辑器——Neovim + +### 前言 + +Neovim和Vim相比,在性能和易用性上有很大的提升,在异步任务表现突出;使用更加现代的lua脚本配置,可读性更高。 + +#### 为什么不用Lazyvim? + +答:我个人用了很长一段时间Lazyvim,虽然开箱即用,简单调试就可以使用,但是我并不能清除的理解他到底给我装了什么,我是否需要那些插件。感觉像在用别人的软件,而自己从头开始配置vim的掌控感是使用他人的配置文件无法比拟的,在配置的过程中也可以培养排错和程序调试能力,唯一的缺点就是略微耗费时间。 + +### 安装 + +先滚一把系统保证软件包都是最新的 + +`sudo pacman -Syyu` + +安装Neovim + +`sudo pacman -S neovim` + +这时候在终端输入`nvim`就可以打开neovim了。,官方文档永远都是最好的教程。这里有一段代码 + +```lua +-- Bootstrap lazy.nvim +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not (vim.uv or vim.loop).fs_stat(lazypath) then + local lazyrepo = "https://github.com/folke/lazy.nvim.git" + local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath }) + if vim.v.shell_error ~= 0 then + vim.api.nvim_echo({ + { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, + { out, "WarningMsg" }, + { "\nPress any key to exit..." }, + }, true, {}) + vim.fn.getchar() + os.exit(1) + end +end +vim.opt.rtp:prepend(lazypath) + +-- Make sure to setup `mapleader` and `maplocalleader` before +-- loading lazy.nvim so that mappings are correct. +-- This is also a good place to setup other settings (vim.opt) +vim.g.mapleader = " " +vim.g.maplocalleader = "\\" + +-- Setup lazy.nvim +require("lazy").setup({ + spec = { + -- import your plugins + { import = "plugins" }, + }, + -- Configure any other settings here. See the documentation for more details. + -- colorscheme that will be used when installing plugins. + install = { colorscheme = { "habamax" } }, + -- automatically check for plugin updates + checker = { enabled = true }, +}) +``` + +这段代码主要在为Lazy包管理器初始化,所以按照官网的目录结构,我们在`~/.config/nvim/lua`下新建一个config文件夹,把代码粘贴进去。 + +注意到,代码中有一段是导入plugins这个模块,所以我们需要在`~/.config/nvim/lua`下创建一个plugins文件夹 + +然后在`~/.config/nvim/init.lua`里粘贴这行代码 + +```lua +require("config.lazy") +``` + +`init/lua`是Neovim的初始化配置文件,程序会首先读取这个文件里的代码。 + +这行代码是引入config/lazy这个文件,初始化Lazy,所以要放在第一行。 + +那么经过这一番操作,Lazy安装好了,我们的目录结构应该如下: + +``` +`-- nvim + `-- lua + `-- config + `-- lazy.lua +``` + +现在在终端输入`nvim`启动Neovim,会发现有个报错 + +``` +No specs found for module "plugins" +``` + +查阅[bug: No specs found for module "plugins" (Structured Setup) · folke/lazy.nvim · Discussion #1875](https://github.com/folke/lazy.nvim/discussions/1875)可得,这个问题是由于我们还没有安装任何插件导致的,他不影响什么,但是很烦人。如果想要关掉,可以在plugins下新建一个lua文件,然后输入 + +```lua +return{ + +} +``` + +这样就可以正常启动nvim不报错了。由此可见,Lazy安装插件是返回一张表,所以以后每次新建插件文件的时候都要填写以上内容。 + +### 基础配置 + +在安装插件前,我们要先进行一些基础配置,让这个编辑器用的舒服一点。 + +设置别名:`` + +```lua +local opt = vim.opt +``` + +声明一个本地变量opt=vim.opt,简写提高效率。 + +为什么要显示声明local?原因是lua脚本的所有变量默认都是全局变量,很怪对吧,我也觉得。 + +```lua +opt.relativenumber = false -- 禁用相对行号 +opt.number = true -- 启用绝对行号 +vim.api.nvim_set_hl(0, "LineNr", { fg = "#FFD700" }) -- 所有行号设为金色 +``` + +相对行号可以更容易的数行数来达到`hjkl/d/v等 + 行数`来快速进行文本编辑操作,但是我个人不太适应,就没开,后期可以通过修改按键配置来做到随时开关。 + + + +### 安装插件 + +#### neo-tree + +neo-tree 编辑器的文件系统资源管理器。使用此插件,用户可以直观地浏览复杂的目录层次结构,快速打开文件进行读取或编辑,并执行基本的文件系统作。 + +仓库:[nvim-neo-tree/neo-tree.nvim: Neovim plugin to manage the file system and other tree like structures.](https://github.com/nvim-neo-tree/neo-tree.nvim) + +进入Plugins目录,新建一个文件名为nerdtree的lua脚本。先把上文提到的返回表写进去。 + +```lua +-- neo-tree.lua +-- 代码来自仓库README +{ + "nvim-neo-tree/neo-tree.nvim", + branch = "v3.x", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-tree/nvim-web-devicons", -- not strictly required, but recommended + "MunifTanjim/nui.nvim", + -- {"3rd/image.nvim", opts = {}}, -- Optional image support in preview window: See `# Preview Mode` for more information + }, + lazy = false, -- neo-tree will lazily load itself + ---@module "neo-tree" + ---@type neotree.Config? + opts = { + -- fill any relevant options here + }, +} +``` + +插件装好了发现,不知道怎么打开啊。这时候就需要我们自己动手改一个舒服点的键位。在`~/.config/nvim/lua/config`中新建一个keymaps.lua,并在init.lua中引用 + +```lua +-- 习惯上,我喜欢把leader键映射到空格,敲起来顺手 +-- 基础按键配置 +vim.g.mapleader = " " +local opt = { noremap = true, slient = true } +-- 窗口切换更顺手,少按一个w +vim.keymap.set("n", "<C-h>", "<C-w>h") +vim.keymap.set("n", "<C-j>", "<C-w>j") +vim.keymap.set("n", "<C-k>", "<C-w>k") +vim.keymap.set("n", "<C-l>", "<C-w>l") + +-- Neotree +vim.keymap.set("n", "<Leader>e", "<cmd>Neotree toggle<CR>", opts) +``` + +#### 代码补全、格式化、检查 + +要让vim看起来像一个正经的处理代码的文本编辑器,这些是必不可少的。 + +```lua +-- 文件路径:lua/plugins/code-edit.lua +return { + -- LSP 核心组件 (必须最先声明) + { + "neovim/nvim-lspconfig", + dependencies = { + "williamboman/mason.nvim", + "williamboman/mason-lspconfig.nvim", + }, + config = function() + -- 延迟加载 LSP 配置 + vim.schedule(function() + local lspconfig = require("lspconfig") + local mason = require("mason") + local mason_lspconfig = require("mason-lspconfig") + + -- 通用 LSP 配置 + local on_attach = function(client, bufnr) + -- 快捷键配置... + end + + mason.setup() + mason_lspconfig.setup({ + ensure_installed = { "tsserver", "cssls", "html", "clangd", "eslint" } + }) + + mason_lspconfig.setup_handlers({ + function(server_name) + lspconfig[server_name].setup({ + on_attach = on_attach, + capabilities = require("cmp_nvim_lsp").default_capabilities(), + -- 各语言特殊配置... + }) + end + }) + end) + end + }, + + -- 自动补全引擎(需在 LSP 之后加载) + { + "hrsh7th/nvim-cmp", + dependencies = { + "hrsh7th/cmp-nvim-lsp", + "L3MON4D3/LuaSnip", + }, + config = function() + -- cmp 配置... + end + }, + + -- 格式化工具 + { + "stevearc/conform.nvim", + config = function() + -- conform 配置... + end + }, + + -- 语法高亮增强 + { + "nvim-treesitter/nvim-treesitter", + build = ":TSUpdate", + config = function() + -- treesitter 配置... + end + } +} +``` + +代码编辑器的配置就告一段落了,真写规范的代码还是建议vscode(虽然有点偏离终端的主题了)。如果你爱折腾vim那当然也可以,工具自己用的趁手就是最好的。 + + + +## Oh-My-Zsh + +Oh My Zsh 是基于 zsh 命令行的一个扩展工具集,提供了丰富的扩展功能。 + +### 安装**ZSH** + +`sudo pacman -S zsh` + +设置默认终端为zsh + +`chsh -s /bin/zsh` + +### 安装Oh-My-Zsh + +国内镜像 + +`sh -c "$(curl -fsSL https://gitee.com/pocmon/ohmyzsh/raw/master/tools/install.sh)"` + +我个人觉得这个主题就挺好的了,不多改动。 + +#### 插件安装 + +#### zsh -autosuggestions + +预测命令 + +```bash +git clone https://github.moeyy.xyz/https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions +``` + +#### zsh-syntax-highlighting + +语法检查,命令正确时为绿色,否则红色。 + +``` +git clone https://github.moeyy.xyz/https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting +``` + + +#### 启用插件 + +`nvim ~/.zshrc` + +修改: + +``` +plugins=( + git + zsh-autosuggestions + zsh-syntax-highlighting + ) +``` + +重启终端即可启用。 + +#### 别名设置 + +别名可以更快地帮助我们启用命令 + +`nvim ~/.zshrc` + +``` +alias s="neofetch" +alias vim="nvim" +alias c="clear" +alias gcl = "git clone" +``` + +这里根据我的习惯改了几个别名。 diff --git a/content/posts/从四年前的夏天说起。.md b/content/posts/从四年前的夏天说起。.md new file mode 100644 index 0000000..4addc62 --- /dev/null +++ b/content/posts/从四年前的夏天说起。.md @@ -0,0 +1,57 @@ +--- +date: '2025-11-15T19:24:14+08:00' +draft: false +title: '从四年前的夏天说起。' +slug: '' +categories: + - 随笔 +tags: + - 散文 + - 美术 + - 素描 +--- +那时候还不懂人事,记忆似乎还没有形成一条流畅的线性结构,只是几个简陋的画面拼凑。大概是在二零二一年,我开始学习素描。 + +那时候机构就在家楼下,甚至从窗户就能望到那里落地窗后的人影,每周六下午两点,我带着电话手表去上课,明明就在小区里,到地方后还是要拍上一张自拍证明自己安全到达目的地。那里只有四五间教室,其它的教室都关着门,只有走廊尽头的那间时常开着。屋子里摆着一排笨重的木质画架,墙中央有一台挂壁电视,老师用一根HDMI线将自己的笔记本电脑和那台电视连接上,放着幻灯片。第一节课讲很基础的内容,比如坐姿、握笔方式。 + +老师看起来像刚毕业不久的大学生。只记得有一段时间她变着花样扎头发,最近几个月剪成短发了。 + +之后的一段时间,我每天都很盼望周六的素描课,源于什么呢?学习到新东西催生出的热情?还是三分钟热度的第一秒?无从得知。也许只是一种本能上的喜爱。我断断续续地学了两年,从基础的正方体、棱锥,到贯穿体,正十二面体、多种几何体组合,我画了两年的几何体。 + +除了几何体外,有些节假日也会组织外出写生。 + +<details> +<summary>2022年劳动节 极其稚嫩的笔触</summary> +<img src="https://images.glowisle.me/7f3bee45f2840a22ed7749f338f21e47.jpg"> +</details> + +写生,对线条的掌控能力远不如现在的三分之一的我,抱着画板坐在斑驳的树影里,画过远处的河湖楼房,画过近处的花草树木。每次地点都选在热闹的公园里僻静的角落,有一种偷偷摸摸的感觉。 + +那两年我对画画的热情极高涨,有时间也有精力去练习。当时我的造型能力在同龄人中比较出众,因此还获得了美术老师,也是我们的副班主任的青睐,有相关的任务都会布置给我。 + +我们在画了两年几何体之后开始学习简单的静物,从切面苹果开始。梨、洋葱、菠萝……能进嘴里的画了个遍后,开始画罐子杯子:陶瓷的罐子、不锈钢的壶、玻璃的酒瓶…… + +无论是学画画,还是学跳舞、钢琴、吉他,考级都是必不可少却没什么实际用途的工作,至少素描是这样的。我先后考取了素描二级、三级、四级、六级和七级证书,积分入团制度的有关文件明确表示不可以用考级证书,显而易见地,也没有任何一场考试会因为你有考级证书而加分。而考试的内容和难度堪称儿戏,交完报名费,在培训机构考完寄走,过几个月证书就会被寄回来。我没有经历过一次失败,这就使我不禁怀疑成功的含金量。或许下一次我应该尝试只画到明暗关系就交卷,如果这样也能拿到证书的话,就能完美地证明这场考试是骗小孩的。 + +但我还是一级一级地考下来了。 + +这是让我在人前能稍微抬得起头的为数不多的资本。或者说,这可能是我的特长。在一个身高特矮、样貌特丑、脾气特怪、脑子特笨的人身上找到特长是一件多么不容易的事!这是我在积极的方面与众不同的地方! + +我感谢我的父母,没有阻止我踏上学习绘画这条路。我也感谢我的老师,如果没有她成熟且深刻的教育理念、方法和耐心,我绝对没有今天的技术。 + +今天写下这篇文章,就是因为我发现我唯一的特长似乎要被磨灭了。 + +素描是一切绘画的基础中的基础,如果没有素描经验,学习任何类别的绘画都是困难的,素描从思维上提供了几乎贯穿所有绘画类别的思考方式。在素描的基础之上,我开始发展板绘。以单色插画和漫画为主。 + +练习了一段时间后,老师说我的水平可以接稿赚些零用钱。能凭手艺赚钱是非常了不起的,也需要极其成熟的技术。我曾经在网络上见到很多线条都画不稳,结构更是一团糟的所谓「画师」在社交媒体发表自己的画作,表示自己要接稿。而评论区清一色都是夸赞。点开那些人的主页,同样的画风、同样的问题。 + +我不是好为人师的那种人,也知道自己是什么货色。但想也明白,这些一味的夸赞与被夸赞是不能促成进步的,因此他们才会一直停留在这样的水平。如果指出问题,不仅伤人家的心,也容易卷入骂战,恶臭缠身。这种小圈子自嗨的现象并不少见。在绘画教程视频的评论区能见到不少说「求评价」,但指出问题又怼人拉黑的。想获得夸赞,没有过硬的实力就是痴心妄想。我非常厌恶这种自以为是,只能听进去佞语的家伙。 + + +一分钟,五分钟,十分钟,三十分钟,一小时…… + +周一,周二,周三,周四,周五,周六,周日,周一…… + +时间、精力、活力,都被这一轮又一轮的循环绞杀了。我的水平在急速下降。近些天一直保持绘画,只是为了证明些什么,也许是证明我还有擅长的事。我却发现我画出的东西和我讨厌的那类人几乎属于同一个水平了。看不到进步不可怕,看见退步也不可怕,看见自己的水平退步到于自己曾经最讨厌的一类人几乎齐平,这才是最令人生理性反胃的。一种熟悉的自我厌恶感在纸上的墨水里汇聚成了一股,贯穿我的眉心。这几个月,成绩平平、身体虚弱、心力矫情又拧巴的我,最终画画这件事也变成了这样。 + +热情的洪水决堤,淹没一切的行动力,溃散。 diff --git a/content/posts/从编译原理到物理原理剖析程序的编译与执行.md b/content/posts/从编译原理到物理原理剖析程序的编译与执行.md new file mode 100644 index 0000000..a969019 --- /dev/null +++ b/content/posts/从编译原理到物理原理剖析程序的编译与执行.md @@ -0,0 +1,138 @@ +--- +categories: +- 往昔 +date: "2025-07-29T15:55:14+08:00" +draft: false +slug: "" +tags: +- 底层技术 +- 编译器 +- 编译原理 +title: 从编译原理到物理原理剖析程序的编译与执行 +--- +## 编译过程 + +以C语言为例,编译成可执行文件一共要经历:**预处理=>狭义编译=>汇编=>链接**,最终成为可执行文件。 + +### 预处理 + +输入源代码文件以及其包含的头文件,由预处理器执行展开宏定义、处理,条件编译指令、将包含的头文件直接插入到指令位置,删除注释。 + +输出纯净的、宏已展开、注释已删除、头文件已包含的中间代码文件,通常为`.i`。 + +编写一个简单的程序: + +```c +#include <stdio.h> +#define STRING "Program" + +int +main() { + // 打印一些内容 + printf("Hello world!\n"); + printf("%s\n", STRING); + return 0; +} +``` + +使用gcc的`-E`选项生成中间代码: + +`gcc exam.c -E -o ./exam.i` + +他生成了非常长的代码 + +可以验证预处理器是直接把头文件替换进来的。而代码中类似`# 5 "exam.c"`的标记用于记录源代码的位置信息,便于调试器和错误诊断程序追踪代码位置。 + +### 编译(狭义编译) + +#### 词法分析 + +输入预处理后的源代码文件,有编译器执行词法分析,将字符流分解成有意义的词素(Token),例如: + +```c +int sum = a + b; +``` + +分解成`int`, `sum`, `=`, `a`, `+`, `b`等Token。 + +#### 语法分析 + +根据语言的语法规则,将Token序列组合成抽象语法树(Abstract Syntax Tree),简称AST,表达了代码的结构和层次关系。 + +#### 语义分析 + +检查程序的语义是否正确,例如变量是否声明、类型是否匹配等。 + +#### 中间代码生成 + +将AST转换成一种独立于CPU架构的中间表示形式(intermediate Representation),即IR。常见的IR有三地址码、LLVM IR、Java字节码等,为了优化和转移成多种目标机器码。 + +#### 优化 + +对IR进行处理,目的是在不改变程序行为的前提下,提高代码效率。包括: + +- 常量折叠:如计算`3 + 5`为`8`。 +- 死代码消除:移除永远不会执行到的代码。 +- 循环优化:如循环展开。 +- 函数内联。 +- 寄存器分配:决定哪些变量存储在高速的CPU寄存器中。 + +输出优化后的中间代码。 + +### 汇编 + +输入IR,或直接由编译器生成的汇编代码。由汇编器`as`执行。将汇编指令一对一地转换成特定CPU架构的机器操作指令。处理伪汇编指令,如定义数据段`.data`,定义代码段`.text`,分配存储空间`space`等。最后解析符号、如函数名、变量名等,生成符号表。 + +输出目标文件,如.o,.obj,包含机器指令、全局变量、静态变量的初始值等、符号表、重定位信息。 + +### 链接 + +输入一个或多个.o文件夹+库文件(静态.a/.lib,动态.so/.dll)。由链接器进行符号解析、重定位、库处理,最输出可执行文件或库文件。 + +--- + + +## CPU如何识别指令 + +CPU执行程序的循环称为Fetch-Decode-Execute Cycle(取指-译码-执行周期)。 + +### 取指 + +CPU内部有一个寄存器叫程序计数器(Program Counter, PC),它保存着下一条要执行的指令的内存地址,CPU将PC中的地址发送到地址总线,内存控制器根据地址总线上的地址,找到对应的内存单元,将其存储的指令通过数据总线送回CPU。取回来的指令被放入指令寄存器IR。PC的值自动增加,指向下一条指令的地址。 + +### 译码指令 + +CPU的控制单元读取IR中的指令,控制单元包含一指令译码器,译码器分析指令 操作码部分,操作码唯一表示CPU应该执行什么操作,如ADD MOV JMP等。 + +根据操作码,译码器决定: +- 操作的性质(算术、逻辑、数据传输、跳转等)。 +- 操作需要多少个操作数。 +- 操作数存放位置(寄存器、内部地址指令本身中的立即数) + +译码器激活执行该操作所需要的CPU内部电路通路和控制信号,结果决定了下一个阶段(执行)需要做什么。 + +### 执行指令 + +CPU的算术逻辑单元(Arithmetic Logic Unit, ALU)或去他功能单元(FPU MMU)根据译码器产生的控制信号执行实际操作。 + +操作数可能从寄存器文件中读取,或者从内存中加载,ALU执行加减与或移位等操作,如果指令是JMP/CALL/RET/分支指令等跳转指令,可能会修改PC的值,从而改变下一条指令的位置。计算结果可能写回寄存器,或者通过数据总线写会内存。 + +上述的操作循环以极高的速度(GHz级别)不断重复,构成了CPU运行程序基础。 + +## 编译后的指令在物理层面上是什么 + +答:**内存中的电荷状态**。 + +程序被操作系统加载到计算机的RAM中,RAM由无数的存储单元(通常是电容)组成,每一个单元可以存储一个bit的信息。 + +高电平电荷(通常代表1)或低电平电荷(通常代表0)的状态,就表示一个二进制位。 + +每条指令由多个bit组成。指令序列在RAM中是一系列连续存储单元的电荷状态。当CPU取指令时,PC寄存器的值,也就是一组触发器的电平状态被送到地址总线,也就是一组物理导线。 + +地址总线上的电平信号激活内存控制器和特定的存储单元。 + +被选中的内存单元的电荷状态被读出,转换为相应的电平信号,通过数据总线传回CPU。 + +这些电平信号进入CPU的指令寄存器IR,也是一组触发器的电平状态。 + +一组一组电平状态激活着CPU中的组件,从而执行指令。 diff --git a/content/posts/会考地理复习笔记.md b/content/posts/会考地理复习笔记.md new file mode 100644 index 0000000..d6ccf99 --- /dev/null +++ b/content/posts/会考地理复习笔记.md @@ -0,0 +1,50 @@ +--- +abbrlink: 4056468020 +categories: +- 往昔 +date: "2025-06-22 08:49:40" +tags: +- 考试 +- 学业 +- 笔记 +title: 会考地理复习笔记 +--- +## 地球公转自转与季节气候 +1. 东西半球分界线:20W 160E +2. 地球自转方向:自西向东 +3. 南北半球季节相反 +4. 夏至日太阳直射北回归线,北半球昼最长也最短,南半球昼最短夜最长,北极圈及其以北极昼,南极圈以其南极夜 +5. 冬至日太阳直射南回归线,北半球昼最短夜最长,南半球昼最长夜最短,北极圈及其以北极夜,南极圈及其以南极昼 +6. 春分秋分,太阳直射赤道,昼夜等长 + +7. 根据各地获得太阳光照的多少,把地球表面分为五个带:**热带、北温带、南温带、北寒带、南寒带** + + +## 地图 +1. 比例尺=图上距离/实地距离,指示表大多指向正北方向 +2. 同一条等高线上的海拔相同;等高线越密集,坡度越陡;等高线越稀疏,坡度越缓。 +3. **等高线上不同的山体部位** +  + 1. 山峰:等高线闭合,数值从中间向四周递减 +  + 2. 山脊:等高线的弯曲部分向低处突出 +  + 3. 山谷:等高线的弯曲部分向高处突出,常形成河流 +  + 4. 陡崖:等高线重叠,适合开展攀岩运动 +4. **陆地表面的地形类型** + 1.高原:海拔在500米以上,面积较大,外围较陡,内部起伏较为缓和 +5. **大洲分界线** +  + 1. 亚欧分界线:乌拉尔山脉、乌拉尔和、厉害、大高加索山脉、黑海、土耳其海峡 + 2. 亚非分界线:苏伊士运河 + 3. 北美南美分界线:巴拿马运河 + 4. 欧非分界线:直布罗陀海峡 +### 板块构造学说 +1. 板块内部地壳比较稳定;板块与板块交界的地带,地壳比较活跃,多火山地震 +2. 在板块交界处,两个板块发生张烈,。常常形成裂谷或海洋;两个板块发生碰撞,在陆地常常形成山脉 +  +3. 世界上许多高大绵长的山脉主要分布在板块挤压碰撞的地带,如阿尔卑斯——喜马拉雅山系,科迪勒拉山系等 +4. 世界上的火山和地震也集中分布在地壳比较活跃的板块交界地带,例如环太平洋地带和地中海——喜马拉雅地带 +  + diff --git a/content/posts/使用Emacs收发邮件.md b/content/posts/使用Emacs收发邮件.md new file mode 100644 index 0000000..da211c0 --- /dev/null +++ b/content/posts/使用Emacs收发邮件.md @@ -0,0 +1,151 @@ +--- +date: '2025-11-12T16:48:02+08:00' +draft: false +title: '使用Emacs收发邮件' +slug: 'email-with-emacs' +categories: + - 往昔 +tags: + - GNU/Emacs + - Linux +--- +作为一个合格的操作系统,肯定少不了Email. 我的配置很简单,只要实现基础的收发功能即可,每天的邮件量不大。在这里记录一下配置。 + +## 收邮件 + +我尝试过 **[fetchmail](https://www.fetchmail.info)**,但不知道这个东西拿到的邮件都在哪,所以最后还是选择了 **mbsync**. + +``` +# ~/.mbsyncrc +# GlowIsle 账户配置 +IMAPAccount GlowIsle +Host imap.qiye.aliyun.com +Port 993 +User i@glowisle.me +Pass ****** +TLSType IMAPS +AuthMechs LOGIN +CertificateFile /etc/ssl/certs/ca-certificates.crt + +# 远程存储 +IMAPStore glowisle-remote +Account GlowIsle + +# 本地存储 +MaildirStore glowisle-local +Path ~/mail/GlowIsle/ +Inbox ~/mail/GlowIsle/Inbox +Subfolders Verbatim + +# 同步通道 +Channel glowisle +Far :glowisle-remote: +Near :glowisle-local: +Patterns * +Create Both +Sync All +Expunge Both +SyncState * + +``` + + +## 发邮件 + +``` +# ~/.msmtprc +# glowisle +account glowisle +host smtp.qiye.aliyun.com +from i@glowisle.me +auth login +port 465 +user i@glowisle.me +password ******* +auth on +tls on +tls_starttls off #使用465端口时不能开启 +tls_certcheck off +tls_trust_file /etc/ssl/certs/ca-certificates.crt + +account default : glowisle + +``` + + +## Emacs 配置 + +在Doom Emacs的`init.el`中开启 mu4e + +```lisp + :email + (mu4e +org) + +``` + + +```lisp +;; config.el +(after! mu4e + ;; 基本设置 + (setq mu4e-maildir "~/mail" ; 邮件目录 + mu4e-get-mail-command "mbsync -a" ; 接收邮件命令 + mu4e-update-interval 300 ; 自动更新间隔(秒) + mu4e-view-show-images t ; 显示图片 + mu4e-compose-signature "Best regards.\nVerdant") ; 邮件签名 + + ;; 使用 msmtp 发送邮件 + (setq message-send-mail-function 'message-send-mail-with-sendmail + sendmail-program "/usr/bin/msmtp" + sendmail-arguments '("--read-envelope-from" "--read-recipients")) + + + (setq mu4e-contexts + (list + (make-mu4e-context + :name "GlowIsle" + :match-func (lambda (msg) + (when msg + (string-match-p "^/GlowIsle" (mu4e-message-field msg :maildir)))) + :vars '((user-mail-address . "i@glowisle.me") + (user-full-name . "Verdant") + (smtpmail-smtp-server . "smtp.qiye.aliyun.com") + (smtpmail-smtp-service . 465) + (smtpmail-stream-type . starttls))))) + + ) + +``` + +## 基本使用 + +- `SPC o m` 进入 mu4e 主页面 + +``` +Basics + + * [J]ump to some maildir + * enter a [s]earch query + * [C]ompose a new message + +Bookmarks + + * [bu] Unread messages (0/0) + * [bt] Today's messages (0/14) + * [bw] Last 7 days + * [bp] Messages with images (0/0) + * [bf] Flagged messages (0/1) + +Misc + + * [;]Switch focus + * [u]pdate email & database + + * [N]ews + * [A]bout mu4e + * [H]elp + * [q]uit +``` +--- + +微软的Outlook邮箱使用OAuth2.0认证,我暂时没找到成功的解决方案能在Emacs上使用,如果有哪位路过的好哥们知道方法请留言或[发个邮件](mailto:i@glowisle.me)探讨一下! diff --git a/content/posts/信息节食.md b/content/posts/信息节食.md new file mode 100644 index 0000000..743b188 --- /dev/null +++ b/content/posts/信息节食.md @@ -0,0 +1,25 @@ +--- +abbrlink: 3628666444 +categories: +- 往昔 +date: "2025-07-03 21:22:44" +tags: +- 信息节食 +- 阅读 +title: 信息节食 +--- +## 起因 + +信息节食这个概念,大概是我初一的时候在政治课本听说的。当时还不以为然,现在越来越觉得信息节食很重要。 + +## 行动 + +我是个注意力比较涣散的人,可能是因为我常年熬夜等不健康的生活习惯,在家的时候注意力只能维持四十分钟左右,想持续一个小时的高效学习非常困难。其原因就在于我非常喜欢看QQ群,经过层层筛选后的QQ群是真正有共同话题的地方。问题就在于此,太有共同话题了,群友说的每一句话都能参与,这也就让我做一半事情就拿起手机看QQ,又是因为经过筛选,所以群很少,哪怕没有消息也要等上一会消息。长此以往,浪费时间还伤眼睛伤颈椎,而且极大部分消息都是娱乐,对提升自身完全没有帮助。所以我把QQ号退出了登录并在空间留下了邮箱,有重要且正经的事时,能高效交流。 + +关于微信朋友圈,经过[上一篇](https://www.yingyu5658.me/post/707697709/)文章的思考后,我还是决定把它保留下来,对每个好友都设置了不看ta们,少看一些人虚假的合群、努力营造人设也清净,可以很好地自娱自乐了。这也是信息节食的一部分了。有什么想记录的,就发一条私密朋友圈,或者打开备忘录、Obsidian等能写字的地方记录下来,定期整理成文。 + +我注销了N年前看的抖音、小红书、贴吧等账号,我知道那些平台上面也有优质内容,可查找、筛选、分辨太耗费精力了。幸好去年开始学习编程,就完全没有玩游戏的心思了,除了开一些游戏私服、制作插件以外没什么能让我重新打开游戏的理由。但今年暑假前有一个同学早就兴致勃勃地想和我联机Minecraft,盛情难却,不好推脱,但我实在对那游戏再提不起兴趣了。 + +今天在学校时,我想过,如果我把这些信息全部切断,我该做点什么?其实信息节食的目的之一就包括少一些打扰我读书的声音,要做的事情之一就包括读书。说得笼统点,要做的事情就是阅读。我关注了一些公众号和博客,闲暇时间可以阅读公众号、博客、新闻,也可以听听播客。只是苦于每次想阅读公众号上的文章就要打开微信,看那些犯人的红点,听那些让人抓狂的消息提示音,所以我会寻找一种把信息聚合起来,像RSS那样。看腻了就继续磨练速写和琴技,总之有营养的事多了去。 + +该去整理一下博客订阅列表了,不得不说,RSS真是伟大的发明。 diff --git a/content/posts/修复Geyser下基岩版玩家无法在地狱基岩层放置方块.md b/content/posts/修复Geyser下基岩版玩家无法在地狱基岩层放置方块.md new file mode 100644 index 0000000..f4bfabf --- /dev/null +++ b/content/posts/修复Geyser下基岩版玩家无法在地狱基岩层放置方块.md @@ -0,0 +1,32 @@ +--- +CopyRight: true +NoCover: false +ShowReward: false +ShowToc: show +abbrlink: 1177643335 +author: yingyu5658 +categories: +- 往昔 +cid: 184 +cover: images/1203260069.jpg +date: "2025-01-08 17:26:00" +desc: null +keywords: null +layout: post +showTimeWarning: true +slug: 184 +status: publish +summaryContent: null +tags: +- Java +- 服务器 +- Minecraft +- Geyser +thumb: null +title: 修复Geyser下基岩版玩家无法在地狱基岩层放置方块 +updated: 2025/01/08 17:26:41 +--- + + +在`plugins\Geyser-Spigot\config.yml`中把第160行的`above-bedrock-nether-building: false`改为`true`,重启服务器,问题解决~ +原理:geyser把下界翻译成了末地,会导致下界天空变成末地的样式,不过可以解决基岩版玩家在地狱基岩层的问题。 diff --git a/content/posts/八下历史复习笔记.md b/content/posts/八下历史复习笔记.md new file mode 100644 index 0000000..dc49364 --- /dev/null +++ b/content/posts/八下历史复习笔记.md @@ -0,0 +1,109 @@ +--- +abbrlink: 3107952300 +categories: +- 往昔 +date: "2025-06-26 19:17:46" +tags: +- 笔记 +title: 八下历史复习笔记 +--- +1. 临时宪法作用:《中国人民政治协商会议共同纲领》 +2. 中国人民政治协商会议第一届全体会议确立的制度:中国共产党领导的多党合作和政治协商制度 +3. 中国人民站立起来的标志:新中国成立 +4. 中国半半社会结束的标志:新中国成立 +5. 中国现代史开端:新中国成立 +6. 祖国大陆统一,各族人民实现了大团结的标志:西藏和平解放 +7. 抗美援朝目的:抗美援朝,保家卫国 +8. 捍卫新中国安全,大大提高我国国际地位的事件:抗美援朝战争 +9. 土地改革的依据:《中华人民共和国土地改革法》 +10. 彻底摧毁我国存在2000多年的封建土地制度,消灭了地主阶级的标志:土地改革的完成 +11. 新中国土改特点:采取保存富农经济,政治上中立富农的政策 +12. 新中国成立后巩固政权的事件:西藏和平解放、抗美援朝、土地改革 +13. 一五计划主要集中力量发展重工业 +14. 使我国土地所有制从私有制变为公有制的事件是:三大改造的完成 +15. 我国开始改变工业落后面貌,向社会主义工业化迈进的标志是:第一个五年计划的完成 +16. 我国根本政治制度:人民代表大会制度 +17. 人民代表大会制度确立的标志:第一届全国人民代表大会的召开 +18. 我国第一部社会主义类型的、有史以来第一部真正反应人民利益的宪法:1954年《中华人民共和国宪法》 +19. 我国社会主义改造的三个方面:农业、手工业、资本主义工商业 +20. 我国社会主义改造的创举:赎买政策 +21. 进入社会主义初级阶段的标志:三大改造的基本完成 +22. 社会主义基本制度在我国建立起的标志:三大改造的完成 +23. 三大改造实质:生产资料转变为社会主义公有制 +24. 三年经济困难是指1956-1961年为克服经济困难提出的`调整、巩固、充实、提高`的八字方针 +25. 1958年,社会主义建设中出现的曲折和失误是:“大跃进”和人民公社化运动 +26. 新中国成立后经历的最严重的挫折是:文化大革命 +27. 文化大革命中最大冤案的受害者:刘少奇 +28. 1967年6月,我国成功爆炸了第一颗氢弹 +29. 1970年4月,我国成功发射了第一颗人造地球卫星 +30. 1973年,我国在世界上首次培育成功强优势的籼型杂交水稻 +31. 我国在社会主义建设火热年代涌现的英雄人物:王进喜、焦裕禄、雷锋 +32. 中国共产党开辟的符合中国国情的道路是:中国特色社会主义道路 +33. 新中国成立后一场深刻的思想解放运动是:真理标准问题大讨论 +34. 新中国成立以来党的历史上具有深远意义的伟大转折是:中共十一届三中全会 +35. 开启了改革开放和社会主义新时期的事件是:中共十一届三中全会的召开 +36. 作出把党和国家工作中心转移到经济建设上来、实行改革开放的历史性决策的会议:中共十一届三中全会 +37. 党和政府对农村实行的改革是:实行家庭联产承包责任制 +38. 家庭联产承包责任制最早在安徽凤阳小岗村实行 +39. 为农民致富和实现现代化开辟出的一条新道路是:发展农村乡镇企业 +40. 城市经济体质改革的中心环节:增强企业活力 +41. 提出要建立社会主义市场经济体质的会议:中共十四大 +42. 我国经济特区的代表和对外开放的窗口:深圳 +43. 1980开放的四个经济特区是:深圳、珠海、汕头、厦门 +44. 对外开放的意义:引进外资技术、扩大对外影响、为改革开放探路 +45. 我国对外开放的格局:经济特区--沿海开放城市--沿海经济开放区--内地 +46. 对外开放的特点:全方位、多层次、宽领域 +47. 为我国参与经济全球化开辟了新途径的事件:中国加入世界贸易组织 +48. 提出“建设有中国特色的社会主义”的会议是:中共十二大 +49. 阐述了社会主义初级阶段的理论,明确概括了党在社会主义初级阶段的基本路线的会议是:中共十三大 +50. 1992年进一步解放了人们的思想,推动改革开放和社会主义现代化建设进入新阶段的是:邓小平南方谈话 +51. 我国改革开放和社会主义现代化的总设计师:邓小平 +52. 马克思主义在中国发展的新阶段是:邓小平理论 +53. 把邓小平理论确立为党的指导思想的会议是:中共十五大 +54. 把江泽民三个代表重要思想确立为中国共产党指导思想的会议是:中共十六大 +55. 把科学发展观确立为中国共产党的指导思想的会议是中共十八大 +56. 习近平新时代中国特色社会主义思想被确立为中国共产党必须长期坚持的指导思想的会议是:中共十九大 +57. 马克思主义中国化、时代化的新的飞跃是:习近平新时代中国特色社会主义思想 +58. 为了实现中国梦,中国共产党实现的奋斗目标是:“两个一百年”奋斗目标 +59. 中共十八届五中全会提出的新发展理念是:创新、协调、绿色、开放、共享 +60. 宣布我国实现了第一个百年奋斗目标,全面建成小康社会的会议是:庆祝中国共产党成立100周年大会 +61. 重点总结新时代党和国家取得的历史性成就,发生的历史性变革和积累的新鲜经验的会议是:中共十九届六中全会 +62. 做出了统筹推进“五位一体”总体布局、协调推进“四个全面”战略布局全面部署的会议是:中共二十大 +63. 为解决我国民族问题确立的基本政策和基本政治制度是:民族区域自治制度 +64. 我国建立的第一个自治区:内蒙古自治区 +65. 20世纪末,我国实行的为民族地区加快发展,创造了巨大的历史机遇的政策是:西部大开发 +66. 邓小平从维护祖国和中华民族根本利益出发,提出的伟大构想是:“一国两制”伟大构想 +67. 香港回归:1997.7.1 +68. 澳门回归:1999.12.20 +69. 中国人民洗雪了百年国耻,在完成祖国统一大业的道路上迈出的重要一步的标志是:香港、澳门的回归 +70. 改革开放后对台基本方针:和平统一、一国两制 +71. 海峡两岸近四十年的隔绝状态终于被打破,两岸关系发生了历史性变化的事件:台湾当局开始被迫调整“三不”政策 +72. 标志海峡两岸关系的发展迈出历史性的重要一步的事件是:海基会与海协会达成九二共识 +73. 九二共识的内涵:海峡两岸均坚持一个中国原则 +74. 全面阐述了新时代解决台湾问题的总体方略的文件是:《台湾问题与新时代中国统一事业》白皮书 +75. 中共二十大进一步强调实现两岸统一的最佳方式是:“和平统一、一国两制”方针 +76. 中国人民解放军的第一支海军部队是:华东军区海军 +77. 2012.9我国的第一艘航空母舰:辽宁舰 +78. 中国战略威慑的核心力量:导弹部队 +79. 2015年,第二炮兵部队更名为火箭军 +80. 我国的五大军种:陆军、海军、空军、火箭军、战略支援部队 +81. 五大战区:东部、南部、西部、中部战区 +82. 形成的新格局:形成中央军委指导下的陆军、海军、空军、火箭军等军种,军事航天不对、网络空间部队、信息支援部队、通勤保障部队等兵种的新型兵种结构布局 +83. 新中国成立后奉行的外交政策:独立自主的和平外交政策 +84. 周恩来提出的处理国与国之间关系的基本准测:和平共处五项原则 +85. 和平共处五项原则的内容:互相尊重主权和领土完整、互不侵犯、互不干涉内政、平等互利、和平共处 +86. 1955年万隆会议召开的地点:印度尼西亚 +87. 万隆会议地位:第一次没有西方殖民主义国家参加的亚非会议 +88. 万隆会议上周恩来提出的外交方针:“求同存异”方针 +89. 20世纪70年代,中国外交取得重大胜利的事件:中华人民共和国回复在联合国的合法席位 +90. 中美关系开始走向正常化的标志是:中美双方签署并发表了《联合公报》 +91. 中国特色大国外交全面推进,形成的外交布局是:全方位、多层次、立体化 +92. 1989年成立的亚洲太平洋地区的经济合作机制,中国与1991年加入亚太经合组织 +93. 我国成功发射的第一课人造地球卫星:东方红一号 +94. 为两弹的研究做出突出贡献的科学家代表有:钱学森、邓稼先 +95. 我国首位乘坐神舟五号载人飞船升入太空的宇航员是:杨利伟 +96. 成功培育籼型杂交水稻,被称为杂交水稻之父的科学家是:袁隆平 +97. 领导科研团队发现青蒿素,获得2015年诺贝尔生理学或医学奖的中国药学家是:屠呦呦 +98. 2012年获得诺贝尔文学奖的中国作家:莫言 +99. 1956年,毛泽东提出在科学文化工作中实行“百花齐放、百家争鸣”的方针 +100. 新中国成立后,使我国人民衣食住行方面发生巨大变化的政策是:改革开放 diff --git a/content/posts/写一个下载B站视频的小工具.md b/content/posts/写一个下载B站视频的小工具.md new file mode 100644 index 0000000..795acfa --- /dev/null +++ b/content/posts/写一个下载B站视频的小工具.md @@ -0,0 +1,104 @@ +--- +date: '2025-11-08T12:20:36+08:00' +draft: true +title: '写一个下载B站视频的小工具' +slug: 'download-bilibili-video-with-golang' +categories: + - 往昔 +tags: + - Golang +--- +## 前置条件 + +Bilibili的视频接口链接是这样的 + +``` +https://api.bilibili.com/x/player/playurl?fnval=80&cid=746904707&bvid=BV1pT41157it +``` + +- avid可以用bvid,也就是视频的BV号代替 +- cid的值可以通过aid获取,它是每个视频的分p编号,同个av号视频里的每p视频都有不同cid值[^1] + +json数据中,`baseUrl`就是视频下载链接,根据清晰度的不同,有多条下载链接。 + +### 构造请求 + +#### 获得 cid + +``` +https://api.bilibili.com/x/player/pagelist?bvid=填写视频的BV号 +``` + +使用这个接口也是可以得到cid的 + +``` +https://api.bilibili.com/x/web-interface/view?bvid= +``` + + +一个标准的B站视频网页PC端链接是这样的: + +``` +https://www.bilibili.com/video/BV1YUs5zVE2w/ +``` + +最后以BV开头的字符就是BV号。我们可以得到以下链接: + +``` +https://api.bilibili.com/x/player/pagelist?bvid=BV1YUs5zVE2w +``` + +对这个url发送请求,可以得到以下内容 +```json +{ + "code": 0, + "message": "0", + "ttl": 1, + "data": [ + { + "cid": 33335151537, // 我们需要的cid + "page": 1, + "from": "vupload", + "part": "防波堤にいた白猫をナデナデしたらコロコロ転がって落ちた", + "duration": 172, + "vid": "", + "weblink": "", + "dimension": { "width": 1920, "height": 1080, "rotate": 0 }, + "first_frame": "http://i2.hdslb.com/bfs/storyff/_000003dxlmk3m5bg52v8f5zbx7p5hyb_firsti.jpg", + "ctime": 1761233073 + } + ] +} + +``` + +#### 构造下载链接 + +这个结构有cid和bvid两个参数: + +``` +https://api.bilibili.com/x/player/playurl?fnval=80&cid=&bvid= +``` + +根据上面的结果,我们可以构造以下url: +``` + https://api.bilibili.com/x/player/playurl?fnval=80&cid=33335151537&bvid=BV1YUs5zVE2w +``` + +这个url返回的数据中,baseUrl即为下载链接。 + +## 写代码 + +我们需要做的事有: + +- 发送网络请求 +- json 解析 +- 文件IO +- 日志输出 + +### 网络请求 + +在go语言中,发送http请求的最简单方法就是使用`net/http` + + +[^1]: https://zhuanlan.zhihu.com/p/541308878 diff --git a/content/posts/写在九月的开头.md b/content/posts/写在九月的开头.md new file mode 100644 index 0000000..d8ac9d7 --- /dev/null +++ b/content/posts/写在九月的开头.md @@ -0,0 +1,142 @@ +--- +date: '2025-09-01T16:35:23+08:00' +draft: false +title: '写在九月的开头' +slug: 'beginning-of-september' +categories: + - 随笔 +tags: + - 月度总结 + - 暑假总结 + - 总结 +description: "挺开心的暑假。" +--- + + +又到了喜闻乐见的结算环节,其实这篇文章是想写给这个暑假的,但标题起作「暑假总结」,总感觉非常掉价。 + +今天是九月一日,全国大部分省份都开学了,天津因上海合作组织峰会,延后开学,所以我今天才能在大下午,悠哉悠哉地坐在电脑前写总结。 + +## 旅游 + +这个暑假过得真的是非常的[**宅**](https://www.yingyu5658.me/posts/%E5%AE%85/),爸妈硬拉着我出去玩,我还写出了一篇[负能量满满的游感](https://www.yingyu5658.me/posts/%E5%A4%8F%E6%97%A5%E6%AE%8B%E5%BD%B1/),可见对于这种耗费精力的事情有多抗拒。 + +如果是去一些自然景观、有人文历史可探究的地方,我还是很提倡的,但花了小一千块去游乐场玩,不觉得多有收获。 + +除了按时出去上素描课以外,我几乎很少再外出活动了。体育中考应该能靠在学校的锻炼拿点分吧。 + +其实我也比较向往出去玩。尤其是看了[《二零二五 - 六七月读书随笔》](https://lhasa.icu/reading-log-2025-06-07/)这篇文章。但是我想自己一个人出去,或者和同学出去。总之,绝对不会想和家人一起,最后的结果一般都是谁也不开心,简直是负担。 + +## 阅读 + +这个暑假我一直在读日本文学。从我的 Obsidian 备份仓库的 git 提交里可以看到一开始计划的书单,大概是七月初: + +| 📚书名 | 👨🏻🎓作者 | 🖊️字数(千字) | 🔵状态 | +| ---------- | ------------------------------ | ------------- | ------ | +| 白夜行 | 【日】东野圭吾 | 474 | 已读完 | +| 金色夜叉 | 【日】尾崎红叶 | 277 | 已读完 | +| 解忧杂货店 | 【日】东野圭吾 | 218 | 未读完 | +| 我是猫 | 【日】夏目漱石 | 307 | 未读完 | +| 呼啸山庄 | 【英】艾米莉·勃朗特 | 325 | 未读完 | +| 堂吉诃德 | 【西】塞万提斯 | 826 | 未读完 | +| 窄门 | 【法】安德烈·纪德 | 66 | 未读完 | +| 百年孤独 | 【哥】加夫列尔·加西亚·马尔克斯 | 262 | 未读完 | +| 知道分子 | 【中】王朔 | 270 | 未读完 | + +但现在的状态是这样的: + +```markdown +## 七月 + +- [x] 《白夜行》东野圭吾 +- [x] 《解忧杂货店》东野圭吾 +- [x] 《金色夜叉》尾崎红叶 + +## 八月 + +- [x] 《仲夏之死》三岛由纪夫 +- [x] 《潮骚》三岛由纪夫 +- [x] 《金阁寺》三岛由纪夫 +- [x] 《伊豆的舞女》川端康成 + +## 九月 +- [ ] 《雪国》川端康成 +- [ ] 《罗生门》芥川龙之介 +- [ ] 《知道分子》王朔 +- [ ] 《活着》余华 +- [ ] 《生死疲劳》莫言 +``` +我承认,《百年孤独》现在对我来说实在是太难了。《雪国》,八月三十一日已经看了一半了,就先把它放到九月的书单里吧。 + +《伊豆的舞女》有一篇[读后感](https://www.yingyu5658.me/posts/izu-no-odoriko/),当时正好在电脑边读完了。有感而发,立刻写了一篇。实际上我不太擅长写这种类型的文字,算是文学评论吧。 + +八月份读了整整三本三岛由纪夫的书,那本《仲夏之死》其实也是短篇小说集。我对三岛文字的印象就是**相当地妖艳**。刻画人物心里的挣扎和思辩非常细致入微,简直到了变态的程度。他对行文节奏和结尾留白、以及意象的运用简直炉火纯青,用词也非常华丽但有分量,甚至让我读着读着浑身起鸡皮疙瘩,非常喜欢三岛由纪夫的文字。 + +我在初读《金阁寺》时,有不解的地方,在读完后查阅了大量评论和解读,再回头去看里面的一些情节和描写才有了自己的一点粗浅的理解。为什么说三岛的文字妖艳呢,就是因为你越读,越会陷入角色的思考和情绪里;越不懂,越撩拨着你的心,去研究,体悟那种独特的风格。找时间一定要再看一遍。 + +川端康成与之相比就是一种细腻柔和的美,这种切换让我有点不适应。三岛的叙述手法是一种标准的小说家的手法,讲故事的手法,但川端康成是在展示日常的细节碎片,用这种手法把读者一下子拉入到情节中,节奏比较缓慢,像流水一样,虽然潺潺流过,但把手指伸进去,能感受到水流湿滑的触感和阵阵沁人心脾的清凉。 + +东野圭吾的两本书,《解忧杂货店》可以称得上是无聊的。关于《白夜行》,我对推理题材没有想象中的那么感兴趣,或者是没有读到合口味的书,只能说悬念环环相扣,但节奏比较拖沓,看得很心急。 + +《金色夜叉》和《潮骚》又让我对爱情有了新的感受,前者权衡爱情和钱财,揭露批判拜金,后者则是纯洁美好的初恋,很「不三岛」的一本书。 + +另外,在图书馆读了四十页的《喧哗与骚动》,为什么记得这么清楚是四十页?因为是真煎熬啊!太难读了!现在还不适合我,但早晚有一天我要带着更高的阅读能力和文学素养,征服这座高山。 + +除了书,我也经常用博客圈子提供的随机访问网站,找几个博客读一读,有喜欢的就加入到RSS订阅。 + +## 博客 + +暑假里我写了几万字,平均四五天更新一次。由于开学时的博客大部分都是在写学校遇见的烂人烂事,放假前还会担心,在家里闷着是不是没有什么东西可写?事实证明并不会。 + +这两个月我换了不少主题,也自己写过一两个主题,最后还是没能用下去。挑来挑去,最后还是选择了以前用 Hexo 最喜欢的主题的 Hugo 移植版(不太清楚哪个博客程序的才是本家) —— [Maupassant](https://github.com/JokerQyou/maupassant-hugo/). + +大刀阔斧地砍掉了很多功能,模仿 Typecho 的默认主题,添加了暗色模式,看起来舒服多了。我对目前的主题非常满意。 + +对永久链接格式也进行了几轮改革: + +```bash +1. + /post/技术/* => /post/tech/* + /post/随笔/* => /post/jottings/* + /post/读书/* => /post/readings/* +2. + /post/tech/* => /posts/tech/* + /post/jottings/* => /posts/jottings/* + /post/readings/* => /posts/readings/* +3. + /posts/tech/* => /posts/* + /posts/jottings/* => /posts/* + /posts/readings/* => /posts/* + +``` + +第一次为了去除又长又蠢的链接,把汉字改成了英文,第二次突然发现post是不是要用复数更恰当?又改了一次。第三次发现目录嵌套有点深,就把第一次改的分类名删掉了。 + +真是想到什么就做什么啊。 + +为了SEO权重考虑,废了很大力气调试`vercel.json`的重定向,好在大部分页面都能正常跳转了,以前的水文我也不打算处理。 + + +## 画画 + + + +这是我临摹的在知乎上找到的一张图,来源已不可考。佩服那位大佬的能力,这种画面风格再给我十年我也达不到...... + + + +这张来自我很喜欢的一个博客「[極客死亡計劃](https://www.geedea.pro/)」网站顶部的一张图。 + + + +凭印象画出的[《夏日残影》](https://www.yingyu5658.me/posts/%E5%A4%8F%E6%97%A5%E6%AE%8B%E5%BD%B1/)结尾提到的那只鸟。 + +## 最后 + +总结一下,不就是两个月都窝在家里看书画画吗!化学也没学,物理数学也没学...... 到现在为止连暑假作业都没完全写完。 + +希望开学以后,依然能保持现在这种心态吧。 + +--- + +封面图作者为Dan Black, 来自[Unsplash](https://unsplash.com/photos/brown-dried-leaf-on-brown-tree-branch-K7f1BKy41aE)
\ No newline at end of file diff --git a/content/posts/写在十一月的开头.md b/content/posts/写在十一月的开头.md new file mode 100644 index 0000000..033bad0 --- /dev/null +++ b/content/posts/写在十一月的开头.md @@ -0,0 +1,83 @@ +--- +date: '2025-11-01T19:54:36+08:00' +draft: false +title: '写在十一月的开头' +slug: 'beginning-of-november' +categories: + - 随笔 +tags: + - 月度总结 +--- +十月的总结忘写了,原来现在已经十一月了吗! + +我在[九月总结](https://www.glowisle.me/posts/beginning-of-september/)的结尾,天真地以为开学后我也能保持那种心情或心态: + +> 希望开学以后,依然能保持现在这种心态吧。 + +事实证明,开学后的精神状态比较差,也没有动力写东西,重要的是,可写的事也不多,所以这篇就当流水帐,想到什么就写什么吧。 + +## 新域名 + +我至今位置用过几个域名,里面都包含`yingyu5658`这个字眼,它的优点是很随意,不用花多少钱就能买到相应的域名,而它的缺点就是太随意了,容易和「英语」混淆,倒不如说实际上它就是英语的意思,因为这是我小时候玩游戏起 id 乱敲的。我不想再被别人叫「英语5658」了…… + +远古时期,我的博客叫「yingyu5658的博客」、「yingyu5658's Blog」、「yingyu5658的万事屋」,但后来发现那样实在是太烂大街且随意了,在这三者中,我最不明白为什么我曾经用了最后一个名字,这就像中二时期发的朋友圈一样羞耻,但是我好像没有中二时期,或者说中二时期是十岁以前。 + +后来我强行给「yingyu」这个词安上了一个意义:「映屿」,当时的域名是`yingyu5658.me`,也对应上了。这下我要佩服我自己了,胡邹能力还真不错,能拼凑出一个这么有画面感和美感的词,就沿用下来了了。但一直觉得`yingyu5658`这个词太扎眼了,尤其是后面的无意义数字。大概在二十号,我整理 RSS 订阅源,发现大家的域名都真好看啊,于是就动了换域名的念头。 + +首先域名一定要简短,毕竟是给访客的第一印象。博友圈的群友帮我想了个「inyu」,短是短,但还是太随意了,如果翻译成英文可能会更好,所以定下了以下几个翻译: + +- HueIsle +- ShineIsle +- GlowIsle + +首先是 Hue,这个单词更侧重于**色彩、色调**的意味,重点在传达「映照出色彩」,主题不是「映」而是「色」,Pass. + +其次是 ShineIsle,太直白了,有一种强烈的向上的积极感,和风格不匹配,Pass. + +综上,Glow 这个词更合适,它的意思是**「柔和的光」**,呈现光泽、微光之意,比 Shine 温柔,比 Hue 恰当。 + +后缀考虑过`.zone`、`.me`、`.com`,最终还选择了`.me`,更符合个人博客的定位。 + +经过了一系列域名解析和重定向的折腾,终于算是顺利更换了,只是在搜索引擎的收录和排名上急不来,只能多提交 Sitemap 了。 + +## 新主题 + +之前使用自己搓的仿 Typecho 默认主题,主要是喜欢双栏布局和简介风格,但后来我仔细思考了一下,我的侧边栏或许是一个非常糟糕的设计。 + +首先,我的站点并没有一套成体系的知识网络,所以分类的作用对读者来说并不大,不值得单独放在侧边栏。其次,**最近文章**是侧边栏最大的败笔,用户动动鼠标就能看到新文章,为什么要用侧边栏的宝贵空间? + +我见到有一些博主喜欢把自己的介绍信息放在侧边栏,我也想尝试,直到我发现我并不会自我介绍,也很少拍照片,头像只能放 favicon 的图片,效果反而不如不放。而且我相信读者并不在意我是谁,而在意我想说什么。 + +所以我之前的侧边栏非常多余。由于长期加需求改需求,CSS 代码膨胀到了两千多行,其中包含了许多无用代码,重构难度极大,只好弃坑!我也看腻那个主题了。 + +我在寻找真正简介的单栏主题,比如 [typo](https://themes.gohugo.com.cn/themes/typo/) ,在尝试修改代码的时候,出现了一个非常诡异的问题:任何修改都不起作用。我随即想到是不是引入方式的问题?大概是git submodule导致的,但这个主题如果不如是引用,某些组件就无法渲染,只好作罢。 + +最后选择了 [BearNeo](https://github.com/rokcso/hugo-bearneo/),简单修改后投入了使用。它符合我对博客网站的思想理念 —— 简介、高效、主次分明。读者不是想来看我的大头照、樱花飘落、鼠标点击特效、背景图片、标签页离开特效、音乐播放器、各种网站的热搜和当地天气的。另一个方面,它很符合我目前理想中的博客的「质感」。 + +## 新闻组 + +十月二十一日,我在新闻组发布了停止维护的通知。我实在没有时间精力和财力去维护新闻组。一开始本来抱着搭着玩玩的心态,在知乎、Emacs China 宣传了一两次,没想到还有那么多对互联网文物技术感兴趣的同志,一起参与新闻组里的话题,帖子快突破两百条了。 + +现在在 Bing 搜索「新闻组」,往后翻一两页就能找到我在 Emacs China 发的帖子和博客里关于新闻组的文章,或许是由于近些年这个话题实在没有什么讨论,权重才会比较高吧。服务器里所有帖子都备份了下来,之后会重新启动,可能是几个月之后,也可能是几年之后…… + +## 新座位 + +在学校由于我的默默无闻,导致我看起来很像一个好学生,至少是老实的学生。常年坐在偏僻的角落。有两个同学不知道犯了什么错,班主任非常生气,把他们两个的座位调开,安排我坐到了其中一人的位置。那是倒数第三排。 + +这并不是对我的惩罚,这应该是提拔。我前面的三个人,还有右边一组的四个人,都是年级前列,学霸中的学霸,学习氛围相当好。但很显然,我无法融入他们,无论是社交还是成绩。虽然他们对我很友好。我能感觉到我与他们之间有一种微妙的距离。 + +他们越是完美,就越映照出我的瑕疵;越是强大,就越体现出我的弱小。哪怕他们身上有什么缺点或不良习惯,都可被视作一种风趣,而这种事发生在我身上,只能是**毛病**。 + +我前面的两位都是数学课代表,数学是我最不擅长的学科。那次跑操请假在教室自习,本以为会度过安静的三十分钟,但那两人给老师帮忙回来了,有正当理由不用去跑操。他们抱着一叠数学卷子在班里讨论。其中一个人是女生,她高兴时说的每一句话的尾音都会上扬并且拉长,用「嗲」这个字不至于,但确实类似。 + +扎耳。 + +这让我想起换座位前身后的那个女生,她似乎永远保持着开心的状态,即使遇到了困难或不公的事情,也只是用如唱歌一般动听的语调,脸上挂着自信的微笑而说出:「哎呀!我不行啦!」 + +三个数学课代表都回来了,他们围在其中那个女生的桌子周围,也就是我的前桌讨论成绩。我只能低头写作业,因为我知道我和这群人没有任何共同话题可言,我不敢抬起头,他们也默契地就像班里不存在我这个人一样,自顾自地看大家的卷子。 + +三个阳光开朗、文化体育成绩都优秀的人,其中任何一个人的智力和体力都是不敢想象的程度,这样的人就在我面前谈笑风生。 + +## 最后 + +活下去吧!活着!像牲口一样活着! diff --git a/content/posts/初折腾Emacs记录.md b/content/posts/初折腾Emacs记录.md new file mode 100644 index 0000000..60106df --- /dev/null +++ b/content/posts/初折腾Emacs记录.md @@ -0,0 +1,107 @@ +--- +abbrlink: 2193909713 +categories: +- 往昔 +date: "2025-04-13 12:15:33" +tags: +- Emacs +title: 初折腾Emacs记录 +--- + +## 基础配置 + +Windows下需要在软件顶部Toolbar的Options中随便更改一个选项,然后再点Save Options,这样就会再`C:\Users\Username\appdata\Roaming\`下生成.emacs和.emacs.d/ + +在emacs.d中新建一个文件`init.el`,填写如下配置 + +```lisp +;;; init.el --- Load the full configuration -*- lexical-binding: t -*- +;;; Commentary: + +;; This file bootstraps the configuration, which is divided into +;; a number of other files. + +;;; Code: + +(let ((minver "25.1")) + (when (version< emacs-version minver) + (error "Your Emacs is too old -- this config requires v%s or higher" minver))) +(when (version< emacs-version "26.1") + (message "Your Emacs is old, and some functionality in this config will be disabled. Please upgrade if possible.")) + +(add-to-list 'load-path (expand-file-name "lisp" user-emacs-directory)) ; 设定源码加载路径 +;; (require 'init-benchmarking) ;; Measure startup time + +(defconst *spell-check-support-enabled* nil) ;; Enable with t if you prefer +(defconst *is-a-mac* (eq system-type 'darwin)) + +;; Adjust garbage collection thresholds during startup, and thereafter + +(let ((normal-gc-cons-threshold (* 20 1024 1024)) + (init-gc-cons-threshold (* 128 1024 1024))) + (setq gc-cons-threshold init-gc-cons-threshold) + (add-hook 'emacs-startup-hook + (lambda () (setq gc-cons-threshold normal-gc-cons-threshold)))) + + + + +;; ========================================================================================================== +;; ===========================================日常使用配置=================================================== +;; ========================================================================================================== +(setq confirm-kill-emacs #'yes-or-no-p) ; 在关闭 Emacs 前询问是否确认关闭,防止误触 +(electric-pair-mode t) ; 自动补全括号 +(add-hook 'prog-mode-hook #'show-paren-mode) ; 编程模式下,光标在括号上时高亮另一个括号 +(column-number-mode t) ; 在 Mode line 上显示列号 +(global-auto-revert-mode t) ; 当另一程序修改了文件时,让 Emacs 及时刷新 Buffer +(delete-selection-mode t) ; 选中文本后输入文本会替换文本(更符合我们习惯了的其它编辑器的逻辑) +(setq inhibit-startup-message t) ; 关闭启动 Emacs 时的欢迎界面 +(setq make-backup-files nil) ; 关闭文件自动备份 +(add-hook 'prog-mode-hook #'hs-minor-mode) ; 编程模式下,可以折叠代码块 +(global-display-line-numbers-mode 1) ; 在 Window 显示行号 +(tool-bar-mode -1) ; (熟练后可选)关闭 Tool bar +(when (display-graphic-p) (toggle-scroll-bar -1)) ; 图形界面时关闭滚动条 + +(savehist-mode 1) ; (可选)打开 Buffer 历史记录保存 +(setq display-line-numbers-type 'relative) ; (可选)显示相对行号 +(add-to-list 'default-frame-alist '(width . 90)) ; (可选)设定启动图形界面时的初始 Frame 宽度(字符数) +(add-to-list 'default-frame-alist '(height . 55)) ; (可选)设定启动图形界面时的初始 Frame 高度(字符数) + + +;; ========================================================================================================== +;; ===========================================插件镜像配置=================================================== +;; ========================================================================================================== +; 腾讯镜像 +(require 'package) +(setq package-archives '(("gnu" . "http://mirrors.cloud.tencent.com/elpa/gnu/") + ("melpa" . "http://mirrors.cloud.tencent.com/elpa/melpa/"))) +(package-initialize) + + +;;; init.el ends here +``` + +基础的设置和插件镜像源就配置好了,此配置可完全复制照抄。 + +重启Emacs,按下`M-x`输入`package-list-packages`即可查看仓库中的所有插件 + +> 在此列表界面下还可按下h显示帮助,按U检查所有已安装插件是否需要更新,如有就标注更新,按i标记想要安装,最后按下x就可更新。 + +插件默认会被安装到`~/.emacs.d/elpa`下,Windows同理。 + +删除插件输入`package-delete`,然后输入想删除的插件名即可。 + + + +## use-package + +### 安装 + +输入命令`package-install`回车后输入use-package回车,然后在init.el的最上面写 + +```lisp +(eval-when-compile + (require 'use-package)) +``` + +每次启动Emacs优先加载此插件 diff --git a/content/posts/别吵了,大家一样烂.md b/content/posts/别吵了,大家一样烂.md new file mode 100644 index 0000000..4755da8 --- /dev/null +++ b/content/posts/别吵了,大家一样烂.md @@ -0,0 +1,61 @@ +--- +categories: +- 随笔 +date: "2025-08-17T14:54:06+08:00" +draft: false +slug: we-are-all-bull-shit +tags: +- 网络环境 +- B站 +- 知乎 +- 豆瓣 +title: 别吵了,大家一样烂 +--- + +突然想起来之前刷到过的一张图,是一个看起来就**和蔼可亲的**黄豆摊手,配文:「别吵了,大家一样烂」,手里是一圈国内主流的娱乐软件图标。大概有百度贴吧、B站、知乎、豆瓣、小红书等。 + +不得不承认,大家确实烂,但各有各的程度和地方。就在前几个小时我还说,等我B站六级了就卸载。很快了。 + + + +## B站 + +至于为什么我有这个想法,现在还在用B站的人应该都知道,B站和妓院的唯一区别就是,你不能花钱买到肉体寻欢。但是你可以花钱买到擦边UP主的视频,并用以意淫。晚上她们就出没了。 + +有些B站用户会有一种莫名的优越感,尤其是在一些刚刚从抖音、快手这种平台转到B站的,你可以见到他们一些二级号,说出「抵制B站快手化」此类的展现人类智商情商判断力下限的**皈依者狂热**现象。这是一种寻求群体认同感所作出的举动。他们认为看B站,就比看短视频优越。大家都是在娱乐,况且真正的优质长视频UP主有几个有热度?大家还不都是点开那个短视频的按钮一直在刷?还是尽早找点事做,不要妄想用个软件就能走上人生巅峰了。 + +但回归到标题:**大家都一样烂**。 + +我认为B站之所以烂,是因为有上文描述的幽默行为。这是评论区中的,弹幕更是看得想让人用头撞墙,比如书名号、并非、「相信咱妈」等,还有「有人吗」、「某年某月某日某时某分有人吗」、「跟我一起看的人举个手」。那个显示几个人在同时看的功能简直是这种弱智的温床。童厕名不虚传。 + +话说回来,B站确实有不少优质的UP主,但比起用碎片时间学碎片知识,不如静下心来读一本书、一篇文章,或看一部电影。我没有在否定B站知识区优质长视频的价值,但要清楚,频繁的信息切换会阻断思维流,长时间积累就会导致无法深度思考。很多视频只是告诉了观众:「是什么」,而不探究「为什么」,中间很大一部分内容都被省略、简化、剔除了。这也是很多情况下,人们看问题只浮于现象、无脑开喷的原因之一。如果目标是深度研习,在B站找大课看会比所谓的科普短视频有益的多,当然,如果的目标是快速扫盲,看科普短视频无可厚非,问题的重点在于**结合实际**。 + +## 知乎 + +最近我的新宠是知乎,谈起为什么我喜欢知乎,是因为它能满足我的好奇心,看文字比看视频省力一些。在一些离谱的问题下,会有短小精悍的回怼,比较有意思,在一个问题下,大家讨论的集中度和强度也很高,信息密度大。 + +但知乎确实烂,盐选的垃圾小故事总是披着回答的外衣恶心人。不过除此之外,没感觉到环境多恶劣,都在友善的阴阳怪气。 + +## 豆瓣 + +我身边的一位朋友听说我刷豆瓣,非常震惊,他一向认为豆瓣和小红书是一个性质,是女拳大本营。在我这里就大错特错了,我可以放一张我豆瓣首页的截图证明。 + +<details> +<summary>展开</summary> +<img src="https://images.glowisle.me/douban.jpg"> +</details> + + +除了读书就是广告,没有见到过什么女拳或者吵架,环境非常好。可能是因为我一直拿它来看书评。虽然我有点讨厌我的班主任,但还是要举一个她曾经说过的例子。 + +我们学校对行为规范的管控特别严格,谈恋爱这种事情更是不要想,她带过一个学生,之前跟他交谈中,他一直认为学校里谈恋爱的人非常多,满操场都是情侣。 + +后来他受到那些所谓情侣的影响,也和班里一个女同学好上了,被班主任抓住,及时熄灭了火苗,但最后他还是坚称:「们学校谈恋爱的真的特别多!」 + +其实本质上就是他个人想谈恋爱,才会去注意那些情侣。就像一个悲观的人,看夕阳都能觉得那是太阳的尸体,所以自己心里想得东西占比大。这在软件的个性化推荐里体现的就更淋漓尽致了。我的一位同学,对历史和时治有兴趣浓厚,尤其是中国现代史,尤其是「文化大革命时期」的历史。不过具体细节,应该是一问三不知的,他只是痴迷于国家对此言论管控严格,自己却用各种意象指代,那种微妙的刺激的叛逆快感,我愿意称之为**政治露阴癖**。他经常给我转发一些时政历史之类的短视频,我呢,佩服他的分享欲、求知欲,但对这种狗屁话题根本不感兴趣,也不方便骂他,只好承受狂轰乱炸。 + +从他给我转发的视频和他的言论看,应该是认为马上第三次世界大战就要开始了......他非常热衷于发表各类偏激评论,却又自以为有主见、学识渊博,很喜欢一些宏大的议题,如民族、政府、国家等。在他经常聊天的那个群里,几个人都凑不出一份入团申请书,他在里面义愤填膺,慷慨激昂地批判国内外各大事,有趣。有网友调侃这类人:「暑假结束后,国际共运就要陷入低谷。」岂是精辟二字了得。 + +正如刚刚举的例子,他就喜欢看时政历史,软件一直给他推送,又碰巧国外不太平,总以为要打仗,这两个例就很好的说明了,想成为什么,就会看到什么;越希望什么,就越会看到什么。 + +大家一样烂,但这不全是平台的问题,一直抱怨平台环境差,多少是因为自己没有进入环境好的圈子,理解了这个概念,所有的平台只是交流的载体和形式的区别了。 diff --git a/content/posts/别闲着没事自搜,黑历史啊.md b/content/posts/别闲着没事自搜,黑历史啊.md new file mode 100644 index 0000000..11cb067 --- /dev/null +++ b/content/posts/别闲着没事自搜,黑历史啊.md @@ -0,0 +1,54 @@ +--- +categories: +- 往昔 +date: "2025-08-06T10:07:38+08:00" +draft: false +slug: "" +tags: +- 自搜 +- 搜索引擎 +- SEO +title: 别闲着没事自搜,黑历史啊 +--- +### 在Bing自搜 +今天实在是太闲了,在bing搜了一下我自己的id,结果看到了早期刚建站时的各种黑历史。搜索引擎的缓存还没有消失,已经快一年了。甚至连最早用的第一个域名都挂在上面,但是那个域名现在已经易主了,现在是一个卖赌博机器的网站。估计站长看到有一个很蠢的中文页面还被搜索引擎收录也是很困惑。 + +这么说来,我这一年的成长倒是挺多,证据就是看到这些东西就像看到自己四五年前发的朋友圈和QQ空间一样羞耻。可是前者能删,但搜索引擎也不是我家开的,只能保证不要经常更换域名和永久链接格式,等着搜索引擎自己移除了,以前分享自己Vim的配置,甚至传网盘,现在都想穿越回去给自己一巴掌。 + +<!--more--> + +### 在BiliBili自搜 + + + +我能说什么,我只能呵呵呵。一群娼妓已经把这个网站占领了。在我关闭个性化推荐之前,满屏幕都是赛博妓女。乐器视频底下出奇多。但它们不如妓女,只要坐在镜头前,甚至不开摄像头,就会有人给这种人送钱,妓女起码付出了身体换取钱财,这种人就是典型的不劳而获。用赛博妓女这个词称呼都算侮辱了妓女。 + +### 在Google自搜 + + + +比Bing收录的内容及时多了,起码不会到黑历史的程度。不过确确实实有一个真正意义上的黑历史,我承认当时的言论过于激进和轻浮了。但我会保持对跨性别群体的看法。 + +### 在百度自搜 + + + +很遗憾,只有指定`site:www.yingyu5658.me`才能看到我的站点。 + + + +### 在360自搜 + + + +搜`yingyu5658`没有什么结果,但`映屿`的权重甚至比那几个卖房的网页还高,在Bing上不是这样的。 + +### 在Yandex自搜 + + + +Github页面比较靠前,前一阵子在Bing上几乎搜不到`yingyu5658.me`这个域名,结果都是Github Pages。 + +看似自搜,实际上是检测各大搜索引擎对自己网站的收录情况,现在国人用的最多的搜索引擎应该是Bing吧,对个人站算是比较友好了,甚至一年前的链接都不下,可能和我之前弃用服务器、更换域名的处理手法有关,但那时候真是什么都不懂,虽然现在也是。 + +还有一些不知名的小网站收录了我以前写的技术文章,不过也都是老链接,hexo的链接。 diff --git a/content/posts/博客一周年,谈谈感想.md b/content/posts/博客一周年,谈谈感想.md new file mode 100644 index 0000000..8058ee8 --- /dev/null +++ b/content/posts/博客一周年,谈谈感想.md @@ -0,0 +1,91 @@ +--- +date: '2025-11-08T22:18:05+08:00' +draft: false +title: '博客一周年:我的表达、自由与偏见 —— 当一个「反流行」写作者' +slug: 'first-blog-anniversary' +categories: + - 随笔 +tags: + - 博客 +--- +## 搭建 + +### 探索时期 + +在2023年9月16日,我在腾讯云注册了第一个域名,使用一台轻量服务器搭建了WordPress博客,但也仅限于此,我只是搭建好了服务,并没有在上面写点什么,只是觉得有一个自己的网站很酷,这并不能作为我开始写博客的准确日期。实际上在这之前,我就用 [Ksweb](https://kslabs.ru/) 尝试搭建过自己的网站,并且Typecho和WordPress都尝试过,但当时没有做内网穿透,所以也不能算作正式开始写博客。 + +严格意义上讲,我是从2025年11月3日使用 [Gmeek](https://github.com/Meekdai/Gmeek/releases)正式搭建完第一个认真更新的博客,12月迁移到了Typecho,我当时发了一篇很短的文: + +>> 将会迁移到这里。我会把有价值的文章转过来 原因仅仅是gmeek有点太简陋了,虽然typecho也差不多,不过他可以折腾一下主题之类的,并且我每个月还多花出去九十大洋。但是总比gmeek逼格高点吧。 不得不说,Linux绝对是世界上最麻烦的玩意,解压下载文件都费劲。要不是Windows资源占用多我绝对不会去用这玩意。 这次可是孤军奋战,背后没有github服务器的靠山了。要是忘了续费服务器我会丢失所有的文章,又是一个负担和一个纠结的点 +> +>——[网站迁移](https://www.glowisle.me/posts/6/) + +之后回看连我自己都忍不住吐槽自己的无知: + +> 2025.8.24二编:Gmeek简直太符合博客的定位了,不花里胡哨,完全够用,有网就能写文章…… +> +> Linux太好用了,目前Debian12养老中。 + +现在发现,自己以前做了很多不明智的决定,比如放弃使用Gmeek…… + +使用Typecho期间,我开始学习Java编程,早期有很多简陋的笔记文章充数,但那时候学习和写博客是一个**相互促进**的过程,我相信很多技术博主能体会到我说的这一点。 + +### 转型时期 + +在2025年3月3日,我[ 从Typecho迁移到了Hexo](https://www.glowisle.me/posts/4/),在这之后博客的内容开始聚焦于**骂人**,对,就是骂人。骂老师,喷学校占用午休时间搞课桌舞,喷素质低下的同学等等,但只有情绪输出,写得很垃圾,大部分都删掉了。 + +在25年5月份到8月份是更新频率最高的一段时间,主要围绕折腾Linux, C, 数据结构与算法,一些技术内容为主,少部分是非技术类内容。7 月份到8月份写了一些很矫情的散文以及自以为是的书评,还有根本站不住脚的议论类文章,满满的黑历史。 + +其中,7 月7日我从Hexo转移到Hugo,我认为这是静态博客的最优选择了,高性能、易配置,如果一定要我挑出一个毛病,那也不是程序上的,而是中文文档的数量和质量略差,但无伤大雅,只要有翻译插件和基础的英语水平还是可以读得来英文文档的。 + +## 所见和所感 + +我加入了一些博客圈子,某些组织给我的印象并不是特别好——各种方面上。我最早加入的是[博友圈](https://www.boyouquan.com/home),氛围很好,关于网站的Bug,维护者跟进非常积极,但我不常访问这个网站,它的随机博客功能总是有重复,没有什么新鲜感。 + +另一个常访问的是[十年之约](https://www.foreverblog.cn/go.html),主要是为虫洞功能,重复博客出现的次数很少。 + +我这么做,一是为了看看别人都在写点什么,找点有意思的博客订阅,二是看看别人网站的样式都是怎么设计的。前者老生常谈,我觉得样式设计问题可以仔细聊一聊。 + +### 某种意义上样式最重要 + +虽然博客确实应该最优先考虑内容质量,但是不能否认一个好的样式设计能更加分。而且在读者深度阅读前,先看到的是样式,这属于第一印象。每个人都有不同的审美倾向,但我个人不太喜欢的就是类似[安知鱼](https://github.com/anzhiyu-c/hexo-theme-anzhiyu)和[Joe](https://78.al/)臃肿的设计风格(没有说用这两个主题的博客不好的意思,不要打我!!!)。 + +我的观点是,样式的设计始终是为内容服务的,而博客最主要的内容一定是文章,文章。所以一些组件就是非必要的,所谓 Less is more, 博客主题的设计应该始终放在博客的本质:「你想说什么」上,其他东西都是**锦上添花**,但把握不好就会成**画蛇添足**! + +#### 非必要的组件 + +某个主题默认引用了大量外部资源,访问速度很不稳定,点进来需要看博主的大头照一分钟左右,难道这是什么展示开屏页面的手段吗?侧边栏还有公告、音乐、舔狗日记、最近回复等等,看上去一幅百家争鸣的场面。还有我最不理解的:Joe主题的**人生倒计时**。这让一个有时间焦虑的人非常难受啊! + +以上所述,还不能算是拉低访问体验的,最让人难受的是**封面图**。 + +有一些博客主题,专门给封面图很多存在感,而加载速度又极其慢,加载完成后又是和文章内容关联不大的通用插画,甚至有些博客的文章封面图干脆用通一张,个人认为该约一下分了! + +其他的看板娘、背景特效、音乐播放器等不在此过多赘述,已经成一个梗了: + +> 感觉你是那种博客一打开就bgm响个不停、樱花飘屏、瞅瞎眼看不清和背景色颜色一致的字体、鼠标屏蔽右键、顶部挂春节已经过时的灯笼、谷歌广告多余博客文章、底部20多个山寨备案号、加载5分钟才能出来的 猪腰子皮鞋 蕾丝小白袜 短裙 张开双臂拥抱的二次元幼女背景 + +我认为,**个人作品集**和**博客**是有本质上的区别的。而且放上一堆根本不是自己写的东西,并不会觉得有多自豪。 + +一些热门的开源样式在一百个博客中应用的概率,就和你在火车站上喊上一嗓子张伟有一堆人答应的概率一样大。这里我要引用一个有些可悲的例子:考场作文怎样博阅卷人欢心?答案是打破他的审美疲劳。而寻求新鲜感的前提条件,也就是博客样式设计的基本理念是:**服务于内容**、**主次分明**、**少即是多**。 + +话又说回来了,写博客不是上班,自己玩得开心最重要,但样式的选择和设计,更多的是审美和价值理念的双重体现。 + +## 为什么我还在写博客 + +这个问题一直被文字或图文创作者所津津乐道,大概理由会扯到短视频、思考、阅读的对比,并把短视频踩得一无是处,把文字和书籍捧上天,认为为那是通向成功的唯一途径。虽然我不刷短视频,但我认为搞拉踩不是好的行为,如果短视频真的一无是处它就不会存在。但在这里谈论短视频的问题,不如单独写成一篇文章。 + +我的理由是:自由和酷,以及习惯。 + +酷这词并不能准确表达那种状态,也许更多的是归属感和安全感共同作用所产生的自豪,「我有一片能自言自语的天地」的幼稚的优越感吧。 + +我讨厌平台的审查机制、推送算法和编辑方式。中文互联网的审查机制非常**幽默**,如果你在 Bing 国内版搜「谈笑风生」,就会有一幅非常诡异的画面——《新京报:领导人的漫画形象》《求是网:毛泽东耐人寻味的生日宴》《新民网:追忆江泽民同志在上海的日子》…… + +另外,在平台上,几乎不会有人关心「我」,创作始终是围绕观众喜爱来的,从中脱离出来想写什么就写什么,这也是自由的体现。 + +关于习惯,我这人有个毛病就是,一写东西就收不住,状态好了就能写好多,也许是与我说话罗嗦有关。但如果不多写几个字,怎么能准确地描述事件的起因、经过、结果等必不可少的东西呢?我在发朋友圈说什么事的时候经常写一大段字,和其他朋友上下几张图片的画风完全不相称,自己都觉得有些尴尬。 + +有人就不喜欢写字,也不喜欢看字,只喜欢图片和视频,我能理解这种心情,这只是习惯问题。我选择写博客,只是因为我认为比起坐在镜头前一边拉手风琴一边说话,又要关注打光和背景等前期工作,又要关注剪辑和配乐等后期工作,还是写字的成本更低。 + +## 总结 + +写了这么长时间博客,其实一开始只是抱着玩玩的心态,后来变得越来越认真了。表达和写作能力有提升吗?我感觉不到,但看到别人写得文章很好,一种奇妙的胜负欲和攀比心就会促使我学习得更多更深,继续写下去,既然做了,就做到底,做得更好吧! diff --git a/content/posts/博客文章加密码的意义是?.md b/content/posts/博客文章加密码的意义是?.md new file mode 100644 index 0000000..42954a7 --- /dev/null +++ b/content/posts/博客文章加密码的意义是?.md @@ -0,0 +1,39 @@ +--- +abbrlink: 493132927 +categories: +- 往昔 +date: "2025-05-19 21:53:10" +tags: +- 博客 +title: 这样的博客的意义是? +--- + +## 博客文章的密码 + +博客文章加密码,意义何在? + +写博客的意义是? + +写博客的意义之一,不是放大自己的声音,表达自己的观点吗? + +这就要牵扯到你写博客的目的。如果你说,你写博客是为了取悦自己,那为什么要把文章发出来?取悦自己是真的吗?还是对自己网站没有流量的自我安慰?不允许他人看见,那我只能认为您财力精力都很强盛,有财力购买服务器、主题;有精力维护服务器、网站。为什么不写在备忘录里呢? + +发出来,不是为了被人看见? + +还是说,是在扮演什么角色、人设给什么人看? + +--- + +我个人一直十分痛恨各大平台的强制注册手段,复制代码要注册、展开文章要注册,打开评论区还要注册。所以在我一开始使用动态博客程序的时候,从来没想过有强迫读者注册才能评论。 + +这个问题依然要归结到写博客的意义。如果你写博客,是为了变现,利用在各个博客的评论区乱尿增加的一点SEO权重带来的可怜流量,和不知道从哪里抄搬来的技术文章,连格式都不调一下就挂在网站上又或是分享一大堆所谓免费资源,引流关注微信公众号的,强迫注册,为了赚钱,不寒碜。吗? + +很他妈寒碜! + +读者吃着你搬来的别人拉的屎,又要被你骗去你自建的茅房,这钱就算拿到,也是脏的,好好掂量一下这钱里都有什么。 + +如果是正常的博客,要强迫读者注册才可评论,查看文章,那更令人费解。技术文章下,读者遇到了问题,或想更近一步讨论;表达观点、分享日常的文章下,读者看到一个有趣的灵魂,一个,强迫注册,都无异于直接抹杀读者讨论的念头。输入邮箱或手机号,接收验证码、输入验证码,再登录。加之服务器地理位置、配置等原因导致的访问不畅,每一秒所做的每一个行为,都是在一丝丝抽离由文字与读者建立起的联系。 + +最后,只能说上一句: + +> 我写博客只为取悦自己。 diff --git a/content/posts/在2025年,搭建新闻组.md b/content/posts/在2025年,搭建新闻组.md new file mode 100644 index 0000000..ebf24fd --- /dev/null +++ b/content/posts/在2025年,搭建新闻组.md @@ -0,0 +1,107 @@ +--- +categories: +- 技术 +date: "2025-07-26T12:05:39+08:00" +draft: false +slug: set-up-newsgroup +tags: +- 新闻组 +- 怀旧 +title: 在2025年,搭建新闻组 +--- + +## 介绍 + +新闻组(英文名Usenet或NewsGroup),简单地说就是一个基于网络的计算机组合,这些计算机被称为新闻服务器,不同的用户通过一些软件可连接到新闻服务器上,阅读其他人的消息并可以参与讨论。新闻组是一个完全交互式的超级电子论坛,是任何一个网络用户都能进行相互交流的工具。现在已经没落,1990年前后是新闻组的鼎盛时期。很可惜,我晚了20年。 + +新闻组基于古老的NNTP协议,又名Usenet,类似一个巨大的论坛,用户可以在不同的组中发表内容,其他用户也可以回复内容,一切基于Email。 + +## 搭建 + +**这可能是当今互联网上,你能找到的为数不多的最新的有关新闻组的文章。** + +我使用[newsd](https://github.com/erco77/newsd)这个服务端来搭建,至于为什么没有使用**inn**,有两个原因:教程过时、软件库中没有。 + + +### 编译与初始化 + +``` +git clone https://github.com/erco77/newsd.git +make +``` + +如果没有错误的话,输出是这样的: +``` +yingyu5658@bongo ~/e/newsd (master)> make +g++ -Wall -DSPOOL_DIR=\"/var/spool/newsd\" -DCONFIG_FILE=\"/etc/newsd.conf\" -DSENDMAIL=\"/usr/sbin/sendmail\" -g -c newsd.C +g++ -Wall -DSPOOL_DIR=\"/var/spool/newsd\" -DCONFIG_FILE=\"/etc/newsd.conf\" -DSENDMAIL=\"/usr/sbin/sendmail\" -g -c Subs.C +g++ -Wall -DSPOOL_DIR=\"/var/spool/newsd\" -DCONFIG_FILE=\"/etc/newsd.conf\" -DSENDMAIL=\"/usr/sbin/sendmail\" -g -c Article.C +g++ -Wall -DSPOOL_DIR=\"/var/spool/newsd\" -DCONFIG_FILE=\"/etc/newsd.conf\" -DSENDMAIL=\"/usr/sbin/sendmail\" -g -c Configuration.C +g++ -Wall -DSPOOL_DIR=\"/var/spool/newsd\" -DCONFIG_FILE=\"/etc/newsd.conf\" -DSENDMAIL=\"/usr/sbin/sendmail\" -g -c Group.C +g++ -Wall -DSPOOL_DIR=\"/var/spool/newsd\" -DCONFIG_FILE=\"/etc/newsd.conf\" -DSENDMAIL=\"/usr/sbin/sendmail\" -g -c Server.C +g++ -Wall newsd.o Subs.o Article.o Configuration.o Group.o Server.o -o newsd +pod2man --center "newsd Documentation" --section=8 newsd.pod > newsd.8 +pod2man --center "newsd Documentation" --section=8 newsd.conf.pod > newsd.conf.8 +pod2html newsd.pod > newsd.html +pod2html newsd.conf.pod > newsd.conf.html +``` + +前台调试模式:sudo ./newsd -d -f +后台守护进程:sudo ./newsd(日志输出至 ${LOG_DIR}/newsd.log) + +### 创建`sendmail`文件 + +``` +sudo touch /usr/sbin/sendmail +chmod a+x /usr/sbin/sendmail +``` + +### 创建新闻组 + +``` +sudo ./newsd -newgroup +``` + +运行这条命令后,程序会依次要求输入: + +- 组名 + +- 是否允许用户发件 + +- 字数限制(?) + +- 描述 + +- 管理员的邮箱 + +- 将所有帖子的副本密送到的邮箱 + +创建好后,运行`sudo ./newsd -d -f`。 + +``` +Sat Jul 26 12:28:48 2025 newsd[38895]: -- newsd started - V1.54-- +Sat Jul 26 12:28:48 2025 newsd[38895]: -- start config summary -- +Sat Jul 26 12:28:48 2025 newsd[38895]: ErrorLog stderr +Sat Jul 26 12:28:48 2025 newsd[38895]: HostnameLookups off +Sat Jul 26 12:28:48 2025 newsd[38895]: Listen 0.0.0.0:119 +Sat Jul 26 12:28:48 2025 newsd[38895]: LogLevel debug +Sat Jul 26 12:28:48 2025 newsd[38895]: MaxClients 0 +Sat Jul 26 12:28:48 2025 newsd[38895]: MaxLogSize 1048576 +Sat Jul 26 12:28:48 2025 newsd[38895]: SendMail /usr/sbin/sendmail -t +Sat Jul 26 12:28:48 2025 newsd[38895]: ServerName bongo +Sat Jul 26 12:28:48 2025 newsd[38895]: SpamFilter +Sat Jul 26 12:28:48 2025 newsd[38895]: SpoolDir /var/spool/newsd +Sat Jul 26 12:28:48 2025 newsd[38895]: Timeout 43200 +Sat Jul 26 12:28:48 2025 newsd[38895]: User news +Sat Jul 26 12:28:48 2025 newsd[38895]: -- end config summary -- +``` + +其中,我们需要注意的信息是监听地址,由于我这里是本地环境,是`0.0.0.0`。这时用客户端连接这个地址,订阅刚刚创建的组就可以使用了。 + +这个服务端自己搭着玩玩还是足够的,大规模还是要用其他的,不过现在大规模的新闻组肯定不多了。 + +## 附:关于新闻组的文档资料(hypermemo整理) + +- nntp 协议的参考资料: https://www.eyrie.org/~eagle/nntp/ +- inn 文档(英文):[https://www.eyrie.org/~eagle/software/inn/](https://www.eyrie.org/~eagle/software/inn/) + diff --git a/content/posts/基于身边扩列者行为观察的结论.md b/content/posts/基于身边扩列者行为观察的结论.md new file mode 100644 index 0000000..3073398 --- /dev/null +++ b/content/posts/基于身边扩列者行为观察的结论.md @@ -0,0 +1,58 @@ +--- +categories: +- 往昔 +date: "2025-07-12T16:13:14+08:00" +draft: false +slug: kuo-lie +tags: +- 社交 +- 扩列 +title: 基于身边扩列者行为观察的结论 +--- + +> 本文描绘的群体画像仅代表个人在社交媒体上所见,尤其是**音游圈**的行为,不代表所有人。观点包含个人主观推测,谨慎甄别。 + +我把朋友圈和QQ空间关闭的原因之一就是有很多扩列的。一直很不解,扩列的意义到底是什么? + +微信和QQ的扩列(在我的圈子里)堪称两个极端。微信的扩列:无自我介绍,无任何信息,甚至连小朋友们最喜欢玩的MBTI也不贴,直接就是一个二维码,旁边放一个前凸后翘大长腿的网图,文案是“➕”。 + +而QQ的扩列是另一个极端。滑好几页的自我介绍。年龄、MBTI人格、玩什么游戏,玩到了什么成绩、看什么动漫、坐标(也就是所在省份)等等面面俱到。 + + +一些扩列条我甚至第一条都读不懂:“**cn是他妈的什么?**” + +查了一下才知道,原来这是类似“圈名”的概念,类似的术语还有很多,但这又是另一个圈子的分支。 + +点进精心装修得金碧辉煌的QQ空间,读着会员专属字体配色的尊贵文字,可以发现扩列行为大概可以分类两种:以兴趣为导向,寻找游戏玩伴等;缓解孤独感:纯粹交友。前者在筛选把控和精准匹配上很是下功夫。 + +--- + +这个扩列这个圈子有一个很有意思的词:“雷”。据业内人士透露,雷就是指讨厌的事情,在扩列条上写明自己讨厌的事,防止踩雷,这在我看来是一种挺高明的做法,有概率避免被冒犯,但也无形中增加了交流负担,且易暴露关系的脆弱性。如果“雷”被踩直接炸,确实危险。 + +什么雷、单删等条条框框,有些人极端夸张,甚至因为对方“单删”自己,直接把ta挂在空间,意图网暴。高强度活跃于空间/朋友圈也能说明ta们有着很强的分享欲。无论好事坏事,美事糗事,都要往朋友圈/空间发。此时,开头的问题有了答案。 + +扩列的意义究竟是什么? + +我得出的结论之一是:**建立自我价值感**。 + +自我价值感包含自信、自爱和自尊三个递进层,最终发展为**自尊**。在认知层面,是个体对自身才能,社会地位,声誉的评估。 + +我所观察到的部分群体在扩列活动中,自我价值感的建立主要体现在自信层面,由空间互赞的行为,在主观上提升自己的声誉;在高强度活跃于圈子中渐渐积累地位。 + +说说/朋友圈的赞数和评论量化了声誉和社会地位,这在自我价值感的建立中是起正向作用的。但极端者,表达欲会被扭曲,从“我想分享什么”,变成总在想“别人会喜欢我分享什么”的转变,标志着自我价值以内在感受和体验评估,变成了由外部反馈提供。彻底迷失在众人目光注视之下。 + +结论之二是:**获得新鲜感**。 + +一块刚出锅的红薯和放了一下午的红薯口感肯定不同。持续交友,保持新鲜感。我也见过有人很喜欢社交媒体的红点,能营造出一种自己很受欢迎的氛围,而扩列就能做到这点:“新的好友申请”、“新消息”等。 + +人与人之间的交际关系可以用图的结构来表示,扩列条的转发让一个节点的属性放射性地广播出去,跨更远的节点,建立链接。这张图几乎是不会断的,因为人的社交网络是不会断的,如果这个扩列条一直被转发,那么理论上就有可能走到互联网的每一个角落,从而产生持续性。如果人们停止转发,那自己就再发一条,请求好友们继续转发。 + +然而这仅仅是理论上的设想,社交网络并非一张无限连接到全世界所有人的图,而是分裂成一小块一小块不同的图,各为一个圈,仅少数活跃在多个圈子的人可能链接着两个小图。所以信息的传递效率没有理论上那么恐怖,这也就为兴趣为导向的扩列提供了积极作用,至少可以在小圈子内传播,找到同好。 + +扩列行为中普遍存在的一个现象是加了好友,几乎没有任何互动,我称之为“僵尸好友”。这是[邓巴数字](https://baike.baidu.com/item/150%E5%AE%9A%E5%BE%8B/2112262)的一个很好的验证。 + +小圈子中个体的小圈子浓缩再浓缩,最后形成所谓的小团体,高强度互动,筛选把控和精准匹配此时已经达到最终目的。 + +这也就是我得出的第三个结论:**获得归属感**。 + +包括MBTI、属性图等主观上容易被判断为贴标签的行为,也是在寻找归属感。 diff --git a/content/posts/夏日残影.md b/content/posts/夏日残影.md new file mode 100644 index 0000000..93270f1 --- /dev/null +++ b/content/posts/夏日残影.md @@ -0,0 +1,58 @@ +--- +categories: +- 往昔 +date: "2025-08-14T11:04:30+08:00" +description: “请各位勇士们扣好胸前的安全带。” +draft: false +slug: "" +tags: +- "" +title: 夏日残影 +--- +## 一 + +“请各位勇士们扣好胸前的安全带。” + +一个甜美的机械女声响起。那是跳楼机开始运行前例行朗读的温馨提示。 + +我从来都对这种游乐园没兴趣,但还是被硬拉来了。我当然不会花钱,冒着危险体验所谓的刺激感。 + +我们在一个静僻的拐角,弟弟被挖掘机铲土的项目吸引住了。八月醉人的阳光和聒噪的蝉鸣把周围一切事物都裹挟起来了,有时其他游乐项目的方向传来的尖叫刺痛着颅骨。我趴在租赁来的观光车上,望着眼前摆动的树影。 + +透过树影,看到了一条河,那条弯弯的波光粼粼的水道两边只有两排木栏杆,上面贴着“禁止攀爬”的告示。我向来都一个怕水、怕河、怕海,所以和河湖海有关的旅游提议都被我坚决反对了。 + +对于一个不会游泳的人来说,生与死之间隔着的,就是这一栏崎岖的木头吧?如果那个人站在了那栏杆旁,生与死就在一念之间吧?那一排木栅栏就是这一念幻化的实体吧? + +我感觉花钱体验濒死快感和溺在刺眼的阳光普照的,温暖的河水里区别并不大。但我再怎么争辩,在勇士眼中,也都是胆小者的狡辩了。我看到那澄澈的水面下有一条红鲤鱼。 + +想得出神,被一阵化学试剂的刺鼻味道拉了回来,转头一看是母亲在往自己脸部喷不知道是什么东西。 + +母亲的心情一直很高涨,她一直元气满满地对待每一件事,可能是因为有期待吧,她期待晚上九点钟开始的烟花表演。可以说,我们这次来,就是为了看烟花。 + +母亲的情绪越高涨,我心头那一根根稻草就越发沉重。为了防晒,她捂得严严实实。墨镜帽子黑口罩,活脱脱一个女明星上街的阵仗。 + +防晒措施越完备,我体内灌的铅就越多。我无法通过她的表情,揣测当前的局势究竟怎样。恐惧来源于未知,但我已经不怎么怕了。 + +很长时间没见到弟弟,父母在暑假刚开始把他送到农村的姥姥家了,我渡过了安静、平和、美好的一个半月。今天就把他接回家了,图书馆是个逃避的好去处,如果弟弟一定要在家的话。 + +他终于玩腻了那堆土,我终于不用被囚禁在影子里享受游客的尖叫声了。 + +--- + +## 二 + +升空、翻腾,闪耀着。炽热的烟花冲破黑夜的阴冷和浮躁,飞上高空。 + +但那都不是烟花最美的时候。烟花最美,最为人赞叹的那一瞬,一定是爆裂开来的那一瞬,随即就像欧律狄刻一样,湮灭在寂冷的夜空中了。 + +舞台中央喷射出的八九道火舌贪婪地舔舐着上方烟花残余的硝烟,一股令人窒息的热浪扑面袭来。 + +母亲很尽兴,带着满相册的照片上了回家的车,我也很尽兴。 + +快到家时,后脖上突然传来一阵瘙痒。一抓,竟是一股树叶般的触感——软绵绵无力,又毛茸茸的触感,似乎要被团成一个球了。拿到眼前一看,是一只半死的蛾子,它右边的翅膀折断了,是乱飞,撞到我脖子上的吧。随手一丢,掉在挡把下了,被父亲来回挂挡折磨得奄奄一息。 + +下了车,拿好东西准备上楼。我落脚太快,被咯了一下,正顾及脚趾传来的阵阵剧痛时,发现脚边有一个黑色的小身影。那是一只鸟。 + +它立在楼梯的栏杆下边,还睁着眼。见人不跑,我断定它是死了,母亲呵斥我不许动“人家”,我当然没有那么缺德,只是看看。等父亲走上来了,我跟他说了这件事,他用脚碰了一下那只鸟,翅膀挣扎着扇动了一下,但没有飞走。 + +楼道里昏暗的灯光一个劲儿地倾洒在这只鸟的身体,一片潦草的羽毛插在背上清晰可见。在那惨白灯光映衬下的无神的双眼更显呆滞和诡异,我又想起车上的那只蛾子。 diff --git a/content/posts/好文章.md b/content/posts/好文章.md new file mode 100644 index 0000000..2fd5449 --- /dev/null +++ b/content/posts/好文章.md @@ -0,0 +1,24 @@ +--- +abbrlink: 3975852992 +categories: +- 往昔 +date: "2025-06-18 21:53:51" +tags: +- 写作 +- 文章 +title: 好文章 +--- + +## 心灵小语 + +我们的语文作业从初一开始就偶尔留一项叫“心灵小语“的作业,文风可以和博客比较相似。但毕竟是要给老师看的,措辞还是要严谨一点。前两天的语文课老师读了两篇文章,巧了,我最受不了这种文章————用力堆砌耀眼夺目的辞藻,如青春、奋斗、阳光、生活。这就是老师眼中的好文章,扮演一个老师喜欢的性格,讲写点能敲出回声的文字,点意林风格的俗套故事。 + +对不起,这种耀眼的词汇会让我被燃烧成灰。 + +我不是标榜我的文章写的多好,只是单纯厌恶这种堆辞藻、假大空。以我的水平五十步笑百步又如何,名为心灵小语,心灵敲出的回声比文字还大,老师美其名曰:”以文观人”,好好观吧,多观观吹口气就破的纸壳吧;多观观用图钉钉在脸上的真诚的笑吧;多观观炽热的可燃的木头削成的心灵吧。烧了都嫌**恶臭**。 + +活了十四年,我感受到的所谓的青春就是四五十个人挤在一个小屋子里研究一个这辈子也不会用到的式子的结果是什么。明明任何一个理科都非常有趣,但总是被迫去研究最没有意义的一个环节,痛苦又无奈。所以我痛恨代数,几何多在探究“为什么“而不是”是什么”。这才是数学让人有成就感的一环。 + +现在明白了,大家很爱说上岸这个词,原来是从苦海游上来了。 + +真他妈恶心,我的青春啊。 diff --git a/content/posts/如何订阅新闻组.md b/content/posts/如何订阅新闻组.md new file mode 100644 index 0000000..df8e8a1 --- /dev/null +++ b/content/posts/如何订阅新闻组.md @@ -0,0 +1,51 @@ +--- +categories: +- 技术 +date: "2025-08-07T11:52:23+08:00" +draft: false +slug: how-to-subscribe-newsgroup +tags: +- 新闻组 +- Thunderbird +title: 如何订阅新闻组 +--- +## 新闻组简介 + +新闻组(Usenet) 是互联网早期最重要、最具影响力的分布式讨论系统之一,可以把它理解为现代网络论坛(BBS)、社交媒体群组或Reddit版块的前身。它的核心特点是去中心化,提供一个平台,让用户可以在不同的主题分类(新闻组) 中发表文章(类似于帖子)。 + +<!--more--> + +## 订阅 + +*如果有Emacs使用经验,可以用Gnus,本文使用[Thunderbird](https://www.thunderbird.net/zh-CN/thunderbird/all/)。* + +运行Thunderbird,点击左下角的齿轮。 + + + +点击账户设置。 + +点击上方的账户操作,选择新建新闻组账户。 + + + +填入昵称、邮箱等基本信息。 + +在下一个服务器地址页面填入`news.yingyu5658.me`,点击确定。回到最左边的标签页。 + + + +找到刚刚输入的服务器,选择顶部第二个“管理新闻组订阅”选项。 + + + +选好要订阅的组,点击右边一栏的订阅,确定。 + +在最左边的列表中,右键刚刚填入的服务器,点击收取邮件,每次想要阅读消息时就收取一次邮件。 + + + +如果有想参与讨论的话题,点进那个邮件,选择回复组即可。 + + + diff --git a/content/posts/学习文本编辑器的随想.md b/content/posts/学习文本编辑器的随想.md new file mode 100644 index 0000000..11d2f9a --- /dev/null +++ b/content/posts/学习文本编辑器的随想.md @@ -0,0 +1,214 @@ +--- +date: '2025-12-06T13:26:47+08:00' +draft: false +title: '剖析千行C语言文本编辑器Kilo的技术细节' +slug: 'kilo-analysis' +categories: + - 技术 +tags: + - C语言 + - 文本编辑器 + - Kilo +description: "关于Kilo的学习笔记。" +--- +今天上午学习了一下[Kilo](https://github.com/antirez/kilo)的源代码。我很早以前就对文本编辑器的实现方法感兴趣了。 + +Kilo是一个很简易却不简陋的项目,清晰地展示了如何构建一个终端下的文本编辑器,它的目的不是真正让你学会去开发一个高标准高质量,能投入使用的文本编辑器,而是理解文本编辑器的核心骨架、理解一个看似庞大一团糟的问题的拆解思路。这是一个很好的起点。也过了一把爽玩C语言的瘾(虽然我并没有写几行代码)。 + +## 程序分析 + +整个项目只有一个文件,一千三百行代码。我用了大概一个半小时梳理了程序的执行流程,手画了一个流程图。为了美观,我又用[Graphviz](https://www.glowisle.me/posts/%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8graphviz%E7%BB%98%E5%88%B6%E7%A8%8B%E5%BA%8F%E6%B5%81%E7%A8%8B%E5%9B%BE/)绘制了一个电子版: + + + +这张图我省略了一些深的函数调用,但也能帮助我大体上掌握这个程序的执行流程。结合这张图与源码,我发现文本编辑器的核心功能——打开、编辑、保存,实现难度并不大,在C语言中容易踩坑的是缓冲区处理、文件读写这种老生常谈的内容。在这个程序中,调用最多、最重磅的部分是`initEditor`这个函数,以及后续的高亮处理,尤其是前者在窗口尺寸计算、修改后的做法上花费了大功夫。其实和终端环境的交互才是最麻烦的点,它提供的封装和抽象并不多,有很多需要自己手动调试的地方,繁琐是显著特征。 + +### 终端信号处理 + +我发现在终端程序里,需要快捷键的部分都是使用Raw mode和signal相关的函数组合实现的,在理解`signal`这个函数和它的有关宏的概念时,耗费了比较长的时间。 + +简单来说,signal用于处理用户在终端发出的信号,比如`SIGINT`代表由`C-c`产生的中断信号,`SIGIGN`代表忽略信号,即接受到这个信号以后什么都不做,关于如何接受信号,就要说起`signal()`这个函数。定义如下: + +```c +void (*signal(int sig, void (*func)(int)))(int); +``` + +看起来非常复杂,说人话就是接受两个参数,第一个参数是int类型的`sig`,是信号编号,比如`SIGINT`,这是要接收的信号。第二个参数是一个函数指针,接受一个返回void,参数是int类型的信号处理函数,使用第二个函数中的函数对接受到的信号做处理。函数返回原来的信号处理函数(函数指针)。 + +可以用typedef简化理解: + +```c +// 定义信号处理函数的类型 +typedef void (*sighandler_t)(int); + +// 用 typedef 重写 signal 声明 +sighandler_t signal(int sig, sighandler_t func); +``` + +在Kilo中,`C-c`是被忽略的,因为它非常容易导致丢失修改,可以这样实现: + +```c +signal(SIGINT, SIGIGN); +``` + +不过,在Kilo的实现,是通过调用`editorReadKey()`,从Raw Mode 中读取一个按键存入数组,用switch匹配按键对应的值再返回给调用方,调用方也通过switch,匹配对应的操作函数。而在`C-c`的部分,则是直接break掉了。 + +```c +... + +case CTRL_C: /* Ctrl-c */ + /* We ignore ctrl-c, it can't be so simple to lose the changes + * to the edited file. */ + break; + +... +``` + +这种实现方法也有一定局限性,不同的终端模拟器可能发送不同的转义字符,硬编码转义字符会出现不适配的情况。并且使用`read()`阻塞读取输入有性能瓶颈。 + +### 精妙的数据结构与算法 + +这个程序最有趣的地方在于清晰、通用的数据结构的设计,以`editorConfig`为例: + +```c +struct editorConfig { + int cx, cy; /* Cursor x and y position in characters */ + int rowoff; /* Offset of row displayed. */ + int coloff; /* Offset of column displayed. */ + int screenrows; /* Number of rows that we can show */ + int screencols; /* Number of cols that we can show */ + int numrows; /* Number of rows */ + int rawmode; /* Is terminal raw mode enabled? */ + erow *row; /* Rows */ + int dirty; /* File modified but not saved. */ + char *filename; /* Currently open filename */ + char statusmsg[80]; + time_t statusmsg_time; + struct editorSyntax *syntax; /* Current syntax highlight, or NULL. */ +}; +``` + +我们定义了一个`editorConfig`类型的变量,它全局唯一,维护了程序的基本状态,包括行、列、滚动偏移、终端尺寸。让程序状态的流转非常清楚。这些内容都是一个文本编辑器需要关心的最核心内容:光标位置、视图偏移、数据和文件的状态等信息。 + +通过这个结构体,能简单地获取程序当前的状态,或者为某项功能对状态作出修改,对一个新手来说还是挺拓宽思路的,至少我想不到怎么设计这些数据结构。 + +### 数据与显示的分离 + +在`editorConfig`中嵌套了一个`erow`类型的变量,里面的东西也可以展开说说,定义如下: + +```c +typedef struct erow { + int idx; /* Row index in the file, zero-based. */ + int size; /* Size of the row, excluding the null term. */ + int rsize; /* Size of the rendered row. */ + char *chars; /* Row content. */ + char *render; /* Row content "rendered" for screen (for TABs). */ + unsigned char *hl; /* Syntax highlight type for each character in render.*/ + int hl_oc; /* Row had open comment at end in last syntax highlight + check. */ +} erow; +``` + +这里面有一个`render`字段,在`editorUpdateRow()`中,有这样的代码: + +```c +unsigned int tabs = 0, nonprint = 0; + int j, idx; + + /* Create a version of the row we can directly print on the screen, + * respecting tabs, substituting non printable characters with '?'. */ + free(row->render); + for (j = 0; j < row->size; j++) + if (row->chars[j] == TAB) + tabs++; + + unsigned long long allocsize = + (unsigned long long)row->size + tabs * 8 + nonprint * 9 + 1; + if (allocsize > UINT32_MAX) { + printf("Some line of the edited file is too long for kilo\n"); + exit(1); + } +``` + +循环的if中使用的 `TAB` 定义在KEY_ACTION枚举,值为9,在ASCII码中是`\t`也就是水平制表符。代码在统计tab的数量。 + +问题在于,一个`\t`在内存中占1字节,但在屏幕显示的时候会占据八个字符的宽度,这里就体现出`render`的作用了,如果一行有两个`\t`,每个最多展开为八个空格,那么所需要计算的大小就是`2 * 8 + chars的大小`: + +```c +(unsigned long long)row->size + tabs * 8 + nonprint * 9 + 1; +``` + +那个恒为0的变量`nonprint`可能是为将来打印不可见字符设计的。结尾的`+1`为`'\0'`预留。 + +按照这个公式,给`render`分配内存: + +```c +row->render = malloc(row->size + tabs * 8 + nonprint * 9 + 1); +``` + +随后,这些代码在非制表位填充空格: + +```c +idx = 0; + for (j = 0; j < row->size; j++) { + if (row->chars[j] == TAB) { + row->render[idx++] = ' '; + while ((idx + 1) % 8 != 0) // 在非制表位填充空格 + row->render[idx++] = ' '; + } else { // 正常字符直接赋值 + row->render[idx++] = row->chars[j]; + } + } + +row->rsize = idx; // 在循环结束的时候,idx等于写入字符总数 +row-render[idx] = '\0'; //在字符末尾添加结束符 +``` + +虽然有点绕,但设计还是非常巧妙的! + +--- + +### 代码高亮 + +源码中使用大量篇幅实现了代码高亮,定义了一些关键字: + +```c +char *C_HL_extensions[] = {".c", ".h", ".cpp", ".hpp", ".cc", NULL}; +char *C_HL_keywords[] = { + /* C Keywords */ + "auto", "break", "case", "continue", "default", "do", "else", "enum", + "extern", "for", "goto", "if", "register", "return", "sizeof", "static", + "struct", "switch", "typedef", "union", "volatile", "while", "NULL", + + /* C++ Keywords */ + "alignas", "alignof", "and", "and_eq", "asm", "bitand", "bitor", "class", + "compl", "constexpr", "const_cast", "deltype", "delete", "dynamic_cast", + "explicit", "export", "false", "friend", "inline", "mutable", "namespace", + "new", "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq", + "private", "protected", "public", "reinterpret_cast", "static_assert", + "static_cast", "template", "this", "thread_local", "throw", "true", "try", + "typeid", "typename", "virtual", "xor", "xor_eq", + + /* C types */ + "int|", "long|", "double|", "float|", "char|", "unsigned|", "signed|", + "void|", "short|", "auto|", "const|", "bool|", NULL}; + +``` + +然后在具体实现`editorUpdateSyntax()`中,简单粗暴地遍历字符匹配这些关键字。在一般的教学例子中这样实现是可以的,我认为在具体的工程中应当用词法分析、语法分析和字典树去匹配。更易于维护和拓展,也能适配复杂的嵌套。 + +--- + +上述分析提到的缺点都可以作为优化方向,比如提供更简单操作接口,用词法分析技术或接入LSP服务器,为程序提供Lua接口来扩展插件……不过我相信在古老的纯C应用中,添加这些功能的繁琐程度和开发周期简直是灾难级别的。但是在处理快捷键上,使用`termcap`库的难度应该小于修改代码高亮部分的难度。 + +这个项目最值得学习的点是如何将抽象的功能和终端联系起来、如何设计合理的数据结构以及标准库的使用。是阐释「程序 = 数据结构 + 算法」的很好例子。不过我自己是想不到那些函数该什么时候用,没准还会手动实现标准库造好的轮子呢。 + +学习的过程很好玩,从主函数开始探索整个程序,一段一段地跳转调用,A调用B,B调用C,C调用D,理解了逻辑后再把它们画成图,对感兴趣的部分深入研究,有一种前人用他的智慧抚平我大脑褶皱的感觉……读懂它,几乎就等于一只脚趾踩上了理解Vim / Nano等项目的大门吧。 + +想自己重新实现一次,然后加入自己的优化,比如联动Lua / Zig甚至是Go来实现上层的功能,好玩好玩真好玩。 + +头皮好痒,要长脑子了! + +--- + +- 在查资料的过程中又发现了 [vis](https://github.com/martanne/vis) 和 [micro](https://github.com/zyedidia/micro)(它甚至是用Go写的),又有新玩具了! diff --git a/content/posts/宅.md b/content/posts/宅.md new file mode 100644 index 0000000..9f85cd8 --- /dev/null +++ b/content/posts/宅.md @@ -0,0 +1,25 @@ +--- +abbrlink: 4248710545 +categories: +- 往昔 +date: "2025-06-30 19:47:00" +tags: +- 随笔 +title: 宅 +--- + +朋友上周几次约我出去打羽毛球,都被我婉拒了。那个周末刚刚考完期末,又是我最爱的阴雨天,很难不趁着大好时光不在家修养身心,而是冒着雨出去打羽毛球几个小时,大汗淋漓,虚弱疲惫地走回家,做什么事都提不起精神,睡觉也觉得浪费时间。在家里并没有什么很想干的事,我没有打游戏的习惯,很早之前就已经戒掉电子游戏。在家里的娱乐活动无非就是看书、听歌、画画、练琴,写代码折磨一下自己应该也能凑个数。我非常依赖在家里独处时的充电,只要远离人群的嘈杂即可。 + +他们吐槽了一下我有点宅,只喜欢呆在家里,我无法反驳,确实是这样。没什么别的原因,单纯觉得家里安全,我是一个很怕死的人。今天去奶奶家拿饭,突然发现那里简直集齐了让我感到恐惧的所有元素。 + +小区旁有一条铁轨,时常有火车呼啸而过,我对噪音极度敏感。走到楼栋前,左右两旁各两个楼道入口,正常人当然选择坐电梯,第二个让我感到恐惧的,幽闭的电梯。小时候奶奶为了保障我坐电梯的安全,会讲一些关于电梯的安全事故来吓唬我,虽然今天我已经知道了那些大部分都不是真的,而且电梯层层保护非常安全,但每次走到电梯里我都会死死盯着显示楼层的那块屏幕(虽然这并没有任何作用),生怕冲顶或坠落,命丧于电子棺材里。终于煎熬地乘完电梯,可以往家门走了。楼道前一个没有封窗的常年大开的窗户,狭窄的楼道里光是远远往下眺望就已经让人胆寒,但神奇的是有那么一两个瞬间,我竟然生出了跳下去的念头,我应该很怕死的。难以想象我童年的日子是怎么近乎每天都在这里度过的。 + +同样地,我也抗拒旅游。也许是因为回忆起近些年旅游的滋味都不是很好。拖着个不懂事的弟弟,他总是会让所有人都不开心,大家不开心,我也没什么能开心的。冬天冷夏天热,景点人挤人,只有能量相当大的人才能感受到快乐吧。 + +在朋友圈里看到一个亲戚发带着自家孩子出门去苏州旅游,我很佩服她。带着家人跨越小半个中国。其中有一张照片是她的孩子站在船上,身后就是一片水。这就是我恐惧的又一个元素,水。 + +小时候泡温泉,失足滑落到大概高我两头的池子里,在水里扑腾了半分钟才出来,索性憋住一口气,当时我的身高是完全不足以控制自己的身体朝向的,最后抓住岸边的栏杆才保住小命。自那次以后,我对水的恐惧就开始伴随我到现在了,我也许一辈子都不会去苏州那种水乡或海边。 + +每次出去旅游,甚至是上立交桥都会胡思乱想。比如车子突然失控从桥上坠落,家人走散,落水......我无法继续写下去我的内心所想,这又会把我拉入恐惧。语文老师曾经读过我的某一篇文章后,评价道我是很典型的悲观主义者,无法反驳,确实典型。 + +综上,我为了保命,保证精神不崩溃,会减少旅游等危险活动。 diff --git a/content/posts/安装配置Rime输入法.md b/content/posts/安装配置Rime输入法.md new file mode 100644 index 0000000..7711523 --- /dev/null +++ b/content/posts/安装配置Rime输入法.md @@ -0,0 +1,59 @@ +--- +abbrlink: 2682509886 +categories: +- 往昔 +date: "2025-03-24 20:37:38" +tags: +- Linux +title: 安装配置Rime输入法 +--- +# 前言 +其实我有能用的fcitx5+搜狗输入法的方案,但奈何kitty终端有对这个输入法的兼容性问题,无法启用中文,又奈何kitty的界面多美观舒服,和Konsole比起来简直就不是一个时代的产物。 + +# 安装Ibus框架和Rime输入法引擎 +**安装 IBus 和 Rime 组件**: +`sudo pacman -S ibus ibus-rime` + +**安装 Rime 双拼方案:** +`sudo pacman -S rime-double-pinyin` + +## 配置 IBus 和 Rime + +**设置环境变量** +在`~/.xprofile`添加以下内容 +```bash +export GTK_IM_MODULE=ibus export QT_IM_MODULE=ibus export XMODIFIERS=@im=ibus +``` +重启系统或执行 `source ~/.xprofile` 使配置生效 + +**启动 IBus 并添加 Rime 输入源** +```bash +ibus-daemon -drx +``` +右键点击系统托盘中的 IBus 图标,选择 **Preferences** → **Input Method** → **Add**,选择 **Chinese (Rime)**。 + +**配置双拼方案** +编辑 Rime 的配置文件 `~/.config/ibus/rime/default.custom.yaml`: +```bash +patch: +schema_list: + - schema: double_pinyin # 自然码双拼 + - schema: luna_pinyin # 全拼备用 +``` + +## 优化 Rime 的智能联想与词库 +**启用雾凇拼音方案(推荐)** +```bash +cd ~/.config/ibus/rime +git clone https://github.com/iDvel/rime-ice.git +cp -r rime-ice/* . +``` + +## 安装小鹤双拼方案 +```bash +# 安装 plum 工具 +curl -fsSL https://git.io/rime-install | bash -s -- double-pinyin flypy +``` + + + diff --git a/content/posts/家和万事兴.md b/content/posts/家和万事兴.md new file mode 100644 index 0000000..accb6a8 --- /dev/null +++ b/content/posts/家和万事兴.md @@ -0,0 +1,45 @@ +--- +date: 2025-09-21T21:29:22+08:00 +draft: false +title: 家和万事兴 +slug: harmony-in-a-family-makes-everything-successful +categories: + - 随笔 +tags: + - 家庭 + - 婚姻 + - 散文 +--- +有一种感觉,父母要不是因为生了两个孩子,早就离了。 + +总是因为各种各样的小事,小到不能再小的事吵来吵去,吵架也不能痛痛快快地吵一场,打架也下不去手,情感永远压抑在一个中间点,上不去下不来。 + +客观地来讲,弟弟的出生正值疫情,经济不景气,父亲公司裁员减薪,我的父亲被贬谪到了一个小维护站,从站长变成站员了。 + +从一万月薪骤降到三千,经济压力暴增,又有两个孩子要养活,父亲开起了出租车。 + +我们家当然买不起出租车,他是跟一个“哥们”借车开的,父亲是现代版的骆驼祥子,奔波在大街小巷,但祥子一人吃饱全家不饿,父亲还要赚够租金后养活家里三口人。出租车的生态位又被网约车挤压。 + +<!--more--> + +车主是典型的小资产阶级嘴脸,凭着出租车剥削我的父亲,时常以各种借口揩父亲的油,家里有点小钱就趾高气昂。前两天车被追尾,对方全责,父亲是个实诚人,跟他汇报了情况。车主以此为理由,拨弄弦外之音,向父亲索要对方依法给予的大部分赔偿,父亲知道他是什么意思,但还是反复斟词酌句,按着语音键的手向上滑了好几次,最后挤出了句: + +“鑫哥,咱们兄弟间有什么事就直说吧,你这什么意思看不懂呢。” + +“看不懂?是我打字有问题吗?需要我找个看得懂的人来给你解释解释吗?” + +他以挖苦剥削人为乐趣,估计那可怜的虚荣心又一次得到了满足,正筹划着拿到钱后带着家人去哪旅游,再发条朋友圈。 + +父亲把手机往桌子上一摔,又点上一根烟,望着窗外的一片昏暗。 + +弟弟上幼儿园后,母亲也去上班了,每天由年迈的爷爷接送弟弟上下学,我们家成了典型的双职工家庭。 + +母亲在一家酒店当经理,虽说是经理,每月工资比父亲还少,索性待遇福利还不错,职场环境相对轻松,只是每天公务繁重,母亲每天回来都瘫在床上呼呼大睡。用父亲的话说,他自己成了“老妈子”,休息日洗衣做饭,工作日下班后照顾孩子。 + +这样的压力下,人自然容易斤斤计较,唯利是图,即使是小利,即使对方是自己的丈夫,即使对方是自己的妻子。 + +弟弟今年五岁了,还是不懂人事,哭闹耍嚷,总是把家里所有人的耐心和精力都消磨殆尽,我连坐在自己的屋子里,而不是去帮父母应付弟弟都感到罪恶。我用两百多天后的中考作为幌子整天在屋子里逃避。我想把身心寄托在阅读和写作,以及幻想。但在一个极度喧闹的环境,思考一加一等于二都是奢侈。 + +我和弟弟成了维系父母关系的纽带,几乎属于典型的“看在孩子的份上凑合过吧”。我有时也在想,如果父母真的离婚了,我该怎么办?其实父母离婚了,对于我来说,世界并没有毁灭,地球还在转,秋风还在吹,毒辣的阳光还是恶狠狠地扎入大地。离婚,父母不会双双离世,对于我来说只是家里少了一个人。跟谁过,在五六年后都会自己一个人生活了。父母离婚只是代表着他们间的纽带断裂,但我和父母仍然有连接。只是我和弟弟,跟父母的关系围成一个优雅的四边形,两个对立的端点永不相连罢了。 + +百年以后,弟弟望着三个紧挨着的小土包上堆着的簇簇鲜花,那时候他已经长成独当一面的大人了吧。
\ No newline at end of file diff --git a/content/posts/对博客主题的一点想法.md b/content/posts/对博客主题的一点想法.md new file mode 100644 index 0000000..f2fb5a9 --- /dev/null +++ b/content/posts/对博客主题的一点想法.md @@ -0,0 +1,25 @@ +--- +date: "2025-07-10T21:12:51+08:00" +draft: false +title: 对博客主题的一点想法 +categories: + - 往昔 +--- + +简单回顾以下建站历程,博客的内容从“我是谁”转移到了"我想说什么"。从最早开始正式写博客的**Gmeek**,到后来使用**Typecho**,再到**Hexo,Hugo**,这几个不同的时期是我对主题看法的不同阶段。 + +Gmeek时期,没有概念,没看过几个人的博客,后来接触得多了,看了很多主题才意识到自己博客的主题有多简陋,换到Typecho,开始折腾主题,经历了一段不堪回首的时期。经典的一些元素:左下角挡字小人、底部音乐播放器、背景樱花飘落特效、点击特效,总之就是各种花里胡哨。文章,没有几篇,但是你可以在网页上找到任何你想找到的东西,除了文章。当时很喜欢Butterfly主题 + +后来换到了Hexo,也有Butterfly,继续用。发现点二十个网站,三十个都是Butterfly,很尴尬,后来经过几经波折,换到了Maupassant,输出了几篇自认为有点内容的文章,主要还是有感而发,我写东西不在乎谁看了,谁怎么看。我只是享受编辑和发送的过程。有人说心情不好,就把让你不开心的事写在纸上然后团成球扔进垃圾桶。这样还是太浪费了,毕竟是自己亲笔写下的文字,另说浪费纸张也不好。 + +在Hexo时期,我一直在寻找让读者弱化“我是谁”,专心聚焦与内容的主题。Maupassant就很好。后来转来Hugo,是看中了云风博客的那种千禧年的风格,不花哨,也不简陋。基于[JiaoYuan](http://jiaoyuan.org/)的移植后简单修改了以下配色之类,就正式投入使用。 + +我认为,博客重在内容,想表达什么观点、想记录什么事件。毕竟Blog,Web Log,Log,日志,记录。除了记录,也可以是扩大自己声音的一个渠道,独立于平台,起码不会有**跳墙的**删掉你辛辛苦苦打出来的一大段字。 + +而把重心放到了“我是谁”的站点,应该算作“个人主页”,并非博客,用作于一些项目展示、网络名片也是很好的。 + +而ta说“我是谁”,和自己观察“ta是谁“,是两种截然不同的感受。前者能迅速建立起一个停留于表层但具体的印象,而后者多出一种**视奸**的快感。从字里行间里感受ta是什么人,虽然建立印象的周期长,但深入。值得。 + +所以很多人博客的关于页面,我就当看个乐呵就过去了,仔细看每一篇文章,从ta的文字、观点、立场、价值观和认知来建立起ta的形象。有些人宏伟庄严,有些人冷漠麻木,有些人用平实朴素的语言记录,有些人用各种**恶心到家的语气词和括号里补充的动作描写**,绞尽脑汁想怎么把自己表现得多可爱。想可爱,先从**扮演人类**开始吧。这么在意别人怎么看自己,我替你感到疲惫。 + +好吧,我承认我有点冒犯了,一些朋友看到标题是关于主题的点进来还躺枪,那对不起,我冒犯的就是你。 diff --git a/content/posts/市井漫步.md b/content/posts/市井漫步.md new file mode 100644 index 0000000..4c19233 --- /dev/null +++ b/content/posts/市井漫步.md @@ -0,0 +1,41 @@ +--- +date: 2025-10-26T22:10:45+08:00 +draft: false +title: 市井漫步 +slug: "" +categories: + - 往昔 +tags: + - 散文 + - 散步 + - 意识流 +--- +我很喜欢随便坐上一路公交车,一边听歌一边看窗外的风景,想在哪站下就在哪站下,想往哪走就往哪走。这是自己出去玩最经济实惠的方案。 + +<!--more--> + + + +某地道入口上方的铁路,栏杆上锈迹斑斑,铁路边杂草丛生。 + + + +海河边,禁止游泳的告示牌上,「禁止」两个字被磨掉了。牌子后面不远处就是穿着泳衣的大爷。大爷没有游泳,只是在跳水呢。这么冷的天,我穿得里三层外三层手都冻僵了,大爷只穿着一条内裤光脚站在岸边,应该是刚上来。 + + + +正午阳光下的海河的阵阵波浪,把映进去的太阳的倒影打散了,耀眼的太阳分成无数片,又在水面炸裂了。细碎的太阳光从河水中央闪烁着飘来。星星点点的太阳光,没能到岸边就消散了,下一波又赶了上来,循环往复。水面上摇曳的楼影见证着这飞蛾扑火般的徒劳。 + + + +回家的路上经过书店,没经住诱惑。进去逛了逛,买了一本《我与地坛》,收录了史铁生的很多文章,装帧精美排版舒适,甚至侧面书页还有手绘风格的图案,本来我看书就非常珍惜刚拆封的脆弱的完美无损状态,这下更甚…… + + + +在网上买的《花未眠》也到了,同样是散文集,看了几篇后感觉川端的散文造诣比不上小说,那些是真正的「散」文,不过,好像还是我这篇文章更散。 + + + +读《晓寺》。快要放弃了,和前两部的风格转变太大,长句嵌套繁复,叙事节奏缓慢,大量景物描写和宗教哲学思辩,十分晦涩。如果把这本书和另一代表作《金阁寺》的语言做对比,《金阁寺》是恰到好处的精准,而《晓寺》则是华丽隆重的全感官盛宴。 + +还没进入十一月,夜晚就已经有冬天独特的气味了,具体什么味说不上来,只是一闻,先前在冬天的回忆就全部涌上来了。 diff --git a/content/posts/思想驯化不是艺术.md b/content/posts/思想驯化不是艺术.md new file mode 100644 index 0000000..f083672 --- /dev/null +++ b/content/posts/思想驯化不是艺术.md @@ -0,0 +1,44 @@ +--- +abbrlink: 3993050935 +categories: +- 往昔 +date: "2025-04-08 20:18:36" +draft: true +layout: post +tags: +- 学校 +title: 思想驯化不是艺术 +--- + +> “有什么可笑的?没见过艺术吗?” + +一个老师带着即将喷薄出来的优越感怒吼道。 + +--- + +什么是艺术?艺术,至少是应该是美的。几十个人挤在方寸压抑的教室里,身体像被枷锁锁住,只有上肢能挣扎的“舞蹈”应该是艺术?畸形的审美! + +班主任非常重视这件事,甚至不惜浪费午休时间来练习这荒唐的动作。 + +**课桌舞**这种畸形的产物与应遭人唾弃遗臭万古的形式主义,与艺术相提并论,完全就是在侮辱艺术!配乐是毫无编曲技术含量的土嗨DJ Remix版本,更是在侮辱原唱歌手和作词,更是在侮辱艺术!课桌舞,不配! + +不巧的是,领导们就独爱这种形式主义,学生们笑得多开心,即使被囚禁在课桌上也能这么活泼! + + + +整幅画面,除了压抑,能想到的形容词只有可笑、可憎、可恶、可怜、可悲! + +学生穿着整齐划一的服装,喊着空洞的口号,和工厂批量生产的,没有灵魂的产品有什么区别!青春应该是这样的吗?什么人对青春的定义是这样的? + +学生们的性格被杀死、尊严被践踏、思想被驯化、才华被埋没。何等的惨案,每天都在上演。青春绝不该是这般肮脏丑陋病态癫狂! + +这种活动既增加负担,又没有任何锻炼作用,纯粹的服从性测试。不服从,就是工厂的残次品,必定被淘汰。 + +驯化人的思想到一定程度,就没有人反抗;把棱角磨平,就没有人敢于质疑。有思想就是残次品,必定被淘汰。不顺从就是残次品,必定被淘汰。 + + +三座工厂日夜不停地生产加工,流水线批量生产的零件按质量给不同的场景使用。有的材料本来适合被雕刻成真正的艺术品,却被当成助燃的废木;有的外表精美华丽,实则内部已经千疮百孔! + +穷凶极恶的罪犯们要好好改造。他们笑得多开心啊。一定没有为自己正在做这么可悲的事而难过! + +可笑就是可笑,笑他们,笑制度,笑风气。笑身陷泥潭无法自救的自己。要放肆的笑,大胆的笑。本身可笑的事被训斥不准笑,才是最可笑的。 diff --git a/content/posts/怪癖.md b/content/posts/怪癖.md new file mode 100644 index 0000000..e24c3a5 --- /dev/null +++ b/content/posts/怪癖.md @@ -0,0 +1,24 @@ +--- +abbrlink: 4155363784 +categories: +- 往昔 +date: "2025-06-12 21:16:01" +tags: +- 我 +title: 怪癖 +--- +我这人怪癖挺多的,屋子里不能拉开窗帘,我讨厌被别人看到;屋子里只留一盏台灯和电子设备的光,很有安全感;电脑桌面上不能有任何图标,我爱干净。 + +屋子里静静的,只有空调运转和电脑硬盘读写的机械声。暖黄色的台灯灯光不会分散太多注意力,在学校喧闹一天后,这是最快的“回血”方法。很难想象那些住宿学校的学生是什么支撑着他们活下去,如果是我,我大概率会跳楼。我喜欢雨天,也跟这个有点关系,非常有安全感,非常舒适,望着天上的云,总有种熟悉的感觉,说不上来是什么,是在梦里,又或许是小时候见到过类似的场景,冷白色调的阴天光线总是有种熟悉感。 + +我对噪音非常敏感,完全受不了人群的嘈杂声,那会让我筋疲力尽,除了睡的晚,这也是我在学校课间几乎睡满的原因。每天中午打饭时,百家争鸣百花齐放,没有一个人类,没有一个人类的行为,我正好坐在第一排,所有表演我都是最近距离的观众。光是看着折腾吵闹就已经让人筋疲力尽。 + +手机常年静音勿扰,我极度厌恶手机的提示音,别人能动几下手指就简单地侵入我的生活,极度厌恶。把手机打开静音模式,是我自己在主动接受信息,只有在我想看的时候才能输入信息,而不是做一半事情就被突兀的响铃和震动打断。 + +所有软件都是暗色模式,所有。如上文,我经常在灯光昏暗的环境下,刺眼的白光很不舒服,最极端的时间,手机、电脑、平板壁纸都是一张纯黑的图片,大道至简。但博客不同,内容风格不太适合暗色,我感觉纯技术博客更适合暗色,极客风吧。 + +由于长期使用Vim,我也讨厌操作鼠标,甚至浏览器都装上了Vim插件,所有能用Vim模式的软件都在用Vim模式。 + +高考最后一天,我们学校是考点,我在家休假。实在无聊,就去镜子前看自己,盯着看,镜子里的世界太真实了,哪一个才是真正的我?看得出神,感觉下一秒就能冲破镜框,搂到对方的后背。看着镜子里的自己,一种陌生感和恐惧感油然而生。我真的活着,我真的是我,镜子里这个人是谁?会不会他才是真正的我? + +又是一段东拼西扯的意识流文字。 diff --git a/content/posts/意识的消散.md b/content/posts/意识的消散.md new file mode 100644 index 0000000..baae69a --- /dev/null +++ b/content/posts/意识的消散.md @@ -0,0 +1,79 @@ +--- +date: '2025-08-30T21:31:26+08:00' +draft: false +title: '「我害怕死」' +slug: 'dissipation-of-consciousness-after-death' +categories: + - 往昔 +tags: + - 生命 +--- +我十三岁那年和父母说,以后就不过生日了。 + +那时候我惊奇地发现,每过一次生日,就代表那可怜的生命正式少了一年。又向终点迈出了蹒跚的一步。 + +最近有一个朋友一直在和我聊他对死亡的恐惧,特别是对死亡后意识消散的恐惧。我能理解这种作为动物,对死亡最原始最本能的恐惧,被时间推着走向死亡的无力感。随着阅历的增加,出现对存在和死亡的思考是正常的。 + +但我不是很能理解,小小年纪,九月份就上高中了,想这个干嘛? + +他的问题是:「既然人最后意识都要消散,为什么要去做那么多事情?」 + +感觉他会提出这个问题,离某些危险的思想已经不远了。一定要在这个阶段性的迷茫中,阻止他向深渊滑落。 + +我分析并提出了三点: + +1. 太闲了,闲下来就容易想东想西,但不否认这种思想活动的积极意义,总比稀里糊涂过一辈子强。 +2. 比较空虚,找不到意义或「价值感」。建议找一点喜欢的事多做做。 +3. 是不是看了什么不该看的东西?看了什么理解不了的作品走火入魔了? + +然后,他提出了一个有点噎住我的问题: + +「什么是有意义?」 + +「意义是怎么定义的?」 + +这个问题在之后的讨论中都没有得到让双方都信服的解答。我自己的观点是:**让自己有「价值感」,就是有意义**。 + +应第二点,就是找点喜欢的事。喜欢旅游就旅游,喜欢画画就画画等。但是这件事对他来说有难度,因为**他根本不知道自己喜欢什么**。 + +据回答,他的活动除上学外,就是玩两个固定的游戏,看一个视频软件,用社交软件聊天。 + +我给他的建议是,读一读史铁生的文字,应该能从那里面找到一点答案。但是他对看书没什么兴趣,上学了也觉得没有时间看书。所以最后还是建议写作。把思考、观点、疑问全部写出来,让这些情绪有一个出口。 + +但当时凌晨十二点,没有那个精力了,困得说话都有可能不通顺,只好作罢。当时延伸探讨了一些细节可以作为他文章的题材,但直到现在也不提起写东西的事,我也不便再追问,可能对写作兴趣也不大。 + +但从讨论中也可以梳理出一些东西。 + +> 他:我害怕死 +> +> 我:你往深了想想,为什么害怕死? +> +> 他:我害怕意识的消散 +> +> 我:为什么害怕意识的消散? +> +> 他:不知道。为什么呢? +> +> 他:因为人生太短了、太有限。 +> +> 我:你为什么会担忧人生的长度?你还有什么想做的事情吗? +> +> 他:因为,我所有的一切消失得太快了,我想让他们一直在我身边,我想一直思考。我想一直拥有意识。 +> +> 我:他们里面,谁最重要,为什么那个人你觉得最重要? +> +> 他:我的家人最重要。 +> +> 我:你拥有意识,想一直保持思考,思考什么? +> +> 他:可能是基本的生命活动,说白了就是我想活着。 + +我认为,他可能有濒死的经历,或者有对他打击很大的亲人去世事件。前者被否定了,但后者确实有,我们刚认识的时候,他家中有一位老人驾鹤西去,他非常伤心。那件事可能是思考死亡的启蒙,但他无法完全消化这种悲痛的情绪,或者缺乏引导,所以就成了一个创伤。所以这件事在我们讨论的时候就不太方便提。 + +这种「怕死」和纠结,也有好的一面。起码不会做出某些过激行为,总体上人是比较稳定的。但这已经属于内耗而不属于思辩了,已经有强烈的恐惧甚至是焦虑情绪在里面,这样下去精力迟早要消耗殆尽。 + +他可能缺失对生命的除必然走向死亡的额外感受,生命对他来说可能是一个泛泛抽象的概念。如此恐惧死亡,恐惧意识的消散,用人话讲就是「没活够」,这种情绪多数源于**时间和生命如此真实,但自己却没有掌握住的空虚感**。所以我主张找点事做,把时间和生命从游戏和视频手中夺回来。进行长时间有深度的活动后,获得的成就感,就是意义所在。有意义感,就是存在的意义,就是「做那么多事的意义」。 + +所以开头的问题,显然有一个错误,那就是:**站在终点回头看**。 + +我觉得,一个七八十岁的老人这么想是没有问题的,因为他们已经有了足够的阅历,支撑的起这种回望。但一个十五六岁的小伙子,这么想就会**走火入魔**。当你试图站在终点回望,你就会发现大段大段的空白,无法找到真正可供观赏的,有价值东西,从而就会生出这种疑问,引发思辩。甚至由于当前的思想境界无法完成这样的思辩,引发无意义的**内耗**。 diff --git a/content/posts/感谢恩师夸奖.md b/content/posts/感谢恩师夸奖.md new file mode 100644 index 0000000..d1b6c5b --- /dev/null +++ b/content/posts/感谢恩师夸奖.md @@ -0,0 +1,35 @@ +--- +abbrlink: 2981262757 +categories: +- 往昔 +date: "2025-05-28 20:27:55" +description: 选择、信任、奋斗、感恩、驯化、忠诚、死亡、堙灭。 +tags: +- 感谢恩师夸奖 +title: 感谢恩师夸奖 +--- +课上没能回答出某个问题,遂借势挖苦批评,其中几个句子记忆犹新:“你主意太正”、“成绩不上不下”、“回家不知道是研究问题了还是学习了”。 + +感谢恩师夸奖。我就是主意正。 + +我主意正,因为我是一个有血有肉,更有灵魂的活生生的人,我有思想,我主意正,人和猩猩在行为上的显著区别就是,人知道自己在做什么,因为人的脑子很好用。我不会被戴上项圈,又或是打磨成木偶任人操控。这是我作为活人,基本该有的。 + +我不碌碌无为,不生活不平淡平庸。我既不会被你驯化,也没有成为推荐算法定时批量投喂的赛博牲畜,无休止地享受奶头乐,因为我主意正。 + +我活着有我自己的目的和意义,我主意非常正。 + +--- + +感谢恩师夸奖,我成绩确实不上不下。 + +我成绩不上不下,但我至少有一颗健全健康的心。我还是不会戴上项圈,被驯化成跪坐在主人身旁吐舌头的狗。我成绩不上不下,但是我能保证有学上。上学,成绩固然重要,但最基本要保证是活着的,肉体活着,灵魂活着。我活着快乐,我活着有意义,我活着为我。 + +--- + +感谢恩师夸奖,我回家就是在学习,研究问题。 + +我不沉迷电子游戏,也不刷短视频。我有值得我付出的事情等着我去做,并且都小有了一番成就。我从来没有停止过学习,极度的求知欲和好奇心是我保证灵魂活下去的因素之一。课余生活从逻辑冷硬的计算机到感情喷薄的文学美术作品,再到观察披着人皮的地外物种。做什么都比死读书,读死书,读书死好。我能保证有学上,而且保证灵魂活着。 + +因为主意正,成绩不上不下,回家学习,研究问题,我才真正的活着。永远不要试图驯化我,我永远也不会被驯化,永远不会成为谁。 + +感谢恩师夸奖。 diff --git a/content/posts/我有厌蠢症.md b/content/posts/我有厌蠢症.md new file mode 100644 index 0000000..6eb69d5 --- /dev/null +++ b/content/posts/我有厌蠢症.md @@ -0,0 +1,39 @@ +--- +abbrlink: 460449479 +categories: +- 往昔 +date: "2025-05-20 19:48:56" +tags: +- “厌蠢症” +title: “我有厌蠢症” +--- +> 2025.12.10: 这个文章的观点已经过时,其中包含偏激的、攻击性的话语,很多内容甚至现在的我都不认同。 + + +“厌蠢症”大概是迄今为止我听到的唯一一个能与近些年很火的一个心理测试——MBTI抗衡的。 + +前两年MBTI这东西刚出来时,很多人争着抢着去做测试,把自己标签上的四个字母如数家珍,甚至为了维持人设,去扮演人格,倒反天罡。但不能否认,这个测试确实能在与陌生人的聊天中快速找到话题切入点,以两大种类属性人格为根,横向延伸出许多话题,建立起临时的友谊。过两天,结果就是空间互赞,再不联系。 + +同时,这个测试也有一个点,当局者迷。即**筛选**。 + +筛选出分辨能力弱,花钱去做假测试的和不清楚真实的自己,喜欢给自己贴标签,经常把MBTI挂在嘴边的人。这两种人,说难听点,**蠢**。 + +用MBTI的例子来引出本文的核心观点:**厌蠢症才是真的蠢**。 + +不可否认地,高傲自大的人确实蠢。 + +上次让我这么情绪复杂的还是一群没病硬装、拿疾病当挡箭牌的“抑郁症患者”。 + +厌蠢症这三个字,完全是送命题,也筛选出智商和情商都达到“蠢”的标准的人。首先,当你说出这句话,就意味着你把自己当做了聪明人。带着狂妄、自大、轻浮、傲慢的“聪明人”。 + +傲慢才是原罪。 + +带着这份傲慢,厌蠢症发作,完全暴露自己最低智的一面,自诩聪明人。实际上蠢到极点还不自知。用人类的大脑仔细思考一下,这三个字是否写出来咬手、读出来扎嘴?用人类的大脑仔细思考一下,你是否有资格讨厌你所谓的“蠢”?用人类的大脑思考一下,你对聪明的定义,以及对自己的理解是什么样的?仔细思考一下,你能否在生活中完美无缺?你是否在每一场考试都拿到满分?你是否能照顾他人情绪,读懂空气氛围? + +他们思考出结果了吗?没有。厌蠢症患者无法思考。不具备人类的大脑,没有思考的能力。也不愿意去思考,只是一直傲慢自大下去,这才是真的蠢。 + +再把这句愚蠢的话大声地说出来:“我有厌蠢症。” + +自己作何感想?他人作何感想? + +如果你愿意继续做你所谓的聪明人并继续厌蠢下去,那你只有高傲自大、狂妄轻浮,你是真的蠢。 diff --git a/content/posts/我的4k进步史.md b/content/posts/我的4k进步史.md new file mode 100644 index 0000000..c7faba3 --- /dev/null +++ b/content/posts/我的4k进步史.md @@ -0,0 +1,54 @@ +--- +abbrlink: 3402853196 +author: yingyu5658 +categories: +- 往昔 +cid: 4 +date: "2024-11-13T03:41:00+08:00" +layout: post +slug: 4 +status: publish +tags: +- 游戏 +title: 我的4k进步史 +updated: 2024/11/21 23:01:34 +--- + + +截止到目前玩4k也有一年多了,整理一下我的进步历程,给迷茫中的各位一点参考 +# 常规段 +- 2023.5.20 一个别人在和女人亲亲抱抱的日子,我孤身一人在玩4k并且pass掉0dan,开启了漫长的4k之路...... +- 2023.6.4 Regular 1 pass +- 2023.6.22 Regular 2 pass +- 2023.6.25 Regular 3 pass +- 2023.7.26 Regular 4 pass +- 2023.8.22 Regular 5 pass +- 2023.11.24 Regular 6 pass +- 2023.11.24 Regular 7 pass +- 2023.11.27 Regular 8 pass +- 2023.11.28 Regular 9 pass +- 2023.11.28 Regular 10pass 常规段毕业!!! +# Extra与字母段 +- 2023.12.02 Extra-2 Jack pass(神秘4k常数9638) + +> 貌似淡坑了一段时间........ +- 2024.9.15 α Jack 96.21 + +> (Ma侧c判与om的od9天差地别,故不写pass,成绩仅供参考。后文中不予注释) +- 2024.9.22 Extra-4 Jack pass (v2) +- 2024.9.22 Extra-5 Jack pass (Sample) +- 2024.9.28 Extra-3 Jack pass +- 2024.9.30 β Jack 96.29 +- 2024.10.7 Extra-2 pass +- 2024.10.14 Extra-3 Stream pass(v2) +- 2024.10.19 Extra-4 Technical pass(v2) + +> 这玩意其实就是叠,要不我也过不掉 + +- 2024.10.19 γ Jack 96.33 +- 2024.11.18 Extra-5 Jack pass(v3) + +> 我认为此时叠力才算真正e5 + +未完待续....... + diff --git a/content/posts/我的攒钱计划.md b/content/posts/我的攒钱计划.md new file mode 100644 index 0000000..e984907 --- /dev/null +++ b/content/posts/我的攒钱计划.md @@ -0,0 +1,44 @@ +--- +abbrlink: 1557917560 +categories: +- 往昔 +date: "2025-04-11 20:13:20" +tags: +- 日常 +title: 我的攒钱计划 +--- + +一个小目标,初三前攒够两千块。 + +实现难度是不大,已经有了八百多存款,微信里有一百多,一共900。每天早上父母会给我20元买早饭,省省,不吃了,每天稳定收入20。加上每月50 + 70的零花钱。 + +粗略估算一下: + +- 现金:837.00 +- 微信:100.59 +- 支付宝:5.19 +- 共 **944.78** 元 + +与目标差 **1055.22** 。 + +截止到今天(4月11日),这个月还剩 **13** 个工作日。 + +月底可获得 20 * 13 = 260。 + +共 944.78 + 260.00 = 970.78。 + +每月 120 零花钱 + +共 970.78 + 120 = 1090.78 + +与目标差 **909.22** + +同理可得五月份月收入:**560** 元,共计 **1650.78** + +与目标相差 **349.22** + +每月收入280,可得出七月份大概可以完成目标。 + +当然,这是最悲观的情况。也许有哪一天能发一笔横财呢。 + +2000块,攒攒总会有的。 diff --git a/content/posts/我说过吗?.md b/content/posts/我说过吗?.md new file mode 100644 index 0000000..d35c161 --- /dev/null +++ b/content/posts/我说过吗?.md @@ -0,0 +1,30 @@ +--- +abbrlink: 3585041998 +categories: +- 往昔 +date: "2025-06-11 23:11:50" +tags: +- 小品 +title: 我说过吗? +--- +我见到了一个口齿不清又爱自言自语的人。 + +“我说过这个吗?” + +“没说过啊?” + +“哦哦对的对的哦不对不对哦对的对的。” + +“我说过那个吗?” + +“没说过啊?” + +“这个不说了。” + +“那个也不说了!” + +“不对,哦哦对的对的,不对不对。” + +我真说了,我真没说,我真说了!!! + +对,对吗? diff --git a/content/posts/我还是放不下Emacs!.md b/content/posts/我还是放不下Emacs!.md new file mode 100644 index 0000000..440f9f0 --- /dev/null +++ b/content/posts/我还是放不下Emacs!.md @@ -0,0 +1,155 @@ +--- +abbrlink: 393175956 +categories: +- 往昔 +date: "2025-06-03 20:07:15" +tags: +- Emacs +- GNU +- Linux +title: 我还是放不下Emacs! +--- +## 前言 + +难受,真难受呀。作为一个痴迷Vim的人,总是被Emacs的强大勾引,看见别人配的酷炫全能的Emacs就走不动路,脑子里想着“没事没事,我Vim轻量启动极快,Emacs这种重量级是比不上的”,自我安慰。实际上多想玩Emacs只有我自己知道...... + +我之前也试过[配Emacs](https://www.yingyu5658.me/post/2193909713/),但是Windows搞出来的不伦不类还很卡的东西太难受,用WSL尝试了一下Spacemacs,搞不明白那个层机制,也对ELisp这个语言不熟悉(说实话到现在Lua的一些东西我都不明白),而且之前的配置也一直想一口吃个大胖子,一天内就配到IDE的强大程度,经过几次失败和Vim配置经验后,我深知这是不可能的,除非在我使用Emacs后N周年的第N周目重新删干净再配,也许能做到。 + +定个小目标吧,每天配一点点,成果起码要达到以下程度: +- 能胜任前端、Nodejs的开发 +- 能胜任CPP/C的开发 +- 能使用EAF浏览网页 +- 有一点花里胡哨的小功能 + +其实我也挺想把博客迁移到Emacs,完全用org-mode来写,Hexo越来越慢。其实Hugo也不是不行,就是不太熟悉也不喜欢Go。看了[刘家财大佬的博客](https://liujiacai.net/)后感觉这个也太酷了,主题我也很喜欢,但是评论功能可能有点折腾,我对评论系统也有点不太在意。最难割舍的是现在用的这个主题...... + +刘家财老师是这样说的 +> 只不过遗憾的是,即使写了近 10 年的博客,有价值的评论少之又少,可能中文互联网内没多少人认真写技术评论吧。 + +这点我确实认同,观察了一些博客的评论,真正讨论技术内容的没几个,大多都是在围观、附和。但是我的博客类型也不能算是纯技术博客,保持与读者的互动还是很有意思的。 + +言归正传,我现在的Emacs在WSL里,装的是Spacemacs,能正常用eaf,但是写代码很难受,也没有补全,可以说现在它只能当一个浏览器用,我准备推翻重新配。 + +那么,从现在开始,来配Emacs!!! + + + +## 与过去挥手 + +在`rm -rf ~/.emacs.d`后,那个不伦不类、上不去下不来的Emacs彻底成为了历史。重新输入Emacs,又看到熟悉又陌生的丑陋开屏页。 + +## 小插曲 + +WSLg间歇性抽风,打不开GUI +``` +Display 10.255.255.254:0 unavailable, simulating -nw +``` + +打开管理员Powershell,运行`wsl --update` +![[public/images/我还是放不下Emacs!/Pasted image 20250603210050.png]] +~~我草,怎么这么慢??~~ + +## MELPA配置 + +```lisp +(require 'package) +(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) +(package-initialize) +``` + +切换中国镜像源 +```lisp +(require 'package) +(setq package-archives '(("gnu" . "http://mirrors.cloud.tencent.com/elpa/gnu/") + ("melpa" . "http://mirrors.cloud.tencent.com/elpa/melpa/"))) +(package-initialize) +``` +重启Emacs,输入`package-list-packages`就可以查看所有插件。`package-install`,回车输入插件名就可以安装对应插件。 +默认情况下,插件会被安装到 `~/.emacs.d/elpa/` 目录下。 + +## use-package + +输入`package-install`,输入`use-package`,回车安装,然后在init.el中写 +```lisp +(eval-when-compile + (require 'use-package)) +``` + +## ivy + +```lisp +(use-package ivy + :ensure t + :init + (ivy-mode 1) + (counsel-mode 1) + :config + (setq ivy-use-virtual-buffers t) + (setq search-default-mode #'char-fold-to-regexp) + (setq ivy-count-format "(%d/%d) ") + :bind + (("C-s" . 'swiper) + ("C-x b" . 'ivy-switch-buffer) + ("C-c v" . 'ivy-push-view) + ("C-c s" . 'ivy-switch-view) + ("C-c V" . 'ivy-pop-view) + ("C-x C-@" . 'counsel-mark-ring); 在某些终端上 C-x C-SPC 会被映射为 C-x C-@,比如在 macOS 上,所以要手动设置 + ("C-x C-SPC" . 'counsel-mark-ring) + :map minibuffer-local-map + ("C-r" . counsel-minibuffer-history))) +``` + +## amx + +```lisp +(use-package amx + :ensure t + :init (amx-mode)) +``` + +## ace-window + +``` +(use-package ace-window + :ensure t + :bind (("C-x o" . 'ace-window))) +``` + +## mwim + +```lisp +(use-package mwim + :ensure t + :bind + ("C-a" . mwim-beginning-of-code-or-line) + ("C-e" . mwim-end-of-code-or-line)) +``` + +## undo-tree + +```lisp +(use-package undo-tree + :ensure t + :init (global-undo-tree-mode) + :custom + (undo-tree-auto-save-history nil)) +``` + +## smart-mode-line + +```lisp +(use-package smart-mode-line + :ensure t + :init (sml/setup)) +``` + +## good-scroll + +```lisp +(use-package good-scroll + :ensure t + :if window-system ; 在图形化界面时才使用这个插件 + :init (good-scroll-mode)) +``` + +今天就先到这里吧。 diff --git a/content/posts/把主力机系统换成Arch-Linux是我这辈子做过的最蠢的决定.md b/content/posts/把主力机系统换成Arch-Linux是我这辈子做过的最蠢的决定.md new file mode 100644 index 0000000..6f22146 --- /dev/null +++ b/content/posts/把主力机系统换成Arch-Linux是我这辈子做过的最蠢的决定.md @@ -0,0 +1,145 @@ +--- +abbrlink: 4108562128 +categories: +- 往昔 +date: "2025-04-06 17:58:48" +tags: +- Arch +- Linux +title: 把主力机系统换成Arch Linux是我这辈子做过的最蠢的决定 +--- + +# 前言 + +先说结论。 + +**我是傻逼!** + +**我是傻逼!!** + +**我是傻逼!!!** + +本文将讲述 +- 为什么我放弃了Arch +- 为什么我放弃了Linux。 +- 什么人适合用Linux做主力系统 + +本文的所有观点仅仅代表个人观点,我纯菜。你问我为什么要选择Arch,而不是Ubuntu或者其他新手友好的发行版,我不知道,正如上文所说,我是傻逼! + +## 为什么我放弃了Arch +说到这个问题,就要先来谈谈为什么我要把Windows换成Linux。 + +Linux这个系统对于我来说一直是神秘而美好的,至少在当时。我痴迷于命令行、终端、Vim这种工具。小时候也看过爸爸零几年买的《鸟哥的Linux私房菜》,给我当时幼小的心灵带来的极大的震撼。 + +我当时也对Linux的目录结构非常新鲜,不分盘的设定感觉很好玩。 + +我网站的服务器是Linux、身边的各种设备都有Linux的影子,这更加提高了我对Linux的向往程度。 + +还有一个原因是,我当时正在用C语言写一个小工具,Windows下的gcc无法使用通配符`*`,要想用只能去打开Git Bash或者MSYS2,这俩东西界面的丑陋程度相比就不用我多说了,我当时就是喜欢把精力浪费在不必要的地方上,Windows的那个终端被我“美化”得花里胡哨的,上面两者的界面当然入不了我的眼。 + +为了解决这个问题,我开始使用WSL2,但仅仅停留在开始阶段。 + +我这个系统不知道怎么回事,根本没办法用WSL2。 + +全网都没有遇到这个问题的,那既然如此,重装系统吧。 + +和系统相处就像谈恋爱,总有一段热恋期,过了这个时期后就冷淡了、矛盾也就浮出水面。刚装好的前几天,我的热情前所未有的高涨,学习各种命令、各种工具,当然少不了配置我最爱的Vim。那么说到Vim,归根结底是文本编辑器对吧,打字的软件,那么就要说说我用Linux的第一大困难——**输入法配置难** + +### 输入法配置难 +我是双拼用户,从小学六年级就开始用小鹤双拼打字了,这么长时间的习惯很难改,我也不想改。但是Linux上对双拼友好的输入法方案几乎没几个,我尝试过两个,Fcitx5 + 搜狗, Fcitx5 + Rime。 + +这两个方案都大差不差,只是搜狗的可能略微智能一点,下载源什么的换成国内镜像,分分钟搞定下载问题。难就难在,我使用的终端不兼容Fcitx。 + +没错,我用的就是Kitty。 + +那么,肯定有人就想说,KDE自带的Console不能用吗?非得额外下载一个干什么?? + +我的答案就是:**丑**。 + +没错,就是因为Console丑。当然他也可以美化,但问题就在于,他的窗口圆角不彻底,而且把标签页显示关掉后,只能额外开一个窗口,占用屏幕空间。 + +而Kitty就不同,窗口边框干净利落,看起来很舒服,而且配色看起来也比Konsole那高饱和度的方案舒服太多了。标签页不是类似于系统组件的那种形式,所以不会额外占窗口空间。 + +虽然不兼容问题,在程序启动参数添加一条指定ibus接口的命令就解决了。 + +你问我为什么非得要追求好看,闲的么?我当时可能会扣一大串字来回怼你,但是我现在觉得我错了,我认同你的观点,就是闲的。 + +如开头所说,我是傻逼! + + +配置各种东西就免不了使用Github下载,那么就由此引出了第二个问题,**代理配置难** + +### 代理配置难 +我这边访问Github非常不稳定,有时候能丝滑裸连,有时候挂代理都难上。我先用了Steam++的Github加速服务,但是他会把Github的一些地址都重定向到localhost导致使用Git的某些功能如`git push`异常。我又换到FastGithub,这东西很好用,但也有不稳定的时候,当他作为系统服务启动的时候,发生异常,想杀死他就变得十分困难,然后导致几乎所有Git功能都瘫痪,非常麻烦,`git clone`都跑不下来。 + +### 显卡驱动安装难 +Linux显卡驱动问题一直都是社区津津乐道的蛋疼问题,更蛋疼的是我的显卡还是英伟达的,你问我为什么用英伟达显卡还玩Linux,我不知道。正如开头所说,我是傻逼! + +显卡驱动的问题,我研究了一周左右,虽然最后还是成功了,但是离正常使用还有一段距离。也是有很多小问题,比如使用系统自带的截图会黑屏,用不了i3等窗口管理器等等。 + +当初安装显卡驱动导致的问题包括但不限于: +- 鼠标灵敏度异常 +- 显示比例异常 +- 画面撕裂 +- 系统炸了 +- 桌面炸了 +- 能进图形界面但是不能登录 + +嗯对就是这么离谱。当然经过我一番折腾还是达到了能用但体验不好的程度。 + +### 安装软件难 +拿QQ举例,QQ官网的Linux安装包是.deb,如果我想安装,还是要经过一大通折腾,拼凑出来一个半成品QQ,而且最难受的是,每次他都会自动推送更新,我还更不了,还不能忽略版本,让我这个强迫症非常折磨。 + +## 为什么我放弃了Linux +其实原本我是不打算放弃Linux的,因为我突然想玩星露谷物语了,就想着要不要装双系统,但是我装Arch根本没有经验,磁盘分区做的很烂,上面的一番折腾已经让我筋疲力尽,我不想再玩Arch,只想找一个开箱即用的Linux发行版。 + +我的目光理所应当地投到了Ubuntu,这是我小时候体验的第一个Linux发行版,对我来说意义有点特殊,而且也属于开箱即用,所以Arch就光荣的升级为我的前任了。 + +Windows系统的安装非常简单,只要一直下一步下一步下一步,然后等就行了。Ubuntu也差不多,但需要注意的一点是,有一个步骤让用户选择以怎样的方式安装Ubuntu,给了三个选项,一个是用Windows Boot Manager管理,一个是擦除磁盘,好像还有一个,没注意。 + +我要装双系统,当然是选第一个选项,系统正常装上了,一切正常。下载软件,Neovim、VSCode、kitty。 + +kitty...... + +上文提到,Kitty不支持fcitx5,理论上这个问题还是可以像Arch时期那么解决,但是我当时没找到怎么给程序添加启动参数。跟着网上的教程折腾了半天系统配置文件后,我成功的又把系统玩炸了,进不去桌面。 + +当时已经是晚上十点多了,当天上午刚出去踏青,走了一万一千步,对于我来说已经把这一个月的活动量都用完了,筋疲力尽。非常困倦的状态下,我打算重装Ubuntu,正式因为特别困,智商下降得厉害,在安装程序选择了第二个:擦除磁盘。 + +我原本Windows系统的D盘擦干净装了个Ubuntu。 + +.......... + +那就这样吧,也行,我试着在Windows里把C盘装的那个坏掉的Ubuntu删掉,但是Windows访问不了那块神秘区域。。。 + +那行吧,重装系统。我格式化了C盘,删除了所有的分区,重装了Windows。在下载软件的时候猛地一惊。 + +> 我为什么现在不用WSL了呢? + +这是个好问题,对吧,你问我为什么到这时候才想起来用WSL,我不知道,正如开头所说,我是傻逼! + +于是,我不再安装Ubuntu,执行wsl的安装命令,没有像上次使用Windows那样报错,报各种偏门错,报全网都找不到解决方法的错。 + +此时我心中一万头曹尼玛奔腾,只有一句话想说: + +**我是傻逼!!!!!!** + +## 什么人适合用Linux做主力系统 +我个人认为,对Linux有刚需,如嵌入式、AI、机器学习这种领域,离开Linux干不了活的,我会推荐你用WSL,而不是主力Linux。我不建议任何人主力系统用Linux。。。。更不建议主力Linux发行版是Arch。 + +WSL的好处太多了,最大的好处就是方便。 + +当然,你爱折腾,对Linux有热情,有好奇心,完全可以把我这话当放屁。 + +## 结语 +**我是傻逼!** + +**我是傻逼!!** + +**我是傻逼!!!** + + + + + + + diff --git a/content/posts/摩擦起电.md b/content/posts/摩擦起电.md new file mode 100644 index 0000000..48b1596 --- /dev/null +++ b/content/posts/摩擦起电.md @@ -0,0 +1,37 @@ +--- +date: 2025-09-12T19:52:04+08:00 +draft: false +title: 摩擦起电 +slug: electrification-by-friction +categories: + - 随笔 +tags: + - 物理 + - 学校 + - 散文 +--- +物理课讲电荷,一个实验用丝绸摩擦玻璃棒、毛皮摩擦橡胶棒,将其一放在底托上,另一个去靠近,根据吸附或排斥的现象,引出同种电荷互相排斥,异种电荷互相吸引的定律。 + +老师在台上演示着,玻璃棒在丝绸上快速摩擦。 + +在有些人眼中,这个用丝绸摩擦玻璃棒这一类动作,甚至所有的棍状物体本身,都是极其富有官能意义上的美感的。于是见到这类动作便露出意味深远的笑容。如果做这个动作的人,在他们心目中被痛恨、或具威严,那么这种笑容就会变成狂笑、浪荡地笑,但在课堂上要忍住,于是就可以看见这样一道风景 —— 或消瘦或臃肿的身躯捂着嘴低着头,眼睛眯成一条缝,身体一阵一阵地抽搐。 + +而在他们眼中,能由自己做这个摩擦动作,体验至高无上的甘美的快乐 —— 引起他人注意的快乐,就成为了最伟大的目标。 + +今天阴天,空气粘腻,这个实验很难做成,我想老师也不愿再忍受有些人猥琐的笑,就让感兴趣的同学上来给大家演示。那些人炸开了锅,离那快乐仅一步之遥。 + +第一位同学抱着对知识强烈的好奇心与敬畏上去了,但他没有成功,于是第二次的机会变得更珍贵。 + +在眼神传递与恶趣味的互相举荐中,小王自告奋勇,主动起身,大步走上前。他热衷于追求那快乐。激昂与邪魅交织在一起从他眼中闪过。 + +他接过来玻璃棒,把丝绸裹在玻璃棒前端,把玻璃棒顶在身上,面向全班同学。那些人终于控制不住自己的笑声了。 + +小王此刻握住的仅仅是玻璃棒和丝绸吗?听着耳边的笑声,握住了自豪,握住了与他人的联结,握住了自己的人生!自己是站在教室里吗?站在聚光灯下! + +实验在喧闹中开始,他上下运动着丝绸,快速摩擦着。他们终于看见自己津津乐道的那个动作。 + +在实验中,小王的生命升华了,他的实质已经和班级里的同学异常遥远,不能再回到这个脱位的现实,只好暂时沉溺在自我中,感受「自然科学」的魅力。 + +扭曲的笑声还在耳边回响,兴奋的余波还在心里荡漾。老师的一声呵斥把他拉回了这个已经不属于他的现实,那美好的幻想离他而去,但余味已经在他的脑海反复品尝起来。老师的那声呵斥应带来的羞耻感在他心中从来没存在过。 + +欢声笑语里,小王看着周遭同学们的表情,看着他的朋友们的表情,看向他后座的女生,感受着课堂微妙的气氛。一种他所追求的前所未有的甘美流淌在心里。对小王来说,没有比这感觉更能使他陶醉于其中的了......他细细地品尝着这股甘美,仿佛闭上眼睛就能看见五月灿烂盛开的鲜花......小王靠着自己的行动吸引了人们的目光,但这目光里藏着什么,对他来说都不重要了。
\ No newline at end of file diff --git a/content/posts/攒钱目标达成?!.md b/content/posts/攒钱目标达成?!.md new file mode 100644 index 0000000..ffbd32f --- /dev/null +++ b/content/posts/攒钱目标达成?!.md @@ -0,0 +1,29 @@ +--- +abbrlink: 2718133590 +categories: +- 往昔 +date: "2025-04-19 18:42:29" +tags: +- 日常 +- 贝斯 +- 音乐 +title: 攒钱目标达成?! +--- + +是的,攒钱目标达成。 + +我在[之前的日志](https://www.yingyu5658.me/post/1557917560/)中写道: + +> 每月收入280,可得出七月份大概可以完成目标。 +> +> 当然,这是最悲观的情况。也许有哪一天能发一笔横财呢。 + +这下真发横财了。把一直没上的课外班退掉了。这个过程几经周折,机构老板老奸巨猾。一谈钱的事就转移话题,提出各种方案,就是为了不退全款。不过好在最后钱是拿回来了。加上我自己原本的积蓄,可以再安排个稍微能用的箱子 + + + +琴到手的第一反应就是:“好沉。。。” + +真的很沉。每天为了攒钱,不吃早饭,经常饿得心慌。好在愿望终于实现了,好好练吧。有人和我说,学乐器很难,我不信。我坚信的是,学不会只是因为不够认真。我必须和他碰一碰。暂时先不要告诉任何人我正在学贝斯这件事吧,除非他们看到了这个网站、这篇文章。保持一段时间的神秘感。 + +说起来,我喜欢贝斯这个乐器,没什么理由,也许这就是真正的一见钟情,低调沉稳的音色总是能抓住我的耳朵。我在某社交平台上的头像用了三年孤独摇滚里结束乐队的贝斯手山田凉。可能跟这个番剧也有关。不过最早贝斯给我留下深刻印象的还是《缝纫机乐队》,他们有一段演出最抓耳的就是贝斯。不知道我是有一副好耳机还是有两只好耳朵,贝斯和鼓在我听来总是特别的明显,有时我还会去特意听他们两者的节奏、律动,我评价一首歌好不好听,贝斯和鼓是否合我口味成了决定性因素。当然,自己的爱好在别人眼中是一文不值的,故曰知音难觅,又有多少人仔细去欣赏低音的律动呢? diff --git a/content/posts/文字所承载的东西能跨越时空.md b/content/posts/文字所承载的东西能跨越时空.md new file mode 100644 index 0000000..eba57f2 --- /dev/null +++ b/content/posts/文字所承载的东西能跨越时空.md @@ -0,0 +1,71 @@ +--- +date: '2025-08-29T22:18:20+08:00' +draft: false +title: '文字所承载的东西能跨越时空' +slug: 'what-is-carried-by-words-can-transcend-time-and-space' +categories: + - 随笔 +tags: + - 回忆 + - 记忆 + - 感官 + - 文字 + - 博客 +--- +## 模糊 + +> 文字永远只是形式,而文字所承载的东西,才是可以跨越时空的存在。 +> +> —— [*爱的成文诗 | 莫比乌斯*](https://onojyun.com/2025/08/13/%E7%88%B1%E7%9A%84%E6%88%90%E6%96%87%E8%AF%97/) + +跨越时空这个词,我第一次读来愣了一下。有一种「念天地之悠悠」,发觉自己渺小的感觉,但「独怆然而涕下」到不至于,因为我还没有那么有才华,到不了怀才不遇的悲怆。反而是一种模糊的,缓缓流动的感伤和无奈。 + +不用说十四年,两个月前的记忆都是模糊的。我写的一篇类似日记的文章[《人生中第一次大考》](https://www.yingyu5658.me/post/jottings/%E4%BA%BA%E7%94%9F%E4%B8%AD%E7%AC%AC%E4%B8%80%E6%AC%A1%E5%A4%A7%E8%80%83/)记录了我在会考那一天发生的事。整篇都流露着一股淡淡的死感[^2],和现在的情感差异比较大,主要还是上学导致的。 + +现在想想,那天发生的,只有几个画面和模糊的感觉,比如我在车里看到站在外面被太阳暴晒的同学、还有那天真的很热、考点教室很干净。都是不连贯的一幅一幅画面。不过还是要感谢当时的我,写下了那些文字,不然今天连可供回忆的素材都没有。我现我还记得《爱情公寓》里,有角色说过这样一句话,好像是曾小贤吧: + +「能证明我活过的就只有沙发上的屁股印了!」 + +可惜,我房间里还没有沙发。但是我在网上无病呻吟了很多文字[^1],应该能保存一段时间,证明我活过。我以前也比较喜欢在朋友圈发点东西,但那些表述相对浅显。而且一旦有确切可预测的「观众」,就难以避免地带有夸张和表演情绪,但喜欢在朋友圈表演,也是自我的一个阶段。 + +<details> +<summary><s>现在</s></summary> +<img src="https://images.glowisle.me/what-is-carried-by-words-can-transcend-time-and-space-wechat.webp"> +说真的,可能是我的社交圈子问题吧,我当初就不太应该加那么多人的微信。我感觉我的朋友圈里有不少不太正常的人。 +</details> + +虽然扫一扫在右上角的加号也能打开,但是我还是留下来了,因为我怕我手贱去点设置,打开朋友圈。虽然打开了也无妨,我已经完全把朋友圈这个功能封闭起来了,不看任何人的朋友圈,任何人不能看我的朋友圈。能减少很多看别人营造出来的完美生活的焦虑。 + +我最后一次发朋友圈是在七月三日。近一年左右,我很喜欢发画。手绘,板绘,甚至是一些画得很垃圾的速写。还有一些博客的文章,我会把阴阳怪气,又或是直抒胸臆骂老师引起公愤行为的文章贴在朋友圈。也许没什么人看,但是看的人,应该会觉得出了一口气吧。 + +现实中也有几个同学知道我的博客,有一位还在我当时证书到期的时候提醒过我,甚至跟我探讨过文章里的内容,也许他最近还在看我的博客。从之前网站出问题的时候他发现并提醒,可以推断出他大概是有看这个博客的习惯的。 + +## 记录 + +一切记录都是有意义的。无论是朋友圈、说说,还是一篇日记,一篇长篇大论的文章,一切记录都是有意义的。 + +我最近在构思博客一周年的总结文章,但还有两个月才算狭义上的一周年。但我前两天跟一位朋友复盘过我们的聊天记录,他所保存的最早的,有关「博客」这个关键词的聊天记录来自2023年9月10日,我当时搭建好了一个网站,邀请他来看看。但当时我还没有什么写作能力,搭建完了就搁置了。虽然现在也没有写作能力,但是起码能人模狗样的把话说出来。 + +他把聊天记录转发过来的时候,我很震惊,因为23年9月,我刚刚升入初中。 + +一切主观的记忆都是会随着时间的流逝,和自己的反复咀嚼、品味而被篡改的。关于23年9月搭建博客的记忆甚至没有模糊的过程,直接就被忘却了,需要提供一个锚点来回忆。我使用了那个域名作为「锚点」,那是一个国外托管网站的免费域名,于是我借着这个,回想起了一个模糊的,甚至是第三人称的画面,也有当时的感觉:对这件事一知半解,觉得有点难。 + +那是唯一在我大脑中保存下来的回忆了。 + +另一个让我震惊的事情是,我印象中我是在2024年11月,才开始了我认为能被称为博客的写作,但23年就有记录。当时我用的是Gmeek[^3],把语文作业里写的自认为不错的小短文贴上去了,那篇文章还被老师表扬了,说是很有感染力。具体写的是什么已经无从考证,但是我印象中有一句话:「夕阳是太阳的尸体。」这种悲观甚至有点中二的看法,竟然会被老师表扬。于是这个事成为了我对「写博客」相关回忆的锚点。但很可惜的是,那篇文章已经因为几次博客搬家丢失。 + +回看自己写的文字,是一个重视自我的过程。可能会从中看到这中二、偏激、幼稚、尴尬、羞耻,一旦有了这些情绪,那就证明自己是有进步的。我认为这也是文字的优越性。无论是什么样的自己,都有亲手记录下的价值。 + +这也是证明「我是我」的一个手段。 + +怎么才能证明我是我?是我的长相,还是我的穿衣风格,还是我的人际关系? + +我觉得是我写下的这些文字。 + +无论是偏激的,还是幼稚的,都是当时自己意识的速写。脸可以被毁容,也可以整容;夏天穿短袖,冬天穿长袖;毕业了同学就几乎没任何联系。只有文字才能证明「我」的存在,它是一个人流动的意识和思想的直接抽象。比其它形式更入木三分。虽然根据开头所引用,文字只是形式,但它承载的飘渺却又厚重的东西,对每个人来说都是独一无二的,是一场与自己跨越时空的对话;而在别人看来,每一个字符都是作者精神的直接投射,能从一篇篇文章中拼凑出完整的形象。 + +[^2]: 非医学意义。 + +[^1]: 目前已经在此博客唧唧歪歪了85173字。 + +[^3]: Gmeek,一个完全基于 Github Pages、Github Issues 和 Github Actions 的个人博客模板。详见 [https://github.com/Meekdai/Gmeek](https://github.com/Meekdai/Gmeek). diff --git a/content/posts/无蝉鸣夏.md b/content/posts/无蝉鸣夏.md new file mode 100644 index 0000000..29067ec --- /dev/null +++ b/content/posts/无蝉鸣夏.md @@ -0,0 +1,33 @@ +--- +categories: +- 往昔 +date: "2025-07-22T20:56:08+08:00" +draft: false +slug: "" +tags: +- 随笔 +- 夏 +title: 无蝉鸣夏 +--- + +学校里的海棠花谢了两次了,老师每次都会带着我们出去拍照。花确实很美,但我每次都恐于留下不堪的回忆,拍照时都远远躲去了。一天又一天地盼着的暑假到来了。十几天像流水奔去。 + +总能见到一种人,每天因逝者如斯夫而悲鸣,在网上。慨叹时间太快,自己太空虚。每天抱着手机刷几个小时视频,看到比自己强的人,继续焦虑地刷视频。到了晚上,按照惯例把自己思维反刍的结果公布在群聊里。神奇的是,这种负能量满满的人,反而更有广阔的社交圈子。我的意思是,有很多喜欢安慰这种人的人。能量实在是高,保持自己的情绪不被影响(待研究)的同时,能去安慰别人。 + +我个人当然是对这种负能量者敬而远之的,但实在是好奇那些安慰者是如何保持冷静和感性和那种人沟通。 + +而有的人又不领这份人情,把别人投来的好心曲解成说教,真为那些安慰者愤怒。当然,他们不会愤怒,因为他们永远能保持冷静和感性。 + +去年的七月二十二日我在想些什么呢? + +这个暑假格外寂静。蝉都跑去别的树上了,不愿意在我家门口浪费所生不多的生命。虽聒噪,但好歹也是盛夏元素,以前从来都没有对这个季节抱有那么大的关注。以后一定要移居南方,不为别的,起码在读书、画画时经常可以听到真真切切的雨声。耳机戴时间长了对耳朵也不好。 + +父亲之前买来的虫叫了几周就死了,期末考试的作文我还拿他来凑过字数,现在被扔到了哪个垃圾桶、尸体碎成了几段都不知道了。好像是因为断掉一条腿,就不吃不喝,活生生饿死的,至于那条腿是怎么断的,也和尸体的去向形态一样无从得知。 + +一次上课回来,在植被繁茂的小区,树上的蝉好像约定好了在某一时刻突然一起鸣叫,震耳欲聋。我好奇它们在哪,朝树上张望,什么也看不见,只闻蝉鸣震耳欲聋。 + +暑假确实寂静,不闻蝉鸣,也没有狗叫纷扰,关闭朋友圈和QQ空间确实是一个正确的选择,少了焦虑,多了清净,薄如蝉翼的交情在屏蔽对方的那一刻彻底被撕碎了。 + +开学又要回到聒噪的、持续高压的环境,多希望能一直保持这样的状态,不用接触各种类人生物,安静自在地呼吸,初三的放学时间延后到八点半,但愿能活下来。我会怀念一个人坐在房间里,借着阴雨天窗边映下来的蓝冷色调的光读书,听雨打在玻璃上的哒哒声的日子,和带着耳机,听着自己喜欢的歌,坐在公交车最后排,在去图书馆的路上欣赏风景的日子。 + +这种生活和早上六七点背着沉重的书包,拖着疲惫的身体匆匆出门,在拥挤嘈杂的人群中感受冲天的死气和体臭一对比,顿觉窒息。 diff --git a/content/posts/早睡早起的优点.md b/content/posts/早睡早起的优点.md new file mode 100644 index 0000000..7c021c2 --- /dev/null +++ b/content/posts/早睡早起的优点.md @@ -0,0 +1,34 @@ +--- +categories: +- 往昔 +date: "2025-08-04T08:52:02+08:00" +draft: false +slug: "" +tags: +- 早睡早起 +title: 早睡早起的优点 +--- + +**浪费时间**。 + +<!--more--> + +是的,早睡早起的优点就是可以让我更舒坦、安心地浪费时间。昨天晚上十点十分就睡了,定了一个七点钟的闹钟,准时响,准时起,分毫不差。 + +醒来后十分钟以内比三点睡十二点起的的不同点就是非常清醒,没有那种昏昏沉沉的感觉。当然,这十分钟,我都在看手机,看着和我没多大关系的群,看着没有人@我的群。 + +知乎上的回答有了回复,这个和我关系比较大。是昨天宣传新闻组的回复。从床上下来,打开电脑,在电脑开机时,日常显示出问题的时候,打开收手机,刷刷知乎,并提问考虑要不要换到Debian,起码稳定。 + +在日常打开tty手动重启gdm后,终于可以正常登陆图形界面,打开Thunderbird看了一眼新闻组的消息,多了好几个人的帖子,其中还有一直活跃的老面孔的回复,一片蒸蒸日上的景象。截图发到那个和我没多大关系的群,感叹氛围不错,疑似是互联网现存的为数不多的,沟通建立在互相尊重的基础上的讨论平台,只是因为人少。三个小时后,这个群依然和我没关系,大家各聊各的。又打开粉色视频软件,看大家争吵print和cout到底哪个快、为什么Linux内核开发宁愿加入Rust也不让C++进入。 + +在手机玩腻了后,我又抱起平板,在厕所里浪费了四十分钟。这就是早起床的好处。占着不拉,低头看电子产品也比舒舒服服在床上看书有吸引力。直到我出来,写这行字的时候,才九点出头七分钟。放在平常做完这一套活后,已经快吃中午饭了,虽然我不会吃中午饭。早睡早起后,时间很漫长。 + +我还是会坚持健康作息的,我不想再让珍贵的八月像蝉一样短命了,毕竟我还要浪费,有大把的青春年华等待我去浪费。 + +前天熬到六点多,撑不住睡了三个小时,为了昨天晚上可以在十点钟就上床,把时差掰回来。终于回国了,我现在是中国人,不再过黑白颠倒的生活了。 + +黑白颠倒也不错,我更极端,因为觉得白天睡觉浪费时间,索性就不睡。从直立猿跨物种变成了熊猫,记忆力还不如熊猫,精神还不如猫。 + +上次熬夜的记录是四点,那时七月,四点天就蒙蒙亮了,这次在五点才有差不多的亮度,可见夏日的生命力正在衰退,逐渐滑向死亡。 + +最近正在考虑写一个Android上的新闻组客户端,NNTP协议看起来并不难,做到基础的通信,不会耗费太大功夫。但我不熟悉Android开发。只能尝试用Web套壳写了,比起HTML, CSS, JavaScript,我宁愿去写C。为什么C语言不能直接在Android上运行?哦,可以用Termux,好主意。我会让我内存泄漏得遍地都是的程序污染每一个人的设备的。 diff --git a/content/posts/最膈应不爱惜书的人.md b/content/posts/最膈应不爱惜书的人.md new file mode 100644 index 0000000..5bc01f5 --- /dev/null +++ b/content/posts/最膈应不爱惜书的人.md @@ -0,0 +1,47 @@ +--- +categories: +- 往昔 +date: "2025-08-06T22:50:55+08:00" +draft: false +slug: "" +tags: +- 购物 +- 图书 +title: 最膈应不爱惜书的人 +--- +我最受不了的事之一就是我的书是别人看剩下的。 + +<!--more--> + + + +京东上买了一本书,十几块钱。真是贪图便宜了。一拿到手,看到顶部的塑封是开口的,我就有种不详的预感。 + +我有一个习惯是读书的时候把封皮拿掉,方便携带,手感也好,更不用提文库本这种装帧,主要就是方便携带。但是我发现了: + + + +上一个**蠢货**竟然企图用胶棒把封皮粘在书脊上。 + +看吧,反正我是来看书,又不是藏书。我看到了: + + + +塑封被拆,我忍了;书脊被粘,我忍了;书是二手的,我忍了;可是正文里有笔迹,我忍不了。马上拿起手机,打开京东给店铺扣了百字差评,发新书很难吗?检查一下书的状态很难吗?为什么我要花新书的钱买别人看剩下的?真当这里是日本了,文库本看完就卖?对于上一个买家,爱惜书很难吗,最起码正常人不会用胶棒去粘封皮,还失败了吧? + +十几块钱的东西,难道我还要花时间和钱退换吗?把这本书退回去,这个店家指不定又发回去给谁了。 + +为什么我这么气愤,因为我还买了两本书,是在另一个店铺。 + + + + + + +什么东西我都能接受买到人退掉的,买二手的,唯独书不行,非常恶心! + +最膈应二手书! + +最膈应买到这种不爱惜书的人退掉的书! + +最膈应不爱惜书的人! diff --git a/content/posts/未命名.md b/content/posts/未命名.md new file mode 100644 index 0000000..0c53e6b --- /dev/null +++ b/content/posts/未命名.md @@ -0,0 +1,33 @@ +--- +categories: +- 往昔 +date: "2025-08-08T15:36:41+08:00" +draft: false +slug: "" +tags: +- "" +title: 未命名 +--- +在家太闲,穿着一双比自己脚大的拖鞋,在两个屋子间踱步,想走到窗台边欣赏外面的云时,瞥见父母的结婚照。 + +<!--more--> + +那张巨大的照片垂挂在床头正中间,仔细一看,歪了。这很危险,尤其平常睡在床中间的一般是一个不到五岁的儿童——我的弟弟,发消息通知家人照片歪了后,我踩上床仔细端详这张照片。 + +小时候我一直非常害怕这张照片,尤其是之中的母亲,那邪魅的紫色眼影与眯成一条缝的眼,和夸张的惨白脸色互相映衬,展现出那代人低劣却朴实的修图水平之外,又添了不少令人毛骨悚然的气氛。有一段时间,这张大照片被拿下来,倒摆着靠在墙上,至于为什么又挂起来,已经不记得了,挂起来很长时间了。 + +如今我又仔细观察起这张令我半夜做噩梦的照片,妆容诡异依旧。父母那时非常年轻,即使窗外透进的阴雨天独有的凄蓝色调的光影打在他们脸上,也丝毫不挡青春的男女散射出闪耀着金黄色的生气与活力。 + +这真的是我的父母吗?我不由得想。 + +父亲如今耳朵逐渐不好使,经常独自坐在客厅的桌子前吸烟,用了十几年的玻璃烟灰缸一次又一次盛满烟头。与之相呼应的,是他紧皱的眉头和深沉的目光。他到底在想什么?但每每和他交谈,就会收敛起那副令人一起沮丧的表情。 + +照片中母亲的笑容,是我至今见过最真切、发自心底的、灿烂的笑容。父亲伸出布满青筋的手在身后环搂着母亲。母亲一头干练的短发下,是一对纯洁、闪着光的眸子。呲着与她灵魂同样洁白的两排牙,真切地笑着。很久不见母亲笑得如此幸福。 + +虽然修图技术低劣,但照片中飘逸的、喷薄、溢出的幸福是最可贵且高洁的。 + +如今我仍然害怕着这张照片。它太真了,伸手好像能触摸到父亲脸颊的温度,能触摸到母亲洁白如雪的肌肤,能感受到洋溢在空气中的幸福与爱。 + +它又太假了,如今我只能看到熟悉又陌生的,养育我十余年的父母的沧桑。 + +照片中的两个人真的是我的父母吗? diff --git a/content/posts/杂记-2025-06-06.md b/content/posts/杂记-2025-06-06.md new file mode 100644 index 0000000..6be8f6a --- /dev/null +++ b/content/posts/杂记-2025-06-06.md @@ -0,0 +1,47 @@ +--- +abbrlink: 3691550015 +categories: +- 往昔 +date: "2025-06-06 23:19:56" +tags: +- 杂记 +title: 杂记#2025-06-06 +--- +纠结了很长时间,这篇文章命名的事。我是典型的选择困难,出于文章内容组织的形式,就把他命名为杂记了。不过应该也没什么人看,我就~~(梦)~~想到什么写什么了 + +## 时间感慨 + +今天就上半天学,下午高考布置考场了。一进门就看到教学楼处处拉着横幅,写着给高考考生加油助威的标语。睡眼惺忪的我一下子就惊醒了,高考?又来?下课,和同学聊天,我又想起来这茬,自言自语:“高考,又高考了......”让人听见了,“高考就考呗和你有啥关系?”是啊,和我有什么关系,该和我有关系吗?高考过一阵子后就该中考了。再过一年,我也上中考考场了。 + +今天是我初中三年,第二次,也是最后一次放高考假,初一的时候还什么也不懂,傻了吧唧地,快乐地就活了一年。一升入初二,第一个学期精神状态出奇的差。老师天天讲各种心灵鸡汤、各种教育学生,都放他妈狗屁。只有三年过得太快了这句话是真的。一直感觉自己刚升入初中啊,地生会考迫在眉睫了。 + +端午假期回来的那天,升旗仪式改成了给初高三学生加油的什么仪式,实际上也就是校领导在上面讲讲万年一套的老话,学生在台下鼓鼓掌。可能是吧,初一是什么场面,已经忘了,但依稀记得,我当时很受鼓舞,觉得老师和上台讲话的同学吐出来的每一个字、每一个标点符号都是那么振奋人心。今年只有麻木感和危机感,回班后,班主任说,明年就该你们走那个状元门啦!围着我心的最后那块砖头也被一脚踢飞了。 + +我对毕业不害怕,我甚至有点向往毕业。好像有人初中毕业哭得死去活来的,记得小学就有人这样了。可能我向来都是一个薄情的人,对于同学情这种事,没那么大牵挂,活的也舒心。网络也发达,能联系的自然会联系,没话说的也就不必强找话题,已经不是一路人了。顺其自然?顺其自然。真正让我害怕的是考试,我也没有特别想去的学校,也没有特别想学的专业。计算机?程序员?别操蛋来了,已经不是2020年了,普通人没高学历怎么卷。美术?那更是要饿死的了。没什么学习的动力,唯一的动力就是成绩不差暂且能在同学面前抬起头吧。我感兴趣的方向都有被AI替代的风险了。现在想这个确实为时过早,高中三年活下来才有资格想去哪里要饭。 + +一写学校的事就难免重力展开啊...... +## 夏 + +小时候非常喜欢夏天,现在平等地讨厌春秋,因为会犯鼻炎;一贯地憎恨冬天,太冷了。那只有夏天好了。 + +夏天一直有一层回忆滤镜,今年要仔细感受一下。好好想想,童年夏天回忆有三: + +空调、冰棍、帆布毯。两样陆陆续续都回来了,唯独空调费劲,空调到底是因为热才开,还是因为“时候到了”才开?空调服务的对象是“时候”,还是人? + +## 工具迷恋 + +我承认,我真的没把时间花在刀刃上。经常浪费时间,在一个几百年前的软件上花大力气大时间,甚至废寝忘食,就为了实现一个已经由专业团队开发好的、开箱即用的、体验还更好的功能。美其名曰“极客精神”。我对极客精神没偏见,只是突然发觉,不应该把时间花费在这种事上。对,我就是在说Emacs和Vim。 + +工具说到底还是为了做事的,先选简单的工具,把事情做得精湛,再谈优化工具。代码还写不明白,反到是一直迷恋在配置各种编辑器,白白浪费时间,作业也写不成,代码也写不成,最后配置出来了一块会爆炸的排泄物,一团矛盾。 + + + +去年12月底,我开始知道了Vim这个东西,在折腾了一会被劝退后,发了条朋友圈吐槽。 + + + +但是不得不承认,Vim比Emacs好配多了。现在我的Vim起码到了能畅快写代码的程度。在这之前,一直都在断断续续地折腾Vim、终端、系统。真正写代码的时间没有三分之一。幸好在[玩腻Arch](http://www.yingyu5658.me/post/4108562128/)后及时悔悟,装回了Windows,虽然种种不适应,但用起来很方便,起码不会再像以前那样浪费时间了。 + +感谢Windows,感谢微软......否则我就要成为开机 => 桌面炸了 => 花两天修复桌面 => 开机 => 打开自己半透明+亚克力+二次元小人背景的终端 => 输入neofetch欣赏半个小时桌面并截图发群里:“顺便说一下,我用的是Arch。”的那种人了。偶然间听到过一句话: “如果一块表时间是错的,那他走的每一秒都是错的;如果这块表停了,那它一天中至少有两次是对的。”挺有道理的。 + +翻看了一下自己写的代码和以前的文章,发现自己的快速上手的能力较强,各项技术都有涉猎,知识面较广,但这样的结果就是哪样都不深。尤其是数据结构与算法接触非常少,写不出来什么干巴的代码,之后要改一改了,在数学和算法上深耕一下,也在C语言深耕。C语言一直是很让我向往的语言,运行几乎无开销、对硬件极致的控制能力,灵活、高效、结构紧凑。但他复杂易混淆的指针也多次劝退我这个初学者。这个精髓没领悟到,玩C语言就玩不到灵魂了。 diff --git a/content/posts/深刻认识面向对象.md b/content/posts/深刻认识面向对象.md new file mode 100644 index 0000000..2e785d3 --- /dev/null +++ b/content/posts/深刻认识面向对象.md @@ -0,0 +1,50 @@ +--- +abbrlink: 841546109 +categories: +- 往昔 +cid: 99 +cover: images\2024\12\2743265221.jpg +customSummary: null +date: "2024-12-01T13:31:00+08:00" +layout: post +mathjax: auto +noThumbInfoEmoji: null +noThumbInfoStyle: default +outdatedNotice: false +parseWay: auto +reprint: standard +slug: 99 +status: publish +tags: +- Java +- 笔记 +thumb: null +thumbChoice: default +thumbDesc: null +thumbSmall: null +thumbStyle: default +title: 深刻认识面向对象 +updated: 2024/12/07 10:55:00 +--- + + + +面向对象编程的好处 + +> 按照**詹姆斯·高斯林**的看法,世间万物都是对象。好比要出去旅游,你要找到车这个对象调用他的行驶功能使用来带你出去旅游。 + +所以面向对象编程的好处就是:**符合人类思维习惯,编程更简单,更直观**。 +# 程序中的对象到底是什么 +- 对象本质上是一种**特殊的数据结构**,很像数据库,但是数据库是持久存储的数据。体现出计算机各个学科的交叉。 +一开始设计的类就是一张表,后续在其他类中填入这张表的内容。 +# 对象是怎么出来的 +class也就是**类**,也称为**对象的设计图**(或者**对象的模板**) +- 类里可以设计很多变量,用来说明对象可以处理什么数据。 +- 类里还可以设计很多的方法,描述对象有什么功能,也就是要对数据进行什么样的处理。 +接下来我们就可以在程序中new对象了 +**也就是先用class设计对象,然后再用class new出对象。** + +具体使用语法见上一篇文章[post cid="98" /] + + +[2]: https://www.bilibili.com/video/BV1Cv411372m?spm_id_from=333.788.videopod.episodes&vd_source=c0385e4bcdefa80a5d3d394a8a23df4c&p=69 diff --git a/content/posts/游戏资源下载及连接服务器相关教程.md b/content/posts/游戏资源下载及连接服务器相关教程.md new file mode 100644 index 0000000..3c7fd7b --- /dev/null +++ b/content/posts/游戏资源下载及连接服务器相关教程.md @@ -0,0 +1,67 @@ +--- +categories: +- 往昔 +date: "2024-12-13T20:26:00+08:00" +tags: +- Terrira +- 服务器 +- 教程 +title: 游戏资源下载及连接服务器相关教程 +--- + + + +# 前言 +为了避免不必要的麻烦和纠纷,也是为了打造一个纯粹干净高质量的社区,我们需要对想要参与的人员提出一些条件,请确保你自身可以满足这些条件后再来愉快的玩耍。 +**所有的条件都是最基本的,一点也不苛刻,大部分要求仅仅是一些应该具备的能力。** +# 正文 +1. 具备一定的耐心 +2. 具备文档阅读能力 +3. 不是伸手党,具备在互联网上搜索的能力 +4. 拥有思考和自己解决问题的能力,而不是有点什么问题直接在群里发问,我编写的各种文档已经涵盖了可能出现的大部分问题,请仔细阅读文档。 +5. 拥有支配自己钱财的权利 +6. 不在游戏内使用外挂、修改器。(当然你开了我也没法知道,全凭良心) + +在你确保满足上篇文章的各项要求后,可以开始阅读这篇文章。本文章将详细地讲解**泰拉瑞亚PC/Android端下载**以及**连接服务器**的方法。 + +# 泰拉瑞亚Android版本下载 +你可以直接打开群聊>群文件>泰拉瑞亚>Terraria_1.4.4.9.apk.**1** +## 安装apk.1的方法 +几年前的新版本QQ中,所有的apk都会被强行篡改为apk.1导致很多用户无法正常下载。 +首先,你需要下载**MT管理器**(直接在应用商城搜或者浏览器搜) +下载好后,打开MT管理器,进入/storage/emulated/0/Android/data/com.tencent.mobileqq/tencent/QQfile_recv +找到你刚刚下载好的apk.1文件,点击它,在弹出的窗口中点击左下角的“类型”,点击全部。 +不同型号的手机这个界面的选项会有所不同,以oppo手机为例,在这个页面向下滑动就会找到一个“软件包安装程序”的按钮。点击它就会进入软件安装页面,所有的选项全部点同意后,等待一段时间就可以打开游戏了。 +其他品牌型号的手机也差不多,多尝试寻找。寻找差不多的字样。 + +## 我无法打开/Android/data +自安卓11起,访问Android/data等目录需要授权;自安卓14起,授权途径被阻止。在2024年2月的安全更新中,谷歌将该项限制合入,覆盖到了安卓11、12、12L、13、14。在系统设置-关于手机中安全更新日期大于等于2024年2月的系统可能会遇到无法授权的问题。 + +遇到这种问题的同学,可以点击这个链接从网盘下载。**要点击后缀名为.apk的文件下载** +https://pan.quark.cn/s/a5d434ab6145 + +# 泰拉瑞亚PC版本下载 + +PC端也可以通过群文件或网盘下载 +https://pan.quark.cn/s/856451f8f210 + +把压缩包下载好后,**解压出来**,在解压出来的文件夹内双击``setup_terraria_v1.4.4.9_v4_(60319).exe``运行,弹出的窗口左下角可以配置路径,按照你的需求配置好后同意协议,等待一段时间后安装就完成了(有些电脑时间可能比较长,请耐心等待)。 + +# 连接服务器教程 + +以PC端为例,当你下载安装好了游戏之后,创建一个人物。创建好后,左下角返回。点击多人游戏,选择最上面的加入。把群公告里的ip输入进去,然后输入端口。(手机端要直接添加一个英文冒号并跟上端口) + +## 注册登录 + +为了保证游戏的公平性,本服务器开启了强制开荒,也就是进入服务器后强行把物品栏清除到服务器配置文档的默认值(同志短剑、铜稿、铜斧)。即使毕业人物存档进服也只能被废尽武功从头修炼。 + +连接到服务器后,你会发现你无法进行移动、破坏方块、拾取物品等操作,这是因为你还没有**注册**。 +打开聊天栏,按照以下格式输入命令 +``/register <password>`` +比如我的密码是114514,我就可以输入 +``/register 114514`` +注册好后,再打开聊天栏按照以下格式输入 +``/login username password``即可登录。同一设备登陆过一次后,无需再次登录。 +例如 +``/login yingyu5658 114514`` +恭喜你,你可以开始游玩了! diff --git a/content/posts/猫.md b/content/posts/猫.md new file mode 100644 index 0000000..dee2e73 --- /dev/null +++ b/content/posts/猫.md @@ -0,0 +1,52 @@ +--- +abbrlink: 2245964304 +categories: +- 往昔 +date: "2025-06-01 20:36:05" +tags: +- 猫 +title: 猫 +--- +六年前,曾短暂地拥有过一周的狗。只有一周。 + +那个时候爸妈都出去上班,只留我和我奶奶在家。奶奶不喜欢小动物,不喜欢任何活物,包括我爸爸。据说她年轻时,经常把我爸爸送到邻居家照看,单纯因为不喜欢。同样地,她也不喜欢花草。爷爷养的茉莉花,颜色洁白,屋内也花香飘逸,死了。被奶奶用热水浇死的。 + +奶奶不喜欢任何活物,同样地,她也不喜欢这只狗。不知道为什么,不去跟爸妈说,反而在我面前卖力。装心脏病、哭闹。我当时还小,哪懂什么真假,而且奶奶也是很重要的亲人,我很害怕再也见不到她。小孩子就是这么天真。印象最深刻的就是让我拍她胳膊,我又急又怕,手酸到没力气、颤抖也不敢停下来。 + +多年后,奶奶再次提起这件事,轻描淡写的嬉笑着:“我当时是装的呀。”直到今天,奶奶的心脏依旧强有力而平稳地跳动着。我那些日子倒是被吓得快犯了心脏病。 + +那七天,我度日如年。但仔细回想计算,只过了一周。小时候的时间怎么过都过不完。 + +狗送走了。 + +那天,爸爸开车送我们去到一个很远的地方,我坐在车上没有什么情绪。看着旁边笼子里的狗,没有什么情绪。想起这七天发生的所有事,没有什么情绪。不知道该有什么情绪,是该因伙伴被迫离自己而去感到悲痛欲绝,还是该因自己马上解脱而感到畅快轻松。我没有什么情绪。 + +路程很远,时间很长,我和妈妈坐在车上,一句话没有说。 + +到地方了,我还是麻木的。下车后,把笼子打开,牵出来那条狗,它的下一任主人接过栓绳后,它就再也与我没有任何关系。笼子没让对方拿走,说是留个念想。 + +七天的感情没有多深,没有多深。交接完成后,妈妈和那个人有几句大人之间的寒暄,我没注意听,也听不懂。我没有什么情绪,没有什么记忆。 + +回到车上,我坐在车上不知道该有什么情绪。看着旁边空空的笼子,没有什么情绪。解脱了,成功了。我和妈妈坐在车上,一句话没有说。 + +下车后,妈妈的眼泪率先落下来,我最见不得别人哭,也跟着哭了。 + +那一天,一个懵懂的儿童学会了珍惜,也学会了憎恨。 + +妈妈给我看它的新主人发朋友圈,它生活在一个更大的房子里,有很多玩具,也有人跟它一起玩了。它很开心。我的眼泪又落了下来。时至今日,我的眼泪还是控制不住地流出来。七天的感情,没多深,没多深。 + +送走狗后没多长时间,妈妈就不上班了。可能是发现了我每天的日子过得多精彩,也可能是她累了。总之,我不用再面对奶奶了。 + +19年,印象中只有三件事。中华人民共和国成立七十周年、狗走了、猫来了。 + +三个月后,亲戚开的猫舍送给我们一只小猫。蓝猫,通体灰色,没多好看。我一直很喜欢猫,丑也喜欢。 + +当时酷爱发朋友圈,有点大事小事都要发个朋友圈记录一下,也留下来很多这只猫的照片和视频。我们给他起名叫四喜。已经忘了为什么叫四喜了。 + +我学会了珍惜,非常珍惜这只猫,谁也不让摸,谁也不让碰。有一次厨房窗户没关好,四喜跑到窗户外的封窗框上,正扒着头往外试探。我二话不说,什么也没想就冲出去,踩着封窗框,把它抱了回来。那天我主动要求自己睡,在爬在枕头上哭了一整晚,我太害怕失去她了。 + +时间过得越来越快,越来越快。 + +六年了,六岁了,老了。我太害怕失去她了。今天收集了很多猫毛。我害怕失去她,更害怕她被遗忘,被遗忘就真的什么都没了。 + +仔细回想,太对不起四喜了,最近两年都没怎么好好陪她。她倒是一直很想我,我不在时,爬在我的衣服上,被褥上。回来时,我走到哪跟到哪。睡觉了,爬在枕边,踹起手,睡倒了,就干脆肚皮也露出来。伏案时,趴在纸上,坐在电脑前,爬在鼠标垫上。四喜一直都沉默寡言,但当我一个月没回家,她见到我后也忍不住啼哭起来,一边用头猛蹭我的腿。一对眼眶里镶嵌着两颗晶莹剔透的琥珀,总是温柔地冲我慢慢眨眼。 diff --git a/content/posts/用Javascript-TSS和Highlights构建一个句级文本阅读器.md b/content/posts/用Javascript-TSS和Highlights构建一个句级文本阅读器.md new file mode 100644 index 0000000..e103741 --- /dev/null +++ b/content/posts/用Javascript-TSS和Highlights构建一个句级文本阅读器.md @@ -0,0 +1,353 @@ +--- +abbrlink: 1126783921 +categories: +- 往昔 +date: "2025-07-04 10:46:53" +tags: +- 翻译 +- JavaScript +title: 使用Javascript TSS和Highlights构建一个文本阅读器 +--- + +> 原文:https://jsdev.space/tts-sentence-reader/ +> +> 翻译:Verdant<i@glowisle.me> + + + +在这篇文章中,我们将构建一个简单的Web工具来探究**Text-toSpeech(TTS)**在JavaScript中是如何工作的。我们也将深入研究**句子级高亮**的工作逻辑。这两项功能经常结合在一起使用,以走到浏览器中打造无障碍的动态阅读体验。 + +步骤: + +1. 学习在浏览器中,TTS是如何工作的 +2. 探究动态高亮句子的实现方法 +3. 用HTML, CSS, JavaScript构建一个小工具([Demo & Code](https://codepen.io/jsdevspace/pen/YPXRRjO)) + +## 📢 浏览器中的TTS概述 + +JavaScript提供一个内置的API:[`SpeechSynthesis`](https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesis),它允许我们使用系统中的可用嗓音去大声朗读问文字。 + +### 核心对象: + +- `speechSynthesis` — 控制播放、暂停、恢复、停止 +- `SpeechSynthesisUtterance` — 作为TTS引擎的待播报文本 + +### ✨示例: + +```js +const msg = new SpeechSynthesisUtterance("Hello, world!"); +window.speechSynthesis.speak(msg); +``` + +### ⚙️ 添加嗓音和配置 + +```js +const utter = new SpeechSynthesisUtterance("This is a test"); +const voices = window.speechSynthesis.getVoices(); +utter.voice = voices.find(v => v.lang === 'en-US'); +utter.rate = 1.2; +utter.pitch = 1; +window.speechSynthesis.speak(utter); +``` + +你也可以追踪朗读的开始和结束: + +```js +utter.onstart = () => console.log('Started speaking'); +utter.onend = () => console.log('Finished speaking'); +``` + +## ✍️ 句子高亮 + +展示给用户哪一个句子正在阅读,我们需要用CSS和JavaScript来高亮文本。 + +### 示例 HTML: + +```html +<p> + <span class="sentence">First sentence.</span> + <span class="sentence">Second sentence.</span> +</p> +``` + +### 处理高亮的CSS: + +```css +.sentence.active { + background-color: yellow; + font-weight: bold; +} +``` + +### JavaScript高亮逻辑: + +```js +function highlight(index) { + document.querySelectorAll('.sentence').forEach((el, i) => { + el.classList.toggle('active', i === index); + }); +} +``` + +# 🚀项目: 使用TSS和高亮的阅读器 + +我们的程序将要: + +- 逐句朗读文本 +- 高亮朗读中的文本 +- 提供播放、暂停、恢复、停止 +- 让用户能选择嗓音 + +## 📄 HTML结构 + +```html +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta name="description" content="Build an interactive sentence-level text-to-speech reader with highlight, playback controls, and local progress tracking using HTML and JavaScript." /> + <title>Interactive TTS Article Reader</title> +</head> +<body> + <h1>Read Along TTS Demo</h1> + <div class="toolbar"> + <button id="start">Play</button> + <button id="pause" disabled>Pause</button> + <button id="resume" disabled>Resume</button> + <button id="stop" disabled>Stop</button> + <button id="reset">Reset</button> + <select id="voices"></select> + </div> + <div class="text-block" id="reader"> + <span class="line">Learning to code is a never-ending journey.</span> + <span class="line">Technologies evolve rapidly, requiring constant adaptation.</span> + <span class="line">JavaScript, HTML, and CSS are essential tools for web development.</span> + <span class="line">Frameworks like React and Vue enhance front-end capabilities.</span> + <span class="line">Back-end skills with Node.js extend JavaScript to the server.</span> + </div> + <div class="progress"> + <span id="progressText">0/0</span> + <div class="bar"><div class="bar-fill" id="bar"></div></div> + </div> +</body> +</html> +``` + +## 🎨 CSS 样式 + +```css +body { + font-family: sans-serif; + margin: 0; + padding: 2rem; + background: #f0f4f8; + color: #333; +} +h1 { + text-align: center; + margin-bottom: 2rem; +} +.toolbar { + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 1rem; + margin-bottom: 2rem; +} +.toolbar button, +.toolbar select { + padding: 0.6rem 1.2rem; + border-radius: 4px; + border: none; + font-size: 1rem; +} +.toolbar button { + background: #0077cc; + color: white; + cursor: pointer; +} +.toolbar button:disabled { + background: #ccc; + cursor: not-allowed; +} +.text-block { + background: white; + padding: 1.5rem; + border-radius: 6px; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); +} +.line { + display: block; + margin-bottom: 1rem; + cursor: pointer; + transition: background 0.3s; +} +.line:hover { + background: #f9f9f9; +} +.line.active { + background: #fff3cd; + font-weight: bold; +} +.progress { + text-align: center; + margin-top: 1rem; +} +.bar { + height: 8px; + width: 100%; + background: #eee; + border-radius: 4px; + overflow: hidden; +} +.bar-fill { + height: 100%; + width: 0; + background: linear-gradient(to right, #0077cc, #005fa3); + transition: width 0.3s; +} +``` + +## 💡 JavaScript逻辑 + +```js +const lines = document.querySelectorAll('.line'); +const playBtn = document.getElementById('start'); +const pauseBtn = document.getElementById('pause'); +const resumeBtn = document.getElementById('resume'); +const stopBtn = document.getElementById('stop'); +const resetBtn = document.getElementById('reset'); +const voiceSelect = document.getElementById('voices'); +const progressText = document.getElementById('progressText'); +const progressBar = document.getElementById('bar'); + +const synth = window.speechSynthesis; +let voices = []; +let currentIndex = 0; +let currentUtterance = null; +let isPaused = false; + +function populateVoices() { + voices = synth.getVoices(); + voiceSelect.innerHTML = ''; + voices.forEach((voice, index) => { + const opt = document.createElement('option'); + opt.value = index; + opt.textContent = `${voice.name} (${voice.lang})`; + voiceSelect.appendChild(opt); + }); +} + +synth.onvoiceschanged = populateVoices; +populateVoices(); + +function updateUI() { + progressText.textContent = `${currentIndex + 1}/${lines.length}`; + progressBar.style.width = `${((currentIndex + 1) / lines.length) * 100}%`; +} + +function highlightLine(index) { + lines.forEach((line, i) => { + line.classList.toggle('active', i === index); + }); + lines[index]?.scrollIntoView({ behavior: 'smooth', block: 'center' }); +} + +function speakLine(index) { + if (index >= lines.length) return; + const text = lines[index].textContent; + const utter = new SpeechSynthesisUtterance(text); + const selected = voiceSelect.value; + if (voices[selected]) utter.voice = voices[selected]; + utter.rate = 1; + + utter.onstart = () => { + highlightLine(index); + playBtn.disabled = true; + pauseBtn.disabled = false; + resumeBtn.disabled = true; + stopBtn.disabled = false; + }; + + utter.onend = () => { + if (!isPaused) { + currentIndex++; + if (currentIndex < lines.length) { + speakLine(currentIndex); + } else { + resetControls(); + } + } + }; + + currentUtterance = utter; + synth.speak(utter); + updateUI(); +} + +function resetControls() { + playBtn.disabled = false; + pauseBtn.disabled = true; + resumeBtn.disabled = true; + stopBtn.disabled = true; +} + +playBtn.onclick = () => { + currentIndex = 0; + speakLine(currentIndex); +}; +pauseBtn.onclick = () => { + synth.pause(); + isPaused = true; + pauseBtn.disabled = true; + resumeBtn.disabled = false; +}; +resumeBtn.onclick = () => { + synth.resume(); + isPaused = false; + pauseBtn.disabled = false; + resumeBtn.disabled = true; +}; +stopBtn.onclick = () => { + synth.cancel(); + resetControls(); +}; +resetBtn.onclick = () => { + synth.cancel(); + currentIndex = 0; + highlightLine(currentIndex); + updateUI(); +}; + +lines.forEach((line, index) => { + line.addEventListener('click', () => { + synth.cancel(); + currentIndex = index; + speakLine(currentIndex); + }); +}); + +updateUI(); +``` + +## ✅ 它们如何工作 + +- 每一个句子都是`<span class="sentence">` +- 我们迭代句子并使用`SpeechSynthesisUtterance`大声朗读 +- 在朗读过程中,高亮正确的文本并滚动 +- 一个句子结束后,自动朗读下一个句子 + +## 🔚 尾声 + +阅读了本文,你理解了: + +- 浏览器TTS的运行原理 +- 如何实现动态高亮文本 +- 如何从零构建一个功能齐全的阅读界面 + +你可以扩展项目功能: + +- 在`localStorage`保存阅读进度 +- 添加进度条 +- 加载外部文章或用户输入 diff --git a/content/posts/研读《春雪》笔记三则.md b/content/posts/研读《春雪》笔记三则.md new file mode 100644 index 0000000..04fc0c3 --- /dev/null +++ b/content/posts/研读《春雪》笔记三则.md @@ -0,0 +1,57 @@ +--- +date: 2025-09-22T19:39:35+08:00 +draft: false +title: 研读《春雪》笔记三则 +slug: reading-haru-no-yuki-notes +categories: + - 读书 +tags: + - 读书笔记 + - 日本文学 + - 三岛由纪夫 + - 丰饶之海 + - 春雪 +description: 真正的优雅是不会害怕任何的淫乱的。 +--- +## 淫乱与优雅 + +> 聪子仿佛在教导清显,让他明白真正的优雅是不会害怕任何的淫乱的。 +> —— 《春雪(上)》(一页文库) P175 + +这段话运用了两个抽象的概念:「优雅」和「淫乱」。 + +清显和聪子的爱情发生在聪子被天皇许给亲王后,这使他们之间的爱情变成了一种对至高无上的光圈的冒犯,使他们认为自己的感情超凡脱俗。 + +三岛的思想认为,美是至高无上且无可亵渎的,但只有犯禁才能体会到这种美,对清显而言,聪子的「美」本身是可获得的,所以并不能称之为真正的「美」,当他冒着风险,去触犯禁忌的时候,才感受到了真正的优雅和美,清显为皇后捧裾时失误趔趄,但皇后却回头对他嫣然一笑,也让他从此产生了「禁忌可触」的思想。 + +「淫乱」并非字面含义,在情节中,两人的行为本质上是「通奸」。他们冒犯的是当时日本最神圣的禁忌 —— 天皇的权威。因此,这里的深层含义是「僭越」和「犯禁」。是一种对既定秩序、社会规范等禁锢的主动打破。 + +三岛认为,唯美之物必然伴随着对禁忌的触碰和冒犯,真正的优雅带有一种逆反性和危险性。此淫乱价值中立,是一种强大的、原始的情感生命力和情感力量。通过冒犯最高禁忌,使得爱情达到了前所未有的高度、强度与纯度,从而体验到一种毁灭性的极致的美与优雅,这里是三岛美学思想的有力体现。 + +<!--more--> + +--- + +## 关于松枝清显的性格塑造 + +清显堪称三岛由纪夫所追求的「美」的完美体现,他追求一种不涉入现实,由观念、感性甚至是梦幻构成的真正的「绝对之美」、「纯粹之美」。 + +在三岛的美学谱系中,美本身常常与女性、柔美、易碎等特质关联。清显男性的肉体与女性化的气质构成了一种超越性别的微妙的中性美,更接近理想中的「纯粹」。而清显又是接受和感知美的天线,他能捕捉到最细致的情感涟漪,光影变化和氛围波动,由于这些东西都是易逝的、暂时的,这就使他比常人更接近「美」的本质。 + +清显优柔寡断,他总是被推着走,不主动参与世界,是一个美的体验者与观察者,而非世俗的参与者,保持着精神世界的「纯粹性」。 + +清显的阴柔极大强化了他的「易碎感」,三岛信奉的「夭折美学」,即最美的事物必须在极致的瞬间毁灭,才得永恒。阳光、富有生命力的英雄的毁灭是悲壮的,但一个精致、柔美、如梦似幻的少年的毁灭,带来的是凄美、心痛和无限的悲惋。他仿佛一开始就注定要破碎,他的死亡成为了美学上的必然。 + +而从三岛由纪夫的身世来理解,他幼年在祖母的贵族式的教育下长大,身体有着类似清显的孱弱,但他又极度崇拜强健的体魄、阳刚的男子气概和行动力,以及探讨死亡与使命的,带有悲壮色彩的武士道精神,所以清显可以看作三岛将自身中敏感、文艺、阴柔的一面极致化并投射于外的过程,他通过清显这个角色,彻底地毫无保留地探讨了这种美的可能性,并最终让其毁灭,同样象征着私道在美学上完成了对自身柔美一面的告别与超越,把这种美推向极致最后摧毁的行为,呼应三岛的核心美学(哲学)思想,也能在后续的作品中偏向更阳刚、暴烈、行动性的美学。 + +--- + +## 巅峰即衰败起点 —— 三岛由纪夫毁灭美学的核心宿命论 + +任何具象之美,如青春、容颜、激情,在达到顶点的瞬间,必然开始不可逆的衰减。人对重复的体验也会麻木,如若清显于是聪子的爱情在禁忌中持续,终将沦为庸常,其「神圣性」会被日常消解。 + +美本身是一种易被玷污的脆弱状态,时间、世俗、欲望都会侵蚀其纯粹性,如聪子若剩下清显的孩子,爱情的形而上的意义将被生物学事实瓦解。人为中止美衰败的进程,将其冻结在最饱满的状态,如将鲜花制成标本,是对「美」的最高保护和尊重。 + +三岛认为,毁灭是获得美神性的唯一途径,肉体的消亡使美脱离物质的桎梏,从「有限」跃向「无限」。清显死后,他在聪子与本多的记忆中被抽象为「永恒的幻影」,不再受肉身衰老与情感变质的威胁。毁灭完成了美的形而上学转化,使其成为一个纯粹的符号。 + +我在之前的文章《三岛由纪夫 —— 文化和时代背景塑造的矛盾体》中,简单地把三岛的切腹归为「荒谬的政治闹剧」,实在有失偏颇,仅仅结合一本由第三者撰写的传记来分析这个非常复杂的问题是不辩证的,理解三岛所追求的美学思想与哲学理念,才能为分析提供更客观、多元的视角。 diff --git a/content/posts/私密朋友圈.md b/content/posts/私密朋友圈.md new file mode 100644 index 0000000..b734cf9 --- /dev/null +++ b/content/posts/私密朋友圈.md @@ -0,0 +1,25 @@ +--- +abbrlink: 707697709 +categories: +- 往昔 +date: "2025-06-29 21:13:43" +tags: +- 朋友圈 +title: 私密朋友圈 +--- + +四天前,我发了自我的微信号注册以来,第一个私密朋友圈。九年了,从我五岁开始我就在用这个微信号,一个私密朋友圈都没有发过。 + +<!--more--> + +那条朋友圈的内容是关于期末考试成绩的愿望,其实就是给自己定一个大概的目标分数。如果失败,设置成公开会很丢脸,虽然也不一定有人记得我。第一次发完后,我就猛然意识到,我发朋友圈,不是为了给谁看,立什么人设,装什么X,我只是享受那种表达和发送的感受。表达欲望谁都有,但发送的享受是从何而来的? + +我认为还是可以把它划分到表达的欲望中,发送这个动作,其实也是表达的一部分,而且也是相当重要的一部分,表达是一个需要多个参与者的活动,有内容输出者也有输入者,而发送才是真正的表达,把自己的想法输出给输入者。至于私密朋友圈中,输入者这个概念究竟是谁,我想是自己。发送这个动作实际上是一个思绪的出口,在发送之前的编辑过程只能被称为思考。出于自尊心,人际关系,把向外的表达欲内化,可以享受表达的乐趣,释放表达的欲望,同时也不必担心别人的看法如何。 + +我想这种碎片化的输出是有益的,很多情绪之所以会扩大、升级,就是因为长期在内心积攒,而“流式处理”情绪,就可以有效避免溢出风险。我不愿意把自己的负面情绪过多带给别人,所以一般也不会跟别人聊天,若是说有效的排遣情绪的手段,只有睡觉和写作。但两者的时空要求都有些高,所以发一些尽自己可见的朋友圈表达真正想法或许是一个好方法。 + +央视新闻公众号有一个“夜读”栏目,发表一些关于心理、情绪等方面疏导读者或起到治愈作用的文章。我观察到这类文章私密赞占比极高。 + + + +这也许能说明一些人致力于隐藏自己真正的情绪感受,就怕无法找到情绪的出口,最后StackOverflow。 diff --git a/content/posts/秋天的第一声狗叫.md b/content/posts/秋天的第一声狗叫.md new file mode 100644 index 0000000..d929e4f --- /dev/null +++ b/content/posts/秋天的第一声狗叫.md @@ -0,0 +1,23 @@ +--- +categories: +- 往昔 +date: "2025-08-11T10:46:13+08:00" +draft: false +slug: "" +tags: +- 狗叫 +title: 秋天的第一声狗叫 +--- +老家很多人都养狗,几乎每家每户都有一两条狗。 + +<!--more--> + +二零年的八月,不知道村口那条老黑狗发了什么癫,流着腥臭的口水就大叫起来,惹得人不安生。村里的老人们都说这叫狂犬病犯了。我还以为狗也染上新冠了。 + +它这一叫,不仅惹得人不安生,惹得村里那群狗也不安生。家家的狗,无论大狗还是刚出生的小狗,听见这几嗓子嚎,自己也按捺不住了,扯着嗓子嚎叫。它们关在笼子里,锁在屋子里,哪知道外头这声叫有什么意思。毕竟是狗,有人的脑子,狗就该建立文明了,它们只会跟着叫。 + +可能是出于动物骨子里对环境变化的敏感,村口的那条狗叫了。那其他的狗子是出于什么呢? + +之后的四年,每年它们都在八九月份发一次癫。这场群体性的癫狂,是什么引起的;狗叫声意味着什么,没有人知道。那群狗也不在意自己为什么叫,只要听到别的狗叫,自己也叫,就满足了。 + +今年七号,狗子们又沸腾起来举行它们的“仪式”了。 diff --git a/content/posts/立场与观点.md b/content/posts/立场与观点.md new file mode 100644 index 0000000..1f0bfd3 --- /dev/null +++ b/content/posts/立场与观点.md @@ -0,0 +1,43 @@ +--- +date: 2025-09-19T20:49:24+08:00 +draft: false +title: 立场与观点 +slug: stand-and-thought +categories: + - 往昔 +tags: + - 思考与议论 + - 观察 + - 记事 +description: 最近我们班的英语老师崴脚了,有另一位老师来代课,一些同学对这位老师的评价极负面,我对这个现象很感兴趣,借此次机会来聊聊观点和立场的话题。 +--- + +最近我们班的英语老师崴脚了,有另一位老师来代课,一些同学对这位老师的评价极负面,我对这个现象很感兴趣,借此次机会来聊聊观点和立场的话题。 + +首先,任何一门学科,学生都会因为各种原因,对它持有不同的看法。对于一位老师的评价,主观上除了自认为的「老师的水平」,还有一个很大的元素是老师教的学科。而学科有强势与弱势之分,人面对学科时的激励或挫折感受不同,自然会生出喜爱与厌恶的情绪。对于老师的评价也难免受到自己对科目情绪的影响。 + +<!--more--> + +每次下课都能听到一些同学对老师授课水平的评价:「狗屎」、「又臭又长」,以及人身攻击,直接辱骂老师的。基本都是「我觉得」、「俺寻思」,然后继续追问支支吾吾,仔细观察就能发现,那些恶言相向者都是不擅长英语的,如Q同学每天上课都心不在焉,百无聊赖,成绩不理想归结于「老师教的太烂」。他们的立场,已经开始作用于「评价」了。 + +这些评价可以分为两类,情绪与人身攻击。都是立场的作用。立场,在哲学和社会学中,常指由一个人的社会身份(如阶级、性别、种族)、生活经验所形成的特定视角和认知框架。但我更愿意用这种说法 —— 所站立的地方。站在不同的角度,也就是不同的立场看待问题就会有不同的结果。所以,在一个不擅长英语的人眼中,与英语有关的东西会让他回忆起痛苦,这种偏见的形成,直接导致了评价的方向,也生出了情绪。除学科偏见外,立场的构成也有其他原因,如对原老师的喜爱和留恋,甚至是从众心理等。 + +以上所描述,既不能称之为评价,又不能称之为观点,而是一种因先天能力、后天影响、个人经历等复杂因素共同作用导致的,带有情绪的看法。观点则是基于事实、理性分析形成的判断。何为评价?评定其价值。价值一定是一个值,或者一个区间,不能是负无穷或正无穷,所以价值不能是「好」与「不好」的二元对立。历史学科强调的评价原则是:**辩证、全面、客观、实事求是**。所以把一些相通的概念借鉴来并补充,如何评价一位老师?辩证、全面、客观、实事求是、**区分观点与立场**。 + +实事求是,即根据实证,求索真知;[^1]所以从我们班级的客观情况来分析,由于皇亲国戚[^2]居多和一些职场人情世故,我们班级的师资力量可以说是全年级数一数二,甚至还有高中部的老师曾来代课过,这也基本能说明来我们班代课的老师都不会差,再差也不会到「狗屎」的地步。也有一位在本校工作的老师背后推动优化我班的师资水平,所以这位代课老师的真正水平,已经有两个明显的因素发挥作用。 + +从授课节奏上看,与原老师几乎无异。课文翻译、短语、语法内容以及习题的讲评,也都是深入浅出、鞭辟入里的。只是由于代课老师工作繁忙,还有其它年级的学生要带,默写等基础工作不抓,有同学无自主学习的习惯,所以抱怨「看不懂题了」。即使课堂氛围营造不足,互动方式与原老师不同,也不应下降到人身攻击。 + +另外一个原因,也是由于宽松的管理风格,导致同学们的不适应,只好把情绪宣泄在最明显的一个点 —— 老师身上。说来说去,最后的问题还是落在了自己。 + +明辨是非而非混淆观点立场,调整适应而非辱骂拉踩的能力,在追求统一进度、弱化个性思考的标准化教育环境里异常可贵。这种能力,都是以思考为前提的。班级里用情绪主导判断的行为,是微小的时代缩影,在信息爆炸的时代,操控流量的人们刻意煽动情绪、制造爆点,宣扬极端化的观点,给出片面的,断章取义的结果,抹杀了思考的过程,从而导致很多人懒得思考,放弃思考,「没想过」、「不关心」、「不知道」成为常态,娱乐致死的邪风越刮越猛,麻木愚钝的浪潮愈发澎湃,想和同学交流看法,最后的一份坚守也能被尖锐质问: + +「你想这个干嘛?」 + +> 知音少,弦断有谁听。 +> +> —— 岳飞《小重山 · 昨夜寒蛩不住鸣》 + +[^1]: [实事求是 - 百度百科](https://baike.baidu.com/item/%E5%AE%9E%E4%BA%8B%E6%B1%82%E6%98%AF/36312) + +[^2]: 指教师子女。 diff --git a/content/posts/第三次世界大战.md b/content/posts/第三次世界大战.md new file mode 100644 index 0000000..f206e46 --- /dev/null +++ b/content/posts/第三次世界大战.md @@ -0,0 +1,24 @@ +--- +abbrlink: 37846610 +categories: +- 往昔 +date: "2025-06-19 23:09:59" +tags: +- 时政 +title: 第三次世界大战 +--- +我始终坚信,也能深刻体会到一句话——林子大了什么鸟都有。 + +最近两天伊以冲突闹得很大,工厂停运、百姓流亡,民不聊生,当地居民都处于恐慌和焦虑中。 + +我不对局势做点评,也不站队有立场。我发现了身边有一些人,对战争非常感兴趣,甚至期盼战争。 + +难以想象、不可理喻、不是人类,无法共情。我开始怀疑我自己的立场和价值观是不是有问题。 + +印象很深的一句话:“第三次世界大战要开始了,太好了。” + +我说的明白点,打仗谁能好过?用你跟泌尿系统一次握手都没进行过的低能连接的大脑好好想想,打仗谁能好过?**你是想被送到前线,给上头那帮老家伙们当棋子,当挡子弹的肉盾,还是想当送死的炮灰?** + +还是你觉得打仗就能变革,改变你社会蛀虫父母累赘的现状,还是觉得你FPS游戏经验丰富,上战场能大杀四方为国争光?别跪着求对方不要用钝刀割下自己的猪头都很强了。上了战场就祈求你看军事视频和意淫战争的经验有用吧。 + +好日子过久了,忘却战争的残酷,战争被娱乐化,这种人就出现了。 diff --git a/content/posts/简单使用Graphviz绘制程序流程图.md b/content/posts/简单使用Graphviz绘制程序流程图.md new file mode 100644 index 0000000..fd30869 --- /dev/null +++ b/content/posts/简单使用Graphviz绘制程序流程图.md @@ -0,0 +1,109 @@ +--- +date: '2025-11-12T11:13:24+08:00' +draft: false +title: '简单使用Graphviz绘制程序流程图' +slug: '' +categories: + - 技术 +tags: + - Graphviz +--- +## Graphviz +Graphviz 是一个开源的图形可视化软件,主要用于绘制有向图和无向图。 + +用途: + +1. 数据结构可视化:Graphviz 常用于显示数据结构,如抽象语法树或其他编程语言、工具或服务中的数据结构。 + +2. 软件设计和架构:通过Graphviz,开发者可以可视化系统组件、依赖关系和交互。 + +3. 网络拓扑图:用于显示网络设备和其连接的物理或逻辑视图。 + +4. 业务流程和工作流程图:描述组织或系统中的工作流程。 + +5. 其他任何需要图形表示的场景,例如状态机、决策树、组织结构图等。 + +优势: + +1. 声明性语言:Graphviz 使用一种称为 DOT 的声明性图形描述语言。用户只需描述图形的元素(如节点和边)及其关系,而无需指定其在屏幕上的确切位置。这使得创建和修改图形变得非常简单。 + +2. 自动布局:Graphviz 的一个显著特点是其强大的自动布局工具,这意味着你不需要手动指定节点的位置;Graphviz 将自动为你找到一个有意义和易于阅读的布局。 + +3. 可扩展性:Graphviz 支持多种输出格式,如 PNG、SVG、PDF 等,这意味着你可以轻松地将其图形集成到其他文档、网页或应用程序中。 + +4. 灵活性:虽然 DOT 语言相对简单,但它提供了丰富的特性和属性,允许用户定制图形的外观,如颜色、形状、大小、标签、箭头样式等。 + +5. 跨平台:Graphviz 可在多种操作系统上运行,如 Windows、Linux 和 macOS。 + +6. 活跃的社区和广泛的应用:由于其开源性质,Graphviz 拥有一个活跃的社区,不断有新的工具和库被开发,以支持更多的用例和集成。 + +## 使用 + +Graphviz 使用 DOT 语言来描述图形。在 DOT 中,图分为**有向图**和**无向图**,使用`digraph`和`graph`关键字。 + +安装: + +``` +sudo apt install dot +``` + +- Digraph 有一个明确的起点和终点。 + +- Graph 没有明确的起点和终点。 + +### 节点(Node) + +节点表示图中的一个实体,每一个节点都有唯一标识符。 + +### 边 + +边连接两个节点。在有向图中显示为一个箭头,在无向图中显示为一条线段。 + +- 有向图:`nodeA -> nodeB;` + +- 无向图:`nodeA -- bodeB;` + +### 属性 + +- `color` 元素颜色 + +- `label` 附加到元素上的文本标签 + +- `shape` 节点形状 + +- `style` 元素样式 + +```dot +digraph G { + A -> B; + B -> C; + C -> D; + D -> A; +} +``` + +渲染为图片: + +```bash +dot -Tpng ./test.dot -o ./test.png +``` + +## 示例 + +一个容易的用户登录验证逻辑 + +```dot +digraph UserLogin { + 登录 -> 验证用户名和密码; + + 验证用户名和密码 -> 放行 [label="正确"]; + 验证用户名和密码 -> 重试 [label="错误"]; + 重试 -> 登录 +} +``` + + + +## 参考 + - https://zhuanlan.zhihu.com/p/644358139 + - https://graphviz.org/documentation/ diff --git a/content/posts/红叶攀墙秋萧萧.md b/content/posts/红叶攀墙秋萧萧.md new file mode 100644 index 0000000..9cc292d --- /dev/null +++ b/content/posts/红叶攀墙秋萧萧.md @@ -0,0 +1,28 @@ +--- +date: 2025-10-16T22:40:26+08:00 +draft: false +title: 红叶攀墙秋萧萧 +author: 五葉地錦 +slug: "" +categories: + - 往昔 +tags: + - 散文 +--- +学校操场的围栏上,长满了爬墙虎。自开学起,每次和它们见面,一回比一回红。是夏季烈日残留的一角把它们引燃了吧? + +能见到它们,只有在体育课和做操的时间。上次运动会时还是绿绿的一簇,挂在操场大门上方,几支茎垂下来,稚嫩的绿叶在一阵微风吹过后,它娇妍地摆头。有几片叶子从格子缝隙里探出头,生锈的围栏高墙点缀着生机。 + +<!--more--> + +一次大课间,我们坐在操场上休息。围墙外远方的高楼在暮霭的包裹下,轮廓被细致地描摹,目之所及皆被染上了一抹颓黄,鸟群在几栋楼之间来回穿梭。 + +怎样才能将自己的思绪,融入这缥缈的夕阳、这喧闹、这最后的两百余天中呢?大门上的红叶在风中摇摆。 + +今日再见,那一抹令人惋惜的成熟的艳红,已经不由分说地映在它们昔日稚嫩的脸上。夏季的烈日将它们引燃了。纯粹的美,无暇的美,昂扬的美,低垂的美。它们为自己的美付出了代价。 + +我沿着围墙捡拾红叶。一些最艳的红叶,早早就掉落了,老成的携着腐朽的红叶,把它们可贵的纯粹、干净的艳红衬托得曼妙无比。成熟的深红,破裂与暗淡,在早逝的艳丽衬托下,快要被人唾弃了。已经干瘪发脆的叶子,轻轻一搓就能碎成齑粉,散落在地上,那是红叶,还是小虫的尸骸呢?美丽如此脆弱。 + +与枝干刚刚两断的红叶,周身有着让人悲悯的柔软和湿漉。叶脉纹路清晰可见,光滑的叶肉反射着阴天清冷的光,简直像一件精雕细琢的工艺品。 + +我坐在围栏下,望着大门上方缀着的那簇叶子。它们已经没有了先前的活力。暗红的枝叶,低垂着身姿,散发着淡淡的死和枯萎的幽香。来年的红叶还会等我吗? diff --git a/content/posts/给00后10后的书信来往指南.md b/content/posts/给00后10后的书信来往指南.md new file mode 100644 index 0000000..1b849b2 --- /dev/null +++ b/content/posts/给00后10后的书信来往指南.md @@ -0,0 +1,124 @@ +--- +date: '2025-09-13T13:37:33+08:00' +draft: false +title: '给00后和10后的书信来往指南' +slug: 'guide-to-correspondence' +categories: + - 随笔 +tags: + - 教程 + - 怀旧 +--- +## 0.前言 + +现代社会,网络发达,书信这种原始的联系方式近乎销声匿迹,但仍有爱好者使用书信与朋友交流。为延续这份笔尖上的情谊,特撰此篇,供对书信有兴趣的年轻朋友们参考。本文将从格式、用语、用纸、信封、邮寄六个维度拆解,供示例均为书面用语,书信的魅力不仅在于死板的格式和用语,更在于「专属感」,可根据实际情况略作调整。 + +## 1.书信体格式 + +标准的格式可以体现出书信的正式性。 + +### 1.1 称谓 + +顶格写在**纸张左侧边缘**(即「左顶格」),不空格,独占一行。称谓后加冒号,冒号须写在称谓的**右侧**。 + +对平辈朋友: + +``` +XX 吾友:/ XX 兄: / 姐: +``` + +对年长朋友: + +``` +XX 先生: / 女士: +``` + +### 1.2 问候语 + +接称谓下一行,从**左侧空 2 个字符位置**开始写,独占一行。语气可正式可亲切,避免口语化,不拆分换行。 + +``` +展信佳。 / 别来无恙? / 久未联络,甚念。 +``` + +### 1.3 正文 + +接问候语下一行,从**左侧空 2 个字符位置开始写**,与问候语对齐。每段开头均需左空两格,段与段之间空 1 行,避免拥挤;后续每段开头空 2 格。 + +正文传递近况、想分享的事、对收信人的问候等,是书信内容占比最大的部分,也是核心。结尾盼回复 / 表牵挂,给对方回应的空间,例:「以上便是我的近况,也很想听听你那边的生活 —— 新换的工作是否适应?周末是否还像以前一样喜欢去公园散步?期待你的回信。」 + +### 1.4 祝颂语 + +用凝练的语言表达祝福,是正式书信的「礼仪收尾」。正文最后一段下方空 2 行,整体偏右书写(不用完全右对齐,比正文左边界靠右 2-3 个字符即可,美观不呆板)。 + +#### 1.4.1 格式与正式用语 + +**通用正式款**(推荐,适合多数朋友): + +第一行顶格写「顺颂」(或「敬颂」),第二行写「时祺」(时祺意为时时顺利,中性不挑场景); + +完整示例: +``` + 顺颂 +时祺 +``` +--- + +**最正式敬重**: + +第一行顶格写「此致敬礼」 + +完整示例: +``` + 此致 +敬礼! +``` + + + +注意:不要把祝颂语写在一行(如 “顺颂时祺”),分两行写更显正式。 + +### 1.5 署名日期 + +先写署名,再写日期,日期在署名正下方。 + +署名:正式且让朋友一眼认出,例:「你的朋友:XX」(“XX” 写你的全名 / 朋友平时叫你的名字);若关系近,可简化为「XX」(直接写名字)。 + +日期:通常与信头日期保持一致或接近。若为不同日期,以文末署名下的日期为准,它代表了此信完成或寄出的时间。 + +## 2. 纸笔选择 + +### 2.1 用纸 + +横排左至右的格式对纸张要求不高,优先选易书写、县正式的。首选**横线信纸**,米白色/ 浅米色,横线细且淡,不干扰字迹、**素色无图案信纸**,浅色,无花纹或仅角落有小图案,避免花哨。尺寸选择 16 开,比 A4 小一点。 + +### 2.2 用笔 + +用笔首选钢笔,墨水黑色 / 深蓝色,字迹饱满有轻微笔峰。推荐英雄 616、百乐 78G(入门款,好写不贵)。 + +横排不建议使用毛笔 / 秀丽笔,容易蹭墨,笔画太粗显拥挤。 + +## 3. 邮寄相关 + +信封可在文具店、邮局或网络购买,推荐「标准信封」(白色 / 牛皮纸色,右上角有邮票框) + + + +### 3.1 信封写法 + +- 收信人信息写在信封中间偏上,顶格写收信人地址(省 + 市 + 区 + 街道 + 门牌号),下一行顶格写联系电话(可选) +- 寄信人信息写在信封右下角,格式同上。地址、姓名、电话(确保投递失败时能退回)。 +- 邮票贴在信封右上角的邮票框里,国内平信(20g 以内)贴 1.2 元邮票即可(邮局)。 + +### 邮寄方式 + +1. 找「中国邮政营业厅」(地图搜中国邮政即可),工作人员会帮你检查格式、称重,直接投递。 +2. 找路边的「绿色邮筒」(标注外埠、本埠,朋友在省内写本埠,外地写外埠),投进对应入口即可(建议白天投,邮筒每天会定时开箱)。 + +### 邮编查询 + +微信关注「中国邮政微邮局」服务号,私信发送 4,会收到一个链接,可在链接中选择详细地址查询邮编。 + +--- + +书信教会我们一种珍贵的“迟钝”。它要求我们慢下来,铺开信纸,让思绪在笔尖沉淀,将匆促的想念酝酿成庄重的文字。每一个字迹的深浅,每一处墨点的晕染,都是当下情绪最真实的烙印,是无法被表情包和撤回键替代的真诚。它不仅仅是与人联系的方式,更是更是一次向慢生活与深度情感的诚挚邀约,祝读到这里的读者朋友们都能够亲身感受书信的独特魅力。 diff --git a/content/posts/给比我岁数还大的电脑装Fedora.md b/content/posts/给比我岁数还大的电脑装Fedora.md new file mode 100644 index 0000000..70e724e --- /dev/null +++ b/content/posts/给比我岁数还大的电脑装Fedora.md @@ -0,0 +1,62 @@ +--- +abbrlink: 3824334627 +categories: +- 往昔 +date: "2025-06-13 20:11:49" +tags: +- Linux +- Fedora +title: 给比我岁数还大的电脑装Fedora +--- +## 前言 + + + +印象中,这台电脑在我很小的时候就存在了,我爸的网盘里至今还有我当时用这台电脑播放江南Style,我在床上跳舞的视频。 + +这台机子开Powershell都卡,更不用说日常使用。 + + +我甚至都不想在这台电脑上截图,当拍屏大师吧。 + +听说Linux用户有个刻板印象就是,用着十几年前的笔记本,从来不用最新设备,那这不刚好吻合上了吗。 + +诶......等等,我[之前](https://www.yingyu5658.me/post/3691550015/)好像说过不折腾了?算了,反正Fedora没有Arch那么折腾(吧)。 + +<!--more--> + +## 正文 + + + +镜像下好后,用Rufus拷到U盘。 + +插到电脑上,额,先让我研究一下BIOS怎么进...... + + +把#1改成刚刚做的启动盘。保存后重启。 + + +哎,没想到第一难在这等着我呢。引导进不去。难道是我打开方式有问题?重新进BIOS,#1设置成UEFI巴拉巴拉试试。 + + +诶!成了,等一阵黑屏过后就弹Fedora Logo了。 + + +直接端上来吧!不管三七二十八直接Install! + +整个安装过程还是很傻瓜式的,只要有小学英文基础点点点就好了。 + + +虽然但是,这个简体中文怎么标的是新加坡。 + +一顿等待后,进入系统让选择一下语言,连接个WIFI就算大功告成了。 + +~~本来以为能有什么好玩的,还真这么傻瓜啊。。。~~ + +最后再来个经典的neofetch + + +系统也装完了,文章也写完了,电影也下完了,爽! + + diff --git a/content/posts/网站迁移.md b/content/posts/网站迁移.md new file mode 100644 index 0000000..867a897 --- /dev/null +++ b/content/posts/网站迁移.md @@ -0,0 +1,32 @@ +--- +abbrlink: 45320503 +author: null +categories: +- 往昔 +cid: 6 +date: "2024-11-21 22:59:00" +layout: post +slug: 6 +status: publish +tags: +- 博客 +title: 网站迁移 +updated: 2024/11/25 15:35:20 +url: null +--- + + +原网站 + +> yingyu5658.github.io + +将会迁移到这里。我会把有价值的文章转过来 +原因仅仅是gmeek有点太简陋了,虽然typecho也差不多,不过他可以折腾一下主题之类的,并且我每个月还多花出去九十大洋。但是总比gmeek逼格高点吧。 +不得不说,Linux绝对是世界上最麻烦的玩意,解压下载文件都费劲。要不是Windows资源占用多我绝对不会去用这玩意。 +这次可是孤军奋战,背后没有github服务器的靠山了。要是忘了续费服务器我会丢失所有的文章,又是一个负担和一个纠结的点 + +> 2025.8.24二编:Gmeek简直太符合博客的定位了,不花里胡哨,完全够用,有网就能写文章...... +> +> Linux太好用了,目前Debian12养老中。 +> +> 回看以前的自己实在是蠢。 diff --git a/content/posts/网络死亡计划.md b/content/posts/网络死亡计划.md new file mode 100644 index 0000000..d22c765 --- /dev/null +++ b/content/posts/网络死亡计划.md @@ -0,0 +1,25 @@ +--- +abbrlink: 2631380338 +categories: +- 往昔 +date: "2025-06-11 23:24:42" +tags: +- 社交 +title: 网络死亡计划 +--- +最近要把生活重心和精力再往学业上分配更多,打算逐步减少社交软件的使用。因此产生了些许对自己在社交软件的某些群组上是否需要存在的焦虑。所以有了这个想法:**在网络上死亡。** + +具体应该说是在社交软件上的死亡。为期两周,直到期末考试结束。 + +反正也不会有几个人关注我的博客,那就随便说说吧。如果你疑惑为什么我长时间装死,那看到这篇文章也就解答了。 + +一直感觉很多社交都是热脸贴冷屁股,浪费时间浪费精力。如果长达两周我没有在某个我曾经经常发言的群发言,而且也没有人主动找我,那也就意味着我在那个群不重要,对那群人不重要,不是一个圈子,无共同话题,也就没有留下去的意义。 + +主要包括: +- 停止发布朋友圈和QQ空间 +- 停止在所有非必要微信QQ群发言 +- 多学习,多写博客,多读书 + +如果这样过得很舒服,那可能会一直延续下去。我一直在寻找真正有意义的社交圈和社交方式,但至今为止,觉得最有效的能让自己没那么累的方式就是减少社交。 + +今后会把大部分生活琐事记录和观点表达转移到博客而非朋友圈和QQ空间。后者总是被动接受信息,不一定能找到共鸣,而前者是主动选择文章阅读,而且博客的性质能让人组织起完整的语言,客观地记录和表达;在QQ空间和微信发表出来总是有一种为了给某人看或为了给某些人看的味道,有些不舒服,也影响言语措辞。我这人变得越来越怪。 diff --git a/content/posts/罪恶感.md b/content/posts/罪恶感.md new file mode 100644 index 0000000..7344990 --- /dev/null +++ b/content/posts/罪恶感.md @@ -0,0 +1,53 @@ +--- +date: '2025-09-08T20:08:03+08:00' +draft: false +title: '罪恶感' +slug: 'guilt' +categories: + - 往昔 +tags: + - 学校 +--- +每年的春秋,我都会被极其严重的过敏性鼻炎折磨。 + +长期的睡眠不足,以及永无止境的其他方面的折磨,让我的记忆力和逻辑能力衰退;红肿流泪的眼睛,看周围的一切,唯一的区别只有颜色不同。现实与我从感官上隔绝开了。 + +周日傍晚我给母亲发消息,说明天要请假,我快要死了,不能去上学了。晚上父亲拉着我去了趟医院。回来后得知已经请完假了。 + +早晨五点多惊醒,意识到自己今天不用上学了,但已经醒了,再睡去就很难了,面朝哪个方向,只能听鼻子的,我躺在床上看着外边蒙蒙亮的天,一种难以名状的感觉 —— 我愿称之为罪恶感涌上心头。 + +我确确实实地请假了,我确确实实地在早上七点多不能再入睡,起床了,我确确实实地头脑发昏,我确确实实地低烧了。一切都是那么正当,一切都是那么合理。但那股罪恶感始终在我心头萦绕。 + +昨天去医院的时候我在手机上写下了这几段文字: + +> 我于前往医院的路上,写下这些文字。如果再不倾诉,我将会在路上随机杀掉几个人,或者杀掉最令我痛恨的人,然后自杀。 +> +>自入秋以来,过敏的痛苦如影随形地折磨着我,无论我身处何处。 +> +>旁人看来,只是得了一个长期的感冒,我首先要杀死的就是这种人。视他人苦难如秋风,任它从耳边划过。在他看来这秋风习习,霜叶飘零,一派凄寂唯美;在我看来,这秋风是该被杀害、分解、扒皮饮血、敲骨吸髓的恶畜,是该被杀死的、是苦痛之源! +> +>自九月份以来这短短十七天,我所言次数最多的话语,除泄愤诅咒他人的污秽之语外,就是『我脸上的每一个洞都在漏水』。 +> +>我脸上的每一个洞都在漏水! +> +>一天二十四小时,从何时开始算才是明天?十二点?日出?这个分解是极度模糊的。我看不到时间,我常常在深夜被最原始的,对死亡的恐惧、对窒息的恐惧惊醒。我床边没有任何能让我感知时间的设施,只能从脸上眼眵的覆盖程度,以及喉咙、眼球的疼痛程度,粗略判断现在是前半夜还是后半夜,然后在床上挣扎等待那恶畜放过我,让我入睡。 +> +>六点在昏胀的头痛中,准时起床进行洗漱,脸上永远是黏黏糊糊的,有封住眼睛的眼眵、过敏淌出的眼泪、控制不住的鼻涕,伴有鼻孔撕裂般的疼痛、张嘴睡觉流出的口水。脸上永远是黏黏糊糊的,怎么清洗都如此。及时这样,也要在十分钟内洗漱完,冒着被呛死的风险洗脸,冒着被憋死的风险刷牙。 + +那时还没定下来要请假,我被这种不确定性,或者说是不安感折磨着。终于如愿以偿请假,还不能在家里安心休息,反而继续被罪恶感折磨。 + +随着年龄的增长,随着年级的增长,每一次请假的罪恶感都会增强。 + +这种罪恶感来自我的同龄人们都在学校上课,我在家里睡大觉、看闲书。但这是理所应当的,我生病了。这不是理所应当的,我会落下很多进度。 + +这种紧张的氛围从开学第一天就开始渲染了,那天召开了年级会,会议精神可以粗略概括为初三是决定人生的一年、这是人生的一个转折点。 + +去你妈的吧。 + +又谈起人生,说大话。比起什么腰缠万贯、名利双收、坐办公室吹空调、走上人生巅峰等狗屁,回首十四年,我突然觉得我今天得以存活在这个世界上都是巨大的奇迹。我的母亲没有早产,我出生的时候没有染上大病,我幼年没有被温泉淹死,我没有在那次摔死,我没有磕得头破血流、粉身碎骨,没有在某一时刻从那个完全是为人自杀而准备的教室的窗户跳下去,真是奇迹。 + +每一次请假,我都感觉现实远远离我而去了。有时候它也会停下脚步等着我,但已经不是真正新鲜的现实了。我与今天上学的同学们是割裂的,我与在外上班的父母是割裂的,我与外边的世界是割裂的。我今天没去学校,但秋天恶心的阳光还是沐浴着校门口刻着校训的石头,从早晨睡到放学的那个人从来没醒过,教室空调后面的虫子依然在蠕动。时间依然在流动,现实依然在奔腾着离我而去。 + +初秋的天空湛蓝的可怕,从夏天延续到现在的虫鸣清晰可闻。 + +这太不真实了。 diff --git a/content/posts/聊聊文库本.md b/content/posts/聊聊文库本.md new file mode 100644 index 0000000..8b38724 --- /dev/null +++ b/content/posts/聊聊文库本.md @@ -0,0 +1,56 @@ +--- +date: '2025-11-02T17:40:02+08:00' +draft: false +title: '聊聊文库本' +slug: '' +categories: + - 随笔 +tags: + - 图书 + - 文库本 +--- +本文将从我个人购买、阅读文库本的经验谈谈文库本的优缺点,以及文库本是否适合你。 + +## 什么是文库本 + +文库本,一是在日本明治时期作为全集或丛书的出版形态;二是特指昭和年代后形成的A6尺寸(105mm×148mm)平装小开本书籍,具有便于携带、低价普及的特性。其内容多为经典作品的再版,也包含直接以文库本形式发行的轻小说等新兴出版物。因应关东大地震后对低价书籍的需求,1927年岩波文库开始出版,随后改造社文库、春阳堂文库、新潮文库接连出版,引起了文库热潮。 + + + +我在今年八月份接触到了这种装帧,并且喜欢上了它,后续买了很多文库本。但这个东西,在国内比较少,大部分还是以16开尺寸出版,由于是日本传进来的,至少我的是以日本文学为主。这一摞只有卡夫卡的《变形记》不是日本文学。 + +它真的非常小巧方便携带,罗列数据不是一个直观的方式,把它和我的手机比较一下: + + + +这本是一页文库出品的三岛由纪夫的《潮骚》,只比手机宽一点,可以放在口袋里。有一段时间,我的口袋里只有四样东西:手机、耳机、钥匙、书。——这是文库本的优点,非常方便携带,装帧精美,以及在国内不那么明显的价格优势(仅便宜3-4元)。说完了优点,接下来就该聊聊缺点了。 + +## 纸张和印刷问题 + +有不少读者反映,一页文库的书使用轻型纸,气味难闻且容易氧化发黄,不适合收藏。但这两个对于我个人来说都不是什么大问题,我见过真的呛得头晕的纸:东野圭吾《解忧杂货店》(新经典文化股份有限公司出品)。 + +为了确认出版社,我特意从书架上拿下来了这本书坐到电脑前。在敲上面那行字的时候,我甚至没有打开几秒书,劣质纸张的木臭味就直蹿我的鼻孔,头又开始痛起来了。 + +至于发黄问题,我个人倒还是挺喜欢泛黄的纸张的,比起氧化,我更在意破损。所以这个问题无关紧要。一本书的售价在十五元左右,使用轻型纸这种稍显「廉价」的纸张印刷也合理。 + +## 厚度失调与握持方式不适 + +我手头的《金阁寺》、《春雪》、《奔马》以及川端的四本书,握持感都比较舒适,但到了《晓寺》,体验上简直像是举着一本小词典。我上周在把一本牛津英汉小词典带到学校前和那本《晓寺》对比了一下,它仅仅比词典薄不到一厘米。 + + + +这样的厚度将它的便携性大打折扣,塞进口袋几乎不可能。而且由于装订方式的问题,摊在桌子上看并不舒服,举着的话就会因为太厚,手指疲劳。所以在比较厚的书中,文库本没有优势,除非分卷印刷。在某种程度上,这本《晓寺》是非常失败的,甚至不如买正常尺寸的书,在通勤的碎片时间我也只好转战电子版。 + +## 文库本适合什么人? + +- 通勤的碎片时间想看书的 +- 不太喜欢电子书 +- 想小成本读经典的 +- 喜欢便携小开本的 +- 不重收藏的 + +另外,一页文库的书是分内外封的,外封较薄,在口袋、书包里容易揉褶,如果在意这一点,也不太建议。 + +如果售价能长期控制在 15 至 18 元以下,那将非常实惠。希望国内做文库本的出版商不要拘泥于日本文学,其它经典书籍也多出点吧! + +*关于字体大小问题,原因在于文库本的字体大小和正常尺寸几乎无异,只是纸张尺寸减小,故没有重点讨论。* diff --git a/content/posts/记录Hexo搭建博客.md b/content/posts/记录Hexo搭建博客.md new file mode 100644 index 0000000..52572dc --- /dev/null +++ b/content/posts/记录Hexo搭建博客.md @@ -0,0 +1,222 @@ +--- +abbrlink: 3093271062 +author: yingyu5658 +categories: + - 往昔 +cid: 130 +customSummary: +date: 2024-12-07 23:40:00 +layout: post +mathjax: auto +noThumbInfoEmoji: +noThumbInfoStyle: default +outdatedNotice: true +parseWay: auto +reprint: standard +slug: 130 +status: publish +tags: + - Hexo + - 博客 +thumb: +thumbChoice: default +thumbDesc: +thumbSmall: +thumbStyle: default +title: 记录Hexo搭建博客 +updated: 2024/12/07 23:45:33 +draft: true +--- + + +# 前言 + +我今天在写网页的时候突然发现我居然忘了一些标签的使用格式,只好打开搜索引擎一顿复习。我正在寻找一种更高效的复习方式。 + +我现在的网站风格发布大量的技术文章有点突兀。 + +于是,搭建一个专门用于整理技术的网站的想法浮现在我的脑海中。 + +思想挣扎了一段时间,我考虑了一下他的意义: + +1.如果我再搭建一个网站,那我现在这个站点还有什么意义? + + 如果不新建一个站点,那就只能把网站整个改版,换主题、改名到适合的风格,浪费时间。 + + 2.新建站点有什么实现方法? + +# 实现方法 + +我一下子想到了几种方法。 + +1. 再购买服务器和域名,还是使用typecho或者WordPress搭建一个网站。 +2. 更换typecho主题 +3. 把hexo部署到Github Page上。 +4. 使用Gemeek +5. 自己编写静态站 + +先说结果,由于第一种方法的资金成本和时间成本过高了,直接pass不用考虑。 + +方法二,现在使用的handsome主题还是深得我心的,自定义程度可以很高,而且花了老夫八十八大洋,不用也亏了。再者typecho的主题,我喜欢的并不多 + +方法四是我曾经尝试过的,但因为页面有点单调,所以换到了typecho。 + +但是我这次的需求仅仅是整理知识点,太花哨也会搭建速度和复习效率的。所以hexo大概也要pass掉。 + +方法五,不太现实,我的前端知识远没有那么牢固,我自己也写过几个网页,pc端很完美,可到了手机端排版很丑,还是要在学习沉淀一段时间啊。 + +最后剩下来的方案有: + +3. 把hexo部署到Github Page上 + +4. 使用Gmeek + + + +gmeek原版的布局我不是很喜欢,但这个方案是零成本很快捷的。可以尝试自己修改css文件来达到想要的效果。 + +虽然我自己写网页效果一般般,但是增删改查还行,于是我开始尝试: + + + +我有两个github账号,一个是本站下方挂的大号,另一个是昨天晚上刚创建的小号。 + +大号的page我部署了一个我自己写的个人主页,但是现在来看并没有什么用处,所以我把那个仓库删除了。 + +重新创建了一个仓库,部署好了gmeek,我把里面所有的文件都下载了下来。、 + +看到了几百行压根没有注释的代码,头瞬间炸了,于是修改gmeek的方案也pass + +。。。。。 + +好吧,看来只能用hexo了 + +# 搭建记录 + + +## 部署hexo +1. 安装git和nodejs + + git我已经安装好了 + +去nodejs官网([Node.js — Run JavaScript Everywhere](https://nodejs.org/en/))安装了一下。 + +这两样都准备好了就可以开始安装hexo了 + +```shell +npm install -g hexo-cli +``` + +然后在控制台输入 + +```shell +hexo init myBlog +cd myBlog +npm install +``` + +然后我们就可以运行```hexo s```命令,访问控制台中的网站就可以预览了 + + + +可以看到hexo的默认模板还是很简约大气的。 + + + +部署好后,我打算换一个主题,因为这不是主站,所以也就没必要那么花哨(有一说一hexo那么多主题还真有几个让老夫心动的) + + + +## 更换主题 + +把主题文件夹复制到安装目录下的/themes文件夹内 + +复制好文件名,打开_config.yml + +找到第一百行,把文件名替换 + +修改好后在gitbash中执行```hexo g``` ```hexo s``` + +## 部署github + +- 新建名为```你的用户名.github.io```的新仓库 + +- 配置SSH key,用git工具首先配置,为部署本地博客到github'做准备 + + ```shell + git config --global user.name "你的用户名" + git config --global user.email "邮箱地址" + ssh-key - t rsa -c '上面填写的邮箱地址' + ``` + + **一定要手敲!** + + **一定要手敲!!** + + **一定要手敲!!!** + + 输入这行指令可以查看你的SSH + + ```cat ~/.ssh/id_rsa.pub``` + + 首次使用要确认并添加主机到本机SSH可信列表,若返回啥啥啥successfully什么就代表添加成功了 + + 输入以下代码 + + ```ssh -T git@github.com``` + + 如果出现```ssh: connect to host github.com port 22: Connection refused``` 把你的加速器关了。 + +- 登录github上添加刚刚生成的SSH key + + 步骤:右上角头像>settings>SSH and GPG keys>New一个SSH出来,标题随便写,key把刚刚生成的复制过来,建立。这样在SSH keys列表中就能看到刚刚添加的秘钥。 + + +本地和github的活基本上干完了,该把他俩链接起来了 + +## 链接本地与github + +1. 打开博客根目录下的_config.yml + +2. 拉到末尾。按照下面的例子修改 + + ```yaml + deploy: + type: git + repo: https://github.com/yingyu5658/yingyu5658.github.io.git + branch: master + ``` + +3. 还要安装一个部署插件 hexo-deployer-git + + 打开git bash 输入以下指令 + + ``` npm install hexo-deployer-git --save``` + +4. 最后执行下面两条指令就可以部署上传了如下g是generate的缩写,d是deploy的缩写 + + ```shell + hexo d + hexo g + ``` + + +经历了千辛万苦,终于折腾完了,下一步就是写文章并发布了!!! + +## 撰写并发布文章 + +```hexo new '文章标题'``` + +他会在\source\_posts创建一个markdown文件(.md) + +打开目录写完后保存,然后打开gitbash + +```hexo g``` + +```hexo s``` + +# 后记 + +还是typecho舒服,用hexo写篇文章发篇文章那个费劲呀,前前后后敲了几百万行命令,效率太低了。。。。而且部署在github pages上的页面如果不挂url链接,那个图片压根就加载不出来。。。要不是这玩意不花钱我才不用。。。。。。。 + +> 2025.8.24二编: 静态真好用...... diff --git a/content/posts/记录Typecho博客转移到Hexo.md b/content/posts/记录Typecho博客转移到Hexo.md new file mode 100644 index 0000000..88a2433 --- /dev/null +++ b/content/posts/记录Typecho博客转移到Hexo.md @@ -0,0 +1,64 @@ +--- +abbrlink: 64728457 +categories: +- 往昔 +cid: 4 +date: "2025-03-03T15:40:00+08:00" +layout: post +slug: 4 +status: publish +tags: +- 博客 +title: 记录Typecho博客转移到Hexo +--- + + +# 前言 +折腾来折腾去,最后发现归宿还是静态博客,安全性高、性能开销小,用Github直接省去服务器费用还差不多永生。每年把域名钱交了就得了,图片的问题再想想办法,总能解决的。 +~~突然有一种为了躲避战乱带着一家人四处奔波的悲凉感~~ + +# 分析 +博客网站的内容,都可以拆分为以下几个点: +- 文章 +- 评论 +- 文章插图 +- 网站贴图资源 + +先从最主要的文章开始,想想有没有什么可以用的。 +gitee上有一个[插件](https://gitcode.com/gh_mirrors/ty/Typecho-Plugin-Tp2MD),看起来好像有点用,折腾安装一下试试先。 +# Tp2MD插件迁移文章 + 远程登录服务器,把本地下号的zip传到服务器上并解压。 + cd到插件目录 + `/usr/share/nginx/html/usr/plugins` + + 解压压缩包 + `unzip Typecho-Plugin-Tp2MD-master.zip` + + 重命名为插件的自述文件要求的名称 + `mv Typecho-Plugin-Tp2MD-master Tp2MD` + +登录网站后台,启用插件。点击插件的设置,保存后按照教程访问。 +这里提示`不能写入文件,请检查 cache 文件夹权限!`,我们在插件目录设置一下权限 + `sudo chmod -R 777 cache`a +注意是这个插件目录下的cache!! + +提示导出成功,cd到这个目录,把文件压缩下载下来查看 +可能是因为我有的文章点了多篇分类,导出文件夹有点问题,无所谓,后期再调,拿到了就行。至此,文章部分搞定! + +# 评论 + +评论这里,我折腾了两天,尝试尽了各种方案(Disqus Valine Waline Utterances Twikoo Atalk),最后还是选择了Giscus。我也知道这样读者没有github就没办法发评论,但是其他几种方案都会出现各种奇奇怪怪且无法解决的问题比如Cloudflare拦截、CORS出毛病、服务器被墙以及莫名其妙404、403。我真的尽力了。 +# 文章插图 +## 转移图片文件 +进入`/usr/uploads/`,压缩下载图片 + +重组Hexo图片目录:复制所有图片到Hexo的`source/images/`目录。 + +手动替换图片路径 ,注意,静态资源解析默认以source为根目录,所以直接写以source为根目录的绝对路径就行。 + +# 部署到vercel加速访问 +1. 注册vercel账号 +2. 创建项目,关联仓库 +3. 域名解析 + +2025.3.3,博客全部迁移完毕,粗略累计用时六天,一直没什么时间搞,耗时最长的还是在评论系统上的试错。 diff --git a/content/posts/记录配置SSL证书.md b/content/posts/记录配置SSL证书.md new file mode 100644 index 0000000..e75970d --- /dev/null +++ b/content/posts/记录配置SSL证书.md @@ -0,0 +1,123 @@ +--- +CopyRight: true +NoCover: true +ShowReward: false +ShowToc: show +abbrlink: 1636322595 +author: yingyu5658 +categories: +- 往昔 +cid: 163 +date: "2024-12-17 11:46:07" +desc: null +keywords: null +layout: post +showTimeWarning: true +slug: 163 +status: publish +summaryContent: null +tags: +- 服务器 +thumb: null +title: 记录配置SSL证书 +updated: 2024/12/17 11:46:07 +--- +首先你要有一个SSL证书,建议在阿里云购买或者[免费申请](https://developer.aliyun.com/article/1595201),具体过程阿里云这个页面讲的很详细,在此不过多赘述。 +# 配置证书 +由于我的nginx安装了ssl模块,直接进入配置证书。 + +解压下载好的证书,然后上传到服务器。位置自己方便找到即可 +我放到了root/card + +# 配置nginx.conf +进入nginx.conf,我的文件位置在``/etc/nginx/nginx.conf``,有些可能在``/usr/local/nginx/conf`` +编辑模式,启动! +``` + + + +http { + + include mime.types; # 包含 MIME 类型定义 + + default_type application/octet-stream; + + sendfile on; + + keepalive_timeout 65; + + + + # HTTPS server block + + server { + + # 监听443端口(HTTPS) + + listen 443 ssl; + + + + # 【请修改】您的域名 + + server_name xxx; + + + + # 启用 SSL (注意: "ssl on;" 已被弃用,直接使用 "listen ... ssl;") + + ssl on; + + + + # 【请修改】SSL 证书的 PEM 文件路径 + + ssl_certificate /root/card/www.xxxx.pem; + + + + # 【请修改】SSL 证书的 KEY 文件路径 + + ssl_certificate_key /root/card/www.xxxx.key; + + + + location / { + + # 【请修改】代理转发的目标地址和端口(例如公网IP和项目端口号) + + proxy_pass http://公网地址:项目端口号; + + } + + } + + + + # HTTP server block for redirecting to HTTPS + + server { + + # 监听80端口(HTTP) + + listen 80; + + + + # 【请修改】您的域名 + + server_name huiblog.top; + + + + # 将所有 HTTP 请求永久重定向到 HTTPS + + rewrite ^(.*)$ https://$host$1 permanent; + + } + +} + +``` +# 重新加载Nginx +``sudo systemctl reload nginx`` diff --git a/content/posts/超市见闻.md b/content/posts/超市见闻.md new file mode 100644 index 0000000..f867220 --- /dev/null +++ b/content/posts/超市见闻.md @@ -0,0 +1,18 @@ +--- +abbrlink: 4031192575 +categories: +- 往昔 +date: "2025-06-20 20:24:57" +tags: +- 观察 +- 未成年人保护 +- 酒 +title: 超市见闻 +--- +今天中考布置考场,只上半天课。下周一就是地生会考了,看完考场回来,已经接近一点,早点没吃,去便利店买点面包垫肚子,看到了两个其他学校的学生一人拿着一瓶酒,在台前结账。 + +一开始我并不确定那是不是酒,但当机器冰冷的女声提示工作人员确认顾客是否成年,禁止向未成年人出售烟酒,再加之她们两个鬼鬼祟祟的表情,可以断定就是酒了。那两个人面容有些憔悴,脸上圈着黑眼圈,快三十度的天,依然穿着校服外套,敞开怀,驼着背。看起来跟我同龄。其中一个人尽力用只能让对方听到的声音说出:“吓死我了。”很显然,她失败了。但买酒成功了,别的失败对她讲都不重要了。事发时,我就在她们身后排队结账,这一切都被我完整地看在眼里。 + +结账的小哥麻木地接过瓶子扫码,提醒付款,他好像已经习以为常了。《未成年人保护法》、《酒类流通管理办法》都明确规定禁止向未成年人出售烟酒,所谓上有政策,下有对策。这对策妙,无视法律和政策。 + +我个人对烟酒一直没什么好印象,抽烟的学生都是不良;喝酒的大人耍酒疯很麻烦,不耍也很烦人;旁边有人抽烟难免被二手烟呛到,完全无法呼吸。消遣排解的方式有很多,偏偏选择伤害自己身心又对别人无益的那一个。 diff --git a/content/posts/这可能是最好的Hexo图片管理方案.md b/content/posts/这可能是最好的Hexo图片管理方案.md new file mode 100644 index 0000000..1ea52a0 --- /dev/null +++ b/content/posts/这可能是最好的Hexo图片管理方案.md @@ -0,0 +1,76 @@ +--- +abbrlink: 1950788762 +categories: +- 往昔 +date: "2025-06-29 10:52:05" +tags: +- Hexo +title: 这可能是最好的Hexo图片管理方案 +--- + +## 前言 +通常在Hexo博客中,我们管理图片资源都有以下两种方案: + +1. 在`_post`目录下新建文章同名文件夹 +2. 在`source`目录下新建images文件夹,存放所有图片 + +两种方法各有优劣,前者方便查找但污染目录,后者集中管理但维护成本高。所以就诞生出本文要介绍的方法——`images`目录下新建文章同名目录 + +这是一个折中的办法,既保留方法1的查找方便,又保留方法2的集中性。 + +## 实现方法 + +**创建脚本文件** + +在Hexo根目录的`scripts`文件夹(若不存在则新建)下创建一个javascript脚本,我这里就命名为`auto-image-folder.js` + +```js +const fs = require("fs") +const path = require("path") + +hexo.on("new", function(data) { + const postName = path.basename(data.path, ".md") + const imageDir = path.join(hexo.source_dir, "images", postName) + + if(!fs.existsSync(imageDir)){ + fs.mkdirSync(imageDir, {recusive: true}) + } +}) +``` + +**效果测试** +```bash +hexo new "新文章" +``` + +这时候就在images目录下新建了一个与文章同名的文件夹。 + + +## 编辑器设置优化 + +### Typora + +打开Typora → 偏好设置 → 图像 + +设置: + + - 插入图片时:复制到指定路径 + + - 自定义路径:../source/images/${filename}/ + + - 勾选:优先使用相对路径 + +``` +PS E:\blog> ls .\source\images\测试\ + + + 目录: E:\blog\source\images\测试 + + +Mode LastWriteTime Length Name +---- ------------- ------ ---- +-a---- 2025/6/29 11:14 229 image-20250629111411456.png +``` + +完成! + diff --git a/content/posts/逛逛西西弗,买两本书.md b/content/posts/逛逛西西弗,买两本书.md new file mode 100644 index 0000000..a07d667 --- /dev/null +++ b/content/posts/逛逛西西弗,买两本书.md @@ -0,0 +1,39 @@ +--- +date: 2025-10-04T11:16:21+08:00 +draft: false +title: 逛逛西西弗,买两本书 +slug: book-shopping-sisyphu +categories: + - 随笔 +tags: + - 日常 + - 购物 + - 西西弗 +--- +昨天去了海信广场 B1 层的西西弗。 + +进门左手边有一些钥匙扣之类的小礼品,也有儿童玩具之类,感觉带小孩子来要很麻烦。 + +<!--more--> + + +店里居然有卖漫画。说实话,我是第一次见到现在的实体漫画书,没怎么了解过,比想象中的小。大概跟一页文库出的一些文库本大小差不多,很便携。 + + + + + + +这本《药屋少女的呢喃》,应该出过动画了,去年有一个朋友强力推荐我看。 + +本来是奔着三岛由纪夫的《太阳与铁》去的,但没货了,拿了一本《假面的告白》。结帐的时候柜台小姐姐建议我办会员,但由于不经常去,就拒绝了。她问我要不要买三岛的其他书,就拿了《爱的饥渴》。 + +唉,本来只想买《太阳与铁》的,正当我庆幸没有被忽悠着办会员的时候,才发现又多花了五十多冤枉钱! + + + +在商场逛了一圈,想着刚才去书店只是匆匆地看了一眼三岛的书,又转回 B1 层,仔细看了看,在一个角落发现了《瓦尔登湖》,在刚刚拿《假面的告白》的地方又找到了卡夫卡的《变形记》。 + +共消费127元。唉,最期待的还是《瓦尔登湖》,希望自己能看完吧。 + +
\ No newline at end of file diff --git a/content/posts/那种虚伪的互动和友善,赶快把它撕破吧!.md b/content/posts/那种虚伪的互动和友善,赶快把它撕破吧!.md new file mode 100644 index 0000000..86917cd --- /dev/null +++ b/content/posts/那种虚伪的互动和友善,赶快把它撕破吧!.md @@ -0,0 +1,101 @@ +--- +date: '2025-12-04T16:15:36+08:00' +draft: false +title: '那种虚伪的互动和友善,赶快把它撕破吧!' +slug: 'tear-hypocrisy-apart' +categories: + - 随笔 +tags: + - 社交 + - 博客 + - 评论区 + - Waline +description: "我厌倦了廉价的温情。" +--- +> **本文使用了一些带有攻击性的词汇,言论风格尖锐,介意者谨慎阅读。** + +本来想随便写写近期的事,写到网站最近的变化,写到了评论区的问题,越写越多,单独开一篇文章来说说吧。有时候觉得自己像个愤青一样,或者就是个愤青,整天喷天怼地的,应该平和点,不过实在不吐不快。 + +--- + +## 给评论区做减法 + +最近我把评论系统换成了Giscus,原因很简单:我累了。 + +关于评论系统,我想了很长时间。 + +至少是在我的博客里,如果是议论类文章,基于事实或观点的讨论、延伸,或反驳。偏题跑题、没看完或没看懂文章就急于发表评论的情况并不少见。而且性子比较急的朋友直接看到了评论区,自己的重点也可能会被带跑偏,于是构成恶性循环…… + +如果是记录类,分享见闻的文章,评论除了附和、赞同之类的评论,也难以找其它类型的评论,而且似乎也不会出现其他类型的评论。 + +我不是要说教读者该如何写评论,其实是我并不擅长回应这种评论,或者可以说,我没有跟人闲唠嗑说家常和寒暄的能力。一些评论留下的话茬实在让人很难接上,但不回复又显得冷漠,这是一直以来让我困扰的问题。和社交沾边的事,不是热脸贴冷屁股,就是痛并快乐着,又在期待与不安中挣扎。 + +七八月的时候我特意在评论区上方注了一行小字,具体原文不记得了,但我记得大意是:「**我没回复是因为赞同,或者没什么可说的,而不是因为对你有意见**」。主题改来改去,换来换去,就忘了重新写上这行字了。这是为我不回复这一行为的辩解,也是为读者可能会受到的「冷落」所做的提前安慰。 + +另一方面,维护Waline的外部CSS很麻烦,我也不想再修改CSS了。 + +我在使用Waline的时候尝试给评论功能做减法,我移除了表情回复和正文插入表情的功能、移除了表情包,删除了点赞、头衔,隐藏了头像和IP。力求打造安静的浏览和讨论氛围,甚至有移除网址文本框的想法。出于对博客的理念不同,有些同样在写博客的人就是冲着这个框来的,他们可能就是非常享受与人社交的获得感,把博客作为社交名片。 + +我觉得移除网址框可以减少为了自我营销而发送的评论,因为自己的博客沦为别人的推广场所的滋味很难受,也实在不知道怎么对待这些评论最为恰当。也想过关闭评论区。如果关闭评论区,可能会显得高冷,甚至是封闭。 + +## 折中的方案 + +转念一想,我怕的是什么?怕的是不知道如何接话。那么提高评论的「门槛」,让真正想要讨论的人评论,也许能解决问题。所以我换成了从前被我鄙视的Giscus。我当时觉得一定需要Github帐号才能评论是在一定程度上打消读者互动的积极性的,但现在才意识到了这是在**放过自己**。说真的,我非常佩服那些能一直和人聊得来,接得上话的人,也很佩服从一篇干巴巴的日常分享,甚至只有几张图的文章里找出可以评论的点的人,这确实是一种社交能力。 + +为了照顾没有Github或访问不方便的读者,我也放了一个邮件链接,可以点击发送邮件评论。由于使用场景,它多少会和「正式性」沾边,这也就间接提高了交流的质量。虽然我的博客并没有什么流量,但**有效的交流,总比虚伪的敷衍强**。我知道那些评论可能出于友善,但是妥善处理它们对我真的很难。 + +简单地来说,让说话更麻烦,是一种让说出来的话更有分量的方式。它会让说话的人经过深思熟虑,认真想想这些话到底值不值得我费这么大劲去说。 + +## 为什么我认为新的做法更好 + +可能有人要批判我是「精英主义」,把Email和Giscus强行和高质量讨论绑定在一起,或者认为我说以前的讨论都是低质量,我要为自己辩解。 + +首先,不是会用Github和Email的人都能写高质量的评论,而是这个方法在「倒逼」出正经的评论。 + +Github和技术身份强关联,它代表作为开源社区的一员的你,对某篇文章的看法。如果说得更「敏感」点,为了维护网络上的形象,至少不应该写出冒犯性的话语或无理取闹的反驳。而邮件在其它场合下的使用就如上文所说,是带有一定正式性的,并且写邮件的「仪式感」也很容易让人认真对待这件事。至少需要安安静静坐下来,组织完整的语言表达看法,留有正式的署名和日期,长期可以留存 —— 这些都在间接促成一个或严谨或私密的正式的讨论环境。 + +虽然这种做法可能会拦住内向但真诚或没有技术背景的读者,但也能拦住自我营销与应付不来的闲谈,我没有排斥喜爱轻松交流氛围的读者,这是不得已的取舍。而且博客不是论文期刊和政府文件,不是公示真理和规范的地方,这里是自我表达的地方,我在尽力打造理想中的秩序和风格。 + +此方法也能防止某些幽默的匿名评论。虽然当年百度贴吧和知乎都有很多匿名神贴,匿名才能让他们大胆表达,但总有这么一小波的大胆,给人一种傲慢和轻视的感觉。 + +## 林子不大也有各种鸟 + +比如说[《罪恶感》](https://www.glowisle.me/posts/guilt/)这篇文章写得确实非常矫情,但有人匿名评论: + +> 额…实际上**只要**是病,**都**能够通过医学手段解决的,**有钱人**一般**都**能请私人家教授课,可能这就是**青春期**吧… + +这位网友的评论在不在理,确实是在理的。但连留个邮箱的勇气都没有,匿名在**个人**博客唱反调的行为,高高在上地想轻易解决慢性病,并把情绪都归结给青春期的傲慢的行为,属实让人忍俊不禁。 + +虽然文章发出来了肯定会有被人喷的风险,但我当时还是忍着自己的痛苦和不安,让人轻飘飘地说得一文不值的愤怒,给出了一个回复: + +>1. 文本解读能力的问题 +> +>2. 经历和共情能力的问题 +> +>我尊重你这个没啥大事的看法,不强求共鸣。 +> +>说得好,我同意了,玩去吧。 + +现在再仔细想想,这种文章根本不可能有人从搜索引擎来,大概率是某个混博客圈子的人,大概率也写博客。英国女作家伊夫林·比阿特丽斯·霍尔说过:「虽然我不同意你的观点,但我誓死捍卫你说话的权利。」 + +我今天说,虽然我不同意你的观点,但你唱反调连告诉我你是谁的胆子都没有,**那你他妈的还是闭嘴吧!** + +如果你反对我,那就请你逻辑严密地写出几百字来批判我,即使是匿名我也会输得心服口服,在这种情况里匿名甚至可以促进大胆批判。而傲慢地写下反驳的话语却不敢署名的敢做不敢当的行为,我只能认为你是一个弱者,仗着个人博客对读者隐私的保护与自由的追求,输出轻浮的观点。 + +当然,匿名评论不是一定没有优势,如上文所说可以促进大胆批评,但任何事情都能从不同角度思考出不同的结果,没有人能做到真正的公平和客观,我只是尽力在维护边界。 + +在非匿名的评论中,有些人挂着自己的网站链接,写一句「学习了!」、「写得好!」,甚至连编程语言是哪个都没看清,指鹿为马地夸赞着,长期在各个博客的评论区混迹着。 + +出于人情的默契,这类行为往往被默许。我相信这是中文博客圈的大家都看破不说破的问题。今天我就在这里,以一个和大多数博主比起来确实是小孩的年龄,指出皇帝完全就是光着屁股在大街上乱逛。 + +我并不反对匿名评论和评论区,而是反对形式化的评论区,反对只是为了自己网站的外链的评论,**反对形式化的、缺乏真诚的互动,而非反对社交本身**。评论区应当是能围绕文章展开讨论、甚至是反驳的地方,哪怕意见相左,只要是真诚的表达,任何博主都会愿意真诚回应。但当评论的形式大于其本身的作用时,就该好好思考一下它究竟有没有继续存在下去的意义,以及如何存在下去了。 + +这种你唱我喝,看似牢固的关系,我在其它地方也有感受。 + +大概在十月份,我退掉了很多在上一次[信息节食](https://www.glowisle.me/posts/%E4%BF%A1%E6%81%AF%E8%8A%82%E9%A3%9F/)行动时没有退掉的QQ群。虽然确实有几位群友在问我为什么退群了,但过了一段时间后,仅仅是少了一个人自言自语。该打游戏的还在打游戏,该上班的还在上班,该骂街的还在骂街。这很正常,但也很残酷,少了某个人,大家照样吃饭,中东那几个国家照样战乱不断,地球照样天天转。 + +这种浅层的链接,只是披着一层友情之皮的无关紧要的感情。当然,这都是我的一家之言,你也可以认为我在社交上相当失败。 + +我能理解那种单纯对文章表达欣赏,又期待被回访的复杂心理。我个人的做法是开启一个点赞按钮。如果赞同或欣赏文章,也许不发那些简单但带有善意的评论,按一下那个按钮也能表达认同的态度。关于期待回访的心情,如果不是真正读了你的文字,被你的灵魂打动,那种回访就是肤浅且客套的,也许回访者也是出于迫不得已的礼仪压力。 + +所以无论是Q群聊天还是博客**为了外链**的「互访」,为了自己和他人考虑,为了让自己不再苦恼于如何应对根本没有留下话茬的评论,为了让别人不再绞尽脑汁填写自己博客的链接,如果你也厌倦了廉价的温情,那就来吧,**那种虚伪的互动和友善,赶快把它撕破吧!** diff --git a/content/posts/阴云.md b/content/posts/阴云.md new file mode 100644 index 0000000..4cc465a --- /dev/null +++ b/content/posts/阴云.md @@ -0,0 +1,28 @@ +--- +categories: +- 往昔 +date: "2025-08-20T17:33:10+08:00" +draft: false +slug: overcast +tags: +- 旁观者 +title: 阴云 +--- + +八月变化无常的天气又使大地被一层阴霾笼罩,昨夜刚下了一场暴雨,空气弥漫着潮湿的腥臭。公交车站边有一个老妇领着一个四五岁的小女孩,她背着一个小书包。那老妇是她的奶奶。 + +小女孩生性活泼好动,总是说个不停,跑个不停。她的书包上挂着一个金色吊坠,随着她的脚步一颠一颠的,即使在阴云下也能映出金光。她满怀好奇心地对这个世界角落的细节发问,燃起求知的欲火,被奶奶敷衍的回应无情浇灭,我看到一缕黑烟从那小女孩头上飘走了。 + +我和她们在等的是同一路车。那两人坐在靠前的座位上,我正前方是一对母子,那人背着一个大包,不能直直坐在狭窄的座位里,只好斜靠在母亲的肩头。可能是出于疲惫,不久就睡去了。站在车门口的一群中年大妈七嘴八舌地谈论着好像是邻居的人物。 + +过了一站,又一个老妇领着一个小男孩上车了,二人坐在我旁边的一列座位上。那小男孩约莫七八岁,上身穿着印有队名的足球队服,下身穿着短裤和长筒球袜,没有穿球鞋,是一双运动鞋。他身上流露着这一带的足球小子特有的野气。 + +他一坐下来就吵嚷不停,不停地在座位上扭动。结结巴巴地,用跌宕起伏得如驼峰一样的语调,和家长无礼地争论以前到底有没有来过这里,卖弄着自己的个性。声音大到全车人都听得清清楚楚。 + +「你自己看...不不就...知..知道了吗!」 + +「你看吧,我就...就说...来...来过呢!」 + +他们两个人坐的座位,上一任主人是一对情侣,腻腻歪歪了几站就下车了。前面那人把脸深深埋进他母亲的怀中。我望着窗外,看着阴云下飞奔而过的楼房。车走走停停,人进进出出。下一站,就到目的地了吧,我想。 + +我独自一人下了车,回头一望,那书包上吊坠反射的金光已模糊在迷乱的车流中了。 diff --git a/content/posts/隐居.md b/content/posts/隐居.md new file mode 100644 index 0000000..762b25d --- /dev/null +++ b/content/posts/隐居.md @@ -0,0 +1,21 @@ +--- +abbrlink: 1767559137 +categories: +- 往昔 +date: "2025-04-26 18:42:46" +description: 超前,还是孤僻? +tags: [] +title: 隐居 +--- + +此隐居非彼隐居。残酷的是,人是社会性动物,脱离了社会根本没法生存。既然无法与现实的是是非非一刀两断,那就至少让自己在网络世界耳根清净点。 + +自从前几个月退坑音游后,基本就与游戏没了什么交际。周末空闲时间就听听歌,写写代码,画点画。五一假期也要开始认真练琴了。这么说来还颇有几分文气,琴棋书画几样都有沾点。远离音游圈子后,我的群也退得差不多,为数不多留下来的几个群都是最早进的,或者花了很大劲才进去的,虽然人还在群里,但是已经几乎和群友没什么共同话题了。那几个群里只有痴迷于段位的人们在争论某张图是g+还是d-,毫无意义。在视频平台曾经投稿的音游视频也都设置成了私密,之所以没有删掉有两点原因,一个是全删硬币大出血,另一个则是留个念想,好歹也陪伴了这么长时间,通过这类游戏交到了很多好朋友。 + +与几乎所有人都保持着浅度的社交,非必要不再主动参与哪些圈子的活动。最极端的时候我的QQ只剩五个群,好友只有十几个,账号设置为不可搜索。现在回想起来那段时候是真清净自在。越来越趋近于隐居的状态,极力削弱自己在网络上的存在感。如果有人想接近或了解我,应该没什么途径,为数不多发表言论的地方只有博客和朋友之间的小群。化被动接受为主动寻找应该能免去不少怪人,毕竟主动寻找的在少数,林子大了什么鸟都有。 + +自在,自在。 + +多年之后的我再读起这些文字会有什么感想?是会感叹自己的超前还是悲哀自己的孤僻呢。 + +文字这种古老的载体对于新现的图片、视频来说,最大的优势就是能很好地把心情亦或是观点表达出来。这也是我认为以记录为目的,Blog优于Plog和Vlog的原因。 diff --git a/content/posts/面向对象编程与面向过程编程的本质区别.md b/content/posts/面向对象编程与面向过程编程的本质区别.md new file mode 100644 index 0000000..ba09188 --- /dev/null +++ b/content/posts/面向对象编程与面向过程编程的本质区别.md @@ -0,0 +1,28 @@ +--- +abbrlink: 1518948190 +categories: +- 往昔 +date: "2025-05-29 21:21:36" +tags: +- 编程 +title: 面向对象与面向过程的本质区别 +--- +面向对象与面向过程这两种编程思想主要体现在一件事上:面向对象关心**谁来做**,而面向过程关心**做什么**。 + +举个例子,如果我现在要开发一个五子棋小游戏,在面向对象的思想中,实现步骤应该是这样的。 +- 有一个窗口对象,可以让我的游戏内容展示在里面 +- 创建棋盘对象 +- 初始化棋盘 +- 创建计分板对象 +- 初始化计分板 +- 玩家开始下棋,棋盘对象创建棋子对象,绘制出来 + +不难看出,面向对象就是在关心**谁来做**,先关心哪个对象去做,再去研究这个对象要去**怎么做**。抽象层级更高,但是符合人类的思维。从代码结构上来看,写面向对象更偏向在画一个树状图,一级一级划分谁要做什么事情,而面向过程更像一个线性的流程图,全程都在关心需要做什么事情。 + +更官方地说,面向对象以算法和流程为核心,强调步骤拆解。而面向对象以与对象交互为核心,强调责任分配 + +当然,写法在语言上就有所限定。C更适合面向过程,头文件的引用使用函数做事就意味着C很难实现面向对象的设计模式,当然有一些比较邪门的技巧,容易开枪把自己脚指头崩掉,比如`void*`模拟泛型这种不在本文讨论范围。 + +C缺乏类、继承等基础语法支持,但可以用结构体加函数指针简单模拟对象,但设计难度有所增加,调试难度更有所增加。面向过程更适合处理逻辑简单的任务或算法密集型任务,而面向对象更适合构建GUI应用等复杂系统。 + +面向对象并非在所有情况下都是最优选择。还是需要依据开发项目的实际需求考量。 diff --git a/content/posts/面向对象编程总结.md b/content/posts/面向对象编程总结.md new file mode 100644 index 0000000..2fb96e6 --- /dev/null +++ b/content/posts/面向对象编程总结.md @@ -0,0 +1,83 @@ +--- +CopyRight: true +NoCover: true +ShowReward: false +ShowToc: show +abbrlink: 1385380729 +author: yingyu5658 +categories: +- 往昔 +cid: 166 +cover: images\2024\12\2743265221.jpg +date: "2024-12-18 16:30:00" +desc: null +keywords: 面向对象编程 +layout: post +showTimeWarning: true +slug: 166 +status: publish +summaryContent: null +tags: +- Java +- 笔记 +thumb: null +title: 面向对象编程总结 +updated: 2024/12/18 16:37:09 +--- + + +面向对象(oop) +## 面向对象编程的思想:面向。拿或者找。 +对象:东西 + 面向对象编程:拿东西过来编程 + 面向对象:把现实世界中的食物看成一个一个对象来解决问题的。(万物皆 对象) +面向对象的好处:代码更符合人类的思维习惯。编程更简单。看程序更容易理解(?) +## 类、对象: +类(设计图):相同事物,共同特征的描述。 +对象:对象是类的具体的实例。 + 对象 = 实例 + 在Java中必须先定义类,才能得到对象 +## 定义类来创建对象使用 + +### 定义类的格式 +1. 成员变量(代表属性,一般是名词):数据类型 名称; +2. 成员方法(代表行为,一般是动词) +3. 构造器(前面的区域以后再来探索吧) +4. 代码块(前面的区域以后再来探索吧) +5. 内部类(前面的区域以后再来探索吧) +### 类中具体怎么写: + 一般名词定义成成员变量(属性) +``修饰符 数据类型 变量名称 = 初始值`` + 成员变量不建议给初始值,它存在默认值。 +### 一般动词定义成方法(行为) +#### 创建对象 +``类名 对象名 = new 构造器();`` +### 对象使用: +``对象名.成员变量`` +``对象名.成员方法`` +## 构造器 + 作用: + 初始化一个累的对象并且返回这个类的地址。 + 详细格式:修饰符 类名(形参){...} + 构造器的分类: + 无参数构造器:初始化一个类的对象,里面的数据都是默认值,并返回地址。 + 有参数构造器:初始化一个类的对象,并返回地址,并且可以同时为对象赋值。 + 构造器如何调用: + 类名 对象 = new 构造器; + 注意:任何类写出来,自带无参数构造器 + 但是在这个类中定义了一个有参数构造器了,那么无参数构造器就消失了,此时如果还要使用无参数构造器,必须自己写一个。 +## this关键字 +作用:代表了当前对象的地址。可以访问当前对象的成员变量信息和成员方法 +### 具体应用场景 +可以用在有参数构造器中 +可以用在方法中 +## 封装 +面向对象三大特征:封装、继承、多态。 +封装的基本思想:决定属性和行为归属谁的问题。 +## 如何更好的封装: +成员变量私有化,只能在本类访问。 +#### 合理暴露 + 提供成套的getter和setter方法暴露取值赋值。 +## 标准JavaBean +JavaBean是什么:是实体类。 +作用:创建对象,封装数据。 diff --git a/content/posts/韩愈《师说》.md b/content/posts/韩愈《师说》.md new file mode 100644 index 0000000..c956219 --- /dev/null +++ b/content/posts/韩愈《师说》.md @@ -0,0 +1,31 @@ +--- +date: 2025-10-08T20:32:04+08:00 +draft: false +title: 韩愈《师说》 +slug: "" +categories: + - 往昔 +tags: + - 古文 + - 韩愈 +--- +在视频[【“你这是学生思维”】 ](https://www.bilibili.com/video/BV1bQWPzqEwx/?share_source=copy_web&vd_source=237678275b58b6262a1c529cd96bdc59)中,有一个评论引用了《师说》中的一句话:「是故无贵无贱,无长无少,道之所存,师之所存也。」记一篇原文及翻译。用白话翻译出来就很浅显,甚至是老生常谈的大道理,可能这就是文言文的距离之美和留白之美吧。 + +<!--more--> + +> 古之学者必有师。师者,所以传道受业解惑也。人非生而知之者,孰能无惑?惑而不从师,其为惑也,终不解矣。生乎吾前,其闻道也固先乎吾,吾从而师之;生乎吾后,其闻道也亦先乎吾,吾从而师之。**吾师道也,夫庸知其年之先后生于吾乎?是故无贵无贱,无长无少,道之所存,师之所存也。** + +古代求学的人必定有老师。老师,是靠他来传授道理、教授学业、解答问题的。人不是一生下来就懂得知识的,谁能没有疑惑?有了疑惑而不跟从老师学习,那些成为疑难的问题,就始终不能解开。出生在我之前的人,他知道道理本来比我早,我跟从他学习,把他当作老师;出生在我之后的人,如果他得知道理也比我早,我也跟从他学习,把他当作老师。**我是学习道理的,哪关心他的年龄比我大还比我小呢?因此无论地位高低,年龄大小,道理存在的地方,就是老师存在的地方。** + + +> 嗟乎!师道之不传也久矣!欲人之无惑也难矣!古之圣人,其出人也远矣,犹且从师而问焉;今之众人,其下圣人也亦远矣,而耻学于师。是故圣益圣,愚益愚。圣人之所以为圣,愚人之所以为愚,其皆出于此乎?爱其子,择师而教之;于其身也,则耻师焉,惑矣。彼童子之师,授之书而习其句读者,非吾所谓传其道解其惑者也。句读之不知,惑之不解,或师焉,或不焉,小学而大遗,吾未见其明也。巫医乐师百工之人,不耻相师。士大夫之族,曰师曰弟子云者,则群聚而笑之。问之,则曰:“彼与彼年相若也,道相似也,位卑则足羞,官盛则近谀。”呜呼!师道之不复,可知矣。巫医乐师百工之人,君子不齿,今其智乃反不能及,其可怪也欤! + +唉!古代从师学习的风尚不流传已经很久了!想要人没有疑惑也难了!古代的圣人,他们超出一般人很远,尚且要跟从老师请教了;现在的一般人。他们的才智低于圣人很远,却以向老师学习为耻。因此,圣人就更加声明,愚人就更加愚昧。圣人之所以能成为圣人,愚人之所以成为愚人,大概都是由于这个原因吧?(有些人)疼爱自己的孩子,就选择老师来教他;(但是)对于他自己,却以跟从老师学习为耻,这真是太糊涂了!那些儿童的老师,是教他们读书、学习断句的,不是我所说的那种传授道理、解答疑难的老师。(一方面)不通晓句读,(另一方面)不能解决疑惑,有的(指句读)向老师学习,有的(指疑惑)却不向老师学习,小的方面学习了。大的方面却丢弃了,我看不出这种人是明白事理的!巫师、医生、乐师和各种工匠这些人,不以互相学习为耻。而士大夫这类人,一听到有人称“老师”、称“弟子”等等,就许多人聚集在一起讥笑人家。问他们为什么讥笑,就说:“他和他年龄差不多,懂得的道理也差不多。(以)地位低(的人为师),就足以感到羞耻;(以)官职高(的人为师),就近乎谄媚了。”唉!古代从师的风尚不能恢复,从这里就可以知道了。巫师、医生、乐师和各种工匠这些人,是士大夫们所看不起的,现在他们的见识竟反而比不上这些人,这真是很奇怪啊! + +> 圣人无常师。孔子师郯子、苌弘、师襄、老聃。郯子之徒,其贤不及孔子。孔子曰:三人行,则必有我师。是故弟子不必不如师,师不必贤于弟子,闻道有先后,术业有专攻,如是而已。 + +圣人没有固定的老师。孔子曾以郯子、苌弘、师襄、老聃为师。郯子这些人,他们的贤能都比不上孔子。孔子说:"几个人一起走,其中就一定有可以做我老师的人。"因此学生不一定不如老师,老师也不一定比学生贤明,接受道理的时间有早有晚,学问技艺各有专长,不过是这样罢了。 + +> 李氏子蟠,年十七,好古文,六艺经传皆通习之,不拘于时,学于余。余嘉其能行古道,作《师说》以贻之。 + +李家孩子名叫蟠的,今年十七岁,喜爱古文,六经的经文和传文都已广泛学习,不受当时(耻于从师)风气的拘束,向我求学。我赞许他能够遵行古人(从师)的正道,写了这篇《师说》来赠给他。 diff --git a/content/posts/高效率的沟通绝不会从在吗开始.md b/content/posts/高效率的沟通绝不会从在吗开始.md new file mode 100644 index 0000000..7256900 --- /dev/null +++ b/content/posts/高效率的沟通绝不会从在吗开始.md @@ -0,0 +1,31 @@ +--- +abbrlink: 2523582669 +categories: +- 往昔 +date: "2025-05-26 18:55:29" +tags: +- 人际交往 +- 沟通 +title: 高效率的沟通绝不会从在吗开始 +--- +“在吗?” + +据考证,“在吗”发起聊天的起源,是QQ刚盛行的年代,大家都没有手机,升级普遍需要在电脑上挂QQ。**为了确认在线的是不是本人而使用的**。 + +那么,现在还真的需要这句话吗? + +在吗只对聊天的发起者有好处,从接受者的主观来讲,对接受者无益的请求,在回复了以后,也就难以推脱了,毕竟总不可能装死。一旦在吗这两个字被发送,一个关于对方意图的猜疑链就无穷无尽地延伸下去了。 + +我向来都认为,网络上的沟通效率非常高,至少对于我个人来讲,是这样的。尤其是在邮箱等正式场合,迫于信息传播的时效性,只好组织起完整、官方、正式的语言,而不是东一句西一句,在信息的密度和聚合性上,是远远高于即时通讯软件的。 + +网络的优势也在于,你需要面对的是一块会发光的砖头,而不是长相体态性格各异的复杂的人。这可比现实中自在太多了。在网上沟通,只需要有大脑可以组织语言,有手可以打字,这就足够了。在现实生活中的沟通,既要注意语气、神态,又要关心对方的心情。这点对于不同的人来说,沟通效率也是不同的。网络把人的某个方面几乎带到了同一个高度。人们可以完全出于理性,而不被对方的现实表现影响地思考,在这一点来看,网络可以做到非常高效的交流。 + +“在吗”这两个字,无异于完全拉回到了现实面对面交流,当它被发送,信息的传递状态是阻塞的。如果是因有什么请求而发起聊天,发起者无法直接获得对方态度,接受者也不能直接明确对方意图,乃中华五千年文明之奇大败笔,让信息传播效率直接被打回原始社会。 + +如果是为了解决问题而开始交流,那应当直击要害,保证效率。糙话讲:有话快说,有屁快放。理不糙,只有这样才能让你的问题快速解决,也能不浪费双方的时间。 + +我的QQ好友里就有一位,堪称低效沟通的典范。有一次,他想问一下我曾经使用过的某个网站还有没有链接。他没有直接提出这个问题,而是在一分钟内给我发送了十五个相同的没有任何信息含量的GIF动图。那好吧,我不知道他的意图,我也只好回复一个不能传达任何情绪的动图。长达五分钟的沉默后,他终于开口问出了这个问题。在我从凌乱不堪的收藏夹里找出这个网址时,一分钟又过去了。 + +讲这个例子,我想表达的是,如果在第一句话就抛出问题:“某某某网站你还有吗?”那会得到相当迅速且准确的答复,如果发送了十五个毫无意义的图,那只能白白浪费五分钟。 + +最后,总结一下我这篇东拉西扯的短文,如果目的是解决问题,而不是聊聊天,这种无意义的模糊的文字是在耽误大家的时间。这种沟通方式并非冷漠,而是能解决问题的最直接办法。 diff --git a/content/posts/高超的表达能力.md b/content/posts/高超的表达能力.md new file mode 100644 index 0000000..8daff21 --- /dev/null +++ b/content/posts/高超的表达能力.md @@ -0,0 +1,22 @@ +--- +abbrlink: 3914674283 +categories: +- 往昔 +date: "2025-06-19 23:05:24" +tags: +- 小品 +title: 高超的表达能力 +--- +“帮我拿个东西。” + +“拿什么东西?” + +“就是那个。” + +“在哪里?” + +“就在那里。” + +“到底在哪里?” + +“就是在那里!” diff --git a/content/readings.md b/content/readings.md new file mode 100644 index 0000000..18b710f --- /dev/null +++ b/content/readings.md @@ -0,0 +1,55 @@ +--- +date: "2025-06-07T13:08:07+08:00" +title: 读书 +type: no-comments +--- +这里记录着我读过的书,有时候写写书评或读后感。 + +- 「⭐」表示我很喜欢的书籍 +- 「⚪」表示我觉得还可以的书籍 +- 「❌」表示我不太推荐的书籍 + +## 2025 + +### ✅读完 + +- ⚪ 《白夜行》 东野圭吾 / 日本 +- ❌ 《解忧杂货店》 东野圭吾 / 日本 +- ⚪ 《金色夜叉》 尾崎红叶 / 日本 +- ⚪ 《仲夏之死》 三岛由纪夫 / 日本 +- ⚪ 《潮骚》 三岛由纪夫 / 日本 +- ⭐ 《金阁寺》 三岛由纪夫 / 日本 +- ⭐ [《伊豆的舞女》](/posts/izu-no-odoriko/) 川端康成 / 日本 +- ⭐ 《雪国》 川端康成 / 日本 +- ⭐ [《三岛由纪夫传》](/posts/yukio-mishima/) 约翰·内森 / 美国 +- ⭐ 《活着》 余华 / 中国 +- ⚪ 《变形记》 弗兰兹·卡夫卡 / 奥地利 +- ⭐ [《春雪》](/tags/%E6%98%A5%E9%9B%AA/) 三岛由纪夫 / 日本 +- ⭐ [《奔马》](/posts/honba-mishima-yukio/) 三岛由纪夫 / 日本 + +### 💡在读 + +- 《挪威的森林》 村上春树 / 日本 +- 《晓寺》 三岛由纪夫 / 日本 +- 《思考的乐趣》 顾森 / 中国 + +### 🔆想读 + +- 《中国印刷设计史》 安宝江、张馥玫 / 中国 +- 《西西弗神话》 阿尔贝·加缪 / 法国 +- 《悉达多》 赫尔曼·黑塞 / 德国 +- 《数学之美》吴军 / 中国印刷设计史 +- 《红岩》罗广斌、杨益言 / 中国 +- 《如何阅读一本书》莫提默·J. 艾德勒、查尔斯·范多伦 / 美国 +- 《堂吉诃德》塞万提斯·萨维德拉 / 西班牙 +- 《人生海海》 麦家 / 中国 + +--- + +## 2024(3 本) + +### ✅读完 + +- ⚪ 《朝花夕拾》 鲁迅 / 中国 +- ⚪ 《西游记》 吴承恩 / 中国 +- ⚪ 《骆驼祥子》 老舍 / 中国 diff --git a/hugo.toml b/hugo.toml new file mode 100644 index 0000000..2f68194 --- /dev/null +++ b/hugo.toml @@ -0,0 +1,65 @@ +baseurl = "https://www.glowisle.me/" +title = "映屿" +hasCJKLanguage = true +enableRobotsTXT = true +pagination.pagerSize = 5 +languageCode = "zh-CN" +copyright = "Copyright © 2024, GlowIsle." + +[outputFormats] + [outputFormats.RSS] + baseName = "atom" # 更改文件名(不带扩展名) + mediaType = "application/rss+xml" + isPlainText = true + rel = "alternate" + protocol = "http://" + path = "" # 保持路径在根目录 + +[markup] + [markup.highlight] + style = "onedark" + +[markup.goldmark.renderer] +unsafe = true + +[taxonomies] + category = "categories" + tag = "tags" + +[menu] + +[[menu.main]] + name = "分类" + url = "/categories" + weight = 2 + +[[menu.main]] + name = "友人" + url = "/links" + weight = 3 + +[[menu.main]] + name = "归档" + url = "/archives" + weight = 4 + +[[menu.main]] + name = "关于" + url = "/about" + weight = 5 + +[params] + upvote = true + upvoteURL = "https://upvote.glowisle.me/" + description = "关于互联网、书籍、生活琐事以及那些一闪而过的念头。计算机技术 & 读书感悟 & 日常随笔。映屿(GlowIsle)" + postSearch = false + groupByYear = true + toc = true + showPostCount = true + favicon = "/favicon.png" + hideMadeWithLine = true + imageZoom = true + + [params.author] + name = "五葉地錦" + email = "i@glowisle.me" diff --git a/layouts/404.html b/layouts/404.html new file mode 100644 index 0000000..15198aa --- /dev/null +++ b/layouts/404.html @@ -0,0 +1,4 @@ +{{ define "title" }}404{{ end }} {{ define "main" }} +<h1>404</h1> +<h2>ʕノ•ᴥ•ʔノ ︵ ┻━┻</h2> +{{ end }} diff --git a/layouts/_default/_markup/render-image.html b/layouts/_default/_markup/render-image.html new file mode 100644 index 0000000..bf19bf9 --- /dev/null +++ b/layouts/_default/_markup/render-image.html @@ -0,0 +1,4 @@ +<figure class="image-caption"> + <img src="{{ .Destination | safeURL }}" alt="{{ .Text }}"> + <figcaption>{{ .Text }}</figcaption> +</figure>
\ No newline at end of file diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html new file mode 100644 index 0000000..8729df0 --- /dev/null +++ b/layouts/_default/baseof.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html lang="{{ with .Site.LanguageCode }}{{ . }}{{ else }}en-US{{ end }}"> + +<head> + <meta http-equiv="X-Clacks-Overhead" content="GNU Terry Pratchett" /> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + {{- partial "favicon.html" . -}} + <title>{{ .Title }}</title> + + {{- partial "seo_tags.html" . -}} + <meta name="referrer" content="no-referrer-when-downgrade" /> + + {{ with .OutputFormats.Get "rss" -}} + {{ printf `<link rel="%s" type="%s" href="%s" title="%s" />` .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }} + {{ end -}} + + {{- partial "style.html" . -}} + + <!-- A partial to be overwritten by the user. + Simply place a custom_head.html into + your local /layouts/partials-directory --> + {{- partial "custom_head.html" . -}} +</head> + +<body> + <header> + {{- partial "header.html" . -}} + </header> + <main> + {{- block "main" . }}{{- end }} + </main> + <footer> + {{- partial "footer.html" . -}} + </footer> + + <!-- A partial to be overwritten by the user. + Simply place a custom_body.html into + your local /layouts/partials-directory --> + {{- partial "custom_body.html" . -}} +</body> + +</html> diff --git a/layouts/_default/list.html b/layouts/_default/list.html new file mode 100644 index 0000000..8c1db86 --- /dev/null +++ b/layouts/_default/list.html @@ -0,0 +1,70 @@ +{{ define "main" }} +<content> + {{ if .Site.Params.postSearch }} + <input + id="search-input" + type="text" + placeholder="Search..." + style="margin-top: 16px" + /> + <script> + // 等待 DOM 完全加载后执行 + document.addEventListener('DOMContentLoaded', function () { + // 缓存 DOM 元素 + const searchInput = document.getElementById('search-input'); + const posts = document.querySelectorAll('.blog-posts li'); + const years = document.querySelectorAll('.blog-posts h3'); + + // 更新搜索结果 + function updateSearchResults(searchTerm) { + let visiblePosts = 0; + const displayedYears = new Set(); + posts.forEach(function (post) { + const title = post.querySelector('a').textContent.toLowerCase(); + const year = post.querySelector('time').getAttribute('datetime').split('-')[0]; + if (title.includes(searchTerm)) { + post.style.display = ''; + visiblePosts++; + displayedYears.add(year); + } else { + post.style.display = 'none'; + } + }); + + {{ if .Site.Params.groupByYear }} + years.forEach(function (y) { + const year = y.textContent; + y.style.display = displayedYears.has(year) ? '' : 'none'; + }); + {{ end }} + } + + searchInput.addEventListener('input', function () { + updateSearchResults(this.value.toLowerCase().trim()); + }); + }); + </script> + {{ end }} + <ul class="blog-posts"> + {{ $currentYear := 0 }} {{ range .Pages }} {{ if and (not .Params.hidden) + (not (in .Params.categories "往昔")) }} + + <li> + <span + class="{{ if .Site.Params.groupByYear }} grouped {{ else }} ungrouped {{ end }}" + > + <i> + <time datetime='{{ .Date.Format "2006-01-02" }}' pubdate> + {{ .Date.Format (default "2006-01-02" .Site.Params.dateFormat) }} + </time> + </i> + </span> + <a href="{{ .Permalink }}">{{ .Title }}</a> + </li> + + {{ end }} {{ else }} + <li>No posts yet</li> + {{ end }} + </ul> +</content> +{{ end }} diff --git a/layouts/_default/rss.xml b/layouts/_default/rss.xml new file mode 100644 index 0000000..37ab6ea --- /dev/null +++ b/layouts/_default/rss.xml @@ -0,0 +1,85 @@ +{{- /* Deprecate site.Author.email in favor of site.Params.author.email */}} +{{- $authorEmail := "" }} +{{- with site.Params.author }} + {{- if reflect.IsMap . }} + {{- with .email }} + {{- $authorEmail = . }} + {{- end }} + {{- end }} +{{- else }} + {{- with site.Author.email }} + {{- $authorEmail = . }} + {{- warnf "The author key in site configuration is deprecated. Use params.author.email instead." }} + {{- end }} +{{- end }} + +{{- /* Deprecate site.Author.name in favor of site.Params.author.name */}} +{{- $authorName := "" }} +{{- with site.Params.author }} + {{- if reflect.IsMap . }} + {{- with .name }} + {{- $authorName = . }} + {{- end }} + {{- else }} + {{- $authorName = . }} + {{- end }} +{{- else }} + {{- with site.Author.name }} + {{- $authorName = . }} + {{- warnf "The author key in site configuration is deprecated. Use params.author.name instead." }} + {{- end }} +{{- end }} + +{{- $pctx := . }} +{{- if .IsHome }}{{ $pctx = .Site }}{{ end }} +{{- $pages := slice }} +{{- if or $.IsHome $.IsSection }} +{{- $pages = $pctx.RegularPages }} +{{- else }} +{{- $pages = $pctx.Pages }} +{{- end }} +{{- $limit := .Site.Params.RSS.pageLimit }} +{{- if ge $limit 1 }} +{{- $pages = $pages | first $limit }} +{{- end }} +{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }} +<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> + <channel> + <title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{ . }} on {{ end }}{{ .Site.Title }}{{ end }}</title> + <link>{{ .Permalink }}</link> + <description>Recent content {{ if ne .Title .Site.Title }}{{ with .Title }}in {{ . }} {{ end }}{{ end }}on {{ .Site.Title }}</description> + <generator>Hugo</generator> + <language>{{ site.LanguageCode }}</language> + {{ with $authorEmail }} + <managingEditor>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</managingEditor> + {{ end }} + {{ with $authorEmail }} + <webMaster>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</webMaster> + {{ end }} + {{ with .Site.Params.copyright }} + <copyright>{{ . }}</copyright> + {{ end }} + {{ if not .Date.IsZero }} + <lastBuildDate>{{ (index $pages.ByLastmod.Reverse 0).Lastmod.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate> + {{ end }} + {{ if and .Site.Params.RSS.followFeedId .Site.Params.RSS.followUserId }} + <follow_challenge> + <feedId>{{ .Site.Params.RSS.followFeedId }}</feedId> + <userId>{{ .Site.Params.RSS.followUserId }}</userId> + </follow_challenge> + {{ end }} + {{- with .OutputFormats.Get "RSS" }} + {{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }} + {{- end }} + {{- range $pages }} + <item> + <title>{{ .Title }}</title> + <link>{{ .Permalink }}</link> + <pubDate>{{ .PublishDate.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate> + {{- with $authorEmail }}<author>{{ . }}{{ with $authorName }} ({{ . }}){{ end }}</author>{{ end }} + <guid>{{ .Permalink }}</guid> + <description>{{ .Content | transform.XMLEscape | safeHTML }}</description> + </item> + {{- end }} + </channel> +</rss>
\ No newline at end of file diff --git a/layouts/_default/single.html b/layouts/_default/single.html new file mode 100644 index 0000000..78814e5 --- /dev/null +++ b/layouts/_default/single.html @@ -0,0 +1,297 @@ +{{ define "main" }} {{ if eq .Type "blog" }} {{ if not .Params.menu }} +<h1>{{ .Title }}</h1> +{{ end }} {{ end }} + +<article class="h-entry"> + <h1 class="post-title p-name"><a href="{{ .RelPermalink }}" style="color:#222222;">{{ .Title }}</a></h1> + +<div class="post-info"> + <time class="post-date dt-published" datetime="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}"> + {{ .Date.Format "2006年1月2日" }} + </time> + {{ range .Params.categories }} + {{ $url := printf "/categories/%s/" (. | urlize) }} + <a href="{{ $url }}" class="category-link">{{ . }}</a> + {{ end }} +</div> +<div class="e-content"> + {{ .Content }} +</div> +</article> +<a class="u-url" href="{{ .Permalink }}" style="display:none;">Permalink</a> + +<p> + {{ range (.GetTerms "tags") }} + <a href="{{ .Permalink }}">#{{ .LinkTitle }}</a> + {{ end }} +</p> + +{{ $upvoteEnabled := default .Site.Params.upvote .Params.upvote }} +{{ if $upvoteEnabled }} +<div class="upvote-container"> +<small class="upvote"> + <button class="upvote-btn" id="upvote-btn"> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"> + <polyline points="17 11 12 6 7 11"></polyline> + <polyline points="17 18 12 13 7 18"></polyline> + </svg> + <span class="upvote-count" id="upvote-count">0</span> + </button> +</small> +</div> + +<script> + let hasUpvoted = false; + let upvoteBtn; + let upvoteCount; + + // 页面加载时获取点赞数量 + document.addEventListener('DOMContentLoaded', function() { + const slug = '{{ .Slug }}'; + upvoteBtn = document.getElementById('upvote-btn'); + upvoteCount = document.getElementById('upvote-count'); + getCount(slug); + + // 处理点赞按钮的点击事件 + upvoteBtn.addEventListener('click', handleUpvote); + }); + + // 点赞方法 + async function handleUpvote() { + if (hasUpvoted) { + console.log('You have already upvoted this post!'); + return; + } + const slug = '{{ .Slug }}'; + + // 禁用按钮以防止重复点击 + upvoteBtn.disabled = true; + // 给按钮添加 upvoted 类以赋以点击过的样式 + upvoteBtn.classList.add('upvoted'); + // 更新 upvote-count 的值 +1 + upvoteCount.innerText = parseInt(upvoteCount.innerText) + 1; + + try { + const response = await fetch('{{ .Site.Params.upvoteURL }}upvote', { + method: 'POST', + mode: 'cors', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ postId: slug, diff: 1 }), + }); + + if (response.ok) { + console.log('Upvote successful!'); + hasUpvoted = true; + await getCount(slug, 3); + } else { + console.log('Upvote failed!'); + } + } catch (error) { + console.error('Error: ', error); + } finally { + upvoteBtn.disabled = false; + } + } + + // 获取 Upvote 数量的方法,支持设置重试次数,默认不重试 + async function getCount(slug, retryCount = 0) { + try { + const response = await fetch('{{ .Site.Params.upvoteURL }}count?post=' + slug, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + const data = await response.json(); + + if (data.code === 0) { + const count = data.data.count; + upvoteCount.innerText = count; + hasUpvoted = data.data.hasUpvoted; + if (hasUpvoted) { + upvoteBtn.classList.add('upvoted'); + } else { + upvoteBtn.classList.remove('upvoted'); + } + } else { + console.error('Failed to get upvote count: ', data.msg); + } + } catch (error) { + console.error('Error: ', error); + if (retryCount > 0) { + setTimeout(() => { + getCount(slug, retryCount - 1); + }, 1000); + } + } + } +</script> +{{ end }} + +<!-- Place the TOC at the end to ensure the article content loads first. --> +{{ $tocEnabled := default .Site.Params.toc .Params.toc }} {{ if $tocEnabled }} +<div class="toc">{{ partial "toc.html" . }}</div> +{{ end }} +<hr /> +<details> + <summary> + <p style="display: inline">评论 与 Webmentions</p> + </summary> + <div id="giscus-container"></div> + + <div class="wm"> +<div id="webmentions"></div> +<script src="/js/webmention.min.js" + data-id="webmentions" + data-page-url="https://www.glowisle.me{{ .RelPermalink }}" + data-max-webmentions="50" + data-wordcount="30" + data-sort-by="published" + data-sort-dir="up" + async> +</script> + +<details> + <summary>如何参与 Webmentions 互动?</summary> + <div class="wm-guide-content"> +<div class="webmention-form"> + <p>如果你想回应这篇文章,请在你的博客或社交媒体中链接本页面,然后在下面的表单中提交你的页面链接。</p> + <form id="webmention-submit-form" action="https://webmention.io/www.glowisle.me/webmention" method="post"> + <!-- 自动填充的目标文章链接 --> + <input type="hidden" name="target" value="https://www.glowisle.me{{ .RelPermalink }}"> + + <div> + <label for="webmention-source">你的文章链接:</label> + <input + type="url" + id="webmention-source" + name="source" + required + pattern="https?://.+" + > + <button type="submit" id="webmention-submit-btn">提交</button> + </div> + <div id="webmention-form-feedback"></div> + </form> + <br> +<a href="https://indieweb.org/webmention">关于 Webmention 的更多信息</a> 以及 <a href="https://www.glowisle.me/posts/tear-hypocrisy-apart/">为什么要这么做?</a> +</details> + + + + <script> + /* +src="https://giscus.app/client.js" + data-repo="yingyu5658/yingyu5658.github.io" + data-repo-id="R_kgDOOBetsA" + data-category="Announcements" + data-category-id="DIC_kwDOOBetsM4CoF_Z" + data-mapping="title" + data-strict="0" + data-reactions-enabled="1" + data-emit-metadata="0" + data-input-position="bottom" + data-theme="dark" + data-lang="zh-CN" + crossorigin="anonymous" + async> + + +*/ + function getInitialTheme() { + // 1. 优先检查 localStorage 中的用户偏好 + if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) { + return localStorage.getItem('theme'); + } + // 2. 检查系统偏好 + if (window.matchMedia('(prefers-color-scheme: dark)').matches) { + return 'dark'; + } + // 3. 默认值 + return 'light'; +} + +const currentTheme = getInitialTheme(); +const giscusTheme = currentTheme === 'dark' ? 'dark' : 'light'; + +const giscusScript = document.createElement('script'); +giscusScript.src = 'https://giscus.app/client.js'; +giscusScript.setAttribute('data-repo', 'yingyu5658/yingyu5658.github.io'); +giscusScript.setAttribute('data-repo-id', 'R_kgDOOBetsA'); +giscusScript.setAttribute('data-category', 'Announcements'); +giscusScript.setAttribute('data-category-id', 'DIC_kwDOOBetsM4CoF_Z'); +giscusScript.setAttribute('data-mapping', 'title'); +giscusScript.setAttribute('data-strict', '0'); +giscusScript.setAttribute('data-reactions-enabled', '1'); +giscusScript.setAttribute('data-emit-metadata', '0'); +giscusScript.setAttribute('data-input-position', 'bottom'); +giscusScript.setAttribute('data-theme', giscusTheme); +giscusScript.setAttribute('data-lang', 'zh-CN'); +giscusScript.crossOrigin = 'anonymous'; +giscusScript.async = true; + +document.getElementById('giscus-container').appendChild(giscusScript); + +document.addEventListener('DOMContentLoaded', function() { + const form = document.getElementById('webmention-submit-form'); + const submitBtn = document.getElementById('webmention-submit-btn'); + const feedbackEl = document.getElementById('webmention-form-feedback'); + + if (!form) return; + + form.addEventListener('submit', async function(e) { + e.preventDefault(); + + // 禁用提交按钮防止重复提交 + const originalBtnText = submitBtn.textContent; + submitBtn.disabled = true; + submitBtn.textContent = '发送中...'; + + // 清除之前的反馈信息 + feedbackEl.textContent = ''; + + try { + // 使用 FormData 收集表单数据 + const formData = new FormData(form); + + // 发送 POST 请求 + const response = await fetch(form.action, { + method: 'POST', + headers: { + 'Accept': 'application/json', + }, + body: new URLSearchParams(formData) + }); + + const result = await response.json(); + + if (response.ok) { + // 成功响应 + feedbackEl.textContent = '✅ 提交成功!Webmention 正在处理中。'; + form.reset(); + } else { + // 错误响应 + let errorMsg = '提交失败:'; + if (result.error || result.summary) { + errorMsg += result.error || result.summary; + } + feedbackEl.textContent = errorMsg; + } + } catch (error) { + // 网络错误 + feedbackEl.textContent = '❌ 提交过程中出现网络错误,请稍后重试。'; + } finally { + // 恢复提交按钮状态 + submitBtn.disabled = false; + submitBtn.textContent = originalBtnText; + } + }); +}); + + +</script> + +{{ end }} diff --git a/layouts/_default/term.html b/layouts/_default/term.html new file mode 100644 index 0000000..0d55fc1 --- /dev/null +++ b/layouts/_default/term.html @@ -0,0 +1,36 @@ +{{ define "main" }} +<div class="taxonomy-term"> + <h2>{{ .Title }}</h2> + + <div class="posts-list"> + {{ range .Pages }} + + <li style="list-style-type: none; margin-bottom: 12px"> + <span + class="post-date" + {{ + if + .Site.Params.groupByYear + }} + grouped + {{ + else + }} + ungrouped + {{ + end + }} + > + <time datetime='{{ .Date.Format "2006-01-02" }}' pubdate> + {{ .Date.Format "2006-01-02" }} + </time> + </span> + <a href="{{ .Permalink }}">{{ .Title }}</a> + </li> + + {{ else }} + <p>该分类下还没有文章。</p> + {{ end }} + </div> +</div> +{{ end }} diff --git a/layouts/archives/single.html b/layouts/archives/single.html new file mode 100644 index 0000000..6c43aac --- /dev/null +++ b/layouts/archives/single.html @@ -0,0 +1,94 @@ +{{ define "main" }} +<content> + {{ if .Site.Params.postSearch }} + <input + id="search-input" + type="text" + placeholder="搜索文章..." + style="margin-top: 16px" + /> + <script> + document.addEventListener('DOMContentLoaded', function () { + const searchInput = document.getElementById('search-input'); + const posts = document.querySelectorAll('.blog-posts li'); + const years = document.querySelectorAll('.blog-posts h3'); + + function updateSearchResults(searchTerm) { + let visiblePosts = 0; + const displayedYears = new Set(); + + posts.forEach(function (post) { + const titleLink = post.querySelector('a'); + const timeElement = post.querySelector('time'); + + if (titleLink && timeElement) { + const title = titleLink.textContent.toLowerCase(); + const year = timeElement.getAttribute('datetime').split('-')[0]; + + if (title.includes(searchTerm)) { + post.style.display = ''; + visiblePosts++; + displayedYears.add(year); + } else { + post.style.display = 'none'; + } + } + }); + + {{ if .Site.Params.groupByYear }} + years.forEach(function (y) { + const year = y.textContent; + y.style.display = displayedYears.has(year) ? '' : 'none'; + }); + {{ end }} + + {{ if .Site.Params.showPostCount }} + const countText = `找到 ${visiblePosts} 篇文章`; + const countElement = document.getElementById('post-count'); + if (countElement) { + countElement.innerHTML = countText; + } + {{ end }} + } + + if (searchInput) { + searchInput.addEventListener('input', function () { + updateSearchResults(this.value.toLowerCase().trim()); + }); + } + }); + </script> + {{ end }} {{ $allPosts := where .Site.RegularPages "Type" "eq" "posts" }} {{ + $excludePosts := where $allPosts "Params.categories" "intersect" (slice + "往昔") }} {{ $postPages := $allPosts | complement $excludePosts }} {{ if + .Site.Params.showPostCount }} + <p id="post-count">共有 {{ len $postPages }} 篇文章</p> + {{ end }} + + <ul class="blog-posts"> + {{ if gt (len $postPages) 0 }} {{ $pagesToShow := $postPages.ByDate.Reverse + }} {{ $currentYear := 0 }} {{ range $pagesToShow }} {{ if .Date }} {{ $year + := .Date.Year }} {{ if and (.Site.Params.groupByYear) (ne $year + $currentYear) }} + <h3>{{ $year }}</h3> + {{ $currentYear = $year }} {{ end }} {{ end }} + + <li> + <span + class="{{ if .Site.Params.groupByYear }}grouped{{else}}ungrouped{{end}}" + > + <i> + <time datetime='{{ .Date.Format "2006-01-02" }}' pubdate> + {{ .Date.Format (default "2006-01-02" .Site.Params.dateFormat) }} + </time> + </i> + </span> + <a href="{{ .Permalink }}">{{ .Title }}</a> + </li> + {{ end }} {{ else }} + <li>暂无文章</li> + {{ end }} + </ul> +</content> +<hr /> +{{ end }} diff --git a/layouts/index.html b/layouts/index.html new file mode 100644 index 0000000..d975ecb --- /dev/null +++ b/layouts/index.html @@ -0,0 +1 @@ +{{ define "main" }} {{ .Content }} {{ end }} diff --git a/layouts/no-comments/single.html b/layouts/no-comments/single.html new file mode 100644 index 0000000..58160be --- /dev/null +++ b/layouts/no-comments/single.html @@ -0,0 +1,136 @@ +{{ define "main" }} +{{ if eq .Type "blog" }} +{{ if not .Params.menu }} +<h1>{{ .Title }}</h1> +{{ if .Date }} +<p> + <i> + <time datetime='{{ .Date.Format "2006-01-02" }}' pubdate> + {{ .Date.Format (default "02 Jan, 2006" .Site.Params.dateFormat) }} + </time> + </i> +</p> +{{ end }} +{{ end }} +{{ end }} + +<content> {{ .Content }} </content> + +<p> + {{ range (.GetTerms "tags") }} + <a href="{{ .Permalink }}">#{{ .LinkTitle }}</a> + {{ end }} +</p> + +{{ $upvoteEnabled := default .Site.Params.upvote .Params.upvote }} +{{ if $upvoteEnabled }} +<div class="upvote-container"> +<small class="upvote"> + <button class="upvote-btn" id="upvote-btn"> + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"> + <polyline points="17 11 12 6 7 11"></polyline> + <polyline points="17 18 12 13 7 18"></polyline> + </svg> + <span class="upvote-count" id="upvote-count">0</span> + </button> +</small> +</div> + +<script> + let hasUpvoted = false; + let upvoteBtn; + let upvoteCount; + + // 页面加载时获取点赞数量 + document.addEventListener('DOMContentLoaded', function() { + const slug = '{{ .Slug }}'; + upvoteBtn = document.getElementById('upvote-btn'); + upvoteCount = document.getElementById('upvote-count'); + getCount(slug); + + // 处理点赞按钮的点击事件 + upvoteBtn.addEventListener('click', handleUpvote); + }); + + // 点赞方法 + async function handleUpvote() { + if (hasUpvoted) { + console.log('You have already upvoted this post!'); + return; + } + const slug = '{{ .Slug }}'; + + // 禁用按钮以防止重复点击 + upvoteBtn.disabled = true; + // 给按钮添加 upvoted 类以赋以点击过的样式 + upvoteBtn.classList.add('upvoted'); + // 更新 upvote-count 的值 +1 + upvoteCount.innerText = parseInt(upvoteCount.innerText) + 1; + + try { + const response = await fetch('{{ .Site.Params.upvoteURL }}upvote', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ postId: slug, diff: 1 }), + }); + + if (response.ok) { + console.log('Upvote successful!'); + hasUpvoted = true; + await getCount(slug, 3); + } else { + console.log('Upvote failed!'); + } + } catch (error) { + console.error('Error: ', error); + } finally { + upvoteBtn.disabled = false; + } + } + + // 获取 Upvote 数量的方法,支持设置重试次数,默认不重试 + async function getCount(slug, retryCount = 0) { + try { + const response = await fetch('{{ .Site.Params.upvoteURL }}count?post=' + slug, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + }); + + const data = await response.json(); + + if (data.code === 0) { + const count = data.data.count; + upvoteCount.innerText = count; + hasUpvoted = data.data.hasUpvoted; + if (hasUpvoted) { + upvoteBtn.classList.add('upvoted'); + } else { + upvoteBtn.classList.remove('upvoted'); + } + } else { + console.error('Failed to get upvote count: ', data.msg); + } + } catch (error) { + console.error('Error: ', error); + if (retryCount > 0) { + setTimeout(() => { + getCount(slug, retryCount - 1); + }, 1000); + } + } + } +</script> +{{ end }} + +<!-- Place the TOC at the end to ensure the article content loads first. --> +{{ $tocEnabled := default .Site.Params.toc .Params.toc }} +{{ if $tocEnabled }} +<div class="toc"> +{{ partial "toc.html" . }} +</div> +{{ end }} +{{ end }} diff --git a/layouts/partials/archives-list.html b/layouts/partials/archives-list.html new file mode 100644 index 0000000..b9767f7 --- /dev/null +++ b/layouts/partials/archives-list.html @@ -0,0 +1,30 @@ +{{ $allPages := where .Site.RegularPages "Type" "in" (slice "posts" "blog") }} +{{ $visiblePages := where $allPages "Params.hidden" "!=" true }} +{{ $pagesToShow := $visiblePages.ByDate.Reverse }} + +<div class="archives-content"> + <h2>归档</h2> + + <p>共有 {{ len $pagesToShow }} 篇文章</p> + + <ul class="blog-posts"> + {{ $currentYear := 0 }} + {{ range $pagesToShow }} + {{ $year := .Date.Year }} + {{ if ne $year $currentYear }} + <h3>{{ $year }}</h3> + {{ $currentYear = $year }} + {{ end }} + <li> + <span> + <i> + <time datetime='{{ .Date.Format "2006-01-02" }}'> + {{ .Date.Format "2006-01-02" }} + </time> + </i> + </span> + <a href="{{ .Permalink }}">{{ .Title }}</a> + </li> + {{ end }} + </ul> +</div> diff --git a/layouts/partials/custom_body.html b/layouts/partials/custom_body.html new file mode 100644 index 0000000..529771a --- /dev/null +++ b/layouts/partials/custom_body.html @@ -0,0 +1,5 @@ + <!-- A partial to be overwritten by the user. + Simply place a custom_body.html into + your local /layouts/partials-directory --> + + diff --git a/layouts/partials/custom_head.html b/layouts/partials/custom_head.html new file mode 100644 index 0000000..4ea89a1 --- /dev/null +++ b/layouts/partials/custom_head.html @@ -0,0 +1,11 @@ +<meta name="msvalidate.01" content="2E1AACF009206F2DDBAAD4B98E881460" /> +<link + rel="prefetch" + as="image" + href="https://www.blogsclub.org/badge/www.glowisle.me" +/> +<link href="https://github.com/yingyu5658" rel="me" /> +<link + rel="webmention" + href="https://webmention.io/www.glowisle.me/webmention" +/> diff --git a/layouts/partials/favicon.html b/layouts/partials/favicon.html new file mode 100644 index 0000000..ccf1a5d --- /dev/null +++ b/layouts/partials/favicon.html @@ -0,0 +1,2 @@ +{{ with .Site.Params.favicon }} +<link rel="shortcut icon" href="{{ . | absURL }}" />{{ end }} diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html new file mode 100644 index 0000000..cc5e269 --- /dev/null +++ b/layouts/partials/footer.html @@ -0,0 +1 @@ +<p>© 2024 - 2025 | Made with ❤️ by Verdant.</p> diff --git a/layouts/partials/header.html b/layouts/partials/header.html new file mode 100644 index 0000000..66fa74b --- /dev/null +++ b/layouts/partials/header.html @@ -0,0 +1,4 @@ +<a href="{{ "" | relURL }}" class="title"> + <h1 class="site-name">{{ .Site.Title }}</h1> +</a> +<nav>{{- partial "nav.html" . -}}</nav> diff --git a/layouts/partials/nav.html b/layouts/partials/nav.html new file mode 100644 index 0000000..5b9d089 --- /dev/null +++ b/layouts/partials/nav.html @@ -0,0 +1,7 @@ +<a href="{{ "" | relURL }}">首页</a> +{{ range .Site.Menus.main }} +<a href="{{ .URL }}">{{ .Name }}</a> +{{ end }} +{{ with .Site.GetPage "/blog" }} +<a href="{{ "posts/" | relURL }}">Blog</a> +{{ end }} diff --git a/layouts/partials/seo_tags.html b/layouts/partials/seo_tags.html new file mode 100644 index 0000000..06e90cd --- /dev/null +++ b/layouts/partials/seo_tags.html @@ -0,0 +1,15 @@ +<!-- Primary Meta Tags --> +<meta name="title" content="{{ with .Title }}{{ . }}{{ else }}{{ .Site.Title }}{{ end }}" /> +<meta name="description" content="{{ with .Description }}{{ . }}{{ else }}{{ if .IsPage }}{{ .Summary }}{{ else }}{{ with .Site.Params.Description }}{{ . }}{{ end }}{{ end }}{{ end }}" /> +<meta name="keywords" content="{{ if .IsPage }}{{ range $index, $tag := .Params.tags }}{{ $tag }},{{ end }}{{ else }}{{ range $plural, $terms := .Site.Taxonomies }}{{ range $term, $val := $terms }}{{ printf "%s," $term }}{{ end }}{{ end }}{{ end }}" /> + +<link rel="canonical" href="{{ .Permalink }}"> + +<!-- Open Graph / Facebook --> +{{ template "_internal/opengraph.html" . }} + +<!-- Twitter --> +{{ template "_internal/twitter_cards.html" . }} + +<!-- Microdata --> +{{ template "_internal/schema.html" . }} diff --git a/layouts/partials/style.html b/layouts/partials/style.html new file mode 100644 index 0000000..f108da6 --- /dev/null +++ b/layouts/partials/style.html @@ -0,0 +1,531 @@ +<style> + /* light theme */ + :root { + --width-max: 720px; + --font-primary: "Noto Serif SC", "Source Han Serif SC", serif; + --font-secondary: monospace; + --font-size-primary: 1em; + --font-size-secondary: 0.8em; + --body-bg-color: #ffffff; + --bold-text-color: #222; + --body-text-color: #444; + --link-color: #222; + --link-visited-color: #222; + --table-border-color: #f2f2f2; + --table-th-bg-color: #f2f2f2; + --img-border-color: #f2f2f2; + --code-bg-color: #f2f2f2; + --code-text-color: #222; + --blockquote-border-color: #666; + --blockquote-text-color: #666; + --upvoted-color: #fa8072; + --caption-text-color: #666; + --toc-text-color: #e5e5e5; + --toc-hover-color: #655e5e; + } + + .wm { + border: 1px #d0d7de solid; + border-radius: 0.25em; + padding-top: 0; + padding: 1.5vw; + background-color: #f6f8fa; + margin-top: 1vh; + } + + .wm p { + margin-top: 1px; + } + + .item-link { + white-space: nowrap; + overflow: hidden; + } + + .post-info { + text-align: center; + margin-bottom: 3vh; + } + .category-link { + color: #999; + } + + h1.post-title { + margin-top: 5vh; + margin-bottom: 10px; + text-align: center; + } + + h1.post-title a { + font-size: 30px; + font-weight: 700; + } + + .recent-list { + padding-left: 2vw; + } + + .recent-item { + list-style-type: none; + } + + .post-date { + display: inline; + } + + .post-date, + .post-date-shortcode { + margin-left: auto; + color: #999; + } + + article .post-date::after { + content: "/"; + } + + .site-name:hover { + background-color: transparent; + text-decoration: none; + color: #fff; + background-color: #7e4fa0; + } + + .site-name { + transition: 0.3s; + width: 66px; + border-radius: 5px; + text-transform: uppercase; + } + + @media (prefers-color-scheme: dark) { + :root { + --body-bg-color: #121212; + --bold-text-color: #eee; + --body-text-color: #ddd; + --link-color: #ddd; + --link-visited-color: #c3b1ee; + --table-border-color: #999; + --table-th-bg-color: #999; + --img-border-color: #999; + --code-bg-color: #141414; + --code-text-color: #ddd; + --blockquote-border-color: #ccc; + --blockquote-text-color: #ccc; + --caption-text-color: #aaa; + --toc-text-color: #373737; + --toc-hover-color: #cac3c3; + } + + .wm { + background-color: #161b22; + border-color: #30363d; + color: var(--body-text-color); + padding: 10px; + } + + .wm input { + background-color: #010409; + border: #30363d 1px solid; + color: var(--body-text-color); + outline: none; + transition: border-color 0.2s ease-in-out; + } + + #webmention-source:focus { + border-color: var(--color-accent-fg, #0969da); + box-shadow: 0 0 0 3px rgba(9, 105, 218, 0.1); + } + + .wm button { + color: var(--body-text-color); + background-color: #161b22; + border: #30363d 1px solid; + } + + .post-title a { + color: #fff !important; + } + + .post-summary { + color: var(--text-color-primary) !important; + } + + .post-item { + border-bottom: 1px solid #414141 !important; + } + + .pagination-link { + border: 1px solid #414141 !important; + } + + nav a, + h1.post-title a, + .category-link, + .blog-posts li a { + text-decoration: none !important; + } + + a { + font-weight: 700 !important; + } + + a:hover { + color: #ddd !important; + } + } + + body { + font-family: var(--font-primary); + font-size: var(--font-size-primary); + margin: auto; + padding: 20px; + max-width: var(--width-max); + text-align: left; + background-color: var(--body-bg-color); + word-wrap: break-word; + overflow-wrap: break-word; + line-height: 1.6; + color: var(--body-text-color); + } + + h1, + h2, + h3, + h4, + h5, + h6, + strong, + b { + color: var(--bold-text-color); + } + + h1, + h2, + h3, + h4, + h5, + h6 { + margin: 16px 0; + } + + a { + color: var(--link-color); + cursor: pointer; + text-decoration: underline 0.2px #d4d4d4; + transition-duration: 0.3s; + font-weight: 600; + } + + a:hover { + color: #3273dc; + } + + .posts-list li { + margin-bottom: 12px; + } + + .title { + text-decoration: none; + border: 0; + } + + .title:hover { + text-decoration: none; + } + + .title span { + font-weight: 400; + } + + nav { + margin-bottom: 15px; + } + + nav a { + margin-right: 8px; + } + + textarea { + width: 100%; + font-size: 16px; + } + + input { + font-size: 14px; + } + + article { + line-height: 1.6; + } + + table { + width: 100%; + border-collapse: collapse; + border: 1px solid var(--table-border-color); + border-radius: 4px; + margin-top: 16px; + } + + th, + td { + border: 1px solid var(--table-border-color); + padding: 4px; + } + + th { + background-color: var(--table-th-bg-color); + } + + hr { + border: 0; + border-top: 1px dashed; + } + + img { + max-width: 100%; + display: block; + margin-left: auto; + margin-right: auto; + border: 1px solid var(--img-border-color); + border-radius: 4px; + content-visibility: auto; + loading: lazy; + } + + img[src*="#minipic"] { + max-width: 50%; + margin-left: 0; + margin-right: auto; + } + + .image-caption figcaption { + text-align: center; + font-style: italic; + font-size: 0.8em; + margin-top: 0.6em; + color: var(--caption-text-color); + } + + .image-caption { + margin: auto; + } + + i { + font-style: normal; + } + + time { + font-family: var(--font-secondary); + font-size: 15px; + color: rgb(163, 163, 163); + } + + code { + font-family: var(--font-secondary); + background-color: var(--code-bg-color); + color: var(--code-text-color); + padding: 2px; + border-radius: 4px; + } + + pre code { + display: block; + padding: 16px; + white-space: pre-wrap; + overflow-x: auto; + } + + div.highlight pre { + border-radius: 4px; + } + + div.highlight code { + background-color: var(--code-bg-color); + color: var(--code-text-color); + } + + blockquote { + border-left: 2px solid var(--blockquote-border-color); + color: var(--blockquote-text-color); + margin: 0; + padding-left: 16px; + font-style: normal; + } + + blockquote p { + margin: 0; + } + + footer { + padding: 25px 0; + text-align: left; + font-size: var(--font-size-secondary); + } + + ul li:has(input) { + list-style-type: none; + margin-left: -25.5px; + } + + /* blog post list */ + ul.blog-posts { + list-style-type: none; + padding: unset; + } + + ul.blog-posts li { + display: flex; + margin-bottom: 8px; + } + + ul.blog-posts li span { + flex: 0 0 130px; + } + + ul.blog-posts li span.grouped { + flex: 0 0 80px; + } + + ul.blog-posts li a:visited { + color: var(--link-visited-color); + } + + ul.blog-posts a { + margin-left: 10px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + /* TOC 样式 */ + div.toc { + position: fixed; /* 固定定位 */ + top: 50%; /* 垂直居中 */ + left: calc( + (100vw + var(--width-max)) / 2 + ); /* 水平定位,根据视口宽度和最大内容宽度计算 */ + transform: translateY(-50%); /* 垂直居中调整 */ + width: calc((90vw - var(--width-max)) / 2); /* 宽度计算 */ + max-height: 80vh; /* 最大高度为视口高度的80% */ + overflow-y: auto; /* 垂直方向内容溢出时显示滚动条 */ + border: none; /* 无边框 */ + padding: 0; /* 无内边距 */ + margin: 0; /* 无外边距 */ + z-index: 99; /* 设置堆叠顺序,确保在其他元素之上 */ + + /* 隐藏滚动条 */ + &::-webkit-scrollbar { + /* Webkit 浏览器(Chrome, Safari)滚动条样式 */ + display: none; /* 隐藏滚动条 */ + } + + -ms-overflow-style: none; /* IE 和 Edge 隐藏滚动条 */ + scrollbar-width: none; /* Firefox 隐藏滚动条 */ + } + + .toc-nav { + /* 目录导航容器样式 */ + padding: 1.5rem; /* 内边距 */ + } + + .toc-nav ul { + /* 目录导航无序列表样式 */ + list-style: none; /* 移除列表项标记 */ + padding: 0; /* 移除内边距 */ + margin: 0; /* 移除外边距 */ + } + + .toc-nav li { + /* 目录导航列表项样式 */ + margin: 8px 0; /* 上下外边距 */ + } + + .toc-nav a { + /* 目录链接样式 */ + display: block; /* 块级显示 */ + text-decoration: none; /* 无下划线 */ + color: transparent; /* 默认透明 */ + padding: 0 12px; /* 内边距 */ + transition: all 0.2s ease; /* 所有属性过渡效果 */ + font-size: 0.9rem; /* 字体大小 */ + line-height: 1.4; /* 行高 */ + text-align: left; /* 文本左对齐 */ + white-space: nowrap; /* 禁止换行 */ + overflow: hidden; /* 隐藏溢出内容 */ + text-overflow: ellipsis; /* 显示省略号 */ + max-width: 100%; /* 限制最大宽度 */ + } + + .toc-nav:hover a { + color: var(--toc-text-color); /* hover时显示文字颜色 */ + } + + .toc-nav a::before { + /* 目录链接前的小横线样式 */ + content: ""; /* 生成内容 */ + display: inline-block; /* 行内块级显示 */ + width: 16px; /* 宽度 */ + height: 4px; /* 高度 */ + background-color: var(--toc-text-color); /* 灰色背景 */ + border-radius: 16px; /* 圆角 */ + margin-right: 12px; /* 右外边距 */ + vertical-align: middle; /* 垂直居中对齐 */ + } + + .toc-nav ul ul a::before { + /* 二级目录链接前的小横线样式 */ + width: 12px; /* 显示宽度 */ + margin-right: 16px; /* 调整右外边距,使其与默认 a::before 占据的总宽度一致 (12px + 12px = 24px) */ + } + + .toc-nav ul ul ul a::before { + /* 三级目录链接前的小横线样式 */ + width: 8px; /* 显示宽度 */ + margin-right: 20px; /* 调整右外边距,使其与默认 a::before 占据的总宽度一致 (8px + 16px = 24px) */ + } + + .toc-nav a.active, /* 活跃状态和鼠标悬停状态的目录链接样式 */ + .toc-nav a:hover { + text-decoration: none; /* 无下划线 */ + color: var(--toc-hover-color); /* 文字颜色变为深灰色 */ + } + + .toc-nav a.active::before, /* 活跃状态和鼠标悬停状态的目录链接前小横线样式 */ + .toc-nav a:hover::before { + background-color: var(--toc-hover-color); /* 背景颜色变为深灰色 */ + } + + /* upvote button style */ + button.upvote-btn { + margin: 0; + margin-left: auto; + padding: 0; + border: none; + background: none; + cursor: pointer; + display: flex; + flex-direction: column; + align-items: center; + color: var(--body-text-color); + } + + button.upvoted { + color: var(--upvoted-color); + } + + span.upvote-count { + margin-top: -4px; + font-size: smaller; + } + + @media (max-width: 800px) { + img[src*="#minipic"] { + max-width: 100%; + margin-left: auto; + margin-right: auto; + } + + div.toc { + display: none; + } + } +</style> diff --git a/layouts/partials/toc.html b/layouts/partials/toc.html new file mode 100644 index 0000000..66936a4 --- /dev/null +++ b/layouts/partials/toc.html @@ -0,0 +1,91 @@ +{{/* 根据页面内容生成目录 */}} +{{ if and .TableOfContents (ne .TableOfContents "<nav id=\"TableOfContents\"></nav>") }} +<nav class="toc-nav"> + {{ .TableOfContents }} +</nav> + +<script> + // 为目录添加平滑滚动和当前位置高亮 + document.addEventListener('DOMContentLoaded', function () { + const tocLinks = document.querySelectorAll('.toc-nav a'); + const headings = Array.from(tocLinks).map(link => { + const id = link.getAttribute('href').replace('#', ''); + return document.getElementById(id); + }).filter(h => h); + + // 平滑滚动 + tocLinks.forEach(link => { + link.addEventListener('click', function (e) { + e.preventDefault(); + const targetId = this.getAttribute('href').replace('#', ''); + const target = document.getElementById(targetId); + if (target) { + target.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + + // 更新活动状态 + tocLinks.forEach(l => l.classList.remove('active')); + this.classList.add('active'); + } + }); + }); + + // 滚动时更新当前位置 + function updateActiveLink() { + const scrollTop = window.pageYOffset || document.documentElement.scrollTop; + const windowHeight = window.innerHeight; + + for (let i = headings.length - 1; i >= 0; i--) { + const heading = headings[i]; + const rect = heading.getBoundingClientRect(); + + if (rect.top <= 100) { + // 移除所有活动状态 + tocLinks.forEach(link => link.classList.remove('active')); + + // 高亮当前标题 + const activeLink = document.querySelector(`.toc-nav a[href="#${heading.id}"]`); + if (activeLink) { + activeLink.classList.add('active'); + + // 高亮所有父级标题 + let currentLi = activeLink.closest('li'); + while (currentLi) { + const parentLi = currentLi.parentElement.closest('li'); + if (parentLi) { + const parentLink = parentLi.querySelector('a'); + if (parentLink) { + parentLink.classList.add('active'); + } + currentLi = parentLi; + } else { + break; + } + } + } + break; + } + } + } + + // 节流函数 + let ticking = false; + function throttleScroll() { + if (!ticking) { + requestAnimationFrame(function () { + updateActiveLink(); + ticking = false; + }); + ticking = true; + } + } + + window.addEventListener('scroll', throttleScroll); + + // 初始化时更新一次 + updateActiveLink(); + }); +</script> +{{ end }}
\ No newline at end of file diff --git a/layouts/robots.txt b/layouts/robots.txt new file mode 100644 index 0000000..0326f5c --- /dev/null +++ b/layouts/robots.txt @@ -0,0 +1,2 @@ +User-Agent: * +Sitemap: {{ "sitemap.xml" | absURL }} diff --git a/layouts/shortcodes/archives-list.html b/layouts/shortcodes/archives-list.html new file mode 100644 index 0000000..b9767f7 --- /dev/null +++ b/layouts/shortcodes/archives-list.html @@ -0,0 +1,30 @@ +{{ $allPages := where .Site.RegularPages "Type" "in" (slice "posts" "blog") }} +{{ $visiblePages := where $allPages "Params.hidden" "!=" true }} +{{ $pagesToShow := $visiblePages.ByDate.Reverse }} + +<div class="archives-content"> + <h2>归档</h2> + + <p>共有 {{ len $pagesToShow }} 篇文章</p> + + <ul class="blog-posts"> + {{ $currentYear := 0 }} + {{ range $pagesToShow }} + {{ $year := .Date.Year }} + {{ if ne $year $currentYear }} + <h3>{{ $year }}</h3> + {{ $currentYear = $year }} + {{ end }} + <li> + <span> + <i> + <time datetime='{{ .Date.Format "2006-01-02" }}'> + {{ .Date.Format "2006-01-02" }} + </time> + </i> + </span> + <a href="{{ .Permalink }}">{{ .Title }}</a> + </li> + {{ end }} + </ul> +</div> diff --git a/layouts/shortcodes/recent-posts.html b/layouts/shortcodes/recent-posts.html new file mode 100644 index 0000000..c6c1a3e --- /dev/null +++ b/layouts/shortcodes/recent-posts.html @@ -0,0 +1,55 @@ +{{ $pages := where site.RegularPages "Type" "in" site.Params.mainSections }} {{ +$recent := first 5 $pages.ByDate.Reverse }} +<style> + .recent-list { + margin: 0; + } + + .recent-item { + position: relative; + margin-bottom: 8px; + display: flex; + align-items: flex-start; + } + + .item-link { + display: inline-block; + text-decoration: none; + margin-left: 10px; + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .post-date { + font-size: 0.9em; + color: #666; + display: inline-block; + min-width: 80px; + flex-shrink: 0; + } + + .recent-empty { + text-align: center; + font-style: italic; + } +</style> +<div class="recent-posts"> + {{ if $recent }} + <ul class="recent-list"> + {{ range $index, $page := $recent }} + <li class="recent-item"> + <span class="post-date"> + <time datetime='{{ .Date.Format "2006-01-02" }}'> + {{ .Date.Format (default "2006-01-02" .Site.Params.dateFormat) }} + </time> + </span> + <a href="{{ .RelPermalink }}" class="item-link">{{ .Title }}</a> + </li> + {{ end }} + </ul> + {{ else }} + <p class="recent-empty">暂无文章</p> + {{ end }} +</div> diff --git a/layouts/shortcodes/word-count.html b/layouts/shortcodes/word-count.html new file mode 100644 index 0000000..0621ed9 --- /dev/null +++ b/layouts/shortcodes/word-count.html @@ -0,0 +1,74 @@ +{{ $scratch := newScratch }} +{{ if eq (.Get 0) "posts" }} + {{/* 统计所有博客文章 */}} + {{ range where site.RegularPages "Type" "in" (slice "posts" "jottings" "readings" "tech") }} + {{ $scratch.Add "wordcount" .WordCount }} + {{ end }} +{{ else if eq (.Get 0) "all" }} + {{/* 统计所有内容 */}} + {{ range where site.RegularPages "Type" "in" (slice "posts" "about" "newsgroup" "links" "jottings" "readings" "tech") }} + {{ $scratch.Add "wordcount" .WordCount }} + {{ end }} +{{ end }} + +{{ $count := $scratch.Get "wordcount" }} +{{ if gt $count 0 }} + {{ $count }} 字, + + {{/* 名著数据库(字数单位:汉字) */}} + {{ $classics := slice + (dict "name" "红楼梦" "author" "曹雪芹" "country" "(中)" "words" 731017) + (dict "name" "源氏物语" "author" "紫式部" "country" "(日)" "words" 876000) + (dict "name" "假面的告白" "author" "三岛由纪夫" "country" "(日)" "words" 86000) + (dict "name" "金阁寺" "author" "三岛由纪夫" "country" "(日)" "words" 125000) + (dict "name" "了不起的盖茨比" "author" "菲茨杰拉德" "country" "(美)" "words" 49800) + (dict "name" "傲慢与偏见" "author" "简·奥斯汀" "country" "(英)" "words" 183000) + (dict "name" "呐喊" "author" "鲁迅" "country" "(中)" "words" 152000) + (dict "name" "罗生门" "author" "芥川龙之介" "country" "(日)" "words" 35800) + (dict "name" "老人与海" "author" "海明威" "country" "(美)" "words" 26800) + (dict "name" "简爱" "author" "夏洛蒂·勃朗特" "country" "(英)" "words" 322000) + (dict "name" "三国演义" "author" "罗贯中" "country" "(中)" "words" 640000) + (dict "name" "雪国" "author" "川端康成" "country" "(日)" "words" 78000) + (dict "name" "杀死一只知更鸟" "author" "哈珀·李" "country" "(美)" "words" 187000) + (dict "name" "1984" "author" "乔治·奥威尔" "country" "(英)" "words" 123000) + (dict "name" "围城" "author" "钱钟书" "country" "(中)" "words" 257000) + (dict "name" "我是猫" "author" "夏目漱石" "country" "(日)" "words" 402000) + (dict "name" "飘" "author" "玛格丽特·米切尔" "country" "(美)" "words" 802000) + (dict "name" "呼啸山庄" "author" "艾米莉·勃朗特" "country" "(英)" "words" 282000) + }} + + {{/* 寻找最接近的名著 */}} + {{ $closest := dict "diff" 999999999 "book" (index $classics 0) }} + {{ range $book := $classics }} + {{ $ratio := div (float $count) $book.words }} + {{ if and (ge $ratio 0.8) (le $ratio 1.2) }} + {{ $diff := sub $ratio 1.0 }} + {{ if lt $diff 0 }}{{ $diff = mul $diff -1 }}{{ end }} + {{ if lt $diff $closest.diff }} + {{ $closest = dict "diff" $diff "book" $book }} + {{ end }} + {{ end }} + {{ end }} + + {{/* 输出对比结果 */}} + {{ with $closest.book }} + 约等于 《{{ .name }}》 的{{ div (float $count) .words | printf "%.1f" }}倍 + {{ else }} + {{/* 未找到匹配时显示长度最接近的名著 */}} + {{ $closestBook := index $classics 0 }} + {{ $minDiff := sub $count $closestBook.words }} + {{ if lt $minDiff 0 }}{{ $minDiff = mul $minDiff -1 }}{{ end }} + {{ range $classics }} + {{ $currDiff := sub $count .words }} + {{ if lt $currDiff 0 }}{{ $currDiff = mul $currDiff -1 }}{{ end }} + {{ if lt $currDiff $minDiff }} + {{ $closestBook = . }} + {{ $minDiff = $currDiff }} + {{ end }} + {{ end }} + ≈ {{ $closestBook.name }}{{ div (float $count) $closestBook.words | printf "%.1f" }}倍 + {{ end }} + +{{ else }} + 0字 +{{ end }} diff --git a/publish.sh b/publish.sh new file mode 100644 index 0000000..371276a --- /dev/null +++ b/publish.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +#word_counter=$(find ~/blog/content/ -type f -name "*.md" -exec cat {} + | \ +#perl -CSD -pe 's/[\p{P}\p{S}\s\p{M}\p{C}\p{Z}]//g; s/$$.*?$$$$.*?$$//g; s/[*#_\-`~=+|><\^]//g; s/\!$$.*?$$$$.*?$$//g' | \ +#grep -oP '[\p{Han}a-zA-Z]' | \ +#wc -m) + +commit_date=$(date +"%Y-%m-%d %H:%M:%S") + +if [ "$1" = "-b" ] || [ "$1" = "--blog" ]; then + cd ~/blog || exit 1 + hugo + git add . + git commit -m "自动提交:$commit_date" + echo "pushing hugo-blog-backup" + git push origin main + + cd ~/blog/public || exit 1 + html-minifier index.html --output index.html --collapse-whitespace --remove-comments + git add . + git commit -m "自动提交:$commit_date" + echo "pushing yingyu5658.github.io" + git push origin main + +elif [ "$1" = "-n" ] || [ "$1" = "--newsgroup" ]; then + echo "git clone https://gitee.com/yingyu5658/newsgroup_archives.git" + cd ~/blog || exit 1 + rm -rf newsgroup_archives # Cleanup any existing clone + git clone https://gitee.com/yingyu5658/newsgroup_archives.git + mv newsgroup_archives/index.html ~/newsgroup_archives/index.html + rm -rf newsgroup_archives + + cd ~/newsgroup_archives/ || exit 1 + git add . + git commit -m "$commit_date" + echo "pushing newsgroup_archives" + git pull origin main # Pull latest changes before pushing + git push origin main + +else + echo "No argument!" + exit 1 +fi + + +cd ~/blog || exit 1 +echo "=========" +echo "操作完成!" diff --git a/screenshot.webp b/screenshot.webp Binary files differnew file mode 100644 index 0000000..4e452b6 --- /dev/null +++ b/screenshot.webp diff --git a/static/avatar.webp b/static/avatar.webp Binary files differnew file mode 100644 index 0000000..414df4a --- /dev/null +++ b/static/avatar.webp diff --git a/static/css/font-awesome.min.css b/static/css/font-awesome.min.css new file mode 100644 index 0000000..540440c --- /dev/null +++ b/static/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/static/favicon.png b/static/favicon.png Binary files differnew file mode 100644 index 0000000..e5ba3d8 --- /dev/null +++ b/static/favicon.png diff --git a/static/glowisle b/static/glowisle Binary files differnew file mode 100644 index 0000000..93e9027 --- /dev/null +++ b/static/glowisle diff --git a/static/images/glowisle.jpeg b/static/images/glowisle.jpeg Binary files differnew file mode 100644 index 0000000..93e9027 --- /dev/null +++ b/static/images/glowisle.jpeg diff --git a/static/js/jquery.min.js b/static/js/jquery.min.js new file mode 100644 index 0000000..04dc4db --- /dev/null +++ b/static/js/jquery.min.js @@ -0,0 +1 @@ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}k.fn=k.prototype={jquery:f,constructor:k,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=k.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return k.each(this,e)},map:function(n){return this.pushStack(k.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},k.extend=k.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(k.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||k.isPlainObject(n)?n:{},i=!1,a[t]=k.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},k.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t){b(e,{nonce:t&&t.nonce})},each:function(e,t){var n,r=0;if(d(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(p,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(d(Object(e))?k.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(d(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g.apply([],a)},guid:1,support:y}),"function"==typeof Symbol&&(k.fn[Symbol.iterator]=t[Symbol.iterator]),k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var h=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),ne=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(m.childNodes),m.childNodes),t[m.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&((e?e.ownerDocument||e:m)!==C&&T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!A[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&U.test(t)){(s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=k),o=(l=h(t)).length;while(o--)l[o]="#"+s+" "+xe(l[o]);c=l.join(","),f=ee.test(t)&&ye(e.parentNode)||e}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){A(t,!0)}finally{s===k&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[k]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:m;return r!==C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),m!==C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=k,!C.getElementsByName||!C.getElementsByName(k).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){a.appendChild(e).innerHTML="<a id='"+k+"'></a><select id='"+k+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!==C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!==C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(F," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[S,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===S&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[k]||(a[k]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[S,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[k]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace(B,"$1"));return s[k]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[S,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[k]||(e[k]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===S&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[k]&&(v=Ce(v)),y&&!y[k]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[k]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(B,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(B," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=N[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[k]?i.push(a):o.push(a);(a=N(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=S+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t===C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument===C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(S=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(S=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=k.split("").sort(D).join("")===k,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);k.find=h,k.expr=h.selectors,k.expr[":"]=k.expr.pseudos,k.uniqueSort=k.unique=h.uniqueSort,k.text=h.getText,k.isXMLDoc=h.isXML,k.contains=h.contains,k.escapeSelector=h.escape;var T=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&k(e).is(n))break;r.push(e)}return r},S=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},N=k.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var D=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1<i.call(n,e)!==r}):k.filter(n,e,r)}k.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?k.find.matchesSelector(r,e)?[r]:[]:k.find.matches(e,k.grep(t,function(e){return 1===e.nodeType}))},k.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(k(e).filter(function(){for(t=0;t<r;t++)if(k.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)k.find(e,i[t],n);return 1<r?k.uniqueSort(n):n},filter:function(e){return this.pushStack(j(this,e||[],!1))},not:function(e){return this.pushStack(j(this,e||[],!0))},is:function(e){return!!j(this,"string"==typeof e&&N.test(e)?k(e):e||[],!1).length}});var q,L=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(k.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&k(e);if(!N.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&k.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?k.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(k(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(k.uniqueSort(k.merge(this.get(),k(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),k.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return T(e,"parentNode")},parentsUntil:function(e,t,n){return T(e,"parentNode",n)},next:function(e){return P(e,"nextSibling")},prev:function(e){return P(e,"previousSibling")},nextAll:function(e){return T(e,"nextSibling")},prevAll:function(e){return T(e,"previousSibling")},nextUntil:function(e,t,n){return T(e,"nextSibling",n)},prevUntil:function(e,t,n){return T(e,"previousSibling",n)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return"undefined"!=typeof e.contentDocument?e.contentDocument:(A(e,"template")&&(e=e.content||e),k.merge([],e.childNodes))}},function(r,i){k.fn[r]=function(e,t){var n=k.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=k.filter(t,n)),1<this.length&&(O[r]||k.uniqueSort(n),H.test(r)&&n.reverse()),this.pushStack(n)}});var R=/[^\x20\t\r\n\f]+/g;function M(e){return e}function I(e){throw e}function W(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}k.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},k.each(e.match(R)||[],function(e,t){n[t]=!0}),n):k.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){k.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return k.each(arguments,function(e,t){var n;while(-1<(n=k.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<k.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},k.extend({Deferred:function(e){var o=[["notify","progress",k.Callbacks("memory"),k.Callbacks("memory"),2],["resolve","done",k.Callbacks("once memory"),k.Callbacks("once memory"),0,"resolved"],["reject","fail",k.Callbacks("once memory"),k.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return k.Deferred(function(r){k.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,M,s),l(u,o,I,s)):(u++,t.call(e,l(u,o,M,s),l(u,o,I,s),l(u,o,M,o.notifyWith))):(a!==M&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){k.Deferred.exceptionHook&&k.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==I&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(k.Deferred.getStackHook&&(t.stackTrace=k.Deferred.getStackHook()),C.setTimeout(t))}}return k.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:M,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:M)),o[2][3].add(l(0,e,m(n)?n:I))}).promise()},promise:function(e){return null!=e?k.extend(e,a):a}},s={};return k.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=k.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(W(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)W(i[t],a(t),o.reject);return o.promise()}});var $=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;k.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&$.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},k.readyException=function(e){C.setTimeout(function(){throw e})};var F=k.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),k.ready()}k.fn.ready=function(e){return F.then(e)["catch"](function(e){k.readyException(e)}),this},k.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--k.readyWait:k.isReady)||(k.isReady=!0)!==e&&0<--k.readyWait||F.resolveWith(E,[k])}}),k.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(k.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var _=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)_(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(k(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},z=/^-ms-/,U=/-([a-z])/g;function X(e,t){return t.toUpperCase()}function V(e){return e.replace(z,"ms-").replace(U,X)}var G=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function Y(){this.expando=k.expando+Y.uid++}Y.uid=1,Y.prototype={cache:function(e){var t=e[this.expando];return t||(t={},G(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[V(t)]=n;else for(r in t)i[V(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][V(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(V):(t=V(t))in r?[t]:t.match(R)||[]).length;while(n--)delete r[t[n]]}(void 0===t||k.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!k.isEmptyObject(t)}};var Q=new Y,J=new Y,K=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Z=/[A-Z]/g;function ee(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(Z,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:K.test(i)?JSON.parse(i):i)}catch(e){}J.set(e,t,n)}else n=void 0;return n}k.extend({hasData:function(e){return J.hasData(e)||Q.hasData(e)},data:function(e,t,n){return J.access(e,t,n)},removeData:function(e,t){J.remove(e,t)},_data:function(e,t,n){return Q.access(e,t,n)},_removeData:function(e,t){Q.remove(e,t)}}),k.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=J.get(o),1===o.nodeType&&!Q.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=V(r.slice(5)),ee(o,r,i[r]));Q.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){J.set(this,n)}):_(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=J.get(o,n))?t:void 0!==(t=ee(o,n))?t:void 0;this.each(function(){J.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){J.remove(this,e)})}}),k.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Q.get(e,t),n&&(!r||Array.isArray(n)?r=Q.access(e,t,k.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=k.queue(e,t),r=n.length,i=n.shift(),o=k._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){k.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Q.get(e,n)||Q.access(e,n,{empty:k.Callbacks("once memory").add(function(){Q.remove(e,[t+"queue",n])})})}}),k.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?k.queue(this[0],t):void 0===n?this:this.each(function(){var e=k.queue(this,t,n);k._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&k.dequeue(this,t)})},dequeue:function(e){return this.each(function(){k.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=k.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Q.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var te=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,ne=new RegExp("^(?:([+-])=|)("+te+")([a-z%]*)$","i"),re=["Top","Right","Bottom","Left"],ie=E.documentElement,oe=function(e){return k.contains(e.ownerDocument,e)},ae={composed:!0};ie.getRootNode&&(oe=function(e){return k.contains(e.ownerDocument,e)||e.getRootNode(ae)===e.ownerDocument});var se=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&oe(e)&&"none"===k.css(e,"display")},ue=function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];for(o in i=n.apply(e,r||[]),t)e.style[o]=a[o];return i};function le(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return k.css(e,t,"")},u=s(),l=n&&n[3]||(k.cssNumber[t]?"":"px"),c=e.nodeType&&(k.cssNumber[t]||"px"!==l&&+u)&&ne.exec(k.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)k.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,k.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ce={};function fe(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Q.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&se(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ce[s])||(o=a.body.appendChild(a.createElement(s)),u=k.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ce[s]=u)))):"none"!==n&&(l[c]="none",Q.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}k.fn.extend({show:function(){return fe(this,!0)},hide:function(){return fe(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){se(this)?k(this).show():k(this).hide()})}});var pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Q.set(e[n],"globalEval",!t||Q.get(t[n],"globalEval"))}ge.optgroup=ge.option,ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td;var me,xe,be=/<|&#?\w+;/;function we(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))k.merge(p,o.nodeType?[o]:o);else if(be.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+k.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;k.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<k.inArray(o,r))i&&i.push(o);else if(l=oe(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}me=E.createDocumentFragment().appendChild(E.createElement("div")),(xe=E.createElement("input")).setAttribute("type","radio"),xe.setAttribute("checked","checked"),xe.setAttribute("name","t"),me.appendChild(xe),y.checkClone=me.cloneNode(!0).cloneNode(!0).lastChild.checked,me.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t<arguments.length;t++)u[t]=arguments[t];if(s.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,s)){a=k.event.handlers.call(this,s,l),t=0;while((i=a[t++])&&!s.isPropagationStopped()){s.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!s.isImmediatePropagationStopped())s.rnamespace&&!1!==o.namespace&&!s.rnamespace.test(o.namespace)||(s.handleObj=o,s.data=o.data,void 0!==(r=((k.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,u))&&!1===(s.result=r)&&(s.preventDefault(),s.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,s),s.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<k(i,this).index(l):k.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(k.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[k.expando]?e:new k.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click",ke),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&De(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Q.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},k.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},k.Event=function(e,t){if(!(this instanceof k.Event))return new k.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?ke:Se,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&k.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[k.expando]=!0},k.Event.prototype={constructor:k.Event,isDefaultPrevented:Se,isPropagationStopped:Se,isImmediatePropagationStopped:Se,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=ke,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=ke,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=ke,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},k.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&Te.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&Ce.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},k.event.addProp),k.each({focus:"focusin",blur:"focusout"},function(e,t){k.event.special[e]={setup:function(){return De(this,e,Ne),!1},trigger:function(){return De(this,e),!0},delegateType:t}}),k.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){k.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||k.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),k.fn.extend({on:function(e,t,n,r){return Ae(this,e,t,n,r)},one:function(e,t,n,r){return Ae(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,k(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Se),this.each(function(){k.event.remove(this,e,n,t)})}});var je=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/<script|<style|<link/i,Le=/checked\s*(?:[^=]|=\s*.checked.)/i,He=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n<r;n++)k.event.add(t,i,l[i][n]);J.hasData(e)&&(s=J.access(e),u=k.extend({},s),J.set(t,u))}}function Ie(n,r,i,o){r=g.apply([],r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&Le.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Ie(t,r,i,o)});if(f&&(t=(e=we(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=k.map(ve(e,"script"),Pe)).length;c<f;c++)u=e,c!==p&&(u=k.clone(u,!0,!0),s&&k.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,k.map(a,Re),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Q.access(u,"globalEval")&&k.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?k._evalUrl&&!u.noModule&&k._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")}):b(u.textContent.replace(He,""),u,l))}return n}function We(e,t,n){for(var r,i=t?k.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||k.cleanData(ve(r)),r.parentNode&&(n&&oe(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}k.extend({htmlPrefilter:function(e){return e.replace(je,"<$1></$2>")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Me(o[r],a[r]);else Me(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=k.event.special,o=0;void 0!==(n=e[o]);o++)if(G(n)){if(t=n[Q.expando]){if(t.events)for(r in t.events)i[r]?k.event.remove(n,r):k.removeEvent(n,r,t.handle);n[Q.expando]=void 0}n[J.expando]&&(n[J.expando]=void 0)}}}),k.fn.extend({detach:function(e){return We(this,e,!0)},remove:function(e){return We(this,e)},text:function(e){return _(this,function(e){return void 0===e?k.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Oe(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Oe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(k.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return k.clone(this,e,t)})},html:function(e){return _(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!qe.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=k.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(k.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Ie(this,arguments,function(e){var t=this.parentNode;k.inArray(this,n)<0&&(k.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),k.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){k.fn[e]=function(e){for(var t,n=[],r=k(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),k(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var $e=new RegExp("^("+te+")(?!px)[a-z%]+$","i"),Fe=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},Be=new RegExp(re.join("|"),"i");function _e(e,t,n){var r,i,o,a,s=e.style;return(n=n||Fe(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||oe(e)||(a=k.style(e,t)),!y.pixelBoxStyles()&&$e.test(a)&&Be.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function ze(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(u){s.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",u.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",ie.appendChild(s).appendChild(u);var e=C.getComputedStyle(u);n="1%"!==e.top,a=12===t(e.marginLeft),u.style.right="60%",o=36===t(e.right),r=36===t(e.width),u.style.position="absolute",i=12===t(u.offsetWidth/3),ie.removeChild(s),u=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s=E.createElement("div"),u=E.createElement("div");u.style&&(u.style.backgroundClip="content-box",u.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===u.style.backgroundClip,k.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),a},scrollboxSize:function(){return e(),i}}))}();var Ue=["Webkit","Moz","ms"],Xe=E.createElement("div").style,Ve={};function Ge(e){var t=k.cssProps[e]||Ve[e];return t||(e in Xe?e:Ve[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Ue.length;while(n--)if((e=Ue[n]+t)in Xe)return e}(e)||e)}var Ye=/^(none|table(?!-c[ea]).+)/,Qe=/^--/,Je={position:"absolute",visibility:"hidden",display:"block"},Ke={letterSpacing:"0",fontWeight:"400"};function Ze(e,t,n){var r=ne.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function et(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=k.css(e,n+re[a],!0,i)),r?("content"===n&&(u-=k.css(e,"padding"+re[a],!0,i)),"margin"!==n&&(u-=k.css(e,"border"+re[a]+"Width",!0,i))):(u+=k.css(e,"padding"+re[a],!0,i),"padding"!==n?u+=k.css(e,"border"+re[a]+"Width",!0,i):s+=k.css(e,"border"+re[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function tt(e,t,n){var r=Fe(e),i=(!y.boxSizingReliable()||n)&&"border-box"===k.css(e,"boxSizing",!1,r),o=i,a=_e(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if($e.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||"auto"===a||!parseFloat(a)&&"inline"===k.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===k.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+et(e,t,n||(i?"border":"content"),o,r,a)+"px"}function nt(e,t,n,r,i){return new nt.prototype.init(e,t,n,r,i)}k.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=_e(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=V(t),u=Qe.test(t),l=e.style;if(u||(t=Ge(s)),a=k.cssHooks[t]||k.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=ne.exec(n))&&i[1]&&(n=le(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(k.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=V(t);return Qe.test(t)||(t=Ge(s)),(a=k.cssHooks[t]||k.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=_e(e,t,r)),"normal"===i&&t in Ke&&(i=Ke[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),k.each(["height","width"],function(e,u){k.cssHooks[u]={get:function(e,t,n){if(t)return!Ye.test(k.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?tt(e,u,n):ue(e,Je,function(){return tt(e,u,n)})},set:function(e,t,n){var r,i=Fe(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===k.css(e,"boxSizing",!1,i),s=n?et(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-et(e,u,"border",!1,i)-.5)),s&&(r=ne.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=k.css(e,u)),Ze(0,t,s)}}}),k.cssHooks.marginLeft=ze(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(_e(e,"marginLeft"))||e.getBoundingClientRect().left-ue(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),k.each({margin:"",padding:"",border:"Width"},function(i,o){k.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+re[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(k.cssHooks[i+o].set=Ze)}),k.fn.extend({css:function(e,t){return _(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Fe(e),i=t.length;a<i;a++)o[t[a]]=k.css(e,t[a],!1,r);return o}return void 0!==n?k.style(e,t,n):k.css(e,t)},e,t,1<arguments.length)}}),((k.Tween=nt).prototype={constructor:nt,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||k.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(k.cssNumber[n]?"":"px")},cur:function(){var e=nt.propHooks[this.prop];return e&&e.get?e.get(this):nt.propHooks._default.get(this)},run:function(e){var t,n=nt.propHooks[this.prop];return this.options.duration?this.pos=t=k.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):nt.propHooks._default.set(this),this}}).init.prototype=nt.prototype,(nt.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=k.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){k.fx.step[e.prop]?k.fx.step[e.prop](e):1!==e.elem.nodeType||!k.cssHooks[e.prop]&&null==e.elem.style[Ge(e.prop)]?e.elem[e.prop]=e.now:k.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=nt.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},k.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},k.fx=nt.prototype.init,k.fx.step={};var rt,it,ot,at,st=/^(?:toggle|show|hide)$/,ut=/queueHooks$/;function lt(){it&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(lt):C.setTimeout(lt,k.fx.interval),k.fx.tick())}function ct(){return C.setTimeout(function(){rt=void 0}),rt=Date.now()}function ft(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=re[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function pt(e,t,n){for(var r,i=(dt.tweeners[t]||[]).concat(dt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function dt(o,e,t){var n,a,r=0,i=dt.prefilters.length,s=k.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=rt||ct(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:k.extend({},e),opts:k.extend(!0,{specialEasing:{},easing:k.easing._default},t),originalProperties:e,originalOptions:t,startTime:rt||ct(),duration:t.duration,tweens:[],createTween:function(e,t){var n=k.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=V(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=k.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=dt.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(k._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return k.map(c,pt,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),k.fx.timer(k.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}k.Animation=k.extend(dt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return le(n.elem,e,ne.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(R);for(var n,r=0,i=e.length;r<i;r++)n=e[r],dt.tweeners[n]=dt.tweeners[n]||[],dt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&se(e),v=Q.get(e,"fxshow");for(r in n.queue||(null==(a=k._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,k.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],st.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||k.style(e,r)}if((u=!k.isEmptyObject(t))||!k.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Q.get(e,"display")),"none"===(c=k.css(e,"display"))&&(l?c=l:(fe([e],!0),l=e.style.display||l,c=k.css(e,"display"),fe([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===k.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Q.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&fe([e],!0),p.done(function(){for(r in g||fe([e]),Q.remove(e,"fxshow"),d)k.style(e,r,d[r])})),u=pt(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?dt.prefilters.unshift(e):dt.prefilters.push(e)}}),k.speed=function(e,t,n){var r=e&&"object"==typeof e?k.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return k.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in k.fx.speeds?r.duration=k.fx.speeds[r.duration]:r.duration=k.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&k.dequeue(this,r.queue)},r},k.fn.extend({fadeTo:function(e,t,n,r){return this.filter(se).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=k.isEmptyObject(t),o=k.speed(e,n,r),a=function(){var e=dt(this,k.extend({},t),o);(i||Q.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&!1!==i&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=k.timers,r=Q.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&ut.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||k.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Q.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=k.timers,o=n?n.length:0;for(t.finish=!0,k.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),k.each(["toggle","show","hide"],function(e,r){var i=k.fn[r];k.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(ft(r,!0),e,t,n)}}),k.each({slideDown:ft("show"),slideUp:ft("hide"),slideToggle:ft("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){k.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),k.timers=[],k.fx.tick=function(){var e,t=0,n=k.timers;for(rt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||k.fx.stop(),rt=void 0},k.fx.timer=function(e){k.timers.push(e),k.fx.start()},k.fx.interval=13,k.fx.start=function(){it||(it=!0,lt())},k.fx.stop=function(){it=null},k.fx.speeds={slow:600,fast:200,_default:400},k.fn.delay=function(r,e){return r=k.fx&&k.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},ot=E.createElement("input"),at=E.createElement("select").appendChild(E.createElement("option")),ot.type="checkbox",y.checkOn=""!==ot.value,y.optSelected=at.selected,(ot=E.createElement("input")).value="t",ot.type="radio",y.radioValue="t"===ot.value;var ht,gt=k.expr.attrHandle;k.fn.extend({attr:function(e,t){return _(this,k.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){k.removeAttr(this,e)})}}),k.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?k.prop(e,t,n):(1===o&&k.isXMLDoc(e)||(i=k.attrHooks[t.toLowerCase()]||(k.expr.match.bool.test(t)?ht:void 0)),void 0!==n?null===n?void k.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=k.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(R);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),ht={set:function(e,t,n){return!1===t?k.removeAttr(e,n):e.setAttribute(n,n),n}},k.each(k.expr.match.bool.source.match(/\w+/g),function(e,t){var a=gt[t]||k.find.attr;gt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=gt[o],gt[o]=r,r=null!=a(e,t,n)?o:null,gt[o]=i),r}});var vt=/^(?:input|select|textarea|button)$/i,yt=/^(?:a|area)$/i;function mt(e){return(e.match(R)||[]).join(" ")}function xt(e){return e.getAttribute&&e.getAttribute("class")||""}function bt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(R)||[]}k.fn.extend({prop:function(e,t){return _(this,k.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[k.propFix[e]||e]})}}),k.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&k.isXMLDoc(e)||(t=k.propFix[t]||t,i=k.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=k.find.attr(e,"tabindex");return t?parseInt(t,10):vt.test(e.nodeName)||yt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(k.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),k.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){k.propFix[this.toLowerCase()]=this}),k.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).addClass(t.call(this,e,xt(this)))});if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){k(this).removeClass(t.call(this,e,xt(this)))});if(!arguments.length)return this.attr("class","");if((e=bt(t)).length)while(n=this[u++])if(i=xt(n),r=1===n.nodeType&&" "+mt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=mt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){k(this).toggleClass(i.call(this,e,xt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=k(this),r=bt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=xt(this))&&Q.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Q.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+mt(xt(n))+" ").indexOf(t))return!0;return!1}});var wt=/\r/g;k.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,k(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=k.map(t,function(e){return null==e?"":e+""})),(r=k.valHooks[this.type]||k.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=k.valHooks[t.type]||k.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(wt,""):null==e?"":e:void 0}}),k.extend({valHooks:{option:{get:function(e){var t=k.find.attr(e,"value");return null!=t?t:mt(k.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=k(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=k.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<k.inArray(k.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),k.each(["radio","checkbox"],function(){k.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<k.inArray(k(e).val(),t)}},y.checkOn||(k.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var Tt=/^(?:focusinfocus|focusoutblur)$/,Ct=function(e){e.stopPropagation()};k.extend(k.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!Tt.test(d+k.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[k.expando]?e:new k.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:k.makeArray(t,[e]),c=k.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,Tt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Q.get(o,"events")||{})[e.type]&&Q.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&G(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!G(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),k.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,Ct),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,Ct),k.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=k.extend(new k.Event,n,{type:e,isSimulated:!0});k.event.trigger(r,null,t)}}),k.fn.extend({trigger:function(e,t){return this.each(function(){k.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return k.event.trigger(e,t,n,!0)}}),y.focusin||k.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){k.event.simulate(r,e.target,k.event.fix(e))};k.event.special[r]={setup:function(){var e=this.ownerDocument||this,t=Q.access(e,r);t||e.addEventListener(n,i,!0),Q.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this,t=Q.access(e,r)-1;t?Q.access(e,r,t):(e.removeEventListener(n,i,!0),Q.remove(e,r))}}});var Et=C.location,kt=Date.now(),St=/\?/;k.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||k.error("Invalid XML: "+e),t};var Nt=/\[\]$/,At=/\r?\n/g,Dt=/^(?:submit|button|image|reset|file)$/i,jt=/^(?:input|select|textarea|keygen)/i;function qt(n,e,r,i){var t;if(Array.isArray(e))k.each(e,function(e,t){r||Nt.test(n)?i(n,t):qt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)qt(n+"["+t+"]",e[t],r,i)}k.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!k.isPlainObject(e))k.each(e,function(){i(this.name,this.value)});else for(n in e)qt(n,e[n],t,i);return r.join("&")},k.fn.extend({serialize:function(){return k.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=k.prop(this,"elements");return e?k.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!k(this).is(":disabled")&&jt.test(this.nodeName)&&!Dt.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=k(this).val();return null==n?null:Array.isArray(n)?k.map(n,function(e){return{name:t.name,value:e.replace(At,"\r\n")}}):{name:t.name,value:n.replace(At,"\r\n")}}).get()}});var Lt=/%20/g,Ht=/#.*$/,Ot=/([?&])_=[^&]*/,Pt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Rt=/^(?:GET|HEAD)$/,Mt=/^\/\//,It={},Wt={},$t="*/".concat("*"),Ft=E.createElement("a");function Bt(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(R)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function _t(t,i,o,a){var s={},u=t===Wt;function l(e){var r;return s[e]=!0,k.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function zt(e,t){var n,r,i=k.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&k.extend(!0,e,r),e}Ft.href=Et.href,k.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":$t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":k.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?zt(zt(e,k.ajaxSettings),t):zt(k.ajaxSettings,e)},ajaxPrefilter:Bt(It),ajaxTransport:Bt(Wt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=k.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?k(y):k.event,x=k.Deferred(),b=k.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Pt.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Et.href)+"").replace(Mt,Et.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(R)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Ft.protocol+"//"+Ft.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=k.param(v.data,v.traditional)),_t(It,v,t,T),h)return T;for(i in(g=k.event&&v.global)&&0==k.active++&&k.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Rt.test(v.type),f=v.url.replace(Ht,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(Lt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(St.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Ot,"$1"),o=(St.test(f)?"&":"?")+"_="+kt+++o),v.url=f+o),v.ifModified&&(k.lastModified[f]&&T.setRequestHeader("If-Modified-Since",k.lastModified[f]),k.etag[f]&&T.setRequestHeader("If-None-Match",k.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+$t+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=_t(Wt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(k.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(k.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--k.active||k.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return k.get(e,t,n,"json")},getScript:function(e,t){return k.get(e,void 0,t,"script")}}),k.each(["get","post"],function(e,i){k[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),k.ajax(k.extend({url:e,type:i,dataType:r,data:t,success:n},k.isPlainObject(e)&&e))}}),k._evalUrl=function(e,t){return k.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){k.globalEval(e,t)}})},k.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=k(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){k(this).wrapInner(n.call(this,e))}):this.each(function(){var e=k(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){k(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){k(this).replaceWith(this.childNodes)}),this}}),k.expr.pseudos.hidden=function(e){return!k.expr.pseudos.visible(e)},k.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},k.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var Ut={0:200,1223:204},Xt=k.ajaxSettings.xhr();y.cors=!!Xt&&"withCredentials"in Xt,y.ajax=Xt=!!Xt,k.ajaxTransport(function(i){var o,a;if(y.cors||Xt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(Ut[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),k.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),k.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return k.globalEval(e),e}}}),k.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),k.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=k("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=mt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&k.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?k("<div>").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}}),k.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),k.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}}),k.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||k.guid++,i},k.holdReady=function(e){e?k.readyWait++:k.ready(!0)},k.isArray=Array.isArray,k.parseJSON=JSON.parse,k.nodeName=A,k.isFunction=m,k.isWindow=x,k.camelCase=V,k.type=w,k.now=Date.now,k.isNumeric=function(e){var t=k.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},"function"==typeof define&&define.amd&&define("jquery",[],function(){return k});var Qt=C.jQuery,Jt=C.$;return k.noConflict=function(e){return C.$===k&&(C.$=Jt),e&&C.jQuery===k&&(C.jQuery=Qt),k},e||(C.jQuery=C.$=k),k}); diff --git a/static/js/webmention.js b/static/js/webmention.js new file mode 100644 index 0000000..dc9bc5c --- /dev/null +++ b/static/js/webmention.js @@ -0,0 +1,475 @@ +/* webmention.js + +Simple thing for embedding webmentions from webmention.io into a page, client-side. + +(c)2018-2022 fluffy (http://beesbuzz.biz) + +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. + +GitHub repo (for latest released versions, issue tracking, etc.): + + https://github.com/PlaidWeb/webmention.js + +Basic usage: + +<script src="/path/to/webmention.js" data-param="val" ... async /> +<div id="webmentions"></div> + +Allowed parameters: + + page-url: + + The base URL to use for this page. Defaults to window.location + + add-urls: + + Additional URLs to check, separated by |s + + id: + + The HTML ID for the object to fill in with the webmention data. + Defaults to "webmentions" + + wordcount: + + The maximum number of words to render in reply mentions. + + max-webmentions: + + The maximum number of mentions to retrieve. Defaults to 30. + + prevent-spoofing: + + By default, Webmentions render using the mf2 'url' element, which plays + nicely with webmention bridges (such as brid.gy and telegraph) + but allows certain spoofing attacks. If you would like to prevent + spoofing, set this to a non-empty string (e.g. "true"). + + sort-by: + + What to order the responses by; defaults to 'published'. See + https://github.com/aaronpk/webmention.io#api + + sort-dir: + + The order to sort the responses by; defaults to 'up' (i.e. oldest + first). See https://github.com/aaronpk/webmention.io#api + + comments-are-reactions: + + If set to a non-empty string (e.g. "true"), will display comment-type responses + (replies/mentions/etc.) as being part of the reactions + (favorites/bookmarks/etc.) instead of in a separate comment list. + +A more detailed example: + +<!-- If you want to translate the UI --> +<script src="/path/to/umd/i18next.js"></script> +<script> + // Setup i18next as described in https://www.i18next.com/overview/getting-started#basic-sample +</script> +<!-- Otherwise, only using the following is fine --> +<script src="/path/to/webmention.min.js" + data-id="webmentionContainer" + data-wordcount="30" + data-prevent-spoofing="true" + data-comments-are-reactions="true" + /> + +*/ + +// Begin LibreJS code licensing +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt + +(function () { + "use strict"; + + // Shim i18next + window.i18next = window.i18next || { + t: function t(/** @type {string} */key) { return key; } + } + const t = window.i18next.t.bind(window.i18next); + + /** + * Read the configuration value. + * + * @param {string} key The configuration key. + * @param {string} dfl The default value. + * @returns {string} + */ + function getCfg(key, dfl) { + return document.currentScript.getAttribute("data-" + key) || dfl; + } + + const refurl = getCfg("page-url", window.location.href.replace(/#.*$/, "")); + const addurls = getCfg("add-urls", undefined); + const containerID = getCfg("id", "webmentions"); + /** @type {Number} */ + const textMaxWords = getCfg("wordcount"); + const maxWebmentions = getCfg("max-webmentions", 30); + const mentionSource = getCfg("prevent-spoofing") ? "wm-source" : "url"; + const sortBy = getCfg("sort-by", "published"); + const sortDir = getCfg("sort-dir", "up"); + /** @type {boolean} */ + const commentsAreReactions = getCfg("comments-are-reactions", false); + + /** + * @typedef MentionType + * @type {"in-reply-to"|"like-of"|"repost-of"|"bookmark-of"|"mention-of"|"rsvp"|"follow-of"} + */ + + /** + * Maps a reaction to a hover title. + * + * @type {Record<MentionType, string>} + */ + const reactTitle = { + "in-reply-to": t("replied"), + "like-of": t("liked"), + "repost-of": t("reposted"), + "bookmark-of": t("bookmarked"), + "mention-of": t("mentioned"), + "rsvp": t("RSVPed"), + "follow-of": t("followed") + }; + + /** + * Maps a reaction to an emoji. + * + * @type {Record<MentionType, string>} + */ + const reactEmoji = { + "in-reply-to": "💬", + "like-of": "❤️", + "repost-of": "🔄", + "bookmark-of": "⭐️", + "mention-of": "💬", + "rsvp": "📅", + "follow-of": "🐜" + }; + + /** + * @typedef RSVPEmoji + * @type {"yes"|"no"|"interested"|"maybe"|null} + */ + + /** + * Maps a RSVP to an emoji. + * + * @type {Record<RSVPEmoji, string>} + */ + const rsvpEmoji = { + "yes": "✅", + "no": "❌", + "interested": "💡", + "maybe": "💭" + }; + + /** + * HTML escapes the string. + * + * @param {string} text The string to be escaped. + * @returns {string} + */ + function entities(text) { + return text.replace(/[&<>"]/g, (tag) => ({ + '&': '&', + '<': '<', + '>': '>', + '"': '"', + }[tag] || tag)); + } + + /** + * Creates the markup for an reaction image. + * + * @param {Reaction} r + * @param {boolean} isComment + * @returns {string} + */ + function reactImage(r, isComment) { + const who = entities( + r.author?.name || r.url.split("/")[2] + ); + /** @type {string} */ + let response = reactTitle[r["wm-property"]] || t("reacted"); + if (!isComment && r.content && r.content.text) { + response += ": " + extractComment(r); + } + + let authorPhoto = ''; + if (r.author && r.author.photo) { + authorPhoto = ` + <img + src="${entities(r.author.photo)}" + loading="lazy" + decoding="async" + alt="${who}" + > + `; + } else { + authorPhoto = ` + <img + class="missing" + src="data:image/webp;base64,UklGRkoCAABXRUJQVlA4TD4CAAAvP8APAIV0WduUOLr/m/iqY6SokDJSMD5xYX23SQizRsVdZmIj/f6goYUbiOj/BED7MOPReuBNT3vBesSzIex+SeqMFFkjebFmzH3S7POxDSJ1yaCbCmMnS2R46cRMPyQLw4GBK4esdK60pYwsZakecUCl5zsHv/5cPH08nx9/7i6rEEVCg2hR8VSd30PxMZpVoJZQO6Dixgg6X5oKFCmlVHIDmmMFShWumAXgCuyqVN8hHff/k+9fj8+ei7BVjpxBmZCUJv+6DhWGZwWvs+UoLHFCKsPYpfJtIcEXBTopEEsKwedZUv4ku1FZErKULLyQwFGgnmTs2vBD5qu44xwnG9uyjgrFOd+KRVlXyQfwQlauydaU6AVI7OjKXLUEqNtxJBmQegNDZgV7lxxqYMOMrDyC1NdAGbdiH9Ij0skjG+oTyfO0lmjdgvoH8iIgreuBMRYLSH+R3sAztXgL+XfS7E2bmfo6gnS0TrpnzHT7kL+skj7PgHuBwv/zpN8LDLQg7zfJZLBubMKnyeh6ZGyfDEfc2LYpnlUtG7JqsSHq1WoASbUS4KVaLwB8be5mfsGMDwBcm5VxbuxWxx3nkFanB6lYqsqSkOGkKicoDvXsneR7BkKU7DtaEuT7+pxBGVwx+9gVyqf2pVA9sC2CsmjZ1RJqEJHS4Tj/pCcS0JoyBYOsB91Xjh3OFfQPQhvCAYyeLJlaOoFp0XNNuD0BC8exr8uPx7D1JWkwFdZIXmD3MOPReuDNzHjBesSzIbQD" + alt="${who}$" + > + `; + } + + let rsvp = ''; + if (r.rsvp && rsvpEmoji[r.rsvp]) { + rsvp = `<sub>${rsvpEmoji[r.rsvp]}</sub>`; + } + + return` + <a + class="reaction" + rel="nofollow ugc" + title="${who} ${response}" + href="${r[mentionSource]}" + > + ${authorPhoto} + ${(reactEmoji[r['wm-property']] || '💥')} + ${rsvp} + </a> + `; + } + + /** + * Strip the protocol off a URL. + * + * @param {string} url The URL to strip protocol off. + * @returns {string} + */ + function stripurl(url) { + return url.substr(url.indexOf('//')); + } + + /** + * Deduplicate multiple mentions from the same source URL. + * + * @param {Array<Reaction>} mentions Mentions of the source URL. + * @return {Array<Reaction>} + */ + function dedupe(mentions) { + /** @type {Array<Reaction>} */ + const filtered = []; + /** @type {Record<string, boolean>} */ + const seen = {}; + + mentions.forEach(function(r) { + // Strip off the protocol (i.e. treat http and https the same) + const source = stripurl(r.url); + if (!seen[source]) { + filtered.push(r); + seen[source] = true; + } + }); + + return filtered; + } + + /** + * Extract comments from a reaction. + * + * @param {Reactions} c + * @returns string + */ + function extractComment(c) { + let text = entities(c.content.text); + + if (textMaxWords) { + let words = text.replace(/\s+/g,' ').split(' ', textMaxWords + 1); + if (words.length > textMaxWords) { + words[textMaxWords - 1] += '…'; + words = words.slice(0, textMaxWords); + text = words.join(' '); + } + } + + return text; + } + + /** + * Format comments as HTML. + * + * @param {Array<Reaction>} comments The comments to format. + * @returns string + */ + function formatComments(comments) { + const headline = `<h2>${t('Responses')}</h2>`; + const markup = comments + .map((c) => { + const image = reactImage(c, true); + + let source = entities(c.url.split('/')[2]); + if (c.author && c.author.name) { + source = entities(c.author.name); + } + const link = `<a class="source" rel="nofollow ugc" href="${c[mentionSource]}">${source}</a>`; + + let linkclass = "name"; + let linktext = `(${t("mention")})`; + if (c.name) { + linkclass = "name"; + linktext = entities(c.name); + } else if (c.content && c.content.text) { + linkclass = "text"; + linktext = extractComment(c); + } + + const type = `<span class="${linkclass}">${linktext}</span>`; + + return `<li>${image} ${link} ${type}</li>`; + }) + .join(''); + return ` + ${headline} + <ul class="comments">${markup}</ul> + `; + } + + /** + * @typedef {Object} Reaction + * @property {string} url + * @property {Object?} author + * @property {string?} author.name + * @property {string?} author.photo + * @property {Object?} content + * @property {string?} content.text + * @property {RSVPEmoji?} rsvp + * @property {MentionType?} wm-property + * @property {string?} wm-source + */ + + /** + * Formats a list of reactions as HTML. + * + * @param {Array<Reaction>} reacts List of reactions to format + * @returns string + */ + function formatReactions(reacts) { + const headline = `<h2>${t('Reactions')}</h2>`; + + const markup = reacts.map((r) => reactImage(r)).join(''); + + return ` + ${headline} + <ul class="reacts">${markup}</ul> + `; + } + + /** + * @typedef WebmentionResponse + * @type {Object} + * @property {Array<Reaction>} children + */ + + /** + * Register event listener. + */ + window.addEventListener("load", async function () { + const container = document.getElementById(containerID); + if (!container) { + // no container, so do nothing + return; + } + + const pages = [stripurl(refurl)]; + if (!!addurls) { + addurls.split('|').forEach(function (url) { + pages.push(stripurl(url)); + }); + } + + let apiURL = `https://webmention.io/api/mentions.jf2?per-page=${maxWebmentions}&sort-by=${sortBy}&sort-dir=${sortDir}`; + + pages.forEach(function (path) { + apiURL += `&target[]=${encodeURIComponent('http:' + path)}&target[]=${encodeURIComponent('https:' + path)}`; + }); + + /** @type {WebmentionResponse} */ + let json = {}; + try { + const response = await window.fetch(apiURL); + if (response.status >= 200 && response.status < 300) { + json = await response.json(); + } else { + console.error("Could not parse response"); + new Error(response.statusText); + } + } catch(error) { + // Purposefully not escalate further, i.e. no UI update + console.error("Request failed", error); + } + + /** @type {Array<Reaction>} */ + let comments = []; + /** @type {Array<Reaction>} */ + const collects = []; + + if (commentsAreReactions) { + comments = collects; + } + + /** @type {Record<MentionType, Array<Reaction>>} */ + const mapping = { + "in-reply-to": comments, + "like-of": collects, + "repost-of": collects, + "bookmark-of": collects, + "follow-of": collects, + "mention-of": comments, + "rsvp": comments + }; + + json.children.forEach(function(child) { + // Map each mention into its respective container + const store = mapping[child['wm-property']]; + if (store) { + store.push(child); + } + }); + + // format the comment-type things + let formattedComments = ''; + if (comments.length > 0 && comments !== collects) { + formattedComments = formatComments(dedupe(comments)); + } + + // format the other reactions + let reactions = ''; + if (collects.length > 0) { + reactions = formatReactions(dedupe(collects)); + } + + let finalHtml =`${formattedComments}${reactions}`; + if(!finalHtml.trim()) { + finalHtml = '<p class="wm-empty">Nothing.</p>'; + } + + // 关键修正:将 finalHtml 变量的内容,赋值给容器的 innerHTML 属性 + container.innerHTML = finalHtml; + + }); +}()); + +// End-of-file marker for LibreJS +// @license-end diff --git a/static/js/webmention.min.js b/static/js/webmention.min.js new file mode 100644 index 0000000..61f107d --- /dev/null +++ b/static/js/webmention.min.js @@ -0,0 +1,196 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt +!(function () { + "use strict"; + window.i18next = window.i18next || { + t: function t(e) { + return e; + }, + }; + let t = window.i18next.t.bind(window.i18next); + function e(t, e) { + return document.currentScript.getAttribute("data-" + t) || e; + } + let o = e("page-url", window.location.href.replace(/#.*$/, "")), + n = e("add-urls", void 0), + r = e("id", "webmentions"), + s = e("wordcount"), + l = e("max-webmentions", 30), + i = e("prevent-spoofing") ? "wm-source" : "url", + a = e("sort-by", "published"), + u = e("sort-dir", "up"), + p = e("comments-are-reactions", !1), + c = { + "in-reply-to": t("replied"), + "like-of": t("liked"), + "repost-of": t("reposted"), + "bookmark-of": t("bookmarked"), + "mention-of": t("mentioned"), + rsvp: t("RSVPed"), + "follow-of": t("followed"), + }, + f = { + "in-reply-to": "\uD83D\uDCAC", + "like-of": "❤️", + "repost-of": "\uD83D\uDD04", + "bookmark-of": "⭐️", + "mention-of": "\uD83D\uDCAC", + rsvp: "\uD83D\uDCC5", + "follow-of": "\uD83D\uDC1C", + }, + m = { + yes: "✅", + no: "❌", + interested: "\uD83D\uDCA1", + maybe: "\uD83D\uDCAD", + }; + function d(t) { + return t.replace( + /[&<>"]/g, + (t) => + ({ "&": "&", "<": "<", ">": ">", '"': """ })[ + t + ] || t, + ); + } + function h(e, o) { + let n = d(e.author?.name || e.url.split("/")[2]), + r = c[e["wm-property"]] || t("reacted"); + !o && e.content && e.content.text && (r += ": " + x(e)); + let s = ""; + s = + e.author && e.author.photo + ? ` + <img + src="${d(e.author.photo)}" + loading="lazy" + decoding="async" + alt="${n}" + > + ` + : ` + <img + class="missing" + src="data:image/webp;base64,UklGRkoCAABXRUJQVlA4TD4CAAAvP8APAIV0WduUOLr/m/iqY6SokDJSMD5xYX23SQizRsVdZmIj/f6goYUbiOj/BED7MOPReuBNT3vBesSzIex+SeqMFFkjebFmzH3S7POxDSJ1yaCbCmMnS2R46cRMPyQLw4GBK4esdK60pYwsZakecUCl5zsHv/5cPH08nx9/7i6rEEVCg2hR8VSd30PxMZpVoJZQO6Dixgg6X5oKFCmlVHIDmmMFShWumAXgCuyqVN8hHff/k+9fj8+ei7BVjpxBmZCUJv+6DhWGZwWvs+UoLHFCKsPYpfJtIcEXBTopEEsKwedZUv4ku1FZErKULLyQwFGgnmTs2vBD5qu44xwnG9uyjgrFOd+KRVlXyQfwQlauydaU6AVI7OjKXLUEqNtxJBmQegNDZgV7lxxqYMOMrDyC1NdAGbdiH9Ij0skjG+oTyfO0lmjdgvoH8iIgreuBMRYLSH+R3sAztXgL+XfS7E2bmfo6gnS0TrpnzHT7kL+skj7PgHuBwv/zpN8LDLQg7zfJZLBubMKnyeh6ZGyfDEfc2LYpnlUtG7JqsSHq1WoASbUS4KVaLwB8be5mfsGMDwBcm5VxbuxWxx3nkFanB6lYqsqSkOGkKicoDvXsneR7BkKU7DtaEuT7+pxBGVwx+9gVyqf2pVA9sC2CsmjZ1RJqEJHS4Tj/pCcS0JoyBYOsB91Xjh3OFfQPQhvCAYyeLJlaOoFp0XNNuD0BC8exr8uPx7D1JWkwFdZIXmD3MOPReuDNzHjBesSzIbQD" + alt="${n}$" + > + `; + let l = ""; + return ( + e.rsvp && m[e.rsvp] && (l = `<sub>${m[e.rsvp]}</sub>`), + ` + <a + class="reaction" + rel="nofollow ugc" + title="${n} ${r}" + href="${e[i]}" + > + ${s} + ${f[e["wm-property"]] || "\uD83D\uDCA5"} + ${l} + </a> + ` + ); + } + function g(t) { + return t.substr(t.indexOf("//")); + } + function w(t) { + let e = [], + o = {}; + return ( + t.forEach(function (t) { + let n = g(t.url); + o[n] || (e.push(t), (o[n] = !0)); + }), + e + ); + } + function x(t) { + let e = d(t.content.text); + if (s) { + let o = e.replace(/\s+/g, " ").split(" ", s + 1); + o.length > s && + ((o[s - 1] += "…"), (e = (o = o.slice(0, s)).join(" "))); + } + return e; + } + window.addEventListener("load", async function () { + let e = document.getElementById(r); + if (!e) return; + let s = [g(o)]; + n && + n.split("|").forEach(function (t) { + s.push(g(t)); + }); + let c = `https://webmention.io/api/mentions.jf2?per-page=${l}&sort-by=${a}&sort-dir=${u}`; + s.forEach(function (t) { + c += `&target[]=${encodeURIComponent("http:" + t)}&target[]=${encodeURIComponent("https:" + t)}`; + }); + let f = {}; + try { + let m = await window.fetch(c); + m.status >= 200 && m.status < 300 + ? (f = await m.json()) + : (console.error("Could not parse response"), + Error(m.statusText)); + } catch (y) { + console.error("Request failed", y); + } + let b = [], + k = []; + p && (b = k); + let B = { + "in-reply-to": b, + "like-of": k, + "repost-of": k, + "bookmark-of": k, + "follow-of": k, + "mention-of": b, + rsvp: b, + }; + f.children.forEach(function (t) { + let e = B[t["wm-property"]]; + e && e.push(t); + }); + let S = ""; + b.length > 0 && + b !== k && + (S = (function e(o) { + let n = `<h2>${t("Responses")}</h2>`, + r = o + .map((e) => { + let o = h(e, !0), + n = d(e.url.split("/")[2]); + e.author && e.author.name && (n = d(e.author.name)); + let r = `<a class="source" rel="nofollow ugc" href="${e[i]}">${n}</a>`, + s = "name", + l = `(${t("mention")})`; + e.name + ? ((s = "name"), (l = d(e.name))) + : e.content && + e.content.text && + ((s = "text"), (l = x(e))); + let a = `<span class="${s}">${l}</span>`; + return `<li>${o} ${r} ${a}</li>`; + }) + .join(""); + return ` + ${n} + <ul class="comments">${r}</ul> + `; + })(w(b))); + let D = ""; + k.length > 0 && + (D = (function e(o) { + let n = `<h2>${t("Reactions")}</h2>`, + r = o.map((t) => h(t)).join(""); + return ` + ${n} + <ul class="reacts">${r}</ul> + `; + })(w(k))); + let $ = `${S}${D}`; + ($.trim() || ($ = '<p class="wm-empty">暂无 Webmention 回应。</p>'), + (e.innerHTML = $)); + }); +})(); // @license-end diff --git a/static/tencent9244144536001218249.txt b/static/tencent9244144536001218249.txt new file mode 100644 index 0000000..fa53faa --- /dev/null +++ b/static/tencent9244144536001218249.txt @@ -0,0 +1 @@ +13646878276472045199 diff --git a/static/vercel.json b/static/vercel.json new file mode 100644 index 0000000..bbbd8a0 --- /dev/null +++ b/static/vercel.json @@ -0,0 +1,136 @@ +{ + "redirects": [ + { + "source": "/post/2888969971/:path*", + "destination": "/posts/星落关于我对命运既定的想法/:path*", + "permanent": true + }, + { + "source": "/post/2367861242/:path*", + "destination": "/posts/人生中第一次大考/:path*", + "permanent": true + }, + + { + "source": "/post/技术/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/post/%E6%8A%80%E6%9C%AF/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/post/随笔/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/post/%E9%9A%8F%E7%AC%94/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/post/读书/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/post/%E8%AF%BB%E4%B9%A6/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + + { + "source": "/posts/技术/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/posts/%E6%8A%80%E6%9C%AF/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/posts/随笔/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/posts/%E9%9A%8F%E7%AC%94/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/posts/读书/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/posts/%E8%AF%BB%E4%B9%A6/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/posts/tech/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/posts/jottings/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/posts/readings/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + + { + "source": "/post/tech/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/post/jottings/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + { + "source": "/post/readings/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + + { + "source": "/post", + "destination": "/posts", + "permanent": true + }, + { + "source": "/post/", + "destination": "/posts/", + "permanent": true + }, + + { + "source": "/post/(.*)", + "destination": "/posts/$1", + "permanent": true + }, + + { + "source": "/(.*)", + "destination": "/index.html", + "statusCode": 200 + }, + + { + "source": "/avatar.png", + "destination": "/avatar.webp", + "statusCode": 200 + } + ] +} |
