Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
genary
uni-app
提交
df4265d9
U
uni-app
项目概览
genary
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
df4265d9
编写于
8月 06, 2021
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(app): css scoped
上级
fd63c97c
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
314 addition
and
23 deletion
+314
-23
packages/uni-app-vite/dist/plugin/index.js
packages/uni-app-vite/dist/plugin/index.js
+1
-1
packages/uni-app-vite/dist/plugin/uni.js
packages/uni-app-vite/dist/plugin/uni.js
+26
-10
packages/uni-app-vite/src/plugin/index.ts
packages/uni-app-vite/src/plugin/index.ts
+1
-1
packages/uni-app-vite/src/plugin/uni.ts
packages/uni-app-vite/src/plugin/uni.ts
+23
-10
packages/uni-cli-shared/__tests__/stylePluginScoped.spec.ts
packages/uni-cli-shared/__tests__/stylePluginScoped.spec.ts
+55
-0
packages/uni-cli-shared/src/index.ts
packages/uni-cli-shared/src/index.ts
+2
-0
packages/uni-cli-shared/src/postcss/index.ts
packages/uni-cli-shared/src/postcss/index.ts
+2
-0
packages/uni-cli-shared/src/postcss/plugins/stylePluginScoped.ts
...s/uni-cli-shared/src/postcss/plugins/stylePluginScoped.ts
+196
-0
packages/vite-plugin-uni/src/vue/options.ts
packages/vite-plugin-uni/src/vue/options.ts
+8
-1
未找到文件。
packages/uni-app-vite/dist/plugin/index.js
浏览文件 @
df4265d9
...
...
@@ -7,7 +7,7 @@ const build_1 = require("./build");
const
configResolved_1
=
require
(
"
./configResolved
"
);
exports
.
UniAppPlugin
=
{
name
:
'
vite:uni-app
'
,
uni
:
uni_1
.
uniOptions
,
uni
:
uni_1
.
uniOptions
()
,
config
()
{
return
{
build
:
build_1
.
buildOptions
(),
...
...
packages/uni-app-vite/dist/plugin/uni.js
浏览文件 @
df4265d9
"
use strict
"
;
var
__importDefault
=
(
this
&&
this
.
__importDefault
)
||
function
(
mod
)
{
return
(
mod
&&
mod
.
__esModule
)
?
mod
:
{
"
default
"
:
mod
};
};
Object
.
defineProperty
(
exports
,
"
__esModule
"
,
{
value
:
true
});
exports
.
uniOptions
=
void
0
;
const
path_1
=
__importDefault
(
require
(
"
path
"
));
const
uni_shared_1
=
require
(
"
@dcloudio/uni-shared
"
);
exports
.
uniOptions
=
{
copyOptions
:
{
assets
:
[
'
hybrid/html
'
]
},
compilerOptions
:
{
isNativeTag
:
uni_shared_1
.
isServiceNativeTag
,
isCustomElement
:
uni_shared_1
.
isServiceCustomElement
,
},
transformEvent
:
{
tap
:
'
click
'
,
},
};
const
uni_cli_shared_1
=
require
(
"
@dcloudio/uni-cli-shared
"
);
function
uniOptions
()
{
return
{
copyOptions
:
{
assets
:
[
'
hybrid/html
'
],
targets
:
[
{
src
:
uni_cli_shared_1
.
normalizePath
(
path_1
.
default
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
'
androidPrivacy.json
'
)),
dest
:
process
.
env
.
UNI_OUTPUT_DIR
,
},
],
},
compilerOptions
:
{
isNativeTag
:
uni_shared_1
.
isServiceNativeTag
,
isCustomElement
:
uni_shared_1
.
isServiceCustomElement
,
},
transformEvent
:
{
tap
:
'
click
'
,
},
};
}
exports
.
uniOptions
=
uniOptions
;
packages/uni-app-vite/src/plugin/index.ts
浏览文件 @
df4265d9
...
...
@@ -6,7 +6,7 @@ import { configResolved } from './configResolved'
export
const
UniAppPlugin
:
UniVitePlugin
=
{
name
:
'
vite:uni-app
'
,
uni
:
uniOptions
,
uni
:
uniOptions
()
,
config
()
{
return
{
build
:
buildOptions
(),
...
...
packages/uni-app-vite/src/plugin/uni.ts
浏览文件 @
df4265d9
import
path
from
'
path
'
import
{
isServiceNativeTag
,
isServiceCustomElement
,
}
from
'
@dcloudio/uni-shared
'
import
{
UniVitePlugin
}
from
'
@dcloudio/uni-cli-shared
'
import
{
normalizePath
,
UniVitePlugin
}
from
'
@dcloudio/uni-cli-shared
'
export
const
uniOptions
:
UniVitePlugin
[
'
uni
'
]
=
{
copyOptions
:
{
assets
:
[
'
hybrid/html
'
]
},
compilerOptions
:
{
isNativeTag
:
isServiceNativeTag
,
isCustomElement
:
isServiceCustomElement
,
},
transformEvent
:
{
tap
:
'
click
'
,
},
export
function
uniOptions
():
UniVitePlugin
[
'
uni
'
]
{
return
{
copyOptions
:
{
assets
:
[
'
hybrid/html
'
],
targets
:
[
{
src
:
normalizePath
(
path
.
resolve
(
process
.
env
.
UNI_INPUT_DIR
,
'
androidPrivacy.json
'
)
),
dest
:
process
.
env
.
UNI_OUTPUT_DIR
,
},
],
},
compilerOptions
:
{
isNativeTag
:
isServiceNativeTag
,
isCustomElement
:
isServiceCustomElement
,
},
transformEvent
:
{
tap
:
'
click
'
,
},
}
}
packages/uni-cli-shared/__tests__/stylePluginScoped.spec.ts
0 → 100644
浏览文件 @
df4265d9
import
postcss
,
{
ProcessOptions
}
from
'
postcss
'
import
scopedPlugin
from
'
../src/postcss/plugins/stylePluginScoped
'
const
styleCode
=
`{color:red;}`
const
deepSelectors
=
[
[
'
>>> a
'
,
'
a
'
,
'
:deep(a)
'
],
[
'
a >>> b
'
,
'
a b
'
,
'
a :deep(b)
'
],
[
'
a >>> b>c
'
,
'
a b>c
'
,
'
a :deep(b>c)
'
],
[
'
>>> a b
'
,
'
a b
'
,
'
:deep(a b)
'
],
[
'
/deep/ a
'
,
'
a
'
,
'
:deep(a)
'
],
[
'
a /deep/ b
'
,
'
a b
'
,
'
a :deep(b)
'
],
[
'
a /deep/ b>c
'
,
'
a b>c
'
,
'
a :deep(b>c)
'
],
[
'
/deep/ a b
'
,
'
a b
'
,
'
:deep(a b)
'
],
[
'
::v-deep a
'
,
'
a
'
,
'
:deep(a)
'
],
[
'
a ::v-deep b
'
,
'
a b
'
,
'
a :deep(b)
'
],
[
'
a ::v-deep b>c
'
,
'
a b>c
'
,
'
a :deep(b>c)
'
],
[
'
::v-deep a b
'
,
'
a b
'
,
'
:deep(a b)
'
],
[
'
::v-deep a b,::v-deep a
'
,
'
a b, a
'
,
'
:deep(a b),:deep(a)
'
],
]
const
removeDeepCssCodes
=
Object
.
create
(
null
)
const
rewriteDeepCssCodes
=
Object
.
create
(
null
)
deepSelectors
.
forEach
(([
selector
,
removeDeepSelector
,
rewriteDeepSelector
])
=>
{
removeDeepCssCodes
[
selector
+
styleCode
]
=
removeDeepSelector
+
styleCode
rewriteDeepCssCodes
[
selector
+
styleCode
]
=
rewriteDeepSelector
+
styleCode
})
const
processor
=
postcss
([
scopedPlugin
])
const
processorWithVueSfcScoped
=
postcss
([
scopedPlugin
,
{
postcssPlugin
:
'
vue-sfc-scoped
'
,
},
])
const
options
:
ProcessOptions
=
{
from
:
'
a.css
'
,
map
:
false
}
describe
(
'
cssScoped
'
,
()
=>
{
Object
.
keys
(
removeDeepCssCodes
).
forEach
((
cssCode
)
=>
{
test
(
'
remove
'
+
cssCode
,
async
()
=>
{
return
processor
.
process
(
cssCode
,
options
).
then
((
result
)
=>
{
expect
(
result
.
css
).
toBe
(
removeDeepCssCodes
[
cssCode
])
})
})
})
Object
.
keys
(
rewriteDeepCssCodes
).
forEach
((
cssCode
)
=>
{
test
(
'
rewrite
'
+
cssCode
,
async
()
=>
{
return
processorWithVueSfcScoped
.
process
(
cssCode
,
options
)
.
then
((
result
)
=>
{
expect
(
result
.
css
).
toBe
(
rewriteDeepCssCodes
[
cssCode
])
})
})
})
})
packages/uni-cli-shared/src/index.ts
浏览文件 @
df4265d9
...
...
@@ -10,4 +10,6 @@ export * from './utils'
export
*
from
'
./easycom
'
export
*
from
'
./constants
'
export
*
from
'
./preprocess
'
export
*
from
'
./postcss
'
export
{
checkUpdate
}
from
'
./checkUpdate
'
packages/uni-cli-shared/src/postcss/index.ts
0 → 100644
浏览文件 @
df4265d9
import
uniPostcssScopedPlugin
from
'
./plugins/stylePluginScoped
'
export
{
uniPostcssScopedPlugin
}
packages/uni-cli-shared/src/postcss/plugins/stylePluginScoped.ts
0 → 100644
浏览文件 @
df4265d9
import
{
Plugin
,
PluginCreator
,
Rule
,
AtRule
}
from
'
postcss
'
import
selectorParser
from
'
postcss-selector-parser
'
const
scopedPlugin
:
PluginCreator
<
string
>
=
()
=>
{
return
{
postcssPlugin
:
'
uni-sfc-scoped
'
,
prepare
({
processor
:
{
plugins
}
})
{
const
hasVueSfcScoped
=
!!
plugins
.
find
(
(
plugin
)
=>
(
plugin
as
Plugin
).
postcssPlugin
===
'
vue-sfc-scoped
'
)
return
{
Rule
(
rule
)
{
processRule
(
rule
,
hasVueSfcScoped
)
},
}
},
}
}
const
processedRules
=
new
WeakSet
<
Rule
>
()
function
processRule
(
rule
:
Rule
,
hasVueSfcScoped
:
boolean
)
{
if
(
processedRules
.
has
(
rule
)
||
(
rule
.
parent
&&
rule
.
parent
.
type
===
'
atrule
'
&&
/-
?
keyframes$/
.
test
((
rule
.
parent
as
AtRule
).
name
))
)
{
return
}
processedRules
.
add
(
rule
)
rule
.
selector
=
selectorParser
((
selectorRoot
)
=>
{
selectorRoot
.
each
((
selector
)
=>
{
hasVueSfcScoped
?
rewriteDeprecatedSelector
(
selector
)
:
rewriteSelector
(
selector
,
selectorRoot
)
})
}).
processSync
(
rule
.
selector
)
}
/**
* @param selector
* @returns
*/
function
rewriteDeprecatedSelector
(
selector
:
selectorParser
.
Selector
)
{
const
nodes
:
selectorParser
.
Node
[]
=
[]
let
deepNode
:
selectorParser
.
Pseudo
|
selectorParser
.
Combinator
|
undefined
selector
.
each
((
n
)
=>
{
if
(
deepNode
)
{
nodes
.
push
(
n
)
selector
.
removeChild
(
n
)
}
else
{
const
{
type
,
value
}
=
n
if
(
type
===
'
pseudo
'
&&
value
===
'
::v-deep
'
)
{
deepNode
=
n
as
selectorParser
.
Pseudo
}
else
if
(
type
===
'
combinator
'
&&
(
value
===
'
>>>
'
||
value
===
'
/deep/
'
)
)
{
deepNode
=
n
as
selectorParser
.
Combinator
}
}
})
if
(
!
deepNode
)
{
return
}
if
(
deepNode
.
type
===
'
combinator
'
)
{
const
index
=
selector
.
index
(
deepNode
)
if
(
index
>
0
)
{
selector
.
insertBefore
(
deepNode
,
selectorParser
.
combinator
({
value
:
'
'
}))
}
}
// remove first combinator
// ::v-deep a{color:red;} => :deep(a){color:red;}
const
firstNode
=
nodes
[
0
]
if
(
firstNode
&&
firstNode
.
type
===
'
combinator
'
&&
firstNode
.
value
===
'
'
)
{
nodes
.
shift
()
}
selector
.
insertBefore
(
deepNode
,
selectorParser
.
pseudo
({
value
:
'
:deep
'
,
nodes
:
[
selectorParser
.
selector
({
value
:
''
,
nodes
})],
})
)
selector
.
removeChild
(
deepNode
)
}
function
rewriteSelector
(
selector
:
selectorParser
.
Selector
,
selectorRoot
:
selectorParser
.
Root
)
{
let
node
:
selectorParser
.
Node
|
null
=
null
// find the last child node to insert attribute selector
selector
.
each
((
n
)
=>
{
// DEPRECATED ">>>" and "/deep/" combinator
if
(
n
.
type
===
'
combinator
'
&&
(
n
.
value
===
'
>>>
'
||
n
.
value
===
'
/deep/
'
)
)
{
n
.
value
=
'
'
n
.
spaces
.
before
=
n
.
spaces
.
after
=
''
// warn(
// `the >>> and /deep/ combinators have been deprecated. ` +
// `Use :deep() instead.`
// )
return
false
}
if
(
n
.
type
===
'
pseudo
'
)
{
const
{
value
}
=
n
// deep: inject [id] attribute at the node before the ::v-deep
// combinator.
if
(
value
===
'
:deep
'
||
value
===
'
::v-deep
'
)
{
if
(
n
.
nodes
.
length
)
{
// .foo ::v-deep(.bar) -> .foo[xxxxxxx] .bar
// replace the current node with ::v-deep's inner selector
let
last
:
selectorParser
.
Selector
[
'
nodes
'
][
0
]
=
n
n
.
nodes
[
0
].
each
((
ss
)
=>
{
selector
.
insertAfter
(
last
,
ss
)
last
=
ss
})
// insert a space combinator before if it doesn't already have one
const
prev
=
selector
.
at
(
selector
.
index
(
n
)
-
1
)
if
(
!
prev
||
!
isSpaceCombinator
(
prev
))
{
selector
.
insertAfter
(
n
,
selectorParser
.
combinator
({
value
:
'
'
,
})
)
}
selector
.
removeChild
(
n
)
}
else
{
// DEPRECATED usage
// .foo ::v-deep .bar -> .foo[xxxxxxx] .bar
// warn(
// `::v-deep usage as a combinator has ` +
// `been deprecated. Use :deep(<inner-selector>) instead.`
// )
const
prev
=
selector
.
at
(
selector
.
index
(
n
)
-
1
)
if
(
prev
&&
isSpaceCombinator
(
prev
))
{
selector
.
removeChild
(
prev
)
}
selector
.
removeChild
(
n
)
}
return
false
}
// slot: use selector inside `::v-slotted` and inject [id + '-s']
// instead.
// ::v-slotted(.foo) -> .foo[xxxxxxx-s]
if
(
value
===
'
:slotted
'
||
value
===
'
::v-slotted
'
)
{
rewriteSelector
(
n
.
nodes
[
0
],
selectorRoot
)
let
last
:
selectorParser
.
Selector
[
'
nodes
'
][
0
]
=
n
n
.
nodes
[
0
].
each
((
ss
)
=>
{
selector
.
insertAfter
(
last
,
ss
)
last
=
ss
})
// selector.insertAfter(n, n.nodes[0])
selector
.
removeChild
(
n
)
// since slotted attribute already scopes the selector there's no
// need for the non-slot attribute.
return
false
}
// global: replace with inner selector and do not inject [id].
// ::v-global(.foo) -> .foo
if
(
value
===
'
:global
'
||
value
===
'
::v-global
'
)
{
selectorRoot
.
insertAfter
(
selector
,
n
.
nodes
[
0
])
selectorRoot
.
removeChild
(
selector
)
return
false
}
}
if
(
n
.
type
!==
'
pseudo
'
&&
n
.
type
!==
'
combinator
'
)
{
node
=
n
}
})
if
(
node
)
{
;(
node
as
selectorParser
.
Node
).
spaces
.
after
=
''
}
else
{
// For deep selectors & standalone pseudo selectors,
// the attribute selectors are prepended rather than appended.
// So all leading spaces must be eliminated to avoid problems.
selector
.
first
.
spaces
.
before
=
''
}
}
function
isSpaceCombinator
(
node
:
selectorParser
.
Node
)
{
return
node
.
type
===
'
combinator
'
&&
/^
\s
+$/
.
test
(
node
.
value
)
}
scopedPlugin
.
postcss
=
true
export
default
scopedPlugin
packages/vite-plugin-uni/src/vue/options.ts
浏览文件 @
df4265d9
...
...
@@ -3,8 +3,8 @@ import { SFCTemplateCompileOptions } from '@vue/compiler-sfc'
import
{
isCustomElement
}
from
'
@dcloudio/uni-shared
'
import
{
EXTNAME_VUE_RE
,
// parseCompatConfigOnce,
UniVitePlugin
,
uniPostcssScopedPlugin
,
}
from
'
@dcloudio/uni-cli-shared
'
import
{
VitePluginUniResolvedOptions
}
from
'
..
'
...
...
@@ -49,6 +49,13 @@ export function initPluginVueOptions(
}
vueOptions
.
include
.
push
(
EXTNAME_VUE_RE
)
const
styleOptions
=
vueOptions
.
style
||
(
vueOptions
.
style
=
{})
if
(
!
styleOptions
.
postcssPlugins
)
{
styleOptions
.
postcssPlugins
=
[]
}
// 解析 scoped 中 deep 等特殊语法
styleOptions
.
postcssPlugins
.
push
(
uniPostcssScopedPlugin
())
const
templateOptions
=
vueOptions
.
template
||
(
vueOptions
.
template
=
{})
templateOptions
.
transformAssetUrls
=
createUniVueTransformAssetUrls
(
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录