@oracle/oraclejet-audit 18.1.4 → 19.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/corePackMigrator/corePackMigrator.js +1 -1
  2. package/corePackMigrator/metadata/badgeMetadata.json +66 -0
  3. package/corePackMigrator/metadata/checkboxsetMetadata.json +101 -0
  4. package/corePackMigrator/metadata/inputNumberMetadata.json +0 -3
  5. package/corePackMigrator/metadata/inputTextMetadata.json +0 -3
  6. package/corePackMigrator/metadata/labelMetadata.json +285 -222
  7. package/corePackMigrator/metadata/labelValueMetadata.json +226 -137
  8. package/corePackMigrator/metadata/listviewMetadata.json +7 -0
  9. package/corePackMigrator/metadata/radiosetMetadata.json +20 -9
  10. package/corePackMigrator/metadata/selectorMetadata.json +6 -0
  11. package/corePackMigrator/resource/astUtils.js +1 -1
  12. package/corePackMigrator/resource/componentMigrator.js +1 -1
  13. package/corePackMigrator/resource/fileScanner.js +1 -1
  14. package/corePackMigrator/resource/htmlUtils.js +1 -1
  15. package/corePackMigrator/resource/manifest.json +57 -49
  16. package/corePackMigrator/resource/migrationConfig.json +1 -1
  17. package/corePackMigrator/utilities/logging.js +2 -2
  18. package/jaf-amd.js +1 -1
  19. package/lib/Components.js +1 -1
  20. package/lib/Config.js +1 -1
  21. package/lib/FsUtils.js +1 -1
  22. package/lib/HtmlUtils.js +1 -1
  23. package/lib/JafLib.js +1 -1
  24. package/lib/MetaLib.js +1 -1
  25. package/lib/OjCPack.js +1 -1
  26. package/lib/RegTypes.js +1 -1
  27. package/lib/Registry.js +1 -1
  28. package/lib/Rules.js +1 -1
  29. package/lib/Ts.js +1 -1
  30. package/lib/TsUtils.js +1 -1
  31. package/lib/TsxUtils.js +1 -1
  32. package/lib/checkage.js +1 -1
  33. package/lib/defaults.js +1 -1
  34. package/lib/extends.js +1 -1
  35. package/lib/ns.js +1 -1
  36. package/lib/scaffold.js +1 -1
  37. package/lib/scopewalker.js +1 -1
  38. package/lib/sublib/precomp/Precompiler.js +1 -1
  39. package/libext/expparser.js +1 -1
  40. package/meta/18.0.0/jetauditmeta.js +1 -1
  41. package/meta/18.1.0/jetauditmeta.js +1 -1
  42. package/meta/19.0.0/jetauditmeta.js +9 -0
  43. package/meta/metaverlist.json +1 -1
  44. package/package.json +4 -4
  45. package/profiles/best-practice.json +3 -0
  46. package/profiles/redwood-strict.json +10 -1
  47. package/rulepacks/jetwc/jetwc-use-public-apis.js +6 -0
  48. package/rulepacks/jetwc/msgid.json +1 -1
  49. package/rulepacks/jetwc/rules.json +1 -1
  50. package/rulepacks/jetwc-lib/jetwcutils-componentAuditUtils.js +1 -1
  51. package/rulepacks/jetwc-lib/jetwcutils-componentFinder.js +1 -1
  52. package/rulepacks/jetwco/jetwco-cacc-properties.js +1 -1
  53. package/rulepacks/jetwco/rules.json +1 -1
  54. package/rules/jet/msgid.json +1 -1
  55. package/rules/jet/oj-acc-aria-accessible.js +1 -1
  56. package/rules/jet/oj-acc-aria-prop.js +1 -1
  57. package/rules/jet/oj-acc-navigable-link.js +6 -0
  58. package/rules/jet/oj-acc-select-aria-label.js +1 -1
  59. package/rules/jet/oj-cca-compjson-prop-conflict.js +6 -0
  60. package/rules/jet/oj-css-bp-zindex.js +7 -0
  61. package/rules/jet/oj-html-badge-maintenance.js +6 -0
  62. package/rules/jet/oj-html-binding-as-slot-child.js +1 -1
  63. package/rules/jet/oj-html-corequired.js +6 -0
  64. package/rules/jet/oj-html-nav-tab-nointeractive.js +6 -0
  65. package/rules/jet/oj-html-oj-ux-ico-slot.js +6 -0
  66. package/rules/jet/oj-html-ojtag-id.js +1 -1
  67. package/rules/jet/oj-html-redwood-ojoption-disabled.js +6 -0
  68. package/rules/jet/oj-html-slot-pref-content.js +1 -1
  69. package/rules/jet/oj-html-tabbar-progressive-popup.js +1 -1
  70. package/rules/jet/oj-html-wctag-for.js +1 -1
  71. package/rules/jet/oj-html-wctag-id.js +1 -1
  72. package/rules/jet/oj-html-wctag-maintenance.js +1 -1
  73. package/rules/jet/oj-html-wctag-packprivate.js +1 -1
  74. package/rules/jet/oj-js-poly-promise.js +1 -1
  75. package/rules/jet/oj-ts-poly-promise.js +1 -1
  76. package/rules/jet/oj-tsx-acc-navigable-link.js +6 -0
  77. package/rules/jet/oj-tsx-aria-prop.js +1 -1
  78. package/rules/jet/oj-tsx-corequired.js +6 -0
  79. package/rules/jet/oj-tsx-prop-ko-binding.js +6 -0
  80. package/rules/jet/oj-tsx-tabbar-progressive-popup.js +6 -0
  81. package/rules/jet/oj-tsx-wctag-packprivate.js +1 -1
  82. package/rules/jet/rules.json +1 -1
  83. package/schema/component-schema.json +1 -1
  84. package/src/JafCore.js +1 -1
  85. package/types/index.d.ts +5 -0
  86. package/corePackMigrator/metadata/messagesMetadata.json +0 -41
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
3
+ * Licensed under The Universal Permissive License (UPL), Version 1.0
4
+ * as shown at https://oss.oracle.com/licenses/upl/
5
+ */
6
+ const JsonParser=require("../../lib/AstJson");const nodePath=require("path");const RULENAME="oj-cca-compjson-prop-conflict";const DESCRIPTION="JET custom components should not define custom property names that conflict with HTML global "+"attributes. Overriding standard HTML APIs in a custom component implementation can cause "+"unexpected behavior and bugs that are hard to diagnose.<p>"+"As an alternative, JET custom VComponents have the ability to observe a subset of the available "+"global attributes of their HTML custom element. Refer to the ObservedGlobalProps helper type in "+"the JET VComponent documentation for further details.";const SHORT_DESCRIPTION="JET custom components should not define custom property names that conflict with HTML global attributes";const PROPLIST=["accesskey","accesskeylabel","autocapitalize","autocorrect","autofocus","class","className","contenteditable","dir","draggable","enterkeyhint","hidden","inert","inputmode","is","itemid","itemprop","itemref","itemscope","itemtype","lang","nonce","popover","role","slot","spellcheck","style","tabindex","title","translate","writingsuggestions","innerText","namespaceURI","prefix","localName","tagName","classList","attributes","shadowRoot","nodeType","nodeName","baseURI","isConnected","ownerDocument","parentNode","parentElement","childNodes","firstChild","lastChild","previousSibling","nextSibling","nodeValue","textContent"];const VCOMPLIST=["accesskey","autocapitalize","autofocus","contenteditable","dir","draggable","enterkeyhint","hidden","id","inputmode","lang","role","slot","spellcheck","tabindex","title","translate"];const EVENTLIST=["abort","auxclick","beforeinput","beforematch","beforetoggle","blur","cancel","canplay","canplaythrough","change","click","close","contextlost","contextmenu","contextrestored","copy","cuechange","cut","dblclick","drag","dragend","dragenter","dragleave","dragover","dragstart","drop","durationchange","emptied","ended","error","focus","formdata","input","invalid","keydown","keypress","keyup","load","loadeddata","loadedmetadata","loadstart","mousedown","mouseenter","mouseleave","mousemove","mouseout","mouseover","mouseup","paste","pause","play","playing","progress","ratechange","reset","resize","scroll","scrollend","securitypolicyviolation","seeked","seeking","select","slotchange","stalled","submit","suspend","timeupdate","toggle","volumechange","waiting","webkitanimationend","webkitanimationiteration","webkitanimationstart","webkittransitionend","wheel"];const PROPERTIES="properties";const EVENTS="events";const OJPREFIX="oj";COMPONENT_JSON="component.json";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(regCtx){this._utils=regCtx.utils.utils;this._fsUtils=regCtx.utils.fsUtils;this._propStack=[];this._jsonParser=new JsonParser(regCtx.utils.msgLib);this._debugMode=regCtx.sysOpts.debugMode;return{"startaudit":this._onPreAudit}}_onPreAudit(ruleCtx){var userCompJsons;if(userCompJsons=ruleCtx.utils.metaLib.getAllCustomMetadata()){let sumObj,VCType;for(let compName in userCompJsons){this._propStack.length=0;sumObj=userCompJsons[compName];if(this._debugMode){this._debugCompEntry(ruleCtx,sumObj)}VCType=sumObj.VCType;this._curFolder=sumObj.folder==null?"":sumObj.folder;this._checkProps(ruleCtx,compName,sumObj.json,VCType);this._checkEvents(ruleCtx,compName,sumObj.json,VCType)}}}_checkProps(ruleCtx,compName,json,VCType){var json,properties,lcPropName,o,msgType;if(properties=json.properties){for(let propName in properties){lcPropName=propName.toLowerCase();if(propName!==PROPERTIES&&PROPLIST.includes(lcPropName)){if(!VCType||!VCOMPLIST.includes(lcPropName)){msgType=1}else{msgType=2}this._emitIssue(ruleCtx,msgType,compName,propName,VCType)}}}}_checkEvents(ruleCtx,compName,json,VCType){var events;if(events=json.events){for(let eventName in events){if(!eventName.startsWith(OJPREFIX)){if(EVENTLIST.includes(eventName.toLowerCase())){this._emitIssue(ruleCtx,3,compName,eventName,VCType)}}}}}_emitIssue(ruleCtx,msgType,compName,propName,VCType){var propPath,issue,msg,ast,compPath;if(msgType===1||msgType===2){propPath=(this._propStack.length?this._propStack.join(".")+".":"")+propName}if(msgType===1){msg=`Component '${compName}' custom property '${propPath}' conflicts with a standard HTML name.`}else if(msgType===2){msg=`VComponent '${compName}' custom property '${propPath}' conflicts with a HTML global attribute.`}else if(msgType===3){msg=`Component '${compName}' custom event '${propName}' conflicts with a standard HTML event.`}issue=new ruleCtx.Issue(msg);if(VCType){compPath=nodePath.join(this._curFolder,compName)+".json"}else{compPath=nodePath.join(this._curFolder,COMPONENT_JSON)}ruleCtx.filepath=compPath.replace(/\\/g,"/");if(msgType>1){issue.setMsgKey(RULENAME+"_"+(msgType-1))}if(!ruleCtx.utils.jafLib.isAMD()){if(ast=this._createAST(ruleCtx.filepath)){if(ast.members){let members;if(members=this._findMembers(ast.members,msgType<3?"properties":"events")){if(members=members?.value?.members){let astProp=this._getAstProperty(members,propPath);if(astProp&&astProp.pos){if(astProp.pos){issue.setPosition(astProp.pos)}}}}}}}ruleCtx.reporter.addIssue(issue,ruleCtx)}_getAstProperty(members,propName){var members,member,subProps,subProp,subs,i,j;subProps=propName.split(".");for(i=0;i<subProps.length;i++){subProp=subProps[i];for(j=0;j<members.length;j++){member=members[j];if(member.name===subProp){if(subProps.length===1){return member}if(i<subProps.length){if(subs=this._hasSubproperties(member)){if(member=this._getAstProperty(subs,this._remainingSubProps(subProps))){return member}}}}}}}_remainingSubProps(subProps){var s="",i;for(i=1;i<subProps.length;i++){if(i>1){s+="."}s+=subProps[i]}return s}_hasSubproperties(member){var subs,sub;if(subs=member?.value?.members){let i;for(i=0;i<subs.length;i++){sub=subs[i];if(sub.name==="properties"){return sub?.value?.members}}}}_findMembers(list,propsOrEvents){var o;for(let i=0;i<list.length;i++){o=list[i];if(o.name===propsOrEvents){return o}}}_createAST(filePath){var data,ast;try{data=this._fsUtils.readFileSync(filePath);ast=this._jsonParser.parse(data)}catch(e){}return ast}_debugCompEntry(ruleCtx,sumObj){var fnDebug=ruleCtx.utils.msgLib.debug;var o={...sumObj};if(!this._title){fnDebug("Debugging User/VComponent metadata global HTML props check");this._title=true}if(sumObj){o.json=o.json?JSON.stringify(o.json,null,2).substring(0,80)+" ...":o.json;fnDebug(JSON.stringify(o,null,3))}else{fnDebug("\nEMPTY ENTRY!!!\n")}}}module.exports=Rule;
@@ -0,0 +1,7 @@
1
+ /*
2
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
3
+ * Licensed under The Universal Permissive License (UPL), Version 1.0
4
+ * as shown at https://oss.oracle.com/licenses/upl/
5
+ */
6
+ const RULENAME="oj-css-bp-zindex";const MSG="For best practices, CSS z-index property values should not be used.";const MSG_END="Use of JET standard secondary window components (popup, dialog or messages) is recommended for proper UI element stacking.";const MSG_REPLACE="JET secondary window components (popup, dialog or messages) for UI element stacking.";const DECLARATION="Declaration";const ZINDEX="z-index";class Rule{getName(){return RULENAME}getDescription(){return`${MSG} ${MSG_END}`}getShortDescription(){return MSG}register(regCtx){this._CssUtils=regCtx.utils.CssUtils;return{"css-rule":this._onRule,"style":this._onStyle}}_onRule(ruleCtx,rule){var block,decl,i;block=rule.block.children;for(i=0;i<block.length;i++){decl=block[i];if(decl.type===DECLARATION&&decl.property===ZINDEX&&!_isCssVar(decl)){let issue;issue=new ruleCtx.Issue(`CSS 'z-index' - best practice: replace with ${MSG_REPLACE}`);issue.setPosition(this._CssUtils.getPosition(ruleCtx,decl.loc));ruleCtx.reporter.addIssue(issue,ruleCtx)}}}_onStyle(ruleCtx,attr,value){var prop,issue,s,x,i;for(i=0;i<value.length;i++){s=value[i];x=s.indexOf(":");if(x>=0){prop=s.substring(0,x).trimEnd();if(prop===ZINDEX){issue=new ruleCtx.Issue(`'z-index' property in 'style' attribute. Best practice: replace " +
7
+ "with ${MSG_REPLACE}`);issue.setMsgKey(RULENAME+"_1");ruleCtx.reporter.addIssue(issue,ruleCtx)}}}}}function _isCssVar(decl){var c;c=decl.value.children;if(c){let v=c[0];return v.name==="var"}return false};module.exports=Rule;
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
3
+ * Licensed under The Universal Permissive License (UPL), Version 1.0
4
+ * as shown at https://oss.oracle.com/licenses/upl/
5
+ */
6
+ const RULENAME="oj-html-badge-maintenance";const DESCRIPTION="class 'oj-badge' is moved to maintenance status starting in JET 19.0, and is superseded by oj-c-badge.";const SHORT_DESCRIPTION="class 'oj-badge' is superseded by 'oj-c-badge";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(){return{"class":this._onClass}}_onClass(ruleCtx,attrib,classValue){var classes=classValue.split(" ");if(classes.includes("oj-badge")){let issue=new ruleCtx.Issue("class 'oj-badge' is in maintenance status (since 19.0) and is superseded by 'oj-c-badge'");ruleCtx.reporter.addIssue(issue,ruleCtx)}}}module.exports=Rule;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const RULENAME="oj-html-binding-as-slot-child";const DESCRIPTION="JET binding components such as <oj-bind-if> are not present in the final browser "+"DOM at runtime, and as such will not function correctly when directly assigned to "+"a slot. They should either be relaced with <oj-if> which can be assigned to a slot, "+"or they should be wrapped in another element such as a <div> or <span> which has "+"the slot attribute applied.<br>";const SHORT_DESCRIPTION="The slot attribute should not be applied directly to JET binding components";const SLOT="slot";const TEMPLATE="template";const OJ_BIND="oj-bind";const OJ_BIND_IF="oj-bind-if";const OJ_IF="oj-if";const OJ_OPTION="oj-option";const BODY="body";const EXCEPTION_TAGS=["oj-accordion","oj-buttonset-many","oj-buttonset-one","oj-checkboxset","oj-combobox-many","oj-combobox-one","oj-film-strip","oj-form-layout","oj-c-form-layout","oj-list-item-layout","oj-masonry-layout","oj-menu","oj-menu-select-many","oj-optgroup","oj-radioset","oj-select-many","oj-select-single","oj-toolbar","oj-validation-group","template"];class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(regCtx){this._metaLib=regCtx.utils.metaLib;return{bindingtag:this._onBind}}_onBind(ruleCtx,tag){var attribs,attrib,node,parent,name;node=ruleCtx.tagNode;if(attribs=node.attribs){for(attrib in attribs){if(attrib===SLOT){this._emitIssue(1,ruleCtx,tag);break}}}if(parent=this._getParentElem(node,ruleCtx)){name=parent.name;if(name===OJ_IF){return}if(name===OJ_OPTION){if(parent?.parent?.name===TEMPLATE){return}}if(EXCEPTION_TAGS.includes(name)){return}if(this._metaLib.isWCTag(name)&&this._metaLib.hasTagDefaultSlot(name)){this._emitIssue(2,ruleCtx,node.name,name)}}}_getParentElem(node,ruleCtx){var parent,name;if(node&&(parent=node.parent)){if(name=parent.name){if(name.startsWith(OJ_BIND)||name===TEMPLATE||ruleCtx.utils.DomUtils.isSelfClosingTag(name)){return this._getParentElem(parent,ruleCtx)}if(name===BODY){return null}}return parent}return null}_emitIssue(msgType,ruleCtx,tagName,parentName){var issue;if(msgType===1){let msg=`The slot attribute must not be applied directly on a <${tagName}> : `;msg+=tagName===OJ_BIND_IF?`either relace with <oj-if> which can be assigned to a slot, or wrap in a <div> or <span> and apply the slot attribute to that.`:`wrap it in a <div> or <span> and apply the slot attribute to that.`;issue=new ruleCtx.Issue(msg)}else if(msgType===2){issue=new ruleCtx.Issue(`If <${tagName}> is used as the direct DOM child of <${parentName}>, then <${parentName}> may not reflect updates to the bound value unless the <${tagName}> is enclosed in a DOM element such as <div> or <span>.`);issue.setMsgKey(RULENAME+"_1");issue.setSeverity("info")}ruleCtx.reporter.addIssue(issue,ruleCtx)}}module.exports=Rule;
6
+ const RULENAME="oj-html-binding-as-slot-child";const DESCRIPTION="JET binding components such as <oj-bind-if> are not present in the final browser "+"DOM at runtime, and as such will not function correctly when directly assigned to "+"a slot. They should either be relaced with <oj-if> which can be assigned to a slot, "+"or they should be wrapped in another element such as a <div> or <span> which has "+"the slot attribute applied.<br>";const SHORT_DESCRIPTION="The slot attribute should not be applied directly to JET binding components";const SLOT="slot";const TEMPLATE="template";const OJ_BIND="oj-bind";const OJ_BIND_IF="oj-bind-if";const OJ_IF="oj-if";const OJ_OPTION="oj-option";const BODY="body";const EXCEPTION_TAGS=["oj-accordion","oj-buttonset-many","oj-buttonset-one","oj-checkboxset","oj-combobox-many","oj-combobox-one","oj-film-strip","oj-form-layout","oj-c-form-layout","oj-list-item-layout","oj-masonry-layout","oj-menu","oj-menu-select-many","oj-optgroup","oj-radioset","oj-select-many","oj-select-single","oj-swipe-actions","oj-toolbar","oj-validation-group","template"];class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(regCtx){this._metaLib=regCtx.utils.metaLib;return{bindingtag:this._onBind}}_onBind(ruleCtx,tag){var attribs,attrib,node,parent,name;node=ruleCtx.tagNode;if(attribs=node.attribs){for(attrib in attribs){if(attrib===SLOT){this._emitIssue(1,ruleCtx,tag);break}}}if(parent=this._getParentElem(node,ruleCtx)){name=parent.name;if(name===OJ_IF){return}if(name===OJ_OPTION){if(parent?.parent?.name===TEMPLATE){return}}if(EXCEPTION_TAGS.includes(name)){return}if(this._metaLib.isWCTag(name)&&this._metaLib.hasTagDefaultSlot(name)){this._emitIssue(2,ruleCtx,node.name,name)}}}_getParentElem(node,ruleCtx){var parent,name;if(node&&(parent=node.parent)){if(name=parent.name){if(name.startsWith(OJ_BIND)||name===TEMPLATE||ruleCtx.utils.DomUtils.isSelfClosingTag(name)){return this._getParentElem(parent,ruleCtx)}if(name===BODY){return null}}return parent}return null}_emitIssue(msgType,ruleCtx,tagName,parentName){var issue;if(msgType===1){let msg=`The slot attribute must not be applied directly on a <${tagName}> : `;msg+=tagName===OJ_BIND_IF?`either relace with <oj-if> which can be assigned to a slot, or wrap in a <div> or <span> and apply the slot attribute to that.`:`wrap it in a <div> or <span> and apply the slot attribute to that.`;issue=new ruleCtx.Issue(msg)}else if(msgType===2){issue=new ruleCtx.Issue(`If <${tagName}> is used as the direct DOM child of <${parentName}>, then <${parentName}> may not reflect updates to the bound value unless the <${tagName}> is enclosed in a DOM element such as <div> or <span>.`);issue.setMsgKey(RULENAME+"_1");issue.setSeverity("info")}ruleCtx.reporter.addIssue(issue,ruleCtx)}}module.exports=Rule;
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
3
+ * Licensed under The Universal Permissive License (UPL), Version 1.0
4
+ * as shown at https://oss.oracle.com/licenses/upl/
5
+ */
6
+ const RULENAME="oj-html-corequired";const DESCRIPTION="Some components need to be configured such that at least one property or slot must be populated out "+"of a given set for the component to function correctly (the 'anyOf' requirement), or alternatively the "+"component should not be configured with properties and slots from a given set (the 'not' requirement). "+"This requirements are often used for accessibility.";const SHORT_DESCRIPTION="Check that a webcomponent element contains at least one property or slot out of a given set, or none of them.";const SLOT="slot";const COLON_SLOT=":slot";const LIST_SEPARATOR="', '";const QUOTE="'";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(regCtx){this._ignoreList=null;this._metaLib=regCtx.utils.metaLib;this._attribs=null;if(!this._getOverrides(regCtx)){return false}return{"requirements":this._onRequirements}}_onRequirements(ruleCtx,tagName,reqMeta){if(this._isIgnoreFile(ruleCtx.filepath)){return}reqMeta.forEach(req=>{this._checkRequirement(ruleCtx,req)})}_checkRequirement(ruleCtx,req){switch(req.type){case"anyOf":this._anyOf(ruleCtx,req);break;case"not":this._not(ruleCtx,req);break}}_anyOf(ruleCtx,req){var reqProps,reqSlots;if((reqProps=req.properties)&&reqProps.length){if(this._checkProperties_AnyOf(ruleCtx,reqProps)){return}}if((reqSlots=req.slots)&&reqSlots.length){if(this._checkSlots_AnyOf(ruleCtx,reqSlots)){return}}this._emitIssue_AnyOf(ruleCtx,req)}_not(ruleCtx,req){var reqProps,reqSlots;if((reqProps=req.properties)&&reqProps.length){if(!this._checkProperties_Not(ruleCtx,reqProps)){this._emitIssue_Not(ruleCtx,req);return}}if((reqSlots=req.slots)&&reqSlots.length){if(!this._checkSlots_Not(ruleCtx,reqSlots)){this._emitIssue_Not(ruleCtx,req)}}}_checkProperties_AnyOf(ruleCtx,reqProps){var attribs,reqProp,i;if(reqProps.length==0){return true}if(attribs=ruleCtx.tagNode.attribs){let domUtils=ruleCtx.utils.DomUtils;for(i=0;i<reqProps.length;i++){reqProp=reqProps[i];if(!reqProp.startsWith("aria-")&&!reqProp.startsWith("data-")){if(reqProp.includes(".")){let subs=reqProp.split(".");subs.forEach((sub,x)=>{subs[x]=domUtils.kebabCase(sub)});reqProp=subs.join(".")}else{reqProp=domUtils.kebabCase(reqProp)}}if(attribs[reqProp]||attribs[":"+reqProp]){return true}}}return false}_checkSlots_AnyOf(ruleCtx,reqSlots){let tagNode,slotName,attribs,reqSlot,i;tagNode=ruleCtx.tagNode;if(attribs=tagNode.attribs){if(attribs.hasOwnProperty(SLOT)){slotName=attribs[SLOT]}else if(attribs.hasOwnProperty(COLON_SLOT)){slotName=attribs[COLON_SLOT]}for(i=0;i<reqSlots.length;i++){reqSlot=reqSlots[i];if(slotName){if(slotName===reqSlot){return true}else if(reqSlot===""){if(_hasChildContent(tagNode)){return true}}}else if(reqSlot===""){if(_hasChildContent(tagNode)){return true}}}}return false}_emitIssue_AnyOf(ruleCtx,req){let issue,msg,haveProps;msg=`<${ruleCtx.tagNode.name}> does not satisfy the '${req.type}' requirement "${req.label}".`;if(req.properties){let reqLen=req.properties.length;msg+=" It has not been configured with ";msg+=reqLen>1?"at least one of the properties":"the property";msg+=" ";msg+=QUOTE+req.properties.join(LIST_SEPARATOR)+QUOTE;haveProps=true}if(req.slots){msg+=haveProps?", or with content in ":" It has not been configured with content in ";if(req.slots.length>1){msg+="at least one of the following slots ";msg+=QUOTE+req.slots.join(LIST_SEPARATOR)+QUOTE}else{if(req.slots[0]===""){msg+="the default slot"}else{msg+=`slot '${req.slots[0]}'`}}}msg+=".";msg=_addDescription(msg,req);issue=new ruleCtx.Issue(msg);ruleCtx.reporter.addIssue(issue,ruleCtx)}_checkProperties_Not(ruleCtx,reqProps){var attribs,reqProp,i;if(reqProps.length==0){return true}if(attribs=ruleCtx.tagNode.attribs){let domUtils=ruleCtx.utils.DomUtils;for(i=0;i<reqProps.length;i++){reqProp=reqProps[i];if(!reqProp.startsWith("aria-")&&!reqProp.startsWith("data-")){if(reqProp.includes(".")){let subs=reqProp.split(".");subs.forEach((sub,x)=>{subs[x]=domUtils.kebabCase(sub)});reqProp=subs.join(".")}else{reqProp=domUtils.kebabCase(reqProp)}}if(attribs[reqProp]||attribs[":"+reqProp]){return false}}}return true}_checkSlots_Not(ruleCtx,reqSlots){let tagNode,slotName,attribs,reqSlot,i;tagNode=ruleCtx.tagNode;if(attribs=tagNode.attribs){if(attribs.hasOwnProperty(SLOT)){slotName=attribs[SLOT]}else if(attribs.hasOwnProperty(COLON_SLOT)){slotName=attribs[COLON_SLOT]}for(i=0;i<reqSlots.length;i++){reqSlot=reqSlots[i];if(slotName){if(slotName===reqSlot){return false}else if(reqSlot===""){if(_hasChildContent(tagNode)){return false}}}else if(reqSlot===""){if(_hasChildContent(tagNode)){return false}}}}return true}_emitIssue_Not(ruleCtx,req){let issue,msg,haveProps;msg=`<${ruleCtx.tagNode.name}> does not satisfy the '${req.type}' requirement "${req.label}".`;if(req.properties){let reqLen=req.properties.length;msg+=" It has been configured with ";msg+=reqLen>1?"at least one of the properties":"the property";msg+=" ";msg+=QUOTE+req.properties.join(LIST_SEPARATOR)+QUOTE;haveProps=true}if(req.slots){msg+=haveProps?", or with content in ":" It has been configured with content in ";if(req.slots.length>1){msg+="at least one of the following slots ";msg+=QUOTE+req.slots.join(LIST_SEPARATOR)+QUOTE}else{if(req.slots[0]===""){msg+="the default slot"}else{msg+=`slot '${req.slots[0]}'`}}}msg+=".";msg=_addDescription(msg,req);issue=new ruleCtx.Issue(msg);ruleCtx.reporter.addIssue(issue,ruleCtx)}_isIgnoreFile(file){if(this._ignoreFiles){for(let i=0;i<this._ignoreFiles.length;i++){if(this._ignoreFiles[i].test(file)){return true}}}return false}_getOverrides(regCtx){var files;if(!(files=regCtx.ruleOpts?.customOpts?.files)){return true}if(!Array.isArray(files)){regCtx.utils.msgLib.error(`Rule ${RULE} : config option 'files' is not an array`);return false}let ignoreFiles=[];for(let i=0;i<files.length;i++){if(typeof files[i]==="string"){try{ignoreFiles[i]=new RegExp(files[i].trim())}catch(e){regCtx.utils.msgLib.error(`Config 'ruleMods' ${RULENAME} 'files' entry [${i}]: ${e.message}`);return false}}}if(ignoreFiles.length){this._ignoreFiles=ignoreFiles}return true}}function _hasChildContent(tagNode){var childs;if((childs=tagNode.children)&&childs.length){if(childs.length===1&&childs[0].type==="text"){let s=childs[0]?.data.trim();return!!s.length}return true}return false};function _addDescription(msg,req){if(req.description){msg+=` (Additional - ${req.description.trimEnd()}`;if(!msg.endsWith(".")){msg+="."}msg+=")"}return msg};module.exports=Rule;
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
3
+ * Licensed under The Universal Permissive License (UPL), Version 1.0
4
+ * as shown at https://oss.oracle.com/licenses/upl/
5
+ */
6
+ const RULENAME="oj-html-nav-tab-nointeractive";const HELP="The <template> 'itemTemplate' slot in <oj-tab-bar> and <oj-navigation-list> must not contain interactive tags. "+"That is, content other than <li>, &lt;a>, <div>, &lt;span>, <oj-badge>, text, <oj-bind-text>, <oj-bind-if>, "+"<oj-bind-for-each>, or <oj-if>.";const SHORT_DESCRIPTION="The <template> 'itemTemplate' slot in <oj-tab-bar> and <oj-navigation-list> must not contain interactive tags.";const TEMPLATE="template";const SLOT_ITEMTEMPLATE="itemTemplate";const SLOT="slot";const NODE_TAG="tag";const NODE_TEXT="text";const OK_TAGS=["li","a","div","span","oj-bind-text","oj-badge","oj-bind-if","oj-bind-for-each","oj-if","template"];class Rule{getName(){return RULENAME}getDescription(){return HELP}getShortDescription(){return SHORT_DESCRIPTION}register(){this._okList=new Set(OK_TAGS);this._mismatches=[];return{"<oj-tab-bar>":this._onWComp,"<oj-navigation-list>":this._onWComp}}_onWComp(ruleCtx){var template;if(template=this._getChildTemplate(ruleCtx.tagNode)){this._mismatches.length=0;this._checkNonAcceptableChildren(ruleCtx,template);if(this._mismatches.length){this._emitIssue(ruleCtx)}}}_getChildTemplate(node){var childs,i,child;if((childs=node.children)&&childs.length){for(i=0;i<childs.length;i++){child=childs[i];if(child.type===NODE_TAG){if(child.name===TEMPLATE&&_hasItemTemplateSlot(child)){return child}}}}return null}_checkNonAcceptableChildren(ruleCtx,node){var childs,child,i;if((childs=node.children)&&childs.length){for(i=0;i<childs.length;i++){child=childs[i];if(child.type===NODE_TAG){if(this._okList.has(child.name)){this._checkNonAcceptableChildren(ruleCtx,child);continue}}else if(child.type===NODE_TEXT){continue}if(!this._mismatches.includes(child.name)){this._mismatches.push(child.name)}}}}_emitIssue(ruleCtx){var msg,list,issue;list="('"+this._mismatches.join("', '")+"')";msg=`<${ruleCtx.tagNode.name}> contains interactive content in its <template slot="itemTemplate"> : ${list}`;issue=new ruleCtx.Issue(msg);ruleCtx.reporter.addIssue(issue,ruleCtx)}}function _hasItemTemplateSlot(template){var attribs,attrib;if(attribs=template.attribs){for(attrib in attribs){if(attrib===SLOT&&attribs[attrib]===SLOT_ITEMTEMPLATE){return true}}}return false};module.exports=Rule;
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
3
+ * Licensed under The Universal Permissive License (UPL), Version 1.0
4
+ * as shown at https://oss.oracle.com/licenses/upl/
5
+ */
6
+ const RULENAME="oj-html-oj-ux-ico-slot";const DESCRIPTION="Menus and other action components that can be configured with an icon starting with "+"'oj-ux-ico-', should always have the icon applied via a span tag in the assigned "+"slot. Applying the icon class anywhere else will result in the component not "+"functioning as expected.";const SHORT_DESCRIPTION="Declare icon styles for <oj-button> and <oj-option> in a 'startIcon' or 'endIcon' slot.";const OJ_UX_ICO="oj-ux-ico-";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(){return{"<oj-button>":this._onTag,"<oj-option>":this._onTag}}_onTag(ruleCtx){var rawClazz;this._node=null;if(rawClazz=this._hasIconClasses(ruleCtx.tagNode.children)){let a;if(a=this._extractOjUxIco(rawClazz)){for(let i=0;i<a.length;i++){this._emitIssue(ruleCtx,a[i])}}}}_emitIssue(ruleCtx,clazz){let issue=new ruleCtx.Issue(`<${this._node.name}> class '${clazz}' should be used in a 'startIcon' or 'endIcon' slot.`);issue.setPosition(null,null,this._node.startIndex);ruleCtx.reporter.addIssue(issue,ruleCtx)}_hasIconClasses(childs){if(!childs){return}let child;if(child=this._findChildTag(childs)){let clazz,clazzVal,attribs;if(attribs=child.attribs){if((clazz=attribs["slot"])&&(clazz==="startIcon"||clazz==="endIcon")){return}if(clazzVal=this._hasClass(child)){return clazzVal}else if(child.children){return this._hasIconClasses(child.children)}}}}_findChildTag(childs){if(!childs){return}let child,i;for(i=0;i<childs.length;i++){child=childs[i];if(child.type==="tag"){if(child.name==="span"||child.name==="div"){return child}else if(child.name.startsWith("oj-bind-")||child.name.startsWith("template")){return this._findChildTag(child.children)}}}}_hasClass(node){var attribs,ret;if(attribs=node.attribs){let clazz;if(clazz=attribs[":class"]||attribs["class"]){ret=clazz;this._node=node}}return ret}_extractOjUxIco(rawClazz){var x,i,a;for(i=0;i<rawClazz.length;){if((x=rawClazz.indexOf(OJ_UX_ICO,i))>=0){if(!a){a=[]}a.push(x);i=x+OJ_UX_ICO.length}else{break}}if(a){let b;for(i=0;i<a.length;i++){let s=rawClazz.substring(a[i]);let ret="";let c;b=false;for(let j=OJ_UX_ICO.length;j<s.length;j++){c=s.charAt(j);if(c.toLowerCase()!==c.toUpperCase()||c==="-"||/\d/.test(c)){b=true;ret+=c}else{break}}if(b){a[i]=OJ_UX_ICO+ret}}}return a}}module.exports=Rule;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const RULE_NAME="oj-html-ojtag-id";const SHORT_DESCRIPT="JET custom components should not used hard-coded 'id' attributes";const LONG_DESCRIPT="Hard-coded element IDs should not be used within custom components. Element IDs must be unique for each instance of the component. See context.uniqueId in the custom element documentation for information on how to derive unique IDs for elements."+"<p>If a CCA implements hard-coded IDs for HTML elements in the CCA view, e.g.<p>"+"<oj-input id=\"foo\"><p>"+"then this is guaranteed to cause issues as soon as more than one instance of "+"the component is used on the page (plus there is a significant risk of "+"collision with other IDs in the page as a whole.";function getName(){return RULE_NAME};function getShortDescription(){return SHORT_DESCRIPT};function getDescription(){return LONG_DESCRIPT};function register(){var issue,attrPos;return{"ojtag":function(ruleCtx,tagName){if(ruleCtx.utils.metaLib.isBindingTag(tagName)){return}if(ruleCtx.node.attribs&&ruleCtx.node.attribs.id){var id=ruleCtx.node.attribs.id;if(id.toLowerCase().indexOf("$unique")<0){if(!ruleCtx.ojTag){issue=new ruleCtx.Issue("<"+ruleCtx.tag+"> uses id attribute '"+id+"'. Use $UniqueId.");attrPos=ruleCtx.utils.DomUtils.getAttribPosition(ruleCtx.data,ruleCtx.node,"id");issue.setPosition(attrPos.row,attrPos.col,attrPos.start,attrPos.end);ruleCtx.reporter.addIssue(issue,ruleCtx)}}}}}};module.exports={getName,getDescription,getShortDescription,register};
6
+ const RULE_NAME="oj-html-ojtag-id";const SHORT_DESCRIPT="JET custom components should not used hard-coded 'id' attributes";const LONG_DESCRIPT="Hard-coded element IDs should not be used within custom components. Element IDs "+"must be unique for each instance of the component. See context.uniqueId in the "+"custom element documentation for information on how to derive unique IDs for elements."+"<p>If a component implements hard-coded IDs for HTML elements in the CCA view, e.g.<p>"+"<oj-input id=\"foo\"><p>, "+"then this is guaranteed to cause issues as soon as more than one instance of "+"the component is used on the page (plus there is a significant risk of "+"collision with other IDs in the page as a whole).";function getName(){return RULE_NAME};function getShortDescription(){return SHORT_DESCRIPT};function getDescription(){return LONG_DESCRIPT};function register(){var issue,attrPos;return{"ojtag":function(ruleCtx,tagName){if(ruleCtx.utils.metaLib.isBindingTag(tagName)){return}if(ruleCtx.node.attribs&&ruleCtx.node.attribs.id){var id=ruleCtx.node.attribs.id;if(id.toLowerCase().indexOf("$unique")<0){if(!ruleCtx.ojTag){issue=new ruleCtx.Issue(`<${ruleCtx.tag}> uses id attribute "${id}". Use $UniqueId.`);attrPos=ruleCtx.utils.DomUtils.getAttribPosition(ruleCtx.data,ruleCtx.node,"id");issue.setPosition(attrPos.row,attrPos.col,attrPos.start,attrPos.end);ruleCtx.reporter.addIssue(issue,ruleCtx)}}}}}};module.exports={getName,getDescription,getShortDescription,register};
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
3
+ * Licensed under The Universal Permissive License (UPL), Version 1.0
4
+ * as shown at https://oss.oracle.com/licenses/upl/
5
+ */
6
+ const RULENAME="oj-html-redwood-ojoption-disabled";const DESCRIPTION="By extending the profile 'redwood-strict', Redwood compliance is required by the Audit. Redwood "+"compliant designs do not allow individual child <oj-option> components of <oj-radioset> and <oj-checkboxset> "+"to be disabled, and should be removed. If an option is not available for interaction by the user, it "+"should not be included in the set of options.";const SHORT_DESCRIPTION=DESCRIPTION;class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(){return{"<oj-checkboxset>":this._onComp,"<oj-radioset>":this._onComp}}_onComp(ruleCtx){var childs;if(childs=ruleCtx.tagNode.children){this._searchChildOptions(ruleCtx,childs)}}_searchChildOptions(ruleCtx,childs){var child,attribs,i;for(i=0;i<childs.length;i++){child=childs[i];if(child.type==="tag"&&child.name==="oj-option"){if((attribs=child.attribs)&&attribs.disabled){this._emitIssue(ruleCtx,child,attribs.disabled)}}else if(child.children&&child.children.length){this._searchChildOptions(ruleCtx,child.children)}}}_emitIssue(ruleCtx,child,attrib){var issue,pos;issue=new ruleCtx.Issue(`<oj-option> in <${ruleCtx.tagNode.name}> is disabled. Redwood compliant designs do not allow individual options to be disabled, and should be removed.`);pos=ruleCtx.utils.DomUtils.getAttribPosition(ruleCtx.data,child,"disabled");issue.setPosition(pos);ruleCtx.reporter.addIssue(issue,ruleCtx)}}module.exports=Rule;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const getParentNodeForSlot=require("./helpers/has-slot-name");const RULE_NAME="oj-html-slot-pref-content";const DESCRIPT="When component metadata defines 'preferredContent' for a slot, child elements placed into that slot should "+"implement one or more of the requested interfaces and document that through their 'implements' metadata. "+"This rule applies to components that are directly allocated to a slot, or which are direct children "+"of a template allocated to that slot.";const SHORT=DESCRIPT;const IGNORE_TAG=["oj-defer","html","head","body","script"];const FLATTENABLE_TAGS=["div","oj-bind-if","oj-bind-for-each","oj-defer","template","oj-refresher","oj-validation-group","span","p"];const TEMPLATE="template";const OJ_SWITCHER="oj-switcher";const OJ_IF="oj-if";const OJ_DEFER="oj-defer";const OJ_BIND="oj-bind";const OJ_TOOLBAR="oj-toolbar";const OJ_BIND_SLOT="oj-bind-slot";const OJ_MODULE="oj-module";const OJ_VB_FRAGMENT="oj-vb-fragment";const DIV="div";const SPAN="span";const TAG="tag";const SLOT="slot";const _isBindTag=tagName=>{return tagName.startsWith("oj-bind")};const _ignoreTag=tagName=>{return IGNORE_TAG.includes(tagName)||tagName.startsWith("oj-bind")};const _isExempt=tagName=>{return tagName===OJ_VB_FRAGMENT||tagName===OJ_MODULE};function Rule(){};Rule.prototype.getName=function(){return RULE_NAME};Rule.prototype.getShortDescription=function(){return SHORT};Rule.prototype.getDescription=function(){return DESCRIPT};Rule.prototype.register=function(regCtx){this._metaLib=regCtx.utils.metaLib;this._hasJetWCInterfaces=this._metaLib.hasJetWCInterfaces();this._utils=regCtx.utils.utils;this._domUtils=regCtx.utils.DomUtils;return{"webcomp":this._onTag,"elem":this._onElem}};Rule.prototype._onElem=function(ruleCtx,elemName){if(ruleCtx.utils.DomUtils.isCommonElem(elemName)||elemName===TEMPLATE){if(!_ignoreTag(elemName)){return this._onTag(ruleCtx,elemName)}}};Rule.prototype._onTag=function(ruleCtx,tagName){var attribs=ruleCtx.tagNode.attribs;var slotx,slotName="";this._slotDefined=false;if(slotx=this._hasSlot(ruleCtx.tagNode)){slotName=slotx;this._slotDefined=true}this._onSlot(ruleCtx,slotName)};Rule.prototype._onSlot=function(ruleCtx,slotName){var pnode,slotTag,psc;if(slotName&&ruleCtx.tagNode.name===OJ_BIND_SLOT){return}if(!(pnode=getParentNodeForSlot(ruleCtx,slotName))){return}if(!this._metaLib.isWCTag(pnode.name)){return}if(this._metaLib.isJetTag(pnode.name)&&!this._hasJetWCInterfaces){return}psc=this._metaLib.getPreferredSlotContentEx(pnode.name,slotName);if(!(psc&&psc.interfaces)){return}slotTag=ruleCtx.tag;if(_isExempt(slotTag)){return}if(slotTag===DIV||slotTag===OJ_IF||slotTag===OJ_SWITCHER||slotTag.startsWith(OJ_BIND)||slotTag===OJ_DEFER||slotTag===TEMPLATE){let childs;if(childs=this._flattenDivChildren(psc,pnode,ruleCtx.tagNode,slotName)){let child;for(let i=0;i<childs.length;i++){child=childs[i];if(!_isExempt(child.name)){if(this._hasSlot(child)){continue}if(!this._isSlotInterfaceSupported(child,psc)){this._emitIssue(ruleCtx,child,slotName,pnode.name,psc,4)}}};return}else{this._emitIssue(ruleCtx,ruleCtx.tagNode,slotName,pnode.name,psc,2)}if(slotTag===OJ_SWITCHER||slotTag===OJ_IF){return}}if(ruleCtx.utils.DomUtils.isCommonElem(slotTag)){if(pnode.name!==OJ_TOOLBAR&&ruleCtx.tagNode.name!==SPAN){this._emitIssue(ruleCtx,ruleCtx.tagNode,slotName,pnode.name,psc,3)}return}if(this._metaLib.isWCTag(slotTag)){if(!_isBindTag(slotTag)&&slotTag!==OJ_DEFER&&slotTag!==TEMPLATE){if(!this._isSlotInterfaceSupported(ruleCtx.tagNode,psc)){this._emitIssue(ruleCtx,ruleCtx.tagNode,slotName,pnode.name,psc,1)}}}};Rule.prototype._flattenDivChildren=function(psc,pnode,tagNode,slotName,children){var nodes=tagNode.children;var node,tagName,i;for(i=0;i<nodes.length;i++){node=nodes[i];if(node.type!=="tag"){continue}tagName=node.name;if(FLATTENABLE_TAGS.includes(tagName)){if(!node.attributes?.slot){children=this._flattenDivChildren(psc,pnode,node,slotName,children)}continue}if(!children){children=[]}children.push(node)}return children};Rule.prototype._isSlotInterfaceSupported=function(node,psc){var ret=false,aIfc;if(node){if(aIfc=this._metaLib.getInterfaces(node.name)){for(let ifc of aIfc){if(psc.interfaces.includes(ifc)){ret=true;break}}}}return ret};Rule.prototype._emitIssue=function(ruleCtx,elemNode,slotName,slotOwner,psci,issueType){var ifc=_list(psci.interfaces,"or");var comp=psci.components?` (e.g. ${_list(psci.components,"or",true)})`:"";var multi=psci.interfaces.length>1;var actualSlot=slotName;var slotName=slotName?`slot '${slotName}'`:"default slot";var isDefSlot=!slotName;var issue,msg;if(issueType===1||issueType===4){msg=`<${elemNode.name}> is in${isDefSlot?" the":""} ${slotName} of <${slotOwner}> but does not implement interface${multi?"s":""} ${ifc}${comp}`}else if(issueType===2){msg=`<${elemNode.name}> is in${isDefSlot?" the":""} ${slotName} of <${slotOwner}> but its first child does not implement interface${multi?"s":""} ${ifc}${comp}`}else if(issueType===3){msg=`${slotName} on <${elemNode.name}> for <${slotOwner}> cannot provide ${multi?"interfaces":"an interface"} of type ${ifc}${comp}`}else{return}issue=new ruleCtx.Issue(msg);if(issueType===4){let pos=ruleCtx.utils.DomUtils.getLineCol(ruleCtx.data,elemNode.startIndex);issue.setPosition(pos.row,pos.col,elemNode.startIndex,elemNode.endIndex)}else if(this._slotDefined){let attrPos=ruleCtx.utils.DomUtils.getAttribValuePosition(ruleCtx.data,ruleCtx.tagNode,SLOT);ruleCtx.utils.DomUtils.getAttribPosition(ruleCtx.data,ruleCtx.tagNode,SLOT);issue.setPosition(attrPos.row,attrPos.col,attrPos.start,attrPos.end)}issue.setMsgEx({slotName:actualSlot,slotElem:elemNode.name,slotOwner:slotOwner});ruleCtx.reporter.addIssue(issue,ruleCtx)};Rule.prototype._hasSlot=function(tagNode){var slotName,attribs,slotx;if(attribs=tagNode.attribs){if(this._utils.hasAnyProps(attribs)){slotx=attribs[SLOT];if(slotx||slotx===""){slotName=slotx}}}return slotName};function _getFirstChildTag(childs){var ret,childs,child;if(childs){for(let i=0;i<childs.length;i++){child=childs[i];if(child.type!==TAG){continue}if(child.name.startsWith("oj-bind-")||child.name===OJ_DEFER||child.name===TEMPLATE){return _getFirstChildTag(child.children)}ret=child;break}}return ret};function _list(a,orand,isComp){var s="";for(let i=0;i<a.length;i++){if(i){if(i===a.length-1){s+=(isComp?">":"'")+" "+orand+" "}else{s+=(isComp?">":"'")+", "}}s+=(isComp?"<":"'")+a[i]}return s?s+=isComp?">":"'":s};module.exports=Rule;
6
+ const getParentNodeForSlot=require("./helpers/has-slot-name");const RULE_NAME="oj-html-slot-pref-content";const DESCRIPT="When component metadata defines 'preferredContent' for a slot, child elements placed into that slot should "+"implement one or more of the requested interfaces and document that through their 'implements' metadata. "+"This rule applies to components that are directly allocated to a slot, or which are direct children "+"of a template allocated to that slot.";const SHORT=DESCRIPT;const IGNORE_TAG=["oj-defer","html","head","body","script"];const FLATTENABLE_TAGS=["div","oj-bind-if","oj-bind-for-each","oj-defer","template","oj-refresher","oj-validation-group","span","p"];const TEMPLATE="template";const OJ_SWITCHER="oj-switcher";const OJ_IF="oj-if";const OJ_DEFER="oj-defer";const OJ_BIND="oj-bind";const OJ_TOOLBAR="oj-toolbar";const OJ_BIND_SLOT="oj-bind-slot";const OJ_MODULE="oj-module";const OJ_VB_FRAGMENT="oj-vb-fragment";const DIV="div";const SPAN="span";const TAG="tag";const SLOT="slot";const _isBindTag=tagName=>{return tagName.startsWith("oj-bind")};const _ignoreTag=tagName=>{return IGNORE_TAG.includes(tagName)||tagName.startsWith("oj-bind")};const _isExempt=tagName=>{return tagName===OJ_VB_FRAGMENT||tagName===OJ_MODULE};function Rule(){};Rule.prototype.getName=function(){return RULE_NAME};Rule.prototype.getShortDescription=function(){return SHORT};Rule.prototype.getDescription=function(){return DESCRIPT};Rule.prototype.register=function(regCtx){this._metaLib=regCtx.utils.metaLib;this._hasJetWCInterfaces=this._metaLib.hasJetWCInterfaces();this._utils=regCtx.utils.utils;return{"webcomp":this._onTag,"elem":this._onElem}};Rule.prototype._onElem=function(ruleCtx,elemName){if(ruleCtx.utils.DomUtils.isCommonElem(elemName)||elemName===TEMPLATE){if(!_ignoreTag(elemName)){return this._onTag(ruleCtx,elemName)}}};Rule.prototype._onTag=function(ruleCtx,tagName){var attribs=ruleCtx.tagNode.attribs;var slotx,slotName="";this._slotDefined=false;if(slotx=this._hasSlot(ruleCtx.tagNode)){slotName=slotx;this._slotDefined=true}this._onSlot(ruleCtx,slotName)};Rule.prototype._onSlot=function(ruleCtx,slotName){var pnode,slotTag,psc;if(slotName&&ruleCtx.tagNode.name===OJ_BIND_SLOT){return}if(!(pnode=getParentNodeForSlot(ruleCtx,slotName))){return}if(!this._metaLib.isWCTag(pnode.name)){return}if(this._metaLib.isJetTag(pnode.name)&&!this._hasJetWCInterfaces){return}psc=this._metaLib.getPreferredSlotContentEx(pnode.name,slotName);if(!(psc&&psc.interfaces)){return}slotTag=ruleCtx.tag;if(_isExempt(slotTag)){return}if(slotTag===DIV||slotTag===OJ_IF||slotTag===OJ_SWITCHER||slotTag.startsWith(OJ_BIND)||slotTag===OJ_DEFER||slotTag===TEMPLATE){let childs;if(childs=this._flattenDivChildren(psc,pnode,ruleCtx.tagNode,slotName)){let child;for(let i=0;i<childs.length;i++){child=childs[i];if(!_isExempt(child.name)){if(this._hasSlot(child)){continue}if(!this._isSlotInterfaceSupported(child,psc)){this._emitIssue(ruleCtx,child,slotName,pnode.name,psc,4)}}};return}else{this._emitIssue(ruleCtx,ruleCtx.tagNode,slotName,pnode.name,psc,2)}if(slotTag===OJ_SWITCHER||slotTag===OJ_IF){return}}if(ruleCtx.utils.DomUtils.isCommonElem(slotTag)){if(pnode.name!==OJ_TOOLBAR&&ruleCtx.tagNode.name!==SPAN){this._emitIssue(ruleCtx,ruleCtx.tagNode,slotName,pnode.name,psc,3)}return}if(this._metaLib.isWCTag(slotTag)){if(!_isBindTag(slotTag)&&slotTag!==OJ_DEFER&&slotTag!==TEMPLATE){if(!this._isSlotInterfaceSupported(ruleCtx.tagNode,psc)){this._emitIssue(ruleCtx,ruleCtx.tagNode,slotName,pnode.name,psc,1)}}}};Rule.prototype._flattenDivChildren=function(psc,pnode,tagNode,slotName,children){var nodes=tagNode.children;var node,tagName,i;for(i=0;i<nodes.length;i++){node=nodes[i];if(node.type!=="tag"){continue}tagName=node.name;if(FLATTENABLE_TAGS.includes(tagName)){if(!node.attributes?.slot){children=this._flattenDivChildren(psc,pnode,node,slotName,children)}continue}if(!children){children=[]}children.push(node)}return children};Rule.prototype._isSlotInterfaceSupported=function(node,psc){var ret=false,aIfc;if(node){if(aIfc=this._metaLib.getInterfaces(node.name)){for(let ifc of aIfc){if(psc.interfaces.includes(ifc)){ret=true;break}}}}return ret};Rule.prototype._emitIssue=function(ruleCtx,elemNode,slotName,slotOwner,psci,issueType){var ifc=_list(psci.interfaces,"or");var comp=psci.components?` (e.g. ${_list(psci.components,"or",true)})`:"";var multi=psci.interfaces.length>1;var actualSlot=slotName;var slotName=slotName?`slot '${slotName}'`:"default slot";var isDefSlot=!slotName;var issue,msg;if(issueType===1||issueType===4){msg=`<${elemNode.name}> is in${isDefSlot?" the":""} ${slotName} of <${slotOwner}> but does not implement interface${multi?"s":""} ${ifc}${comp}`}else if(issueType===2){msg=`<${elemNode.name}> is in${isDefSlot?" the":""} ${slotName} of <${slotOwner}> but its first child does not implement interface${multi?"s":""} ${ifc}${comp}`}else if(issueType===3){msg=`${slotName} on <${elemNode.name}> for <${slotOwner}> cannot provide ${multi?"interfaces":"an interface"} of type ${ifc}${comp}`}else{return}issue=new ruleCtx.Issue(msg);if(issueType===4){let pos=ruleCtx.utils.DomUtils.getLineCol(ruleCtx.data,elemNode.startIndex);issue.setPosition(pos.row,pos.col,elemNode.startIndex,elemNode.endIndex)}else if(this._slotDefined){let attrPos=ruleCtx.utils.DomUtils.getAttribValuePosition(ruleCtx.data,ruleCtx.tagNode,SLOT);ruleCtx.utils.DomUtils.getAttribPosition(ruleCtx.data,ruleCtx.tagNode,SLOT);issue.setPosition(attrPos.row,attrPos.col,attrPos.start,attrPos.end)}issue.setMsgEx({slotName:actualSlot,slotElem:elemNode.name,slotOwner:slotOwner});ruleCtx.reporter.addIssue(issue,ruleCtx)};Rule.prototype._hasSlot=function(tagNode){var slotName,attribs,slotx;if(attribs=tagNode.attribs){if(this._utils.hasAnyProps(attribs)){slotx=attribs[SLOT];if(slotx||slotx===""){slotName=slotx}}}return slotName};function _getFirstChildTag(childs){var ret,childs,child;if(childs){for(let i=0;i<childs.length;i++){child=childs[i];if(child.type!==TAG){continue}if(child.name.startsWith("oj-bind-")||child.name===OJ_DEFER||child.name===TEMPLATE){return _getFirstChildTag(child.children)}ret=child;break}}return ret};function _list(a,orand,isComp){var s="";for(let i=0;i<a.length;i++){if(i){if(i===a.length-1){s+=(isComp?">":"'")+" "+orand+" "}else{s+=(isComp?">":"'")+", "}}s+=(isComp?"<":"'")+a[i]}return s?s+=isComp?">":"'":s};module.exports=Rule;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const RULENAME="oj-html-tabbar-progressive-popup";const DESCRIPTION="For JET 18.0.0 and later, <oj-tab-bar> truncation=\"progressive\" should always be used with "+"overflow=\"popup\" for handling overflow properly. If truncation=\"progressive\" is used alone, "+"for long labels it is possible that all items may not fit within oj-tab-bar despite being truncated.";const SHORT_DESCRIPTION="For <oj-tab-bar>, truncation=\"progressive\" requires that overflow=\"popup\" to avoid pssible truncation.";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(){return{"<oj-tab-bar truncation=>":this._onTabBar}}_onTabBar(ruleCtx,attrName,attrValue){if(attrValue==="progressive"){if(!this._hasAttribValue(ruleCtx,"overflow","popup")){let issue=new ruleCtx.Issue("<oj-tab-bar> 'overflow' attribute must be set to \"popup\" if truncation=\"progressive\"");ruleCtx.reporter.addIssue(issue,ruleCtx)}}}_hasAttribValue(ruleCtx,attrName,attrValue){var attribs,ret=false;if(attribs=ruleCtx.tagNode.attribs){let val;if((val=attribs[attrName])&&val===attrValue){ret=true}}return ret}}module.exports=Rule;
6
+ const RULENAME="oj-html-tabbar-progressive-popup";const DESCRIPTION="For JET 18.0.0 and later, <oj-tab-bar> truncation=\"progressive\" should always be used with "+"overflow=\"popup\" for handling overflow properly. If truncation=\"progressive\" is used alone, "+"for long labels it is possible that all items may not fit within oj-tab-bar despite being truncated.";const SHORT_DESCRIPTION="For <oj-tab-bar>, truncation=\"progressive\" requires overflow=\"popup\" to avoid pssible truncation.";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(){return{"<oj-tab-bar truncation=>":this._onTabBar}}_onTabBar(ruleCtx,attrName,attrValue){if(attrValue==="progressive"){if(!this._hasAttribValue(ruleCtx,"overflow","popup")){let issue=new ruleCtx.Issue("<oj-tab-bar> 'overflow' attribute must be set to \"popup\" if truncation=\"progressive\"");ruleCtx.reporter.addIssue(issue,ruleCtx)}}}_hasAttribValue(ruleCtx,attrName,attrValue){var attribs,ret=false;if(attribs=ruleCtx.tagNode.attribs){let val;if((val=attribs[attrName])&&val===attrValue){ret=true}}return ret}}module.exports=Rule;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const RULE_NAME="oj-html-wctag-for";const SHORT_DESCRIPT="Custom components should not used a hard-coded 'for' attribute and it should be set an expression";const LONG_DESCRIPT="Hard-coded 'for' attributes should not be used within custom components. 'for' attributes must be unique for each instance of the component and set to an expression. See context.uniqueId in the custom element documentation for information on how to derive unique values for elements."+"<p>If a webcomponent implements hard-coded 'for's for HTML elements in the web component view, e.g.<p>"+"<oj-input for=\"foo\"><p>"+"then this is guaranteed to cause issues as soon as more than one instance of "+"the component is used on the page (plus there is a significant risk of "+"collision with other attributes in the page as a whole.";const FOR="for";const COLON_FOR=":for";function getName(){return RULE_NAME};function getShortDescription(){return SHORT_DESCRIPT};function getDescription(){return LONG_DESCRIPT};function register(){return{"webcomp":_handle}}function _handle(context,tagName){var attribs,attr,isFor,isColonFor,isExpr,isOjLabel,msg,issue,attrPos;if(!context.ojTag||!context.filepath.includes("jet-composites")||!context.tagNode.attribs){return}if(context.utils.metaLib.isBindingTag(tagName)){return}isOjLabel=tagName==="oj-label";attribs=context.tagNode.attribs;isFor=attribs.hasOwnProperty(FOR);isColonFor=attribs.hasOwnProperty(COLON_FOR);if(!isFor&&!isColonFor){return}attr=isFor?FOR:COLON_FOR;isExpr=_isAttrExpr(attribs[attr]);if(isFor){if(isOjLabel){if(!isExpr){msg="<"+context.tag+"> 'for' should be set to an expression"}}else{msg="<"+context.tag+"> 'for' should be prefixed as ':for'"+(!isExpr?" and set to an expression":"")}}else{if(isOjLabel){msg="<"+context.tag+"> ':for' should be unprefixed"+(!isExpr?", and set to an expression":"")}else{msg="<"+context.tag+"> ':for' should be set to an expression"}}if(msg){issue=new context.Issue(msg);attrPos=context.utils.DomUtils.getAttribPosition(context.data,context.node,attr);issue.setPosition(attrPos.row,attrPos.col,attrPos.start,attrPos.end);context.reporter.addIssue(issue,context)}};function _isAttrExpr(attrValue){var rc=false;if(typeof attrValue==="string"){attrValue=attrValue.trim();rc=attrValue.startsWith("[[")||attrValue.startsWith("{{")}return rc};module.exports={getName,getDescription,getShortDescription,register};
6
+ const RULE_NAME="oj-html-wctag-for";const LONG_DESCRIPT="Hard-coded 'for' attributes should not be used within custom components. 'for' attributes must be "+"unique for each instance of the component and set to an expression. See context.uniqueId in the "+"custom element documentation for information on how to derive unique values for elements."+"<p>If a webcomponent implements hard-coded 'for's for HTML elements in the web component view, e.g.<p>"+"<oj-input for=\"foo\"><p>"+"then this is guaranteed to cause issues as soon as more than one instance of the component is used "+"on the page (plus there is a significant risk of collision with other attributes in the page as a whole.";const SHORT_DESCRIPT="Custom components should not used a hard-coded 'for' attribute and it should be set an expression";const FOR="for";const COLON_FOR=":for";function getName(){return RULE_NAME};function getShortDescription(){return SHORT_DESCRIPT};function getDescription(){return LONG_DESCRIPT};function register(){return{"webcomp":_handle}}function _handle(ruleCtx,tagName){if(!ruleCtx.ojTag||!ruleCtx.filepath.includes("jet-composites")||!ruleCtx.tagNode.attribs){return}if(ruleCtx.utils.metaLib.isBindingTag(tagName)){return}let md;if(md=ruleCtx.utils.metaLib.getTagMetadata(tagName)){if(md.hasOwnProperty("type")&&md.type!=="composite"){return}}let isOjLabel,attribs,isFor,isColonFor;isOjLabel=tagName==="oj-label";attribs=ruleCtx.tagNode.attribs;isFor=attribs.hasOwnProperty(FOR);isColonFor=attribs.hasOwnProperty(COLON_FOR);if(!isFor&&!isColonFor){return}let attr=isFor?FOR:COLON_FOR;let isExpr=_isAttrExpr(attribs[attr]);let msg;if(isFor){if(isOjLabel){if(!isExpr){msg=`<${ruleCtx.tag}> 'for' should be set to an expression`}}else{msg=`<${ruleCtx.tag}> 'for' should be prefixed as ':for'"${!isExpr?" and set to an expression":""}`}}else{msg=isOjLabel?`<${ruleCtx.tag}> ':for' should be unprefixed${!isExpr?", and set to an expression":""}`:`<${ruleCtx.tag}> ':for' should be set to an expression`}if(msg){let issue=new ruleCtx.Issue(msg);let attrPos=ruleCtx.utils.DomUtils.getAttribPosition(ruleCtx.data,ruleCtx.node,attr);issue.setPosition(attrPos.row,attrPos.col,attrPos.start,attrPos.end);ruleCtx.reporter.addIssue(issue,ruleCtx)}};function _isAttrExpr(attrValue){var rc=false;if(typeof attrValue==="string"){attrValue=attrValue.trim();rc=attrValue.startsWith("[[")||attrValue.startsWith("{{")}return rc};module.exports={getName,getDescription,getShortDescription,register};
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const RULE_NAME="oj-html-wctag-id";const SHORT_DESCRIPT="Custom components should not used a hard-coded 'id' attribute and should be set to an expression";const LONG_DESCRIPT="Hard-coded element IDs should not be used within custom components and should be set to an expression. Element IDs must be unique for each instance of the component. See context.uniqueId in the custom element documentation for information on how to derive unique IDs for elements."+"<p>If a CCA implements hard-coded IDs for HTML elements in the CCA view, e.g.<p>"+"<oj-input id=\"foo\"><p>"+"then this is guaranteed to cause issues as soon as more than one instance of "+"the component is used on the page (plus there is a significant risk of "+"collision with other IDs in the page as a whole.";const ID="id";const COLON_ID=":id";class Rule{getName(){return RULE_NAME}getDescription(){return LONG_DESCRIPT}getShortDescription(){return SHORT_DESCRIPT}register(){return{"webcomp":this._onTag}}_onTag(ruleCtx,tag){var attribs,idAttr,isId,isColonId,isExpr,isLit,av,val,msg,mid;if(!ruleCtx.ojTag||!ruleCtx.filepath.includes("jet-composites")||!ruleCtx.tagNode.attribs){return}if(ruleCtx.utils.metaLib.isBindingTag(tag)){return}attribs=ruleCtx.tagNode.attribs;isId=attribs.hasOwnProperty(ID);isColonId=attribs.hasOwnProperty(COLON_ID);if(!isId&&!isColonId){return}idAttr=isId?ID:COLON_ID;av=attribs[idAttr];isExpr=_isAttrExpr(av);val=isExpr?_stripExprDelims(av):av;isLit=_isLiteral(val);if(isId){msg=`<${tag}> 'id' should be prefixed as ':id'${isExpr?"":" and set to an expression"}`;mid=0}else if(!isExpr){msg=`<${tag}> ':id' should be set to an expression`;mid=1}if(msg){_emitIssue(ruleCtx,msg,idAttr,mid)}if(isExpr&&isLit){msg=`<${tag}> '${idAttr}' attribute expression returns a constant - convert to a calculated expression`;_emitIssue(ruleCtx,msg,idAttr,2)}}};function _emitIssue(ruleCtx,msg,idAttr,mid){var issue,attrPos;issue=new ruleCtx.Issue(msg);attrPos=ruleCtx.utils.DomUtils.getAttribPosition(ruleCtx.data,ruleCtx.node,idAttr);issue.setPosition(attrPos.row,attrPos.col,attrPos.start,attrPos.end);if(mid){issue.setMsgKey(RULE_NAME+"_"+mid)}ruleCtx.reporter.addIssue(issue,ruleCtx)}function _isAttrExpr(s){var rc=false;if(typeof s==="string"){s=s.trim();rc=s.startsWith("[[")||s.startsWith("{{")}return rc};function _stripExprDelims(s){return s.substring(2,s.length-2).trim()}function _isLiteral(s){return s.charAt(0)==="'"&&s.charAt(s.length-1)==="'"};module.exports=Rule;
6
+ const RULE_NAME="oj-html-wctag-id";const SHORT_DESCRIPT="Custom components should not used a hard-coded 'id' attribute and should be set to an expression";const LONG_DESCRIPT="Hard-coded element IDs should not be used within custom components and should be set to an expression. Element IDs must be unique for each instance of the component. See context.uniqueId in the custom element documentation for information on how to derive unique IDs for elements."+"<p>If a CCA implements hard-coded IDs for HTML elements in the CCA view, e.g.<p>"+"<oj-input id=\"foo\"><p>"+"then this is guaranteed to cause issues as soon as more than one instance of "+"the component is used on the page (plus there is a significant risk of "+"collision with other IDs in the page as a whole.";const ID="id";const COLON_ID=":id";class Rule{getName(){return RULE_NAME}getDescription(){return LONG_DESCRIPT}getShortDescription(){return SHORT_DESCRIPT}register(){return{"webcomp":this._onTag}}_onTag(ruleCtx,tag){if(!ruleCtx.ojTag||!ruleCtx.filepath.includes("jet-composites")||!ruleCtx.tagNode.attribs){return}if(ruleCtx.utils.metaLib.isBindingTag(tag)){return}let md;if(md=ruleCtx.utils.metaLib.getTagMetadata(tag)){if(md.hasOwnProperty("type")&&md.type!=="composite"){return}}let attribs=ruleCtx.tagNode.attribs;let isId=attribs.hasOwnProperty(ID);let isColonId=attribs.hasOwnProperty(COLON_ID);if(!isId&&!isColonId){return}let idAttr=isId?ID:COLON_ID;let av=attribs[idAttr];let isExpr=_isAttrExpr(av);let val=isExpr?_stripExprDelims(av):av;let isLit=_isLiteral(val);let msg,mid;if(isId){msg=`<${tag}> 'id' should be prefixed as ':id'${isExpr?"":" and set to an expression"}`;mid=0}else if(!isExpr){msg=`<${tag}> ':id' should be set to an expression`;mid=1}if(msg){_emitIssue(ruleCtx,msg,idAttr,mid)}if(isExpr&&isLit){msg=`<${tag}> '${idAttr}' attribute expression returns a constant - convert to a calculated expression`;_emitIssue(ruleCtx,msg,idAttr,2)}}};function _emitIssue(ruleCtx,msg,idAttr,mid){var issue,attrPos;issue=new ruleCtx.Issue(msg);attrPos=ruleCtx.utils.DomUtils.getAttribPosition(ruleCtx.data,ruleCtx.node,idAttr);issue.setPosition(attrPos.row,attrPos.col,attrPos.start,attrPos.end);if(mid){issue.setMsgKey(RULE_NAME+"_"+mid)}ruleCtx.reporter.addIssue(issue,ruleCtx)}function _isAttrExpr(s){var rc=false;if(typeof s==="string"){s=s.trim();rc=s.startsWith("[[")||s.startsWith("{{")}return rc};function _stripExprDelims(s){return s.substring(2,s.length-2).trim()}function _isLiteral(s){return s.charAt(0)==="'"&&s.charAt(s.length-1)==="'"};module.exports=Rule;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const RULE="oj-html-wctag-maintenance";const DESCRIPTION="A notification that the component is in 'maintenance' status. This indicates "+"that the component is fully supported, but will be deprecated in a future release "+"and has no new features planned for it.";const SHORT_DESCRIPTION="The component is in 'maintenance' status and will be deprecated in a future release.";const MSG="<%c> is in 'maintenance' status%s.%d";const MAINTENANCE="maintenance";class Rule{getName(){return RULE}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(regCtx){if(!this._getOverrides(regCtx)){return false}this._metaLib=regCtx.utils.metaLib;return{ojtag:this._onTag}}_onTag(ruleCtx,tag){var stats,status,repl,msgObj;if(this._isIgnoreFile(ruleCtx.filepath)){return}if((stats=this._metaLib.getTagStatus(tag,MAINTENANCE))&&stats.length){let msg=MSG.replace("%c",tag);status=stats[0];if(status.since){msg=msg.replace("%s",` (since ${status.since})`)}if(status.description){msg=msg.replace("%d",` ${status.description}`);if(!msg.endsWith(".")){msg+="."}}else{msg=msg.replace("%d","")}if(status.value?.length){repl="<"+status.value.join(">, <")+">";msg+=` Superseded by ${repl}.`}let issue=new ruleCtx.Issue(msg);msgObj={tag:tag};if(repl){msgObj.supersededBy=status.value}issue.setMsgEx(msgObj);ruleCtx.reporter.addIssue(issue,ruleCtx)}}_isIgnoreFile(file){if(this._ignoreFiles){for(let i=0;i<this._ignoreFiles.length;i++){if(this._ignoreFiles[i].test(file)){return true}}}return false}_getOverrides(regCtx){var files,custOpts,files;if(!(custOpts=regCtx.ruleOpts.customOpts)){return true}if(!(files=custOpts.files)){return true}if(!Array.isArray(files)){regCtx.utils.msgLib.error(`Rule ${RULE} : config option 'files' is not an array`);return false}let ignoreFiles=[];for(let i=0;i<files.length;i++){if(typeof files[i]==="string"){try{ignoreFiles[i]=new RegExp(files[i].trim())}catch(e){regCtx.utils.msgLib.error(`Config 'ruleMods' ${RULE} 'files' entry [${i}]: ${e.message}`);return false}}}if(ignoreFiles.length){this._ignoreFiles=ignoreFiles}return true}}module.exports=Rule;
6
+ const RULE="oj-html-wctag-maintenance";const DESCRIPTION="A notification that the component is in 'maintenance' status. This indicates "+"that the component is fully supported, but will be deprecated in a future release "+"and has no new features planned for it.";const SHORT_DESCRIPTION="The component is in 'maintenance' status and will be deprecated in a future release.";const MSG="<%c> is in 'maintenance' status%s.%d";const MAINTENANCE="maintenance";class Rule{getName(){return RULE}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(regCtx){if(!this._getOverrides(regCtx)){return false}this._metaLib=regCtx.utils.metaLib;return{ojtag:this._onTag}}_onTag(ruleCtx,tag){var stats,status,repl,msgObj;if(this._isIgnoreFile(ruleCtx.filepath)){return}if((stats=this._metaLib.getTagStatus(tag,MAINTENANCE))&&stats.length){let msg=MSG.replace("%c",tag);status=stats[0];if(status.since){msg=msg.replace("%s",` (since ${status.since})`)}if(status.description){msg=msg.replace("%d",` ${status.description}`);if(!msg.endsWith(".")){msg+="."}}else{msg=msg.replace("%d","")}if(status.value?.length){repl="<"+status.value.join(">, <")+">";msg+=` Superseded by ${repl}.`}let issue=new ruleCtx.Issue(msg);msgObj={tag:tag};if(repl){msgObj.supersededBy=status.value}issue.setMsgEx(msgObj);ruleCtx.reporter.addIssue(issue,ruleCtx)}}_isIgnoreFile(file){if(this._ignoreFiles){for(let i=0;i<this._ignoreFiles.length;i++){if(this._ignoreFiles[i].test(file)){return true}}}return false}_getOverrides(regCtx){var files;if(!(files=regCtx.ruleOpts?.customOpts?.files)){return true}if(!Array.isArray(files)){regCtx.utils.msgLib.error(`Rule ${RULE} : config option 'files' is not an array`);return false}let ignoreFiles=[];for(let i=0;i<files.length;i++){if(typeof files[i]==="string"){try{ignoreFiles[i]=new RegExp(files[i].trim())}catch(e){regCtx.utils.msgLib.error(`Config 'ruleMods' ${RULE} 'files' entry [${i}]: ${e.message}`);return false}}}if(ignoreFiles.length){this._ignoreFiles=ignoreFiles}return true}}module.exports=Rule;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const RULENAME="oj-html-wctag-packprivate";const DESCRIPTION="Components marked as 'packPrivate' in their component.json metadata, are private base classes "+"that can be extended by other classes in the same pack. They cannot be used as application "+"'stand-alone' components.";const SHORT_DESCRIPTION="'packPrivate' components cannot be used as application 'stand-alone' components.";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(){return{webcomp:this._onWebComp}}_onWebComp(ruleCtx,tag){if(ruleCtx.utils.metaLib.isTagPackPrivate(tag)){let issue=new ruleCtx.Issue(`<${tag}> is not intended for stand-alone use in an application`);ruleCtx.reporter.addIssue(issue,ruleCtx)}}}module.exports=Rule;
6
+ const RULENAME="oj-html-wctag-packprivate";const DESCRIPTION="Components marked as 'packPrivate' in their component.json metadata, are private base classes "+"that can be extended by other classes in the same pack. They cannot be used as application "+"'stand-alone' components.";const SHORT_DESCRIPTION="'packPrivate' components cannot be used as application 'stand-alone' components.";const JETWC_USE_PUBLIC_APIS="jetwc-use-public-apis";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(){return{startaudit:this._onStartAudit,webcomp:this._onWebComp}}_onWebComp(ruleCtx,tag){if(ruleCtx.utils.metaLib.isTagPackPrivate(tag)){let issue=new ruleCtx.Issue(`<${tag}> is not intended for stand-alone use in an application`);ruleCtx.reporter.addIssue(issue,ruleCtx)}}_onStartAudit(ruleCtx){if(ruleCtx.rulePack.isRuleEnabled(JETWC_USE_PUBLIC_APIS,"JETWC")){ruleCtx.utils.msgLib.info(`Rule ${RULENAME} has disabled itself - deferring to rule ${JETWC_USE_PUBLIC_APIS}.`);ruleCtx.rulePack.disableRule(RULENAME)}}}module.exports=Rule;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- var path=require("path");const RULENAME="oj-js-poly-promise";const SHORT="The 'promise' polyfill should not be declared explicitly in define/require()";const DESCRIPTION="The Promise polyfill is no longer distributed with JET v11 and higher. Support for Internet Explorer 11 and ES5 "+"has been removed starting with JET v11. All modern browsers provide direct support for Promise and the Promise "+"polyfill should no longer be referenced separately.";const DEFINE="define";const REQUIRE="require";const TS="ts";var nt;class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT}register(regCtx){nt=regCtx.jsNodeTypes;return{CallExpression:this._onCall}}_onCall(ruleCtx,node){var args,arg,argVal,i,start,issue;if(node.callee&&(node.callee.name===DEFINE||node.callee.name===REQUIRE)){if(node.arguments&&node.arguments.length>=1){if(node.arguments[0].type===nt.ARRAY_EXPR){args=node.arguments[0].elements;for(i=0;i<args.length;i++){arg=args[i];if(arg&&arg.type==="Literal"){argVal=arg.raw.toLowerCase();argVal=path.basename(argVal);if(argVal.includes("promise")){issue=new ruleCtx.Issue(node.callee.name+"() explicitly loads polyfill 'promise'");start=_isTS(ruleCtx)?arg.range[0]:arg.start;start=start+arg.raw.indexOf("promise");issue.setPosition(null,null,start,start+6);ruleCtx.reporter.addIssue(issue,ruleCtx);break}}}}}}}}function _isTS(ctx){return ctx.filepath.substring(ctx.filepath.lastIndexOf(".")+1)===TS};module.exports=Rule;
6
+ const RULENAME="oj-js-poly-promise";const SHORT="The 'promise' polyfill should not be declared explicitly in define/require()";const DESCRIPTION="The Promise polyfill is no longer distributed with JET v11 and higher. Support for Internet "+"Explorer 11 and ES5 has been removed starting with JET v11. All modern browsers provide "+"direct support for Promise and the 'promise' polyfill should no longer be referenced separately.";const DEFINE="define";const REQUIRE="require";const TS="ts";var nt;var path=require("path");class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT}register(regCtx){nt=regCtx.jsNodeTypes;return{CallExpression:this._onCall}}_onCall(ruleCtx,node){var args,arg,argVal,i,start,issue;if(node.callee&&(node.callee.name===DEFINE||node.callee.name===REQUIRE)){if(node.arguments&&node.arguments.length>=1){if(node.arguments[0].type===nt.ARRAY_EXPR){if(args=node.arguments[0].elements){for(i=0;i<args.length;i++){arg=args[i];if(arg&&arg.type==="Literal"){if((argVal=arg.value)&&argVal==="promise"||_hasSeparator(argVal)&&path.basename(argVal)==="promise"){issue=new ruleCtx.Issue(node.callee.name+"() explicitly loads polyfill 'promise'");start=arg.start;start=start+arg.raw.indexOf("promise");issue.setPosition(null,null,start,start+6);ruleCtx.reporter.addIssue(issue,ruleCtx);break}}}}}}}}}function _hasSeparator(s){return s.includes("/")||s.includes("\\")}module.exports=Rule;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- var path=require("path");const RULENAME="oj-ts-poly-promise";const SHORT="The 'promise' polyfill should not be declared explicitly in define/require()";const DESCRIPTION="The Promise polyfill is no longer distributed with JET v11 and higher. Support for Internet Explorer 11 and ES5 "+"has been removed starting with JET v11. All modern browsers provide direct support for Promise and the Promise "+"polyfill should no longer be referenced separately.";const DEFINE="define";const REQUIRE="require";var nt;class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT}register(regCtx){nt=regCtx.tsNodeTypes;return{CallExpression:this._onCall}}_onCall(ruleCtx,node){var args,arg,argVal,i,start,issue;if(node.callee&&(node.callee.name===DEFINE||node.callee.name===REQUIRE)){if(node.arguments&&node.arguments.length>=1){if(node.arguments[0].type===nt.ARRAY_EXPR){args=node.arguments[0].elements;for(i=0;i<args.length;i++){arg=args[i];if(arg&&arg.type==="Literal"){argVal=arg.raw;argVal=path.basename(argVal).toLowerCase();if(argVal.includes("promise")){start=arg.range[0];start=start+arg.raw.toLowerCase().indexOf("promise");issue=new ruleCtx.Issue(node.callee.name+"() explicitly loads polyfill 'promise'");issue.setPosition(null,null,start,start+6);ruleCtx.reporter.addIssue(issue,ruleCtx);break}}}}}}}}module.exports=Rule;
6
+ var path=require("path");const RULENAME="oj-ts-poly-promise";const SHORT="The 'promise' polyfill should not be declared explicitly in define/require()";const DESCRIPTION="The Promise polyfill is no longer distributed with JET v11 and higher. Support for Internet "+"Explorer 11 and ES5 has been removed starting with JET v11. All modern browsers provide "+"direct support for Promise and the 'promise' polyfill should no longer be referenced separately.";const DEFINE="define";const REQUIRE="require";var nt;var path=require("path");class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT}register(regCtx){nt=regCtx.tsNodeTypes;return{CallExpression:this._onCall}}_onCall(ruleCtx,node){var args,arg,argVal,i,start,issue;if(node.callee&&(node.callee.name===DEFINE||node.callee.name===REQUIRE)){if(node.arguments&&node.arguments.length>=1){if(node.arguments[0].type===nt.ARRAY_EXPR){if(args=node.arguments[0].elements){for(i=0;i<args.length;i++){arg=args[i];if(arg&&arg.type==="Literal"){if((argVal=arg.value)&&argVal==="promise"||_hasSeparator(argVal)&&path.basename(argVal)==="promise"){issue=new ruleCtx.Issue(node.callee.name+"() explicitly loads polyfill 'promise'");start=arg.range[0];start=start+arg.raw.toLowerCase().indexOf("promise");issue.setPosition(null,null,start,start+6);ruleCtx.reporter.addIssue(issue,ruleCtx);break}}}}}}}}}function _hasSeparator(s){return s.includes("/")||s.includes("\\")}module.exports=Rule;
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
3
+ * Licensed under The Universal Permissive License (UPL), Version 1.0
4
+ * as shown at https://oss.oracle.com/licenses/upl/
5
+ */
6
+ const RULENAME="oj-tsx-acc-navigable-link";const DESCRIPTION="In order to be keyboard accessible, hyperlinks must be defined with either an 'href' or a 'tabindex' property (or both).";const SHORT_DESCRIPTION="Ensure that hyperlinks on the page are keyboard accessible";const HREF="href";const TABINDEX="tabindex";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(regCtx){this._tsxUtils=regCtx.utils.tsxUtils;return{"Tsx<a>":this._onAnchor}}_onAnchor(ruleCtx,tsxComp){if(!this._tsxUtils.getProperty(tsxComp,HREF)&&!this._tsxUtils.getProperty(tsxComp,TABINDEX)){let msg="<a> must have an 'href' or 'tabindex' property to be keyboard accessible.";ruleCtx.reporter.addIssue(new ruleCtx.Issue(msg),ruleCtx)}}}module.exports=Rule;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const RULE="oj-tsx-aria-prop";const LONG="Attributes beginning with <i>'aria-'</i> must be valid WAI-ARIA definitions.";const ARIA="aria-";const JSX_SPREAD_ATTRIBUTE="JSXSpreadAttribute";function Rule(){};Rule.prototype.getName=function(){return RULE};Rule.prototype.getShortDescription=function(){return LONG};Rule.prototype.getDescription=function(){return LONG};Rule.prototype.register=function(regCtx){this._tsxUtils=regCtx.utils.tsxUtils;return{"TsxRenderComponent":this._onTsxRC}};Rule.prototype._onTsxRC=function(ruleCtx,tsxRC){this._tsxUtils.extractTsxProperties(ruleCtx,tsxRC,this._onProp.bind(this))};Rule.prototype._onProp=function(ruleCtx,tsxProp){var propName;if(tsxProp===null||tsxProp.parent.isPreact||tsxProp.node.type===JSX_SPREAD_ATTRIBUTE){return}if(!(propName=tsxProp.name)){return}if(propName.startsWith(ARIA)&&!this._tsxUtils.isAriaAttr(propName)){let issue=new ruleCtx.Issue(`<${tsxProp.parent.name}> attribute '${propName}' is not a valid WAI-ARIA definition`);this._tsxUtils.setIssuePosition(issue,tsxProp);ruleCtx.reporter.addIssue(issue,ruleCtx)}};module.exports=Rule;
6
+ const RULE="oj-tsx-aria-prop";const LONG="Attributes beginning with <i>'aria-'</i> must be valid WAI-ARIA definitions.";const JSX_SPREAD_ATTRIBUTE="JSXSpreadAttribute";function Rule(){};Rule.prototype.getName=function(){return RULE};Rule.prototype.getShortDescription=function(){return LONG};Rule.prototype.getDescription=function(){return LONG};Rule.prototype.register=function(regCtx){this._tsxUtils=regCtx.utils.tsxUtils;return{"TsxAria":this._onProp}};Rule.prototype._onProp=function(ruleCtx,tsxProp){if(!this._tsxUtils.isAriaAttr(tsxProp.name)){let issue=new ruleCtx.Issue(`<${tsxProp.parent.name}> attribute '${tsxProp.name}' is not a valid WAI-ARIA definition`);this._tsxUtils.setIssuePosition(issue,tsxProp);ruleCtx.reporter.addIssue(issue,ruleCtx)}};module.exports=Rule;
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
3
+ * Licensed under The Universal Permissive License (UPL), Version 1.0
4
+ * as shown at https://oss.oracle.com/licenses/upl/
5
+ */
6
+ const RULENAME="oj-tsx-corequired";const DESCRIPTION="Some components need to be configured such that at least one property or slot must be populated out "+"of a given set for the component to function correctly (the 'anyOf' requirement), or alternatively the "+"component should not be configured with properties and slots from a given set (the 'not' requirement). "+"This requirements are often used for accessibility.";const SHORT_DESCRIPTION="Check that a webcomponent element contains at least one property or slot out of a given set, or none of them.";const SLOT="slot";const COLON_SLOT=":slot";const LIST_SEPARATOR="', '";const QUOTE="'";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(regCtx){this._ignoreList=null;this._metaLib=regCtx.utils.metaLib;this._tsxUtils=regCtx.utils.tsxUtils;this._utils=regCtx.utils.utils;this._attribs=null;if(!this._getOverrides(regCtx)){return false}return{"TsxRequirements":this._onRequirements}}_onRequirements(ruleCtx,tsxComp,reqMeta){if(this._isIgnoreFile(ruleCtx.filepath)){return}reqMeta.forEach(req=>{this._checkRequirement(ruleCtx,tsxComp,req)})}_checkRequirement(ruleCtx,tsxComp,req){switch(req.type){case"anyOf":this._anyOf(ruleCtx,tsxComp,req);break}}_anyOf(ruleCtx,tsxComp,req){var reqProps,reqSlots;if((reqProps=req.properties)&&reqProps.length){if(this._checkProperties_AnyOf(ruleCtx,tsxComp,reqProps)){return}}if((reqSlots=req.slots)&&reqSlots.length){if(this._checkSlots_AnyOf(ruleCtx,tsxComp,reqSlots)){return}}this._emitIssue_AnyOf(ruleCtx,tsxComp,req)}_not(ruleCtx,tsxComp,req){var reqProps,reqSlots;if((reqProps=req.properties)&&reqProps.length){if(!this._checkProperties_Not(ruleCtx,tsxComp,reqProps)){this._emitIssue_Not(ruleCtx,tsxComp,req);return}}if((reqSlots=req.slots)&&reqSlots.length){if(!this._checkSlots_Not(ruleCtx,tsxComp,reqSlots)){this._emitIssue_Not(ruleCtx,tsxComp,req)}}}_checkProperties_AnyOf(ruleCtx,tsxComp,reqProps){var attribs,reqProp,props,i;if(reqProps.length==0){return true}if(!(props=tsxComp.properties)){return false}for(i=0;i<reqProps.length;i++){reqProp=reqProps[i];if(reqProp.startsWith("aria-")||reqProp.startsWith("data-")||!reqProp.includes(".")){if(this._tsxUtils.getProperty(tsxComp,reqProp)){return true}continue}let subs=reqProp.split(".");let tsxProp,j,obj;for(j=0;j<props.length;j++){tsxProp=props[j];let sub,k;sub=subs[0];if(sub!==tsxProp.name){continue}if(!(obj=this._tsxUtils.getExpressionObject(tsxProp,sub))){continue}for(k=1;k<subs.length;k++){sub=subs[k];if(obj[sub]){if(k+1>=subs.length){return true}obj=obj[sub];if(!this._utils.isObject(obj)){break}}}}}return false}_checkSlots_AnyOf(ruleCtx,tsxComp,reqSlots){let slotName,tsxProp,reqSlot,i;if(tsxComp.properties){if(tsxProp=this._tsxUtils.getProperty(SLOT)){slotName=this._tsxUtils.getPropertyStringValue(tsxProp,SLOT)}for(i=0;i<reqSlots.length;i++){reqSlot=reqSlots[i];if(slotName){if(slotName===reqSlot){return true}else if(reqSlot===""){if(_hasChildContent(tsxComp)){return true}}}else if(reqSlot===""){if(_hasChildContent(tsxComp)){return true}}}}return false}_emitIssue_AnyOf(ruleCtx,tsxComp,req){let issue,msg,haveProps;msg=`<${tsxComp.name}> does not satisfy the '${req.type}' requirement "${req.label}".`;if(req.properties){let reqLen=req.properties.length;msg+=" It has not been configured with ";msg+=reqLen>1?"at least one of the properties":"the property";msg+=" ";msg+=QUOTE+req.properties.join(LIST_SEPARATOR)+QUOTE;haveProps=true}if(req.slots){msg+=haveProps?", or with content in ":" It has not been configured with content in ";if(req.slots.length>1){msg+="at least one of the following slots ";msg+=QUOTE+req.slots.join(LIST_SEPARATOR)+QUOTE}else{if(req.slots[0]===""){msg+="the default slot"}else{msg+=`slot '${req.slots[0]}'`}}}msg+=".";msg=_addDescription(msg,req);issue=new ruleCtx.Issue(msg);ruleCtx.reporter.addIssue(issue,ruleCtx)}_checkProperties_Not(ruleCtx,tsxComp,reqProps){var attribs,reqProp,props,i;if(reqProps.length==0||!(props=tsxComp.properties)){return true}for(i=0;i<reqProps.length;i++){reqProp=reqProps[i];if(reqProp.startsWith("aria-")||reqProp.startsWith("data-")||!reqProp.includes(".")){if(this._tsxUtils.getProperty(tsxComp,reqProp)){return false}continue}let subs=reqProp.split(".");let tsxProp,j,obj;for(j=0;j<props.length;j++){let sub,k;tsxProp=props[j];sub=subs[0];if(sub!==tsxProp.name){continue}if(!(obj=this._tsxUtils.getExpressionObject(tsxProp,sub))){continue}for(k=1;k<subs.length;k++){sub=subs[k];if(obj[sub]){if(k+1>=subs.length){return false}obj=obj[sub];if(!this._utils.isObject(obj)){return false}}else{break}}}}return true}_checkSlots_Not(ruleCtx,tsxComp,reqSlots){let slotName,tsxProp,reqSlot,i;if(tsxComp.properties){if(tsxProp=this._tsxUtils.getProperty(SLOT)){slotName=this._tsxUtils.getPropertyStringValue(tsxProp,SLOT)}for(i=0;i<reqSlots.length;i++){reqSlot=reqSlots[i];if(slotName){if(slotName===reqSlot){return false}else if(reqSlot===""){if(_hasChildContent(tsxComp)){return false}}}else if(reqSlot===""){if(_hasChildContent(tsxComp)){return false}}}}return true}_emitIssue_Not(ruleCtx,tsxComp,req){let issue,msg,haveProps;msg=`<${tsxComp.name}> does not satisfy the '${req.type}' requirement "${req.label}".`;if(req.properties){let reqLen=req.properties.length;msg+=" It has been configured with ";msg+=reqLen>1?"at least one of the properties":"the property";msg+=" ";msg+=QUOTE+req.properties.join(LIST_SEPARATOR)+QUOTE;haveProps=true}if(req.slots){msg+=haveProps?", or with content in ":" It has been configured with content in ";if(req.slots.length>1){msg+="at least one of the following slots ";msg+=QUOTE+req.slots.join(LIST_SEPARATOR)+QUOTE}else{if(req.slots[0]===""){msg+="the default slot"}else{msg+=`slot '${req.slots[0]}'`}}}msg+=".";msg=_addDescription(msg,req);issue=new ruleCtx.Issue(msg);ruleCtx.reporter.addIssue(issue,ruleCtx)}_isIgnoreFile(file){if(this._ignoreFiles){for(let i=0;i<this._ignoreFiles.length;i++){if(this._ignoreFiles[i].test(file)){return true}}}return false}_getOverrides(regCtx){var files;if(!(files=regCtx.ruleOpts?.customOpts?.files)){return true}if(!Array.isArray(files)){regCtx.utils.msgLib.error(`Rule ${RULE} : config option 'files' is not an array`);return false}let ignoreFiles=[];for(let i=0;i<files.length;i++){if(typeof files[i]==="string"){try{ignoreFiles[i]=new RegExp(files[i].trim())}catch(e){regCtx.utils.msgLib.error(`Config 'ruleMods' ${RULENAME} 'files' entry [${i}]: ${e.message}`);return false}}}if(ignoreFiles.length){this._ignoreFiles=ignoreFiles}return true}}function _hasChildContent(tsxComp){var childs,child;if((childs=tsxComp.node.children)&&childs.length){if(childs.length===1&&childs[0].type==="JSXText"){let s=childs[0]?.value.trim();return!!s.length}return true}return false};function _addDescription(msg,req){if(req.description){msg+=` (Additional - ${req.description.trimEnd()}`;if(!msg.endsWith(".")){msg+="."}msg+=")"}return msg};module.exports=Rule;
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
3
+ * Licensed under The Universal Permissive License (UPL), Version 1.0
4
+ * as shown at https://oss.oracle.com/licenses/upl/
5
+ */
6
+ const RULENAME="oj-tsx-prop-ko-binding";const DESCRIPTION="When components are used in VDOM, properties should be using the appropriate "+"VDOM style of binding syntax which uses single curly braces. Knockout style "+"binding syntax using string values with pairs of square brackets or curly "+"braces will be simply treated as a literal strings and this is likely to have "+"unexpected effects on the operation of the component.";const SHORT_DESCRIPTION="Knockout style bindings should not be used for components in VDOM pages.";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(){return{"AssignmentExpression":this._onAssign}}_onAssign(ruleCtx,node){var isSquare,right;if((right=node.right)&&right.type==="Literal"&&typeof right.value==="string"){let val;if(val=right.value.trim()){if((isSquare=val.startsWith("[["))||val.startsWith("{{")){if(val.endsWith(isSquare?"]]":"}}")){this._emitIssue(ruleCtx,node)}}}}}_emitIssue(ruleCtx,node){var issue,loc,range;loc=node.right.loc.start;range=node.right.range;issue=new ruleCtx.Issue("Knockout style binding detected - use VDOM binding syntax style.");issue.setPosition(loc.line,loc.column,range[0],range[1]);ruleCtx.reporter.addIssue(issue,ruleCtx)}}module.exports=Rule;
@@ -0,0 +1,6 @@
1
+ /*
2
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
3
+ * Licensed under The Universal Permissive License (UPL), Version 1.0
4
+ * as shown at https://oss.oracle.com/licenses/upl/
5
+ */
6
+ const RULENAME="oj-tsx-tabbar-progressive-popup";const DESCRIPTION="For JET 18.0.0 and later, <oj-tab-bar> truncation=\"progressive\" should always be used with "+"overflow=\"popup\" for handling overflow properly. If truncation=\"progressive\" is used alone, "+"for long labels it is possible that all items may not fit within oj-tab-bar despite being truncated.";const SHORT_DESCRIPTION="For <oj-tab-bar>, truncation=\"progressive\" requires overflow=\"popup\" to avoid pssible truncation.";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(regCtx){this._tsxUtils=regCtx.utils.tsxUtils;return{"Tsx<oj-tab-bar truncation=>":this._onTabBar}}_onTabBar(ruleCtx,tsxProp){if(this._tsxUtils.getPropertyStringValue(tsxProp)==="progressive"){if(!this._hasPropWithValue(tsxProp.parent,"overflow","popup")){let issue=new ruleCtx.Issue("<oj-tab-bar> 'overflow' property must be set to \"popup\" if truncation=\"progressive\"");ruleCtx.reporter.addIssue(issue,ruleCtx)}}}_hasPropWithValue(tsxComp,propName,propValue){var tsxProp,val,ret=false;if(tsxProp=this._tsxUtils.getProperty(tsxComp,propName)){if(val=this._tsxUtils.getPropertyStringValue(tsxProp)){ret=val===propValue}}return ret}}module.exports=Rule;
@@ -3,4 +3,4 @@
3
3
  * Licensed under The Universal Permissive License (UPL), Version 1.0
