🏗 重组
Index
- 📄 网站结构
- 📄 内容组织
- 📖 历史保留策略
- 📄 Q & A
-
types/index.ts
Status flag
- Draft: 早期讨论。
- Proposal: 基本确定,无需大幅改动。
- Spec: 已执行。
📄 网站结构
- Status: Draft
- Updated: 2021-07-23
Repository structure
下面列出了 master branch 的主要内容。
除非有特殊约定,文件名全小写,单词用连字符 (-) 连接,即 kebab-case。
# 之后是行注释。
/
+-- .devcontainer/
`-- ...
+-- .github/
`-- ...
+-- .vscode/
`-- ...
+-- docs/ # 网站源文件
+-- .vuepress/
+-- components/
+-- Download.vue # “下载”页的内容
+-- Preface.vue # 序言
+-- resource-collection-loader.ts
`-- tsconfig.json
+-- data/
`-- resources/
+-- mathematica/
`-- index.ts
+-- wolfram-alpha-notebook-edition/
`-- index.ts
+-- wolfram-engine-for-developers/
`-- index.ts
+-- ...
`-- index.ts
+-- public/ # Auto-generated. Do not check in.
`-- resources.json
+-- types/ # Type definitions
`-- index.ts
+-- .gitignore
+-- config.ts
+-- generate-public-resources-json.ts # The `onInitialized` hook.
+-- navbar.ts
+-- sidebar.ts
`-- tsconfig.json
+-- article/ # 可独立的篇章
+-- activating-mathematica.md # 激活 Mathematica
+-- activating-mathematica-8-to-10.md # 激活 Mathematica 8 到 10
+-- introduction-to-mathematica.md # 入门 Mathematica
+-- running-wolfram-online.md # 在线运行 Wolfram 计算
`-- ...
+-- contributing/ # 贡献指南
+-- automation/
+-- ci.md
+-- mergify.md
+-- stale.md
`-- workflow-repo-sync.md
+-- README.md
+-- development.md # 网站开发
+-- labels.md
+-- management.md
+-- writing-style-guide.md
`-- ...
+-- question-and-answer/ # 常见问题
`-- README.md
+-- README.md # 主页
`-- download.md # 下载 <Download />
+-- tools/
`-- deploy.ps1
+-- .editorconfig
+-- .gitignore
+-- .mergify.yml
+-- CONTRIBUTING.txt # 占位重定向
+-- LICENSE.txt
+-- README.md
+-- package.json
+-- tsconfig.base.json
`-- ...
References
- #43
📄 内容组织
- Status: Draft
- Updated: 2021-07-23
主目录 (Main sidebar)
用于 /。
- 主页
- 序言
- 关于购买
- 下载须知
- 关于提问
- Wolfram 学生大使计划简介
- Wolfram Engine for Developers 简介
- Wolfram|Alpha Notebook Edition 简介
- 下载
- 常见问题
- 激活 Mathematica
- 入门 Mathematica
- 在线运行 Wolfram 计算
- 位于
/article/的其他文章…
也可以考虑其他方案。这个设计主要是为了避免空白页、多层嵌套、多级导航等干扰体验的事情。可以预见,在很长一段时间里,这个目录都不会变得非常大。
序言
序言是位于主页和下载页开头的 <Preface />。这里应当:
-
放置一些特别情况的通知。
-
告知“最新版本”和最近一个“可靠版本”。
下载须知
每个事项开一个 h3。
涉及下列内容:
- Wolfram Product System Requirements
- 各镜像渠道的说明
- 中文版和英文版的区别
- 兼容性警告
- 其他不与具体资源绑定的琐事
下载页
页面布局
+--------+
| Filter |
+--------+
| List |
+--------+
Filter (筛选器)提供一组控件,允许用户从下述方式中选择一种进行筛选:
-
先选定产品,之后可以随意设置版本、平台、语言等条件,每一个维度都是多选。
-
文本过滤
Resource.name。
List (资源列表)是一个无序列表,默认呈现所有资源,随 Filter 改变,没有满足条件的资源时显示为空白。
初始排序规则
Download.vue 不做排序。
resource-collection-loader.ts 会确保列表前部都是 (!product || product === KnownProduct.Mathematica) 的项目。
初始排序应当在数据源 (data/resources/) 中完成:
-
新版本排在旧版本的前面。
-
同一产品排在一起。宜依次按产品、版本、平台、语言排序资源即可。
贡献指南目录
用于 /contributing/。
- 贡献指南
- 写作风格指南
- 网站开发
- 项目管理
- 标签体系
- 自动化
References
📖 历史保留策略
- Status: Draft
- Updated: 2021-07-24
规则
用 $VersionNumber (Wolfram Language kernel version number) 判断版本号。
在新的大版本发布后,清理上一代。
保留下述安装文件:
-
保留每一个大版本的最后一个小版本的最后一个 release。
-
保留最近一个“可靠版本”。
-
酌情保留重大变化附近的版本。例如,Mathematica 11.3 是最后一代 32 位“可靠版本”。
完全保留记事。可以适当合并 Resource.note,或者整合进“下载须知”。
定义
版本号
Wolfram Language 仅有实数 version number 和整数 release number 这两个概念。
为便于处理,我们参考 SemVer,按下述模式解析版本号。
<Full-version-number> = <Major> "." <Minor> "." <Release>
<Major> = <Non-negative-integer>
<Minor> = <Non-negative-integer>
<Release> = <Non-negative-integer>
<Non-negative-integer> = "0" / (<Positive-digit> *<DIGIT>)
<Positive-digit> = %x31-39
- Major: 大版本。
- Minor: 小版本。
- Release: 发行号。
- Full version number: 完整版本号。简称为“版本号”。
可靠版本
“可靠版本”满足下列条件:
- 已集齐全 3 个平台。
- 已集齐中、英文。
- 没有明显缺陷,可以投入生产环境。
- 其他已知问题都有 workaround。
最新版本
“最新版本”精确到小版本。例如,如果 12.1 是最新一代,那么,12.1.1 和 12.1.0 都属于“最新版本”。
References
📄 Q & A
- Status: Draft
- Updated: 2020-11-20
组织
按热度由高到低排序。不定期调整。
格式
### <!-- 标题 -->
**问题**
<!-- 详细描述 -->
**解决方案**
<!-- 解决方案 -->
标题应当满足下列条件,以便编写内链:
- 控制在 20 字 (code point) 以内,不超过 30 字。
- 仅含 Unicode letter、ASCII 数字、全角逗号 (U+FF0C)、连字符 (U+002D)、空格 (U+0020)。
/[^\p{L}\d\u{FF0C}\- ]/u.test(title) // => false - 创建后不再改变。
🌐 SEO
- Status: Draft
- Updated: 2020-06-20
页面的元数据可以用 jekyll-seo-tag 生成。其他方面我不知道该怎么办。
types/index.ts
- Status: Draft
- Updated: 2021-12-01
Originally posted at https://github.com/TieBaMma/InstallTutorial/issues/72#issuecomment-723544545.
/**
* Known Wolfram product.
*/
export const enum KnownProduct {
Mathematica = 1, // 0b1
/**
* Wolfram Engine for Developers
*/
WolframEngine = 2, // 0b10
WolframAlphaNotebookEdition = 4, // 0b100
}
/**
* IETF language tag.
*
* @see {@link https://www.rfc-editor.org/info/bcp47}
* @see {@link https://www.iana.org/assignments/language-subtag-registry}
*/
export const enum LanguageTag {
English = "en",
ChineseSimplified = "zh-Hans",
}
/**
* Operating environment.
*
* These values roughly follow the pattern of .NET RID: `<os>-<architecture>`
*/
export const enum Platform {
WindowsX86 = "windows-x86",
MacArm = "macos-arm",
MacX86 = "macos-x86",
LinuxX86 = "linux-x86",
}
/**
* A note for human to read.
*/
export interface Note {
/**
* The label of this note.
*/
readonly name: string;
/**
* Use CommonMark.
*/
readonly content: string;
}
/**
* 一个下载源。
*/
export interface Source {
/**
* 名称。
*
* @example
* "天翼云盘"
* "SharePoint-API"
*/
readonly name: string;
/**
* URI.
*/
readonly location: string;
/**
* 备注。
*
* @example
* [
* { name: "提取码", content: "`1234`" },
* { name: "SHA-1", content: "`abcd`" },
* ];
*/
readonly notes?: readonly Note[];
}
/**
* A combination (intersection) of constraints.
*/
export interface TargetFilter {
/**
* A semver version or range used to match Wolfram Language kernel full version number.
*
* To meet the requirement of SemVer, you should normalize Wolfram version numbers
* to the format of `<Major>.<Minor>.<Release>` (`/^\d+\.\d+\.\d+$/`).
* For a non-Wolfram product, this is the kernel version it targets.
*
* @example
* "12.1.1"
* ">=12.0.0 <13.0.0"
* "12.1.1 || 12.2.x"
*
* @see {@link http://reference.wolfram.com/language/ref/$ReleaseNumber.html}
* @see {@link https://www.npmjs.com/package/semver}
*/
readonly versionRange: string;
/**
* If omitted, no constraint will apply to this dimension.
*/
readonly language?: readonly LanguageTag[];
/**
* If omitted, no constraint will apply to this dimension.
*/
readonly platform?: readonly Platform[];
/**
* If omitted, no constraint will apply to this dimension.
*/
readonly product?: readonly KnownProduct[];
}
/**
* 一个资源。
*/
export interface Resource {
/**
* 名称。
*
* @example
* "Mathematica 12.1.1"
* "Mathematica 12 的激活工具"
*/
readonly name: string;
/**
* 源列表。
*
* 各下载源提供相同的内容。
*/
readonly sources: readonly Source[];
/**
* 表示该资源的内容。
*
* 各 `TargetFilter` 独立应用,最后结果取并集。
*/
readonly targets: readonly TargetFilter[];
/**
* 备注。
*
* @example
* [
* { name: "警告", content: "Mathematica 12.0 的 `SystemOpen` 函数的 Unicode 支持存在 bug。" },
* ];
*/
readonly notes?: readonly Note[];
/**
* `true` 表示该资源是历史版本,已经归档。
*/
readonly archived?: boolean;
}
/**
* 资源的集合。
*/
export type ResourceCollection = readonly Resource[];
现在的模型能解决 https://github.com/TieBaMma/InstallTutorial/pull/77#issuecomment-752889118 的问题了。
接下来的难点是 credit mapping。又重建一次,很多内容的起源就几乎没法追溯了。
大概两个处理思路:
-
不管了,像 MDN 那样,做个清单,感谢所有贡献者。
-
找到现存内容的原始贡献者,程序生成 repo,把他们在适当的位置插进去,大致一人一条 commit。
我觉得归档历史版本比直接删除历史版本好一些,搞个 Archive 页,历史版本全丢进去。
“最新版本”精确到小版本。例如,如果 12.1 是最新一代,那么,12.1.1 和 12.1.0 都属于“最新版本”。
我觉得保留 12.1.1 就可以了,12.1.0 丢Archive 。
另外现在要提 PR 应该怎么提,是等改版结束还是按原来的流程提 PR?
PR 应该怎么提
照旧吧。我估计,改版还得再研究一两年,这个 repo 的结构一时半会不会有多少变化。
@TieBaMma 或许有其他见解?
归档历史版本比直接删除历史版本好一些
前提是资金充足。我担心存太多冷数据,你的账户会受不了。
搞个 Archive 页,历史版本全丢进去
好建议。能够减少大多数用户加载的数据量,改善访问速度。
不妨加个属性:
export interface Resource {
readonly isArchived: boolean;
}
这样,resource-collection-loader.ts 暴露两个数组:
export const All_Resources: ResourceCollection = [];
/**
* isArchived === false
*/
export const Non_Archived_Resources: ResourceCollection = All_Resources.filter(
(r) => !r.isArchived
);
之后,download.html 中用 Non_Archived_Resources,另有 download-all.html 用 All_Resources。
或者,仍然只有一个 download.html,但加个选项“包含已归档的版本”。默认呈现是 Non_Archived_Resources,这部分 SSR。而 All_Resources 按需载入(或许可以通过 resources.json,不过,我想先试试 JS asset)。不太清楚在 VuePress 下需要注意什么。
Credit mapping
我最终的建议是:
重建 repo,创建贡献者名单。
变更一层叠一层,从现在的 blame 中溯源既不现实也不合算。而且,这次迁移又相当于删除现有文件,从头再来。
这时,丢弃历史是合理的选择。常规的处理是存档 (archive) 旧 repo,导出数据。虽然这里不能 archive,但贡献者名单还是容易做的。
那么怎样保存名单呢?
我查到最常见的格式是 Git mailmap。但我倾向于结构化数据 (JSON)。因为一旦遇上复杂的内容,比如
mailmap 之类的 "string-encoded data" 很容易离大谱。
所以,我的提案是 AUTHORS.json
{
"comments": ["本文件用于存档 2022-00-00 之前的 contributor 信息。"],
"contributors": [
{
"name": "",
"email": "",
"url": ""
},
{
"name": "",
"url": ""
}
]
}
不过,是否呈现 email 有待讨论,因为一些人可能不希望 email 被明摆出来。
才想起来,“贡献者名单”可以通过 empty commit 实现。加十几条 commit 还是比设计个清单文件更简单。😂
Author 用原始提交信息。
Committer 用 username <[email protected]> 以确保稳定的链接。
靠,VuePress 整成 ESM 了。又得重新设计。
在重新看这个项目, 觉得里面老的内容有点多了(比如例子还是 ver8, 但是最新版已经很方便了).
如果简化到极点.
for newbie:
latest version(包含手册版) + 在线 url 注册工具.
把高频内容放到开头. 后面再提供各种旧版的安装版/手册/etc.
至于归档, 甚至可以用 <summary/> 手动折叠旧版, 要降低维护成本还可以用 hugo 直接从模板生成静态网站. 还能提高 SEO.
现在全上种子了,内容加起来倒是简单多了。索引也如 #128 那样解决了。 ~~后面只需要继续堆文档就行~~ 。
不直接在页面给 torrent 链接是因为变种太多,列起来约等于重抄一遍。借助 link 的参数加个中间层“转发”,页面只需要限定版本让用户选择喜欢的媒介。工作量也降低了。