设计改版 | 腾讯问卷文本编辑模式重构与改进
三分设
共 4130字,需浏览 9分钟
·
2022-02-11 09:02
Background
背景
Part 1
任务
解决每次编辑会重新生成 ID 的问题
Part 2
前置工作
复制题目时 ID 冲突,解决方法:粘贴时先触发 diff ,若文本中已有相同 ID ,则将当前要粘贴的文本 ID 去除。 改题型时导致已回收数据无法使用,解决方法:修改题型时,重新分配 ID 。
Part 3
行动
基于 PEG.js 改造
Part 4
动机
因为 PEG 更加严格更加强大, PEG 可以成为很好的正则表达式的替代品。例如,一个正则表达式本身是无法匹配嵌套的括号对,因为正则表达式不是递归的,但是 PEG 却能做到这点。 所有的 PEG 都能通过使用 Parkrat Parser 达到线性时间解析,如同上文所述。 CFG 表达的解析器,比如 LR 解析器,需要首先进行一个单独的断词步骤。这个步骤根据空白的位置或者发音等等因素把输入分成词。分词是必要的,因为这类解析器使用向前检查来判断上下文无关文法是否匹配要求。PEG 不需要单独的断词步骤,断词的规则和其他文法规则可以用同样的方式写在一起。 许多 CFG 固有的存在二义性,即使它们原本要描述的东西并不具有二义性。C, C++ , Java 里面著名的悬空 else 问题就是一个例子。这个问题通常都是应用文法之外的一个规则解决。而在 PEG 里面,因为使用了优先权,所以根本不存在这种问题。
Part 5
思路
Part 6
解决 ID 问题
有 ID 文本时,使用文本所记录的 ID 。 无 ID 文本时,自动按照规则生成 ID。
什么时候生成 ID 怎么判断 ID 是否需要写入 怎么写入 ID
type Location = { start: { offset: number, line: number, column: number } end: { offset: number, line: number, column: number }}type ASTQuestion = { id: string | null title: { content: object[], location: Location }}const astQuestion = { id: 'q-1-abcd' || null, title: { content: ['a', 'b'], location: { start: { offset: 0, line: 1, column: 1 }, end: { offset: 2, line: 1, column: 3 }, } }}
type Question = { id: string, title: string,}const question = { id: 'q-1-abcd', title: 'ab',}
const refillQid = (text: string, astQuestion, question: Question) { // 旧文本中没有 id if (astQuestion.id === null) { text = insert(text, question.id, astQuestion.title.location) } return text}
Part 7
衍生问题
Part 8
迁移
The End
总结
评论