今热点:【音频】syntax How to Write Custom Syntax
How to Write Custom Syntax
(资料图片仅供参考)
PostCSS can transform styles in any syntax, and is not limited to just CSS. By writing a custom syntax, you can transform styles in any desired format.
Writing a custom syntax is much harder than writing a PostCSS plugin, but it is an awesome adventure.
There are 3 types of PostCSS syntax packages:
Parserto parse input string to node’s tree.Stringifierto generate output string by node’s tree.Syntaxcontains both parser and stringifier.
Syntax
A good example of a custom syntax is SCSS. Some users may want to transform SCSS sources with PostCSS plugins, for example if they need to add vendor prefixes or change the property order. So this syntax should output SCSS from an SCSS input.
The syntax API is a very simple plain object, with parse& stringifyfunctions:
module.exports = { parse: require("./parse"), stringify: require("./stringify")}
Parser
A good example of a parser is Safe Parser, which parses malformed/broken CSS. Because there is no point to generate broken output, this package only provides a parser.
The parser API is a function which receives a string & returns a Rootnode. The second argument is a function which receives an object with PostCSS options.
const postcss = require("postcss")module.exports = function parse (css, opts) { const root = postcss.root() // Add other nodes to root return root}
Main Theory
There are many books about parsers; but do not worry because CSS syntax is very easy, and so the parser will be much simpler than a programming language parser.
The default PostCSS parser contains two steps:
Tokenizer which reads input string character by character and builds a tokens array. For example, it joins space symbols to a ["space", "\n "]token, and detects strings to a ["string", ""\"{""]token.Parser which reads the tokens array, creates node instances and builds a tree.
Performance
Parsing input is often the most time consuming task in CSS processors. So it is very important to have a fast parser.
The main rule of optimization is that there is no performance without a benchmark. You can look at PostCSS benchmarks to build your own.
Of parsing tasks, the tokenize step will often take the most time, so its performance should be prioritized. Unfortunately, classes, functions and high level structures can slow down your tokenizer. Be ready to write dirty code with repeated statements. This is why it is difficult to extend the default PostCSS tokenizer; copy & paste will be a necessary evil.
Second optimization is using character codes instead of strings.
// Slowstring[i] === "{"// Fastconst OPEN_CURLY = 123 // `{"string.charCodeAt(i) === OPEN_CURLY
Third optimization is “fast jumps”. If you find open quotes, you can find next closing quote much faster by indexOf:
// Simple jumpnext = string.indexOf(""", currentPosition + 1)// Jump by RegExpregexp.lastIndex = currentPosion + 1regexp.test(string)next = regexp.lastIndex
The parser can be a well written class. There is no need in copy-paste and hardcore optimization there. You can extend the default PostCSS parser.
Node Source
Every node should have sourceproperty to generate correct source map. This property contains startand endproperties with { line, column }, and inputproperty with an Inputinstance.
Your tokenizer should save the original position so that you can propagate the values to the parser, to ensure that the source map is correctly updated.
Raw Values
A good PostCSS parser should provide all information (including spaces symbols) to generate byte-to-byte equal output. It is not so difficult, but respectful for user input and allow integration smoke tests.
A parser should save all additional symbols to node.rawsobject. It is an open structure for you, you can add additional keys. For example, SCSS parser saves comment types (/* */or //) in node.raws.inline.
The default parser cleans CSS values from comments and spaces. It saves the original value with comments to node.raws.value.rawand uses it, if the node value was not changed.
Tests
Of course, all parsers in the PostCSS ecosystem must have tests.
If your parser just extends CSS syntax (like SCSS or Safe Parser), you can use the PostCSS Parser Tests. It contains unit & integration tests.
Stringifier
A style guide generator is a good example of a stringifier. It generates output HTML which contains CSS components. For this use case, a parser isn"t necessary, so the package should just contain a stringifier.
The Stringifier API is little bit more complicated, than the parser API. PostCSS generates a source map, so a stringifier can’t just return a string. It must link every substring with its source node.
A Stringifier is a function which receives Rootnode and builder callback. Then it calls builder with every node’s string and node instance.
module.exports = function stringify (root, builder) { // Some magic const string = decl.prop + ":" + decl.value + ";" builder(string, decl) // Some science};
Main Theory
PostCSS default stringifier is just a class with a method for each node type and many methods to detect raw properties.
In most cases it will be enough just to extend this class, like in SCSS stringifier.
Builder Function
A builder function will be passed to stringifyfunction as second argument. For example, the default PostCSS stringifier class saves it to this.builderproperty.
Builder receives output substring and source node to append this substring to the final output.
Some nodes contain other nodes in the middle. For example, a rule has a {at the beginning, many declarations inside and a closing }.
For these cases, you should pass a third argument to builder function: "start"or "end"string:
this.builder(rule.selector + "{", rule, "start")// Stringify declarations insidethis.builder("}", rule, "end")
Raw Values
A good PostCSS custom syntax saves all symbols and provide byte-to-byte equal output if there were no changes.
This is why every node has node.rawsobject to store space symbol, etc.
All data related to source code and not CSS structure, should be in Node#raws. For instance, postcss-scsskeep in Comment#raws.inlineboolean marker of inline comment (// commentinstead of /* comment */).
Be careful, because sometimes these raw properties will not be present; some nodes may be built manually, or may lose their indentation when they are moved to another parent node.
This is why the default stringifier has a raw()method to autodetect raw properties by other nodes. For example, it will look at other nodes to detect indent size and them multiply it with the current node depth.
Tests
A stringifier must have tests too.
You can use unit and integration test cases from PostCSS Parser Tests. Just compare input CSS with CSS after your parser and stringifier.
相关推荐:
最新新闻:
- Linux命令之restore命令 使用语法及参数说明
- 女UP主穿紧身衣装奥特曼跳舞?谁当直女的动态图-世界聚看点
- 外媒:今年12月PS会免比去年强得多 游戏数量翻倍-当前信息
- 今热点:【音频】syntax How to Write Custom Syntax
- 天天信息:小岛秀夫:《死亡搁浅2》游戏封面参考了一代设计
- 【世界快播报】外网热议:《艾尔登法环》哪个角色的身世最悲惨?
- 还能这样玩?Twitch主播手脚并用双开《艾尔登法环》
- 《天命奇御:归途》正式发售! 5折优惠价24.5元畅游江湖_天天速看
- 定位赛10连胜是什么段位?LOL S5定位赛胜率高为什么没有上段?
- 玩家根据宝可梦游戏发售规律推测 Switch2|Pro或2023年推出
- 【环球新视野】暴风影音如何倍速播放?暴风影音倍速播放的方法
- 死或生5最后一战怎么反击?死或生5最后一战反击技巧攻略
- 全球观热点:HTC One X Recovery一键刷入步骤介绍 一键刷入的注意事项
- 《天命奇御:归途》正式发售 优惠价24.5元畅游江湖|今日关注
- 焦点滚动:曝斯柯达打算退出中国市场,曾靠“贴牌大众”爆火,下一站发力印度
- 通信行程卡下线,其存储的个人信息可以挪作他用吗?
- 第二代骁龙8赋能Xiaomi 13系列年度旗舰,实现高端探索新突破:世界资讯
- 全球观速讯丨《人中之龙维新!极》公布全新支线剧情、照功能等游戏要素
- 日本知名动画歌手水木一郎因肺癌去世 享年74岁 热头条
- 《云·原神》PC平台公测正式开启,可实现低配置高画质
- 热议:小米1TB移动固态硬盘发布:众筹649元 读写超2000MB/s
- 环球今热点:谐波减速机优点是什么?谐波传动减速器的优点
- 怎么用电脑摄像头录像?使用电脑摄像头录像详细步骤
- 三阶魔方还原公式是什么?三阶魔方的还原公式:环球今日报
- Visio绘图文件阅读器 VSD Viewer版功能介绍
- MetroModernUI库应用实例 MetroModernUI库安装流程_天天速看
- 联想V480EI Capitan完美驱动教程 安装黑苹果的步骤及注意事项|全球百事通
- 诺亚舟np360学习机怎么样?诺亚舟np360性能介绍_世界热推荐
- c语言编程题中华文本库 计算机考试二级C语言上机试题|当前速看
- nginx简单介绍 tomcat与nginx、apache的区别是什么?
- 环球观热点:小米与华为手机哪个好些?小米、华为与手机销量有关的对比
- Slony到底是什么?关于VMware Desktone中的Slony和数据库
- 视觉效果艺术家在“NVIDIA Studio 创意加速”中分享电影幕后制作的故事
- 操作系统有哪些类型?操作系统各自的特点
- 天天微速讯:htc是什么牌子?htc款式推荐
- arp防火墙哪个最好?金山arp防火墙的介绍 世界关注
- 三星9050好不好?三星9050如何刷机?
- 通讯!跳跃忍者怎么玩?若吃完所有能量球最多能保留多少能量?
- 纯甲类功放是什么意思?纯甲类功放价格参考及其介绍 世界今亮点
- 极米投影斩获五项国际大奖:画面自适应技术获日本VGP2023技术奖
- 联想S890支持什么视频格式?联想S890支持RMVB播放吗?-环球关注
- 全球热讯:百度云盒怎么预约购买?电视应用购买教程
- 辽源市谷歌高清卫星地图离线包如何下载?:视焦点讯
- 洛谷 P8400 Cupcake Party 计算机科学教育新生态 :视焦点讯
- 台式机硬盘报价如何?台式机硬盘最新报价:独家
- 光电耦合器的作用是什么?光电耦合器工作原理详解 _世界最资讯
- 环球观察:样本容量怎么确定?影响样本容量n的因素
- 手机钢化膜哪个品牌质量好?手机钢化膜的优缺点有哪些?:世界消息
- 微资讯!【进程通信】Signal信号 信号的来源是哪?
- 计算机主板结构你了解多少?主板的分类
- c语言编程题中华文本库 计算机考试二级C语言上机试题|当前速看
- 全球聚焦:希捷宣布全球大裁员 股价在盘后大涨9%至26.26美元
- 环球观察:样本容量怎么确定?影响样本容量n的因素
- 现在进行时怎么使用?现在进行时和一般现在时的将来时态_微速讯
- Slony到底是什么?关于VMware Desktone中的Slony和数据库
- 世界快看点丨信息的价值是什么?信息的英文名Information
- 图片的格式怎么改?教你快速转格式的方法
- 联想V480EI Capitan完美驱动教程 安装黑苹果的步骤及注意事项|全球百事通
- 三阶魔方还原公式是什么?三阶魔方的还原公式:环球今日报
- 排名精灵怎么样?排名精灵功能评测
- 钛备份怎么用?钛备份怎么还原?
- 怎么用魔影工厂转换视频?魔影工厂怎么识别爱奇艺的视频?
- connectify怎么设置?connectify如何设置使用教程
- Win7系统中WmiPrvSE是什么进程?如何禁止Wmiprvse.exe进程?
- Anyview阅读APP如何使用?Anyview阅读使用图文教程
- win7使用过程中出现错误1079故障的原因及解决方法
- 网页中Flash如何下载?网页中Flash下载方法
- 网络老是掉线怎么回事?wifi一段时间断开怎么办?
- win10怎么升级正版?win10升级正版步骤
- qq远程控制鼠标点不动怎么?qq远程控制鼠标点不动解决方法
- 跨显卡双屏显示怎么设置?跨显卡双屏显示设置问题
- 如何通过Logoup 3D制作立方体?Logoup 3D制作立方体操作步骤
- 视频万能驱动怎么安装?视频万能驱动安装方法
- 怎么给手机版的WPS文档加密?手机版的WPS文档加密方法
- Adblock浏览器怎么用?Adbloc去广告浏览器下载
- win10 Build 9865怎么更新升级?win10 Build 9865更新升级方法
- qq授权管理在哪里?qq授权管理介绍
- 腾讯防沉迷如何通过官方修改?腾讯防沉迷修改方法
- 电脑断网掉线怎么办?电脑断网掉线的解决方法
- 九章云极DataCanvas公司荣获 “WISE2022新经济之王年度企业”
- 如何做好软文推广? 软文推广的方法和技巧是什么?
- alg是什么文件?alg.exe是不是病毒?
- 如何解决电脑开机自动打开文件夹问题?电脑开机自动打开文件夹解决方法
- chkdsk工具怎么运行修复?chkdsk工具运行修复方法
- steam启动游戏失败错误代码83怎么回事?steam错误代码83的原因及解决方法