<commit_before>import {
  report,
  ruleMessages,
  whitespaceChecker
} from "../../utils"

export const ruleName = "rule-semicolon-newline-after"

export const messages = ruleMessages(ruleName, {
  expectedAfter: () => `Expected newline after ";"`,
  rejectedAfter: () => `Unexpected newline after ";"`,
  expectedAfterMultiLine: () => `Expected newline after ";" within multi-line rule`,
  rejectedAfterMultiLine: () => `Unexpected newline after ";" within multi-line rule`,
})

/**
 * @param {"always"|"never"|"always-multi-line"|"never-multi-line"} expectation
 */
export default function (expectation) {
  const check = whitespaceChecker("\n", expectation, messages)
  return function (css, result) {
    css.eachDecl(function (decl) {
      // Ignore last declaration if there's no trailing semicolon
      const parentRule = decl.parent
      if (!parentRule.semicolon && parentRule.last === decl) { return }

      const nextNode = decl.next()
      if (!nextNode) { return }

      // Allow end-of-line comments one space after the semicolon
      let nodeToCheck = (nextNode.type === "comment" && nextNode.before === " ")
        ? nextNode.next()
        : nextNode

      check.afterOneOnly(nodeToCheck.toString(), -1, m => {
        return report({
          message: m,
          node: decl,
          result,
          ruleName,
        })
      }, parentRule.toString().slice("{"))
    })
  }
}
<commit_msg>rule-semicolon-newline-after ignore if no next node to check<commit_after>import {
  report,
  ruleMessages,
  whitespaceChecker
} from "../../utils"

export const ruleName = "rule-semicolon-newline-after"

export const messages = ruleMessages(ruleName, {
  expectedAfter: () => `Expected newline after ";"`,
  rejectedAfter: () => `Unexpected newline after ";"`,
  expectedAfterMultiLine: () => `Expected newline after ";" within multi-line rule`,
  rejectedAfterMultiLine: () => `Unexpected newline after ";" within multi-line rule`,
})

/**
 * @param {"always"|"never"|"always-multi-line"|"never-multi-line"} expectation
 */
export default function (expectation) {
  const check = whitespaceChecker("\n", expectation, messages)
  return function (css, result) {
    css.eachDecl(function (decl) {
      // Ignore last declaration if there's no trailing semicolon
      const parentRule = decl.parent
      if (!parentRule.semicolon && parentRule.last === decl) { return }

      const nextNode = decl.next()
      if (!nextNode) { return }

      // Allow end-of-line comments one space after the semicolon
      let nodeToCheck = (nextNode.type === "comment" && nextNode.before === " ")
        ? nextNode.next()
        : nextNode
      if (!nodeToCheck) { return }

      check.afterOneOnly(nodeToCheck.toString(), -1, m => {
        return report({
          message: m,
          node: decl,
          result,
          ruleName,
        })
      }, parentRule.toString().slice("{"))
    })
  }
}

{'fraction_non_alphanumeric': 0.14344262295081966, 'fraction_numerical': 0.0006830601092896175, 'mean_word_length': 3.034435261707989, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2972414', 'n_tokens_mistral': 848, 'n_tokens_neox': 845, 'n_words': 216}