mirror of
https://github.com/OliveTin/OliveTin
synced 2025-12-18 20:15:38 +00:00
120 lines
2.5 KiB
JavaScript
120 lines
2.5 KiB
JavaScript
import getAtRuleParams from './getAtRuleParams.mjs';
|
|
import getRuleSelector from './getRuleSelector.mjs';
|
|
|
|
import { isObject, isString } from './validateTypes.mjs';
|
|
|
|
/** @import {AtRule, Declaration, Rule} from 'postcss' */
|
|
|
|
/**
|
|
* @param {AtRule} atRule
|
|
* @returns {number}
|
|
*/
|
|
export function atRuleParamIndex(atRule) {
|
|
const index = atRuleAfterNameIndex(atRule);
|
|
|
|
return index + (atRule.raws.afterName?.length ?? 0);
|
|
}
|
|
|
|
/**
|
|
* @param {AtRule} atRule
|
|
* @returns {number}
|
|
*/
|
|
export function atRuleAfterIndex(atRule) {
|
|
// subtract 1 for `}`
|
|
|
|
const endOffset = atRule.source?.end?.offset;
|
|
|
|
if (!endOffset) return atRule.toString().length - 1;
|
|
|
|
const afterLength = atRule.raws?.after?.length;
|
|
|
|
if (!afterLength) return endOffset - 1;
|
|
|
|
return endOffset - (afterLength + 1);
|
|
}
|
|
|
|
/**
|
|
* @param {AtRule} atRule
|
|
* @returns {number}
|
|
*/
|
|
export function atRuleAfterNameIndex(atRule) {
|
|
// Initial 1 is for the `@`
|
|
return 1 + atRule.name.length;
|
|
}
|
|
|
|
/**
|
|
* @param {AtRule} atRule
|
|
* @returns {number}
|
|
*/
|
|
export function atRuleBetweenIndex(atRule) {
|
|
return atRuleParamIndex(atRule) + getAtRuleParams(atRule).length;
|
|
}
|
|
|
|
/**
|
|
* @param {Declaration} decl
|
|
* @returns {number}
|
|
*/
|
|
export function declarationBetweenIndex(decl) {
|
|
const { prop } = decl.raws;
|
|
const propIsObject = isObject(prop);
|
|
|
|
return countChars([
|
|
propIsObject && 'prefix' in prop && prop.prefix,
|
|
(propIsObject && 'raw' in prop && prop.raw) || decl.prop,
|
|
propIsObject && 'suffix' in prop && prop.suffix,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Get the index of a declaration's value
|
|
*
|
|
* @param {Declaration} decl
|
|
* @returns {number}
|
|
*/
|
|
export function declarationValueIndex(decl) {
|
|
const { between, value } = decl.raws;
|
|
|
|
return (
|
|
declarationBetweenIndex(decl) +
|
|
countChars([between || ':', value && 'prefix' in value && value.prefix])
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param {Rule} rule
|
|
* @returns {number}
|
|
*/
|
|
export function ruleBetweenIndex(rule) {
|
|
return getRuleSelector(rule).length;
|
|
}
|
|
|
|
/**
|
|
* @param {Rule} rule
|
|
* @returns {number}
|
|
*/
|
|
export function ruleAfterIndex(rule) {
|
|
// subtract 1 for `}`
|
|
|
|
const endOffset = rule.source?.end?.offset;
|
|
|
|
if (!endOffset) return rule.toString().length - 1;
|
|
|
|
const afterLength = rule.raws?.after?.length;
|
|
|
|
if (!afterLength) return endOffset - 1;
|
|
|
|
return endOffset - (afterLength + 1);
|
|
}
|
|
|
|
/**
|
|
* @param {unknown[]} values
|
|
* @returns {number}
|
|
*/
|
|
function countChars(values) {
|
|
return values.reduce((/** @type {number} */ count, value) => {
|
|
if (isString(value)) return count + value.length;
|
|
|
|
return count;
|
|
}, 0);
|
|
}
|