CLASS zcl_abapgit_syntax_js DEFINITION PUBLIC INHERITING FROM zcl_abapgit_syntax_highlighter CREATE PUBLIC . PUBLIC SECTION. CONSTANTS: " JavaScript " 1) General keywords " 2) Variable types " 3) HTML Tags BEGIN OF c_css, keyword TYPE string VALUE 'keyword', "#EC NOTEXT text TYPE string VALUE 'text', "#EC NOTEXT comment TYPE string VALUE 'comment', "#EC NOTEXT variables TYPE string VALUE 'variables', "#EC NOTEXT END OF c_css . CONSTANTS: BEGIN OF c_token, keyword TYPE c VALUE 'K', "#EC NOTEXT text TYPE c VALUE 'T', "#EC NOTEXT comment TYPE c VALUE 'C', "#EC NOTEXT variables TYPE c VALUE 'V', "#EC NOTEXT END OF c_token . CONSTANTS: BEGIN OF c_regex, " comments /* ... */ or // comment TYPE string VALUE '\/\*.*\*\/|\/\*|\*\/|\/\/', "#EC NOTEXT " single or double quoted strings text TYPE string VALUE '"|''', "#EC NOTEXT " in general keywords don't contain numbers (except -ms-scrollbar-3dlight-color) keyword TYPE string VALUE '\b[a-z-]+\b', "#EC NOTEXT END OF c_regex . CLASS-METHODS class_constructor . METHODS constructor . PROTECTED SECTION. TYPES: BEGIN OF ty_keyword, keyword TYPE string, token TYPE char1, END OF ty_keyword. CLASS-DATA gt_keywords TYPE HASHED TABLE OF ty_keyword WITH UNIQUE KEY keyword. CLASS-DATA gv_comment TYPE abap_bool. CLASS-METHODS init_keywords. CLASS-METHODS insert_keywords IMPORTING iv_keywords TYPE string iv_token TYPE char1. CLASS-METHODS is_keyword IMPORTING iv_chunk TYPE string RETURNING VALUE(rv_yes) TYPE abap_bool. METHODS order_matches REDEFINITION. METHODS parse_line REDEFINITION. PRIVATE SECTION. ENDCLASS. CLASS ZCL_ABAPGIT_SYNTAX_JS IMPLEMENTATION. METHOD class_constructor. init_keywords( ). ENDMETHOD. METHOD constructor. super->constructor( ). " Initialize instances of regular expression add_rule( iv_regex = c_regex-keyword iv_token = c_token-keyword iv_style = c_css-keyword ). add_rule( iv_regex = c_regex-comment iv_token = c_token-comment iv_style = c_css-comment ). add_rule( iv_regex = c_regex-text iv_token = c_token-text iv_style = c_css-text ). " Styles for keywords add_rule( iv_regex = '' iv_token = c_token-variables iv_style = c_css-variables ). ENDMETHOD. METHOD init_keywords. DATA: lv_keywords TYPE string. CLEAR gt_keywords. " 1) General keywords lv_keywords = 'alert|all|body|break|bytetostring|case|continue|default|delete|do|document|else|event|export|for|function|if|' && 'import|in|innerhtml|isnan|item|mimetypes|navigator|new|onabort|onblur|onchange|onclick|ondblclick|ondragdrop|' && 'onerror|onfocus|onkeydown|onkeypress|onkeyup|onload|onmousedown|onmousemove|onmouseout|onmouseover|onmouseup|' && 'onmove|onreset|onselect|onsubmit|onunload|onresize|options|parsefloat|parseint|prototype|return|screen|switch|' && 'unit|var|void|while|window|with|anchor|applet|area|button|checkbox|fileupload|form|frame|hidden|link|mimetype|' && 'password|plugin|radio|reset|select|submit|text|textarea|abs|acos|alert|anchor|asin|atan|atan2|back|big|blink|' && 'blur|bold|captureevents|ceil|charat|charcodeat|clearinterval|cleartimeout|click|close|concat|confirm|cos|' && 'disableexternalcapture|enableexternalcapture|eval|exp|find|fixed|floor|focus|fontcolor|fontsize|forward|' && 'fromcharcode|getdate|getday|getelementbyid|gethours|getminutes|getmonth|getoptionvalue|getoptionvaluecount|' && 'getseconds|getselection|gettime|gettimezoneoffset|getyear|go|handleevent|home|indexof|italics|javaenabled|join|' && 'lastindexof|link|load|log|match|max|min|moveabove|movebelow|moveby|moveto|movetoabsolute|open|parse|plugins|' && 'pop|pow|preference|print|prompt|push|random|refresh|releaseevents|reload|replace|reset|resizeby|resizeto|' && 'reverse|round|routeevent|scroll|scrollby|scrollto|search|select|setdate|sethours|setinterval|setminutes|' && 'setmonth|setseconds|settime|settimeout|setyear|shift|sin|slice|small|sort|splice|split|sqrt|stop|strike|sub|' && 'submit|substr|substring|sup|taintenabled|tan|togmtstring|tolocalestring|tolowercase|tostring|touppercase|' && 'unshift|unwatch|utc|valueof|watch|write|writeln|e|ln10|ln2|log10e|log2e|max_value|min_value|negative_infinity|' && 'nan|pi|positive_infinity|url|above|action|alinkcolor|anchors|appcodename|appname|appversion|applets|arguments|' && 'arity|availheight|availwidth|background|backgroundcolor|below|bgcolor|border|bottom|caller|cancelbubble|' && 'checked|clientheight|clientwidth|clientx|clienty|clip|closed|color|colordepth|complete|constructor|cookie|' && 'count|current|defaultchecked|defaultselected|defaultstatus|defaultvalue|description|display|document|domain|' && 'elements|embeds|enabledplugin|encoding|false|fgcolor|filename|form|formname|forms|frames|hash|height|history|' && 'host|hostname|href|hspace|images|innerheight|innerwidth|language|lastmodified|layers|left|length|linkcolor|' && 'links|location|locationbar|lowsrc|menubar|method|mimetypes|name|next|null|offsetheight|offsetleft|offsetparent|' && 'offsetwidth|opener|outerheight|outerwidth|pagex|pagexoffset|pagey|pageyoffset|parent|parentlayer|pathname|' && 'personalbar|pixeldepth|platform|plugins|port|poswidth|previous|protocol|prototype|referrer|right|scrolltop|' && 'scrollbars|search|selected|selectedindex|self|siblingabove|siblingbelow|src|srcelement|status|statusbar|style|' && 'suffixes|tags|target|text|this|title|toolbar|top|true|type|useragent|value|visibility|vlinkcolor|vspace|width|' && 'window|zindex'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-keyword ). " 2) Variable types lv_keywords = 'array|boolean|date|function|image|layer|math|number|object|option|regexp|string'. insert_keywords( iv_keywords = lv_keywords iv_token = c_token-variables ). ENDMETHOD. METHOD insert_keywords. DATA: lt_keywords TYPE STANDARD TABLE OF string, ls_keyword TYPE ty_keyword. FIELD-SYMBOLS: TYPE any. SPLIT iv_keywords AT '|' INTO TABLE lt_keywords. LOOP AT lt_keywords ASSIGNING . CLEAR ls_keyword. ls_keyword-keyword = . ls_keyword-token = iv_token. INSERT ls_keyword INTO TABLE gt_keywords. ENDLOOP. ENDMETHOD. METHOD is_keyword. DATA lv_str TYPE string. lv_str = to_lower( iv_chunk ). READ TABLE gt_keywords WITH TABLE KEY keyword = lv_str TRANSPORTING NO FIELDS. rv_yes = boolc( sy-subrc = 0 ). ENDMETHOD. METHOD order_matches. DATA: lv_match TYPE string, lv_line_len TYPE i, lv_cmmt_end TYPE i, lv_prev_end TYPE i, lv_prev_token TYPE c. FIELD-SYMBOLS: TYPE ty_match, TYPE ty_match, TYPE ty_keyword. " Longest matches SORT ct_matches BY offset length DESCENDING. lv_line_len = strlen( iv_line ). " Check if this is part of multi-line comment and mark it accordingly IF gv_comment = abap_true. READ TABLE ct_matches WITH KEY token = c_token-comment TRANSPORTING NO FIELDS. IF sy-subrc <> 0. CLEAR ct_matches. APPEND INITIAL LINE TO ct_matches ASSIGNING . -token = c_token-comment. -offset = 0. -length = lv_line_len. RETURN. ENDIF. ENDIF. LOOP AT ct_matches ASSIGNING . " Delete matches after open text match IF lv_prev_token = c_token-text AND -token <> c_token-text. CLEAR -token. CONTINUE. ENDIF. lv_match = substring( val = iv_line off = -offset len = -length ). CASE -token. WHEN c_token-keyword. " Skip keyword that's part of previous (longer) keyword IF -offset < lv_prev_end. CLEAR -token. CONTINUE. ENDIF. " Map generic keyword to specific token lv_match = to_lower( lv_match ). READ TABLE gt_keywords ASSIGNING WITH TABLE KEY keyword = lv_match. IF sy-subrc = 0. -token = -token. ENDIF. WHEN c_token-comment. IF lv_match = '/*'. DELETE ct_matches WHERE offset > -offset. -length = lv_line_len - -offset. gv_comment = abap_true. ELSEIF lv_match = '//'. DELETE ct_matches WHERE offset > -offset. -length = lv_line_len - -offset. ELSEIF lv_match = '*/'. DELETE ct_matches WHERE offset < -offset. -length = -offset + 2. -offset = 0. gv_comment = abap_false. ELSE. lv_cmmt_end = -offset + -length. DELETE ct_matches WHERE offset > -offset AND offset <= lv_cmmt_end. ENDIF. WHEN c_token-text. -text_tag = lv_match. IF lv_prev_token = c_token-text. IF -text_tag = -text_tag. -length = -offset + -length - -offset. CLEAR lv_prev_token. ENDIF. CLEAR -token. CONTINUE. ENDIF. ENDCASE. lv_prev_token = -token. lv_prev_end = -offset + -length. ASSIGN TO . ENDLOOP. DELETE ct_matches WHERE token IS INITIAL. ENDMETHOD. METHOD parse_line. "REDEFINITION DATA lv_index TYPE i. FIELD-SYMBOLS LIKE LINE OF rt_matches. rt_matches = super->parse_line( iv_line ). " Remove non-keywords LOOP AT rt_matches ASSIGNING WHERE token = c_token-keyword. lv_index = sy-tabix. IF abap_false = is_keyword( substring( val = iv_line off = -offset len = -length ) ). CLEAR -token. ENDIF. ENDLOOP. DELETE rt_matches WHERE token IS INITIAL. ENDMETHOD. ENDCLASS.