Skip to content
This repository was archived by the owner on Jun 5, 2018. It is now read-only.

Commit 2cde2f9

Browse files
committed
修复嵌套 bug
1 parent 67dd2fc commit 2cde2f9

File tree

9 files changed

+152
-122
lines changed

9 files changed

+152
-122
lines changed

README.md

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# PowCSS
22

3+
[![badge](https://img.shields.io/badge/Pow-CSS-green.svg?style=flat-square)](https://github.com/powjs/powcss)
4+
[![npm](https://img.shields.io/npm/l/powcss.svg?style=flat-square)](https://www.npmjs.org/package/powcss)
5+
[![npm](https://img.shields.io/npm/dm/powcss.svg?style=flat-square)](https://www.npmjs.org/package/powcss)
6+
[![npm](https://img.shields.io/npm/dt/powcss.svg?style=flat-square)](https://www.npmjs.org/package/powcss)
7+
38
PowCSS 是个 CSS 预处理工具. 特征:
49

510
混合 CSS, JavaScript 缩进语法
@@ -81,18 +86,47 @@ function(ctx) {
8186

8287
## install
8388

84-
nodejs 环境, 演示 [runkit][]
89+
nodejs 环境
8590

8691
```sh
8792
yarn add powcss
8893
```
8994

90-
浏览器环境, 演示 [codepen][], [requirebin][]
95+
浏览器环境
9196

9297
```html
9398
<script src="//unpkg.com/powcss/dist/powcss.min.js"></script>
9499
```
95100

101+
## usage
102+
103+
nodejs 环境, 演示 [runkit][]
104+
105+
```js
106+
const powcss = require('powcss');
107+
108+
// const context = require('powcss/lib/context');
109+
110+
let ctx = powcss().run(`
111+
.class
112+
color: green
113+
`);
114+
// ctx.toCSS() or ...
115+
```
116+
117+
浏览器环境, 演示 [codepen][], [requirebin][]
118+
119+
```html
120+
<script>
121+
// const context = powcss.context;
122+
let ctx = powcss().run(`
123+
.class
124+
color: green
125+
`);
126+
// ctx.toCSS() or ...
127+
</script>
128+
```
129+
96130
## 缩进语法
97131

98132
PowCSS 支持缩进风格的 CSS 源码, 花括号和分号是可选的, 确保正确的缩进即可.
@@ -146,6 +180,10 @@ compile(n, i, ns){}
146180

147181
PowCSS 实现的 Compiler 直接使用原生 JS 语法, 不对语法进行分析.
148182

183+
参见 [API](api.md)
184+
185+
**提示: 把 CSS 当作 JavaScript 来写就对了**
186+
149187
源码中比较容易常犯的错误:
150188

151189
```styl
@@ -174,18 +212,22 @@ color: 1px
174212
border: 1px
175213
```
176214

177-
**提示: 把 CSS 当作 JavaScript 来写就对了**
178-
179-
参见 [API](api.md)
180-
181215
## Context
182216

183-
Context 负责提供生成和维护 CSS 规则的基本方法, 值表达式由配套的 Compiler 提供.
217+
Context 负责提供生成和维护 CSS 规则的基本方法, 值表达式由配套的 Compiler 生成.
184218

185219
PowCSS 实现的 Context 维护规则的 open 和 close 等操作, 并负责处理 '&' 占位符.
186220

187221
参见 [API](api.md)
188222

223+
## 赞助
224+
225+
赞助以帮助 PowCSS 持续更新
226+
227+
![通过支付宝赞助](https://user-images.githubusercontent.com/489285/31326203-9b0c95c0-ac8a-11e7-9161-b2d8f1cc00e8.png)
228+
![通过微信赞助](https://user-images.githubusercontent.com/489285/31326223-c62b133a-ac8a-11e7-9af5-ff5465872280.png)
229+
[![通过 Paypal 赞助](https://user-images.githubusercontent.com/489285/31326166-63e63682-ac8a-11e7-829a-0f75875ac88a.png)](https://www.paypal.me/HengChunYU/5)
230+
189231
## License
190232

191233
MIT License <https://github.com/powjs/powcss/blob/master/LICENSE>

api.md

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,8 @@
22

33
<dl>
44
<dt><a href="#PowCSS">PowCSS</a></dt>
5-
<dd><p>PowCSS 通过插件对 CSS 进行处理, 分多个工作期:</p>
6-
<p>process 解析输入源转换为节点树(root)
7-
compile 使用插件编译节点树中的未决节点
8-
yield 遍历节点树进行构建, 构建行为由 Context 决定.
9-
cssify 输出构建后的 CSS 源码</p>
10-
<p>PowCSS 最重要的核心有两个</p>
11-
<ol>
12-
<li>编译插件模型 @see Plugin</li>
13-
<li>渲染上下文 @see Context</li>
14-
</ol>
15-
<p>在 PowCSS 的设计中, 允许编译后的结果脱离 PowCSS 进行渲染.
16-
Context 就是为了实现这个目标, 它很简单, 重构或扩展非常容易.</p>
5+
<dd><p>PowCSS 负责解析 source 为节点树, 并拼接编译器的编译结果.
6+
在 PowCSS 中的插件就是 compiler, compiler 负责与 context 配合.</p>
177
</dd>
188
<dt><a href="#Compiler">Compiler</a></dt>
199
<dd><p>PowCSS 缺省的 Compiler 实现.
@@ -32,7 +22,7 @@ Context 就是为了实现这个目标, 它很简单, 重构或扩展非常容
3222

3323
<dl>
3424
<dt><a href="#util">util</a></dt>
35-
<dd><p>辅助函数集合, ctx 总是(扩展)继承 util 的所有方法.</p>
25+
<dd><p>辅助方法集合</p>
3626
</dd>
3727
</dl>
3828

@@ -47,20 +37,8 @@ Context 就是为了实现这个目标, 它很简单, 重构或扩展非常容
4737
<a name="PowCSS"></a>
4838

4939
## PowCSS
50-
PowCSS 通过插件对 CSS 进行处理, 分多个工作期:
51-
52-
process 解析输入源转换为节点树(root)
53-
compile 使用插件编译节点树中的未决节点
54-
yield 遍历节点树进行构建, 构建行为由 Context 决定.
55-
cssify 输出构建后的 CSS 源码
56-
57-
PowCSS 最重要的核心有两个
58-
59-
1. 编译插件模型 @see Plugin
60-
2. 渲染上下文 @see Context
61-
62-
在 PowCSS 的设计中, 允许编译后的结果脱离 PowCSS 进行渲染.
63-
Context 就是为了实现这个目标, 它很简单, 重构或扩展非常容易.
40+
PowCSS 负责解析 source 为节点树, 并拼接编译器的编译结果.
41+
在 PowCSS 中的插件就是 compiler, compiler 负责与 context 配合.
6442

6543
**Kind**: global class
6644

@@ -81,18 +59,18 @@ Context 就是为了实现这个目标, 它很简单, 重构或扩展非常容
8159

8260
| Param | Type | Description |
8361
| --- | --- | --- |
84-
| plugins | <code>Array.&lt;Plugin&gt;</code> | 处理器数组缺省为 [compiler()] |
62+
| plugins | [<code>Array.&lt;Compiler&gt;</code>](#Compiler) | 编译器数组, 缺省为 [compiler()] |
8563

8664
<a name="PowCSS+use"></a>
8765

8866
### powCSS.use(plugin) ⇒ <code>this</code>
89-
使用一个插件
67+
使用一个编译器插件
9068

9169
**Kind**: instance method of [<code>PowCSS</code>](#PowCSS)
9270

9371
| Param | Type |
9472
| --- | --- |
95-
| plugin | <code>Plugin</code> |
73+
| plugin | [<code>Compiler</code>](#Compiler) |
9674

9775
<a name="PowCSS+process"></a>
9876

@@ -127,7 +105,7 @@ Context 就是为了实现这个目标, 它很简单, 重构或扩展非常容
127105
<a name="PowCSS+format"></a>
128106

129107
### powCSS.format(root) ⇒ <code>string</code>
130-
格式化输出 root 节点树
108+
格式化输出 root.nodes
131109

132110
**Kind**: instance method of [<code>PowCSS</code>](#PowCSS)
133111
**Returns**: <code>string</code> - CSS 无花括号两空格缩进格式
@@ -304,8 +282,8 @@ PowCSS 缺省的 Context 实现.
304282
<a name="Context+open"></a>
305283

306284
### context.open(name) ⇒ <code>this</code>
307-
当前规则入栈, 并开启一个新具名规则并替换 name 中的占位符 '&'.
308-
该方法必须与 close 成对使用. 只有 '@' 规则下嵌套使用 open 会产生嵌套规则.
285+
开启一个具名规则并替换 name 中的占位符 '&', 该方法必须与 close 成对使用.
286+
嵌套使用时 this.stack 会增长.
309287

310288
**Kind**: instance method of [<code>Context</code>](#Context)
311289

@@ -316,7 +294,7 @@ PowCSS 缺省的 Context 实现.
316294
<a name="Context+close"></a>
317295

318296
### context.close() ⇒ <code>this</code>
319-
关闭当前的规则, 并弹出规则栈. 该方法必须与 .open 成对使用.
297+
关闭当前的规则, this.stack 会减少, 该方法必须与 .open 成对使用.
320298

321299
**Kind**: instance method of [<code>Context</code>](#Context)
322300
<a name="Context+name"></a>
@@ -374,7 +352,7 @@ lineify 是个非空白行扫描器, 扫描并返回非空白行信息.
374352
<a name="util"></a>
375353

376354
## util
377-
辅助函数集合, ctx 总是(扩展)继承 util 的所有方法.
355+
辅助方法集合
378356

379357
**Kind**: global variable
380358

dist/powcss.js

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
22
(function (global){
33
global.powcss = require('./lib/powcss.js');
4-
4+
global.powcss.lineify = require('./lib/lineify');
5+
global.powcss.compiler = require('./lib/compiler');
6+
global.powcss.context = require('./lib/context');
7+
global.powcss.util = require('./lib/util');
58
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
6-
},{"./lib/powcss.js":5}],2:[function(require,module,exports){
9+
},{"./lib/compiler":2,"./lib/context":3,"./lib/lineify":4,"./lib/powcss.js":5,"./lib/util":6}],2:[function(require,module,exports){
710
const IFX = /if[ ]+([_$a-zA-Z]+)[ ]*=/,
811
util = require('./util');
912

@@ -168,39 +171,45 @@ class Context {
168171
}
169172

170173
/**
171-
* 当前规则入栈, 并开启一个新具名规则并替换 name 中的占位符 '&'.
172-
* 该方法必须与 close 成对使用. 只有 '@' 规则下嵌套使用 open 会产生嵌套规则.
174+
* 开启一个具名规则并替换 name 中的占位符 '&', 该方法必须与 close 成对使用.
175+
* 嵌套使用时 this.stack 会增长.
173176
* @param {string} name
174177
* @return {this}
175178
*/
176179
open(name) {
177-
let prev = this.name();
178-
if (prev) {
180+
if (this.rule) {
179181
this.stack.push(this.rule);
180182
if (name.indexOf('&') !== -1)
181-
name = name.replace(/&/g, prev);
182-
}
183-
184-
if (prev && prev[0] === '@') {
185-
let rule = {name};
186-
this.rule.decls = this.rule.decls || [];
187-
this.rule.decls.push(rule);
188-
this.rule = rule;
189-
}else {
190-
this.rule = {name};
191-
this.rules.push(this.rule);
183+
name = name.replace(/&/g, this.rule.name);
184+
185+
if (!this.rule.decls) {
186+
if (this.rule.name[0] === '@') {
187+
this.rule.decls = [];
188+
this.stack.push(this.rules);
189+
this.rules = this.rule.decls;
190+
}else if (
191+
this.rule.name[0] !== '/' &&
192+
this.rule === this.rules[this.rules.length - 1]
193+
) {
194+
this.rules.pop();
195+
}
196+
}
192197
}
193-
198+
this.rule = {name};
199+
this.rules.push(this.rule);
194200
return this;
195201
}
196202

197203
/**
198-
* 关闭当前的规则, 并弹出规则栈. 该方法必须与 .open 成对使用.
204+
* 关闭当前的规则, this.stack 会减少, 该方法必须与 .open 成对使用.
199205
* @return {this}
200206
*/
201207
close() {
202-
let rule = this.stack.pop();
203-
this.rule = rule;
208+
this.rule = this.stack.pop();
209+
if (Array.isArray(this.rule)) {
210+
this.rules = this.rule;
211+
return this.close();
212+
}
204213
return this;
205214
}
206215

@@ -246,7 +255,7 @@ class Context {
246255
css += '}\n';
247256
}else if (rule.name[0] === '/') // comment
248257
css += rule.name + '\n';
249-
else
258+
else if (rule.name[0] === '@') // 有些规则只是为了嵌套 '&', 没有 decls
250259
css += rule.name + ';\n';
251260
return css;
252261
};
@@ -346,32 +355,20 @@ const lineify = require('./lineify'),
346355
/\bcontinue\( *((?:\.|[$a-zA-Z_]+[$\w]*)(?: *, *[$a-zA-Z_.]+[$\w]*)*)* *\)/;
347356

348357
/**
349-
* PowCSS 通过插件对 CSS 进行处理, 分多个工作期:
350-
*
351-
* process 解析输入源转换为节点树(root)
352-
* compile 使用插件编译节点树中的未决节点
353-
* yield 遍历节点树进行构建, 构建行为由 Context 决定.
354-
* cssify 输出构建后的 CSS 源码
355-
*
356-
* PowCSS 最重要的核心有两个
357-
*
358-
* 1. 编译插件模型 @see Plugin
359-
* 2. 渲染上下文 @see Context
360-
*
361-
* 在 PowCSS 的设计中, 允许编译后的结果脱离 PowCSS 进行渲染.
362-
* Context 就是为了实现这个目标, 它很简单, 重构或扩展非常容易.
358+
* PowCSS 负责解析 source 为节点树, 并拼接编译器的编译结果.
359+
* 在 PowCSS 中的插件就是 compiler, compiler 负责与 context 配合.
363360
*/
364361
class PowCSS {
365362
/**
366-
* @param {?Plugin[]} plugins 处理器数组缺省为 [compiler()]
363+
* @param {?Compiler[]} plugins 编译器数组, 缺省为 [compiler()]
367364
*/
368365
constructor(plugins) {
369366
this.plugins = plugins && plugins.length || [compiler()];
370367
}
371368

372369
/**
373-
* 使用一个插件
374-
* @param {Plugin} plugin
370+
* 使用一个编译器插件
371+
* @param {Compiler} plugin
375372
* @return {this}
376373
*/
377374
use(plugin) {
@@ -541,7 +538,7 @@ class PowCSS {
541538
}
542539

543540
/**
544-
* 格式化输出 root 节点树
541+
* 格式化输出 root.nodes
545542
* @param {object} root 解析后的节点树
546543
* @return {string} CSS 无花括号两空格缩进格式
547544
*/
@@ -672,7 +669,7 @@ module.exports = function(plugins) {
672669
const toString = Object.prototype.toString;
673670

674671
/**
675-
* 辅助函数集合, ctx 总是(扩展)继承 util 的所有方法.
672+
* 辅助方法集合
676673
*/
677674
let util = {
678675
/**

0 commit comments

Comments
 (0)