Home

tailwind-ctp-intellisense @2942881928dc0a22949c522e4e575640089c69ee - refs - log -
-
https://git.jolheiser.com/tailwind-ctp-intellisense.git
Tailwind intellisense + Catppuccin
tailwind-ctp-intellisense / packages / tailwindcss-language-service / src / util / jit.ts
- raw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import { State } from './state'
import type { Container, Root, Rule } from 'postcss'
import dlv from 'dlv'
import { remToPx } from './remToPx'

export function bigSign(bigIntValue) {
  // @ts-ignore
  return (bigIntValue > 0n) - (bigIntValue < 0n)
}

export function generateRules(state: State, classNames: string[]): { root: Root; rules: Rule[] } {
  let rules: [bigint, Rule][] = state.modules.jit.generateRules
    .module(new Set(classNames), state.jitContext)
    .sort(([a], [z]) => bigSign(a - z))

  let actualRules: Rule[] = []

  for (let [, rule] of rules) {
    if (rule.type === 'rule') {
      actualRules.push(rule)
    } else if (rule.walkRules) {
      rule.walkRules((subRule) => {
        actualRules.push(subRule)
      })
    }
  }

  return {
    root: state.modules.postcss.module.root({ nodes: rules.map(([, rule]) => rule) }),
    rules: actualRules,
  }
}

export async function stringifyRoot(state: State, root: Root, uri?: string): Promise<string> {
  let settings = await state.editor.getConfiguration(uri)
  let tabSize = dlv(settings, 'editor.tabSize', 2)
  let showPixelEquivalents = dlv(settings, 'tailwindCSS.showPixelEquivalents', true)
  let rootFontSize = dlv(settings, 'tailwindCSS.rootFontSize', 16)

  let clone = root

  if (showPixelEquivalents) {
    clone = root.clone()
    clone.walkDecls((decl) => {
      let px = remToPx(decl.value, rootFontSize)
      if (px) {
        decl.value = `${decl.value}/* ${px} */`
      }
    })
  }

  return clone
    .toString()
    .replace(/([^}{;])$/gm, '$1;')
    .replace(/^(?:    )+/gm, (indent: string) => ' '.repeat((indent.length / 4) * tabSize))
}

export function stringifyRules(state: State, rules: Rule[], tabSize: number = 2): string {
  return rules
    .map((rule) => rule.toString().replace(/([^}{;])$/gm, '$1;'))
    .join('\n\n')
    .replace(/^(?:    )+/gm, (indent: string) => ' '.repeat((indent.length / 4) * tabSize))
}

export function stringifyDecls(rule: Rule): string {
  let result = []
  rule.walkDecls(({ prop, value }) => {
    result.push(`${prop}: ${value};`)
  })
  return result.join(' ')
}

function replaceClassName(state: State, selector: string, find: string, replace: string): string {
  const transform = (selectors) => {
    selectors.walkClasses((className) => {
      if (className.value === find) {
        className.value = replace
      }
    })
  }

  return state.modules.postcssSelectorParser.module(transform).processSync(selector)
}

export function getRuleContext(state: State, rule: Rule, className: string): string[] {
  let context: string[] = [replaceClassName(state, rule.selector, className, '__placeholder__')]

  let p: Container = rule
  while (p.parent.type !== 'root') {
    p = p.parent
    if (p.type === 'atrule') {
      // @ts-ignore
      context.unshift(`@${p.name} ${p.params}`)
    }
  }

  return context
}