refactor: shorten scoped css var / animation prefix
This commit is contained in:
		
							parent
							
								
									73807aeaf7
								
							
						
					
					
						commit
						5f271515cf
					
				@ -155,7 +155,8 @@ describe('SFC scoped CSS', () => {
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('scoped keyframes', () => {
 | 
					  test('scoped keyframes', () => {
 | 
				
			||||||
    const style = compileScoped(`
 | 
					    const style = compileScoped(
 | 
				
			||||||
 | 
					      `
 | 
				
			||||||
.anim {
 | 
					.anim {
 | 
				
			||||||
  animation: color 5s infinite, other 5s;
 | 
					  animation: color 5s infinite, other 5s;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -190,23 +191,27 @@ describe('SFC scoped CSS', () => {
 | 
				
			|||||||
  from { opacity: 0; }
 | 
					  from { opacity: 0; }
 | 
				
			||||||
  to { opacity: 1; }
 | 
					  to { opacity: 1; }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
    `)
 | 
					    `,
 | 
				
			||||||
 | 
					      { id: 'data-v-test' }
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expect(style).toContain(
 | 
					    expect(style).toContain(
 | 
				
			||||||
      `.anim[test] {\n  animation: color-test 5s infinite, other 5s;`
 | 
					      `.anim[data-v-test] {\n  animation: color-test 5s infinite, other 5s;`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(style).toContain(`.anim-2[test] {\n  animation-name: color-test`)
 | 
					 | 
				
			||||||
    expect(style).toContain(
 | 
					    expect(style).toContain(
 | 
				
			||||||
      `.anim-3[test] {\n  animation: 5s color-test infinite, 5s other;`
 | 
					      `.anim-2[data-v-test] {\n  animation-name: color-test`
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    expect(style).toContain(
 | 
				
			||||||
 | 
					      `.anim-3[data-v-test] {\n  animation: 5s color-test infinite, 5s other;`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(style).toContain(`@keyframes color-test {`)
 | 
					    expect(style).toContain(`@keyframes color-test {`)
 | 
				
			||||||
    expect(style).toContain(`@-webkit-keyframes color-test {`)
 | 
					    expect(style).toContain(`@-webkit-keyframes color-test {`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expect(style).toContain(
 | 
					    expect(style).toContain(
 | 
				
			||||||
      `.anim-multiple[test] {\n  animation: color-test 5s infinite,opacity-test 2s;`
 | 
					      `.anim-multiple[data-v-test] {\n  animation: color-test 5s infinite,opacity-test 2s;`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(style).toContain(
 | 
					    expect(style).toContain(
 | 
				
			||||||
      `.anim-multiple-2[test] {\n  animation-name: color-test,opacity-test;`
 | 
					      `.anim-multiple-2[data-v-test] {\n  animation-name: color-test,opacity-test;`
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    expect(style).toContain(`@keyframes opacity-test {`)
 | 
					    expect(style).toContain(`@keyframes opacity-test {`)
 | 
				
			||||||
    expect(style).toContain(`@-webkit-keyframes opacity-test {`)
 | 
					    expect(style).toContain(`@-webkit-keyframes opacity-test {`)
 | 
				
			||||||
@ -268,11 +273,12 @@ describe('SFC scoped CSS', () => {
 | 
				
			|||||||
        font-size: var(--global:font);
 | 
					        font-size: var(--global:font);
 | 
				
			||||||
      }`,
 | 
					      }`,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          id: 'data-v-test',
 | 
				
			||||||
          vars: true
 | 
					          vars: true
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
      expect(code).toMatchInlineSnapshot(`
 | 
					      expect(code).toMatchInlineSnapshot(`
 | 
				
			||||||
        ".foo[test] {
 | 
					        ".foo[data-v-test] {
 | 
				
			||||||
                color: var(--test-color);
 | 
					                color: var(--test-color);
 | 
				
			||||||
                font-size: var(--font);
 | 
					                font-size: var(--font);
 | 
				
			||||||
        }"
 | 
					        }"
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@ const cssVarRE = /\bvar\(--(global:)?([^)]+)\)/g
 | 
				
			|||||||
export default postcss.plugin('vue-scoped', (options: any) => (root: Root) => {
 | 
					export default postcss.plugin('vue-scoped', (options: any) => (root: Root) => {
 | 
				
			||||||
  const { id, vars: hasInjectedVars } = options as { id: string; vars: boolean }
 | 
					  const { id, vars: hasInjectedVars } = options as { id: string; vars: boolean }
 | 
				
			||||||
  const keyframes = Object.create(null)
 | 
					  const keyframes = Object.create(null)
 | 
				
			||||||
 | 
					  const shortId = id.replace(/^data-v-/, '')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  root.each(function rewriteSelectors(node) {
 | 
					  root.each(function rewriteSelectors(node) {
 | 
				
			||||||
    if (node.type !== 'rule') {
 | 
					    if (node.type !== 'rule') {
 | 
				
			||||||
@ -17,7 +18,7 @@ export default postcss.plugin('vue-scoped', (options: any) => (root: Root) => {
 | 
				
			|||||||
          node.each(rewriteSelectors)
 | 
					          node.each(rewriteSelectors)
 | 
				
			||||||
        } else if (/-?keyframes$/.test(node.name)) {
 | 
					        } else if (/-?keyframes$/.test(node.name)) {
 | 
				
			||||||
          // register keyframes
 | 
					          // register keyframes
 | 
				
			||||||
          keyframes[node.params] = node.params = node.params + '-' + id
 | 
					          keyframes[node.params] = node.params = node.params + '-' + shortId
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return
 | 
					      return
 | 
				
			||||||
@ -170,7 +171,7 @@ export default postcss.plugin('vue-scoped', (options: any) => (root: Root) => {
 | 
				
			|||||||
      // rewrite CSS variables
 | 
					      // rewrite CSS variables
 | 
				
			||||||
      if (hasInjectedVars && cssVarRE.test(decl.value)) {
 | 
					      if (hasInjectedVars && cssVarRE.test(decl.value)) {
 | 
				
			||||||
        decl.value = decl.value.replace(cssVarRE, (_, $1, $2) => {
 | 
					        decl.value = decl.value.replace(cssVarRE, (_, $1, $2) => {
 | 
				
			||||||
          return $1 ? `var(--${$2})` : `var(--${id}-${$2})`
 | 
					          return $1 ? `var(--${$2})` : `var(--${shortId}-${$2})`
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
				
			|||||||
@ -15,17 +15,21 @@ describe('useCssVars', () => {
 | 
				
			|||||||
    const state = reactive({ color: 'red' })
 | 
					    const state = reactive({ color: 'red' })
 | 
				
			||||||
    const App = getApp(state)
 | 
					    const App = getApp(state)
 | 
				
			||||||
    const root = document.createElement('div')
 | 
					    const root = document.createElement('div')
 | 
				
			||||||
    const prefix = scopeId ? `${scopeId}-` : ``
 | 
					    const prefix = scopeId ? `${scopeId.replace(/^data-v-/, '')}-` : ``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    render(h(App), root)
 | 
					    render(h(App), root)
 | 
				
			||||||
    for (const c of [].slice.call(root.children as any)) {
 | 
					    for (const c of [].slice.call(root.children as any)) {
 | 
				
			||||||
      expect((c as HTMLElement).style.getPropertyValue(`--${prefix}color`))
 | 
					      expect(
 | 
				
			||||||
 | 
					        (c as HTMLElement).style.getPropertyValue(`--${prefix}color`)
 | 
				
			||||||
 | 
					      ).toBe(`red`)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    state.color = 'green'
 | 
					    state.color = 'green'
 | 
				
			||||||
    await nextTick()
 | 
					    await nextTick()
 | 
				
			||||||
    for (const c of [].slice.call(root.children as any)) {
 | 
					    for (const c of [].slice.call(root.children as any)) {
 | 
				
			||||||
      expect((c as HTMLElement).style.getPropertyValue(`--${prefix}color`))
 | 
					      expect(
 | 
				
			||||||
 | 
					        (c as HTMLElement).style.getPropertyValue(`--${prefix}color`)
 | 
				
			||||||
 | 
					      ).toBe('green')
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -65,7 +69,7 @@ describe('useCssVars', () => {
 | 
				
			|||||||
  })
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test('with <style scoped>', async () => {
 | 
					  test('with <style scoped>', async () => {
 | 
				
			||||||
    const id = 'v-12345'
 | 
					    const id = 'data-v-12345'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await assertCssVars(
 | 
					    await assertCssVars(
 | 
				
			||||||
      state => ({
 | 
					      state => ({
 | 
				
			||||||
 | 
				
			|||||||
@ -5,8 +5,7 @@ import {
 | 
				
			|||||||
  watchEffect,
 | 
					  watchEffect,
 | 
				
			||||||
  warn,
 | 
					  warn,
 | 
				
			||||||
  VNode,
 | 
					  VNode,
 | 
				
			||||||
  Fragment,
 | 
					  Fragment
 | 
				
			||||||
  ComponentInternalInstance
 | 
					 | 
				
			||||||
} from '@vue/runtime-core'
 | 
					} from '@vue/runtime-core'
 | 
				
			||||||
import { ShapeFlags } from '@vue/shared/src'
 | 
					import { ShapeFlags } from '@vue/shared/src'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -20,14 +19,15 @@ export function useCSSVars(
 | 
				
			|||||||
      warn(`useCssVars is called without current active component instance.`)
 | 
					      warn(`useCssVars is called without current active component instance.`)
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const prefix =
 | 
				
			||||||
 | 
					    scoped && instance.type.__scopeId
 | 
				
			||||||
 | 
					      ? `${instance.type.__scopeId.replace(/^data-v-/, '')}-`
 | 
				
			||||||
 | 
					      : ``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  onMounted(() => {
 | 
					  onMounted(() => {
 | 
				
			||||||
    watchEffect(() => {
 | 
					    watchEffect(() => {
 | 
				
			||||||
      setVarsOnVNode(
 | 
					      setVarsOnVNode(instance.subTree, getter(instance.proxy!), prefix)
 | 
				
			||||||
        instance.subTree,
 | 
					 | 
				
			||||||
        getter(instance.proxy!),
 | 
					 | 
				
			||||||
        instance,
 | 
					 | 
				
			||||||
        scoped
 | 
					 | 
				
			||||||
      )
 | 
					 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -35,8 +35,7 @@ export function useCSSVars(
 | 
				
			|||||||
function setVarsOnVNode(
 | 
					function setVarsOnVNode(
 | 
				
			||||||
  vnode: VNode,
 | 
					  vnode: VNode,
 | 
				
			||||||
  vars: Record<string, string>,
 | 
					  vars: Record<string, string>,
 | 
				
			||||||
  owner: ComponentInternalInstance,
 | 
					  prefix: string
 | 
				
			||||||
  scoped: boolean
 | 
					 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
  // drill down HOCs until it's a non-component vnode
 | 
					  // drill down HOCs until it's a non-component vnode
 | 
				
			||||||
  while (vnode.component) {
 | 
					  while (vnode.component) {
 | 
				
			||||||
@ -44,14 +43,10 @@ function setVarsOnVNode(
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  if (vnode.shapeFlag & ShapeFlags.ELEMENT && vnode.el) {
 | 
					  if (vnode.shapeFlag & ShapeFlags.ELEMENT && vnode.el) {
 | 
				
			||||||
    const style = vnode.el.style
 | 
					    const style = vnode.el.style
 | 
				
			||||||
    const prefix =
 | 
					 | 
				
			||||||
      scoped && owner.type.__scopeId ? `${owner.type.__scopeId}-` : ``
 | 
					 | 
				
			||||||
    for (const key in vars) {
 | 
					    for (const key in vars) {
 | 
				
			||||||
      style.setProperty(`--${prefix}${key}`, vars[key])
 | 
					      style.setProperty(`--${prefix}${key}`, vars[key])
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else if (vnode.type === Fragment) {
 | 
					  } else if (vnode.type === Fragment) {
 | 
				
			||||||
    ;(vnode.children as VNode[]).forEach(c =>
 | 
					    ;(vnode.children as VNode[]).forEach(c => setVarsOnVNode(c, vars, prefix))
 | 
				
			||||||
      setVarsOnVNode(c, vars, owner, scoped)
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user