4
4
  * as shown at https://oss.oracle.com/licenses/upl/
5
5
  */
6
- const RULENAME="oj-tsx-wctag-packprivate";const DESCRIPTION="Components marked as 'packPrivate' in their component.json metadata, are private base classes "+"that can be extended by other classes in the same pack. They cannot be used as application "+"'stand-alone' components.";const SHORT_DESCRIPTION="'packPrivate' components cannot be used as application 'stand-alone' components.";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(){return{TsxRenderComponent:this._onTsxRC}}_onTsxRC(ruleCtx,tsxRC){tsxRC.components.forEach(tsxComp=>{this._checkPackPrivate(ruleCtx,tsxComp)})}_checkPackPrivate(ruleCtx,tsxComp){var tagName=tsxComp.name;if(ruleCtx.utils.metaLib.isTagPackPrivate(tagName)){_emitIssue(ruleCtx,tsxComp)}if(tsxComp.children){tsxComp.children.forEach(child=>{if(ruleCtx.utils.metaLib.isTagPackPrivate(child.name)){_emitIssue(ruleCtx,child)}})}}};function _emitIssue(ruleCtx,tsxComp){var tagName=tsxComp.name;var issue=new ruleCtx.Issue(`<${tagName}> is not intended for stand-alone use in an application ('packPrivate')`);issue.setPosition(tsxComp.loc.start.line,tsxComp.loc.start.column,tsxComp.range[0],tsxComp.range[1]);ruleCtx.reporter.addIssue(issue,ruleCtx)}module.exports=Rule;
6
+ const RULENAME="oj-tsx-wctag-packprivate";const DESCRIPTION="Components marked as 'packPrivate' in their component.json metadata, are private base classes "+"that can be extended by other classes in the same pack. They cannot be used as application "+"'stand-alone' components.";const SHORT_DESCRIPTION="'packPrivate' components cannot be used as application 'stand-alone' components.";const JETWC_USE_PUBLIC_APIS="jetwc-use-public-apis";class Rule{getName(){return RULENAME}getDescription(){return DESCRIPTION}getShortDescription(){return SHORT_DESCRIPTION}register(){return{startaudit:this._onStartAudit,TsxRenderComponent:this._onTsxRC}}_onTsxRC(ruleCtx,tsxRC){tsxRC.components.forEach(tsxComp=>{this._checkPackPrivate(ruleCtx,tsxComp)})}_checkPackPrivate(ruleCtx,tsxComp){var tagName=tsxComp.name;if(ruleCtx.utils.metaLib.isTagPackPrivate(tagName)){_emitIssue(ruleCtx,tsxComp)}if(tsxComp.children){tsxComp.children.forEach(child=>{if(ruleCtx.utils.metaLib.isTagPackPrivate(child.name)){_emitIssue(ruleCtx,child)}})}}_onStartAudit(ruleCtx){if(ruleCtx.rulePack.isRuleEnabled(JETWC_USE_PUBLIC_APIS,"JETWC")){ruleCtx.utils.msgLib.info(`Rule ${RULENAME} has disabled itself - deferring to rule ${JETWC_USE_PUBLIC_APIS}.`);ruleCtx.rulePack.disableRule(RULENAME)}}};function _emitIssue(ruleCtx,tsxComp){var tagName=tsxComp.name;var issue=new ruleCtx.Issue(`<${tagName}> is not intended for stand-alone use in an application ('packPrivate')`);issue.setPosition(tsxComp.loc.start.line,tsxComp.loc.start.column,tsxComp.range[0],tsxComp.range[1]);ruleCtx.reporter.addIssue(issue,ruleCtx)}module.exports=Rule;