Home

tailwind-ctp-intellisense @5e9cce64efde7212f5c7748d64110e0861733712 - 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
 99
100
101
102
103
104
105
106
107
108
109
import { State } from './state'
import type { Container, Document, Root, Rule, Node, AtRule } from 'postcss'
import { remToPx } from './remToPx'

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

export function generateRules(
  state: State,
  classNames: string[],
  filter: (rule: Rule) => boolean = () => true
): { 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 root = state.modules.postcss.module.root({ nodes: rules.map(([, rule]) => rule) })
  state.modules.jit.expandApplyAtRules.module(state.jitContext)(root)
  state.modules.jit.evaluateTailwindFunctions?.module?.(state.jitContext)(root)

  let actualRules: Rule[] = []
  root.walkRules((subRule) => {
    if (filter(subRule)) {
      actualRules.push(subRule)
    }
  })

  return {
    root,
    rules: actualRules,
  }
}

export async function stringifyRoot(state: State, root: Root, uri?: string): Promise<string> {
  let settings = await state.editor.getConfiguration(uri)
  let clone = root.clone()

  clone.walkAtRules('defaults', (node) => {
    node.remove()
  })

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

  return clone
    .toString()
    .replace(/([^;{}\s])(\n\s*})/g, (_match, before, after) => `${before};${after}`)
    .replace(/^(?:    )+/gm, (indent: string) =>
      ' '.repeat((indent.length / 4) * settings.editor.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 async function stringifyDecls(state: State, rule: Rule, uri?: string): Promise<string> {
  let settings = await state.editor.getConfiguration(uri)

  let result = []
  rule.walkDecls(({ prop, value }) => {
    let px = settings.tailwindCSS.showPixelEquivalents
      ? remToPx(value, settings.tailwindCSS.rootFontSize)
      : undefined
    result.push(`${prop}: ${value}${px ? `/* ${px} */` : ''};`)
  })
  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)
}

function isAtRule(node: Node): node is AtRule {
  return node.type === 'atrule'
}

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

  let p: Container | Document = rule
  while (p.parent && p.parent.type !== 'root') {
    p = p.parent
    if (isAtRule(p)) {
      context.unshift(`@${p.name} ${p.params}`)
    }
  }

  return context
}