/*
 * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
 * Licensed under The Universal Permissive License (UPL), Version 1.0
 * as shown at https://oss.oracle.com/licenses/upl/
 */
const{LENGTH_PROP_SET,LENGTH_MEMBER_PROP_SET}=require("./helpers/cssHelper");const RULENAME="oj-html-style-abs-units";const DESCRIPTION="In general it is preferable to use relative length units in place of absolute units. "+"Specifically, 'rem' units are recommended because they proportionately adjust to the root "+"font size.  'rem' can be used for anything that takes a length unit - e.g. font-size, line-height, "+"width, height, padding, margin, etc.  However, there are cases where absolute units are "+"required.  This project is configured to allow absolute units in selector names that include "+"one of the following terms: 'image, and 'picture'.";const SHORT_DESCRIPTION="In general it is preferable to use relative length units in place of absolute units.";const ABS_UNITS=["px","cm","mm","in","pt","pc","all"];const COLON=":";const ALL="all";const NUMBER="number";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(regCtx){if(!this._checkRuleOptions(regCtx)){return false}return{"style":this._onStyle,"stylemember":this._onStyle}}_onStyle(ruleCtx,attr,value){var prop,i;this._CssUtils=ruleCtx.utils.CssUtils;if(ruleCtx.type==="stylemember"){i=attr.charAt(0)===":"?7:6;prop=attr.substring(i);this._checkPropAndValue(ruleCtx,prop,value,true)}else{let val,s,x;for(i=0;i<value.length;i++){s=value[i];x=s.indexOf(COLON);if(x>=0){prop=s.substring(0,x).trimEnd();val=s.substring(x+1).trimStart();this._checkPropAndValue(ruleCtx,prop,val,false)}}}}_checkPropAndValue(ruleCtx,prop,value,submember){if(!submember&&LENGTH_PROP_SET.has(prop)||submember&&LENGTH_MEMBER_PROP_SET.has(prop)){let unit;if(unit=_hasAbsUnits(value));{this._prop(ruleCtx,prop,value,unit)}}}_prop(ruleCtx,prop,val,unit){var m,qty,s,i;m=val.match(/[0-9]+(px|cm|mm|in|pt|pc)/g);if(m&&m.length){for(i=0;i<m.length;i++){s=m[i];unit=s.substring(s.length-2);qty=s.substring(0,s.length-unit.length);qty=parseInt(qty);if(!this._okThreshold(unit,qty)||qty===0){this._emitIssue(ruleCtx,prop,m[i],unit,qty)}}}else if(_isExpr(val)){this._emitIssue2(ruleCtx,prop,val,unit)}}_emitIssue(ruleCtx,prop,val,unit,qty){var issue,unit;if(qty){issue=new ruleCtx.Issue(`style '${prop}' value '${val}' - best practices: replace absolute unit '${unit}' with a relative unit (e.g. 'rem' or '%')`)}else{issue=new ruleCtx.Issue(`style '${prop}' value '${val}' - best practices: remove '${unit}' for zero quantity`);issue.setMsgKey(RULENAME+"_1");issue.setSeverity("minor")}ruleCtx.reporter.addIssue(issue,ruleCtx)}_emitIssue2(ruleCtx,prop,val,unit){var issue;issue=new ruleCtx.Issue(`style '${prop}' expression '${val}' generates a '${unit}' length - best practices: convert to a relative unit (e.g. 'rem' or '%')`);issue.setMsgKey(RULENAME+"_2");ruleCtx.reporter.addIssue(issue,ruleCtx)}_okThreshold(unit,qty){var th;if(!this._unitOpts||typeof qty!==NUMBER){return true}th=this._unitOpts[unit];if(th===undefined){th=this._unitOpts[ALL]}return th?Math.abs(qty)<=th:true}_checkRuleOptions(regCtx){var units,unit,th,b,customOpts;if(customOpts=regCtx.ruleOpts.customOpts){if(units=customOpts.absunits){if(!regCtx.utils.utils.isObject(units)){regCtx.utils.msgLib.error(`Rule ${regCtx.ruleName} :  option 'absunits' is not an object`);this._fail=true;return false}for(unit in units){if(!ABS_UNITS.includes(unit)){regCtx.utils.msgLib.error(`Rule ${regCtx.ruleName} :  option 'absunits' value '${unit}' is not absolute`);b=true;continue}if(units.hasOwnProperty(unit)){th=units[unit];if(typeof th!==NUMBER){regCtx.utils.msgLib.error(`Rule ${regCtx.ruleName} :  option 'absunits' threshold '${th}' is not a number`);b=true}}}this._unitOpts=units}}return!b}}function _hasAbsUnits(s){var expr,unit,start,end,i,x;for(i=0;i<ABS_UNITS.length;i++){unit=ABS_UNITS[i];if(unit!==ALL&&s.includes(unit)){return unit}}expr=_isExpr(s);if(!expr){return false}for(i=0;i<ABS_UNITS.length;i++){unit=ABS_UNITS[i];if(unit===ALL){continue}x=s.indexOf(unit);if(x>=0){end=s[x+1];start=s[x-1].toLowerCase();if(start==="."||start==="+"||start.match(/[a-z]/i)){continue}return unit}}return false};function _isExpr(s){return s.includes("$")};module.exports=Rule;