forked from phcode-dev/staging.phcode.dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmain.js
More file actions
1 lines (1 loc) · 19.8 KB
/
Copy pathmain.js
File metadata and controls
1 lines (1 loc) · 19.8 KB
1
define(function(require,exports,module){require("HTMLJumpToDef");const AppInit=brackets.getModule("utils/AppInit"),CodeHintManager=brackets.getModule("editor/CodeHintManager"),HTMLUtils=brackets.getModule("language/HTMLUtils"),PreferencesManager=brackets.getModule("preferences/PreferencesManager"),Strings=brackets.getModule("strings"),NewFileContentManager=brackets.getModule("features/NewFileContentManager"),CSSUtils=brackets.getModule("language/CSSUtils"),StringMatch=brackets.getModule("utils/StringMatch"),LiveDevelopment=brackets.getModule("LiveDevelopment/main"),KeyEvent=brackets.getModule("utils/KeyEvent"),Metrics=brackets.getModule("utils/Metrics"),HTMLTags=require("text!HtmlTags.json"),HTMLAttributes=require("text!HtmlAttributes.json"),HTMLTemplate=require("text!template.html"),XHTMLTemplate=require("text!template.xhtml");require("./html-lint");const{markupSnippets:markupSnippets,htmlTags:htmlTags,positiveSymbols:positiveSymbols,negativeSymbols:negativeSymbols}=require("./emmet-snippets"),expandAbbr=Phoenix.libs.Emmet.expand,markupSnippetsList=Object.keys(markupSnippets);let enabled=!0,tags,attributes;function EmmetMarkupHints(){}function formatEmmetHint(abbr){var $hint=$("<span>").css("margin-right","48px"),$textContent=$("<span>").addClass("emmet-text-content").text(abbr);let $icon=$('<span class="emmet-html-code-hint">Emmet</span>');return $hint.append($textContent),$hint.append($icon),$hint}function _isEmmetChar(char,insideBraces){const validPattern=/[a-zA-Z0-9:+*<>()/!$\-@#}{]/,specialChars=new Set([".","#","[","]",'"',"=",":",",","-"]);return validPattern.test(char)||specialChars.has(char)||insideBraces&&" "===char}function _findAbbreviationStart(line,cursorCh){let start=cursorCh,insideBraces=!1,lastGtPos=-1;for("}"!==line.charAt(start)&&"]"!==line.charAt(start)||(start--,insideBraces=!0);start>0;){const char=line.charAt(start-1);if("}"===char||"]"===char?insideBraces=!0:"{"!==char&&"["!==char||(insideBraces=!1),"<"===char){if(-1!==lastGtPos)return lastGtPos+1;break}if(">"===char&&(lastGtPos=start-1),!_isEmmetChar(char,insideBraces))break;start--}return start}function getWordBeforeCursor(editor){const pos=editor.getCursorPos(),lineText=editor.document.getLine(pos.line),abbreviationStart=_findAbbreviationStart(lineText,pos.ch);let abbreviationEnd=pos.ch;"}"!==lineText.charAt(abbreviationEnd)&&"]"!==lineText.charAt(abbreviationEnd)||abbreviationEnd++;const word=lineText.substring(abbreviationStart,abbreviationEnd);return{word:word,start:{line:pos.line,ch:abbreviationStart},end:{line:pos.line,ch:abbreviationEnd}}}function getLineIndentation(editor,position){const line=editor.document.getLine(position.line),match=line.match(/^\s*/);return match?match[0]:""}function addIndentation(expandedText,baseIndent){const lines=expandedText.split(/(\r\n|\n)/g);let result="",isFirstLine=!0;for(let i=0;i<lines.length;i++){const line=lines[i];"\n"!==line&&"\r\n"!==line?""!==line.trim()?isFirstLine?(result+=line,isFirstLine=!1):result+=baseIndent+line:result+=line:result+=line}return result}function findCursorPosition(editor,indentedAbbr,startPos){const abbrLines=indentedAbbr.split("\n");for(let lineOffset=0;lineOffset<abbrLines.length;lineOffset++){const abbrLine=abbrLines[lineOffset];for(let j=0;j<abbrLine.length-1;j++){const pair=abbrLine[j]+abbrLine[j+1];if('""'===pair||"''"===pair){const absoluteLine=startPos.line+lineOffset,absoluteCh=0===lineOffset?startPos.ch+j+1:j+1;return{line:absoluteLine,ch:absoluteCh}}}for(let j=0;j<abbrLine.length-1;j++){const pair=abbrLine[j]+abbrLine[j+1];if("><"===pair){const absoluteLine=startPos.line+lineOffset,absoluteCh=0===lineOffset?startPos.ch+j+1:j+1;return{line:absoluteLine,ch:absoluteCh}}}}const totalLines=startPos.line+abbrLines.length;for(let i=startPos.line;i<totalLines;i++){const line=editor.document.getLine(i).trim();if(line.endsWith(">")&&line.includes("<")&&!line.includes("</")&&editor.document.getLine(i+1)&&!editor.document.getLine(i+1).trim()){const tempLine=editor.document.getLine(i+2);if(tempLine){const trimmedTempLine=tempLine.trim();if(trimmedTempLine.includes("</")&&trimmedTempLine.startsWith("<")){const openingTagLine=editor.document.getLine(i),indentMatch=openingTagLine.match(/^[\s\t]*/)[0],extraIndent=" ";return{line:i+1,ch:indentMatch.length+extraIndent.length}}}}}return!1}function _updateAbbrInEditor(editor,wordObj,expandedAbbr){const baseIndent=getLineIndentation(editor,wordObj.start),indentedAbbr=addIndentation(expandedAbbr,baseIndent);if(wordObj.word.includes("{")||wordObj.word.includes("[")){const pos=editor.getCursorPos(),line=editor.document.getLine(pos.line),char=line.charAt(wordObj.end.ch),charsNext=line.charAt(wordObj.end.ch+1);"}"!==char&&"]"!==char||(wordObj.end.ch+=1),'"'===char&&charsNext&&"]"===charsNext&&(wordObj.end.ch+=2)}editor.document.replaceRange(indentedAbbr,wordObj.start,wordObj.end);const cursorPos=findCursorPosition(editor,indentedAbbr,wordObj.start);cursorPos&&editor.setCursorPos(cursorPos.line,cursorPos.ch)}function isLoremSafeToExpand(word){const MAX_LOREM_WORDS=1e5,loremPattern=/lorem[a-z]*(\d+)(?:-(\d+))?/gi,loremMatches=[...word.matchAll(loremPattern)];if(0===loremMatches.length)return!0;let maxLoremCount=0;for(const match of loremMatches){const count1=parseInt(match[1])||0,count2=match[2]?parseInt(match[2]):count1,maxCount=Math.max(count1,count2);maxLoremCount=Math.max(maxLoremCount,maxCount)}if(maxLoremCount>1e5)return!1;const multiplierPattern=/\*(\d+)/g,multipliers=[...word.matchAll(multiplierPattern)].map(m=>parseInt(m[1]));if(0===multipliers.length)return!0;const totalMultiplier=Math.min(multipliers.reduce((product,num)=>product*num,1),400),estimatedTotal=maxLoremCount*totalMultiplier;return estimatedTotal<=1e5}function _isExpandable(editor,word){const pos=editor.getCursorPos(),line=editor.document.getLine(pos.line);if(line.includes("<!"))return null;if(line.includes("!!")&&!line.includes("!!!"))return null;if(line.includes("!!!!"))return null;if(negativeSymbols.some(symbol=>word.includes(symbol)))return null;if(markupSnippetsList.includes(word)||htmlTags.includes(word.toLowerCase())||positiveSymbols.some(symbol=>word.includes(symbol))||word.toLowerCase().includes("lorem")){if(word.toLowerCase().includes("lorem")&&!isLoremSafeToExpand(word))return null;try{return expandAbbr(word,{syntax:"html",type:"markup",maxRepeat:400})}catch(error){const nextChar=line.charAt(pos.ch);if(nextChar&&('"'===nextChar||"'"===nextChar)){const modifiedWord=word+nextChar;try{return expandAbbr(modifiedWord,{syntax:"html",type:"markup",maxRepeat:400})}catch(innerError){return null}}return null}}return null}function TagHints(){this.exclusion=null}function AttrHints(){this.globalAttributes=this.readGlobalAttrHints(),this.cachedHints=null,this.exclusion=""}PreferencesManager.definePreference("codehint.TagHints","boolean",!0,{description:Strings.DESCRIPTION_HTML_TAG_HINTS}),PreferencesManager.definePreference("codehint.AttrHints","boolean",!0,{description:Strings.DESCRIPTION_ATTR_HINTS}),EmmetMarkupHints.prototype.hasHints=function(editor,implicitChar){if(enabled){if(this.editor=editor,"php"===editor.getLanguageForSelection().getId())return!1;const pos=editor.getCursorPos(),tagInfo=HTMLUtils.getTagInfo(editor,pos),tokenType=tagInfo.position.tokenType;if(tokenType===HTMLUtils.ATTR_NAME||tokenType===HTMLUtils.ATTR_VALUE)return!1;const wordObj=getWordBeforeCursor(editor);if(wordObj.word.trim()){const expandedAbbr=_isExpandable(editor,wordObj.word);if(expandedAbbr)return!0}}return!1},EmmetMarkupHints.prototype.getHints=function(implicitChar){const wordObj=getWordBeforeCursor(this.editor),expandedAbbr=_isExpandable(this.editor,wordObj.word);if(!expandedAbbr)return null;const formattedHint=formatEmmetHint(wordObj.word);return{hints:[formattedHint],match:null,selectInitial:!0,defaultDescriptionWidth:!0,handleWideResults:!1}},EmmetMarkupHints.prototype.insertHint=function(){const wordObj=getWordBeforeCursor(this.editor),expandedAbbr=_isExpandable(this.editor,wordObj.word);return _updateAbbrInEditor(this.editor,wordObj,expandedAbbr),Metrics.countEvent(Metrics.EVENT_TYPE.CODE_HINTS,"emmet","htmlInsert"),!1},TagHints.prototype.updateExclusion=function(){var textAfterCursor;this.exclusion&&this.tagInfo&&(textAfterCursor=this.tagInfo.tagName.substr(this.tagInfo.position.offset),CodeHintManager.hasValidExclusion(this.exclusion,textAfterCursor)||(this.exclusion=null))},TagHints.prototype.hasHints=function(editor,implicitChar){var pos=editor.getCursorPos();return this.tagInfo=HTMLUtils.getTagInfo(editor,pos),this.editor=editor,null===implicitChar?this.tagInfo.position.tokenType===HTMLUtils.TAG_NAME&&this.tagInfo.position.offset>=0&&(0===this.tagInfo.position.offset?this.exclusion=this.tagInfo.tagName:this.updateExclusion(),!0):"<"===implicitChar&&(this.exclusion=this.tagInfo.tagName,!0)},TagHints.prototype.getHints=function(implicitChar){var query,result;return this.tagInfo=HTMLUtils.getTagInfo(this.editor,this.editor.getCursorPos()),this.tagInfo.position.tokenType===HTMLUtils.TAG_NAME&&this.tagInfo.position.offset>=0?(this.updateExclusion(),query=this.tagInfo.tagName.slice(0,this.tagInfo.position.offset),{hints:result=$.map(tags,function(value,key){if(0===key.indexOf(query))return key}).sort(),match:query,selectInitial:!0,handleWideResults:!1}):null},TagHints.prototype.insertHint=function(completion){var start={line:-1,ch:-1},end={line:-1,ch:-1},cursor=this.editor.getCursorPos(),charCount=0;if(this.tagInfo.position.tokenType===HTMLUtils.TAG_NAME){var textAfterCursor=this.tagInfo.tagName.substr(this.tagInfo.position.offset);charCount=CodeHintManager.hasValidExclusion(this.exclusion,textAfterCursor)?this.tagInfo.position.offset:this.tagInfo.tagName.length}return end.line=start.line=cursor.line,start.ch=cursor.ch-this.tagInfo.position.offset,end.ch=start.ch+charCount,(this.exclusion||completion!==this.tagInfo.tagName)&&(start.ch!==end.ch?this.editor.document.replaceRange(completion,start,end):this.editor.document.replaceRange(completion,start),this.exclusion=null),!1},AttrHints.prototype.readGlobalAttrHints=function(){return $.map(attributes,function(value,key){if("true"===value.global)return key})};const MAX_CLASS_HINTS=250;function formatHints(hints){return StringMatch.basicMatchSort(hints),hints.length>MAX_CLASS_HINTS&&(hints=hints.splice(0,MAX_CLASS_HINTS)),hints.map(function(token){let $hintObj=$(`<span data-val='${token.label||token.value||token.text}'></span>`).addClass("brackets-html-hints brackets-hints");return token.stringRanges?token.stringRanges.forEach(function(item){item.matched?$hintObj.append($("<span>").text(item.text).addClass("matched-hint")):$hintObj.append(item.text)}):$hintObj.text(token.label),$hintObj.attr("data-val",token.label),$hintObj})}function _getAllClassHints(query){let queryStr=query.queryStr;const segments=queryStr.split(" ");queryStr=segments[segments.length-1];const deferred=$.Deferred();return CSSUtils.getAllCssSelectorsInProject({includeClasses:!0,scanCurrentHtml:!0}).then(hints=>{const result=$.map(hints,function(pvalue){return!(pvalue=pvalue.slice(1))||pvalue.includes("#")||pvalue.includes("\\")||pvalue.includes("/")?null:StringMatch.stringMatch(pvalue,queryStr,{preferPrefixMatches:!0})}),validHints=formatHints(result);validHints.alreadyMatched=!0,deferred.resolve(validHints)}).catch(console.error),deferred}AttrHints.prototype._getValueHintsForAttr=function(query,tagName,attrName){var hints=[];if("class"===attrName)return _getAllClassHints(query);var tagPlusAttr,attrInfo=attributes[tagName+"/"+attrName]||attributes[attrName];return attrInfo&&("boolean"===attrInfo.type?hints=["false","true"]:attrInfo.attribOption&&(hints=attrInfo.attribOption)),hints},AttrHints.prototype.updateExclusion=function(attrNameOnly){if(this.exclusion&&this.tagInfo){var tokenType=this.tagInfo.position.tokenType,offset=this.tagInfo.position.offset,textAfterCursor;tokenType===HTMLUtils.ATTR_NAME?textAfterCursor=this.tagInfo.attr.name.substr(offset):attrNameOnly||tokenType!==HTMLUtils.ATTR_VALUE||(textAfterCursor=this.tagInfo.attr.value.substr(offset)),CodeHintManager.hasValidExclusion(this.exclusion,textAfterCursor)||(this.exclusion=null)}};const HISTORY_PREFIX="Live_hint_CSS";let hintSessionId=0,isInLiveHighlightSession=!1;function NewDocContentProvider(){this.CONTENT_PROVIDER_NAME="HTMLCodeHints"}function preferenceChanged(){enabled=PreferencesManager.get("emmet")}AttrHints.prototype.onClose=function(){isInLiveHighlightSession&&(this.editor.restoreHistoryPoint(`Live_hint_CSS${hintSessionId}`),isInLiveHighlightSession=!1),hintSessionId++},AttrHints.prototype.onHighlight=function($highlightedEl,_$descriptionElem,reason){if(!reason)return console.error("OnHighlight called without reason, should never happen!"),void hintSessionId++;const tokenType=this.tagInfo.position.tokenType,currentLivePreviewDetails=LiveDevelopment.getLivePreviewDetails();if(!currentLivePreviewDetails||!currentLivePreviewDetails.liveDocument||tokenType!==HTMLUtils.ATTR_VALUE||"class"!==this.tagInfo.attr.name)return;const currentlyEditedFile=this.editor.document.file.fullPath,livePreviewedFile=currentLivePreviewDetails.liveDocument.doc.file.fullPath;if(currentlyEditedFile!==livePreviewedFile)return;if(reason.source===CodeHintManager.SELECTION_REASON.SESSION_START)return hintSessionId++,void this.editor.createHistoryRestorePoint(`Live_hint_CSS${hintSessionId}`);if(reason.source!==CodeHintManager.SELECTION_REASON.KEYBOARD_NAV)return;const event=reason.event;if(event.keyCode!==KeyEvent.DOM_VK_UP&&event.keyCode!==KeyEvent.DOM_VK_DOWN&&event.keyCode!==KeyEvent.DOM_VK_PAGE_UP&&event.keyCode!==KeyEvent.DOM_VK_PAGE_DOWN)return;Metrics.countEvent(Metrics.EVENT_TYPE.LIVE_PREVIEW,"htmlClassHint","preview");const $hintItem=$highlightedEl.find(".brackets-html-hints"),highligtedValue=$highlightedEl.find(".brackets-html-hints").data("val");highligtedValue&&$hintItem.is(":visible")&&(isInLiveHighlightSession=!0,this.editor._dontDismissPopupOnScroll(),this.editor.restoreHistoryPoint(`Live_hint_CSS${hintSessionId}`),this.insertHint($highlightedEl.find(".brackets-html-hints"),!0))},AttrHints.prototype.hasHints=function(editor,implicitChar){var pos=editor.getCursorPos(),tokenType,offset,query;if(this.editor=editor,this.tagInfo=HTMLUtils.getTagInfo(editor,pos),tokenType=this.tagInfo.position.tokenType,offset=this.tagInfo.position.offset,null===implicitChar){if(query=null,tokenType===HTMLUtils.ATTR_NAME)offset>=0&&(query=this.tagInfo.attr.name.slice(0,offset));else if(tokenType===HTMLUtils.ATTR_VALUE){query=this.tagInfo.position.offset>=0?this.tagInfo.attr.value.slice(0,offset):"";const attrName=this.tagInfo.attr.name;if(attrName&&"class"!==attrName){let hints=this._getValueHintsForAttr({queryStr:query},this.tagInfo.tagName,attrName);if(hints instanceof Array){var i,foundPrefix=!1;for(i=0;i<hints.length;i++)if(0===hints[i].indexOf(query)){foundPrefix=!0;break}foundPrefix||(query=null)}}}return offset>=0&&(tokenType===HTMLUtils.ATTR_NAME&&0===offset?this.exclusion=this.tagInfo.attr.name:this.updateExclusion(!1)),null!==query}return(" "===implicitChar||"'"===implicitChar||'"'===implicitChar||"="===implicitChar)&&(tokenType===HTMLUtils.ATTR_NAME&&(this.exclusion=this.tagInfo.attr.name),!0)},AttrHints.prototype.getHints=function(implicitChar){var cursor=this.editor.getCursorPos(),query={queryStr:null},tokenType,offset,result=[];if(this.tagInfo=HTMLUtils.getTagInfo(this.editor,cursor),tokenType=this.tagInfo.position.tokenType,offset=this.tagInfo.position.offset,tokenType!==HTMLUtils.ATTR_NAME&&tokenType!==HTMLUtils.ATTR_VALUE||(query.tag=this.tagInfo.tagName,offset>=0?(tokenType===HTMLUtils.ATTR_NAME?query.queryStr=this.tagInfo.attr.name.slice(0,offset):(query.queryStr=this.tagInfo.attr.value.slice(0,offset),query.attrName=this.tagInfo.attr.name),this.updateExclusion(!1)):tokenType===HTMLUtils.ATTR_VALUE&&(query.queryStr="",query.attrName=this.tagInfo.attr.name),query.usedAttr=HTMLUtils.getTagAttributes(this.editor,cursor)),query.tag&&null!==query.queryStr){var tagName=query.tag,attrName=query.attrName,filter=query.queryStr,unfiltered=[],hints;if(attrName?hints=this._getValueHintsForAttr(query,tagName,attrName):tags&&tags[tagName]&&tags[tagName].attributes&&(unfiltered=tags[tagName].attributes.concat(this.globalAttributes),hints=$.grep(unfiltered,function(attr,i){return $.inArray(attr,query.usedAttr)<0})),hints instanceof Array&&hints.length)return console.assert(!result.length),{hints:result=$.map(hints,function(item){if(0===item.indexOf(filter))return item}).sort(),match:query.queryStr,selectInitial:!0,handleWideResults:!1};if(hints instanceof Object&&hints.hasOwnProperty("done")){var deferred=$.Deferred();return hints.done(function(asyncHints){deferred.resolveWith(this,[{hints:asyncHints,match:asyncHints.alreadyMatched?null:query.queryStr,selectInitial:!0,handleWideResults:!1}])}),deferred}return null}},AttrHints.prototype.insertHint=function(completion,isLiveHighlight){var cursor=this.editor.getCursorPos(),start={line:-1,ch:-1},end={line:-1,ch:-1},tokenType=this.tagInfo.position.tokenType,offset=this.tagInfo.position.offset,charCount=0,insertedName=!1,replaceExistingOne=this.tagInfo.attr.valueAssigned,endQuote="",shouldReplace=!0,positionWithinAttributeVal=!1,textAfterCursor;if(tokenType===HTMLUtils.ATTR_NAME)textAfterCursor=this.tagInfo.attr.name.substr(offset),CodeHintManager.hasValidExclusion(this.exclusion,textAfterCursor)?(charCount=offset,replaceExistingOne=!1):charCount=this.tagInfo.attr.name.length,!replaceExistingOne&&attributes&&attributes[completion]&&"flag"!==attributes[completion].type?(completion+='=""',insertedName=!0):completion===this.tagInfo.attr.name&&(shouldReplace=!1);else if(tokenType===HTMLUtils.ATTR_VALUE){if(textAfterCursor=this.tagInfo.attr.value.substr(offset),CodeHintManager.hasValidExclusion(this.exclusion,textAfterCursor)?(charCount=offset,this.exclusion=null):charCount=this.tagInfo.attr.value.length,"class"===this.tagInfo.attr.name){completion=completion.data("val");const textBeforeCursor=this.tagInfo.attr.value.slice(0,offset);let lastSegment=textBeforeCursor.split(" ");charCount=offset=(lastSegment=lastSegment[lastSegment.length-1]).length,positionWithinAttributeVal=!0}this.tagInfo.attr.hasEndQuote?completion===this.tagInfo.attr.value&&(shouldReplace=!1):(endQuote=this.tagInfo.attr.quoteChar)?completion+=endQuote:0===offset&&(completion='"'+completion+'"')}if(end.line=start.line=cursor.line,start.ch=cursor.ch-offset,end.ch=start.ch+charCount,isLiveHighlight){if(!this.editor.hasSelection()){const initialOffset=this.tagInfo.position.offset;let firstSegment=(textAfterCursor=this.tagInfo.attr.value.substr(initialOffset)).split(" ");firstSegment=firstSegment[0],end.ch=end.ch+firstSegment.length,this.editor.setSelection(start,end)}return this.editor.replaceSelection(completion,"around","liveHints"),!0}if(isInLiveHighlightSession&&(isInLiveHighlightSession=!1,hintSessionId++),this.editor.hasSelection())return this.editor.replaceSelection(completion,"end"),!0;if(shouldReplace&&(start.ch!==end.ch?this.editor.document.replaceRange(completion,start,end):this.editor.document.replaceRange(completion,start)),positionWithinAttributeVal)this.editor.setCursorPos(start.line,start.ch+completion.length);else{if(insertedName)return this.editor.setCursorPos(start.line,start.ch+completion.length-1),!0;tokenType===HTMLUtils.ATTR_VALUE&&this.tagInfo.attr.hasEndQuote&&this.editor.setCursorPos(start.line,start.ch+completion.length+1)}return!1},NewDocContentProvider.prototype.getContent=function(fileName){return new Promise((resolve,reject)=>{fileName.endsWith(".xhtml")?resolve(XHTMLTemplate):resolve(HTMLTemplate)})},AppInit.appReady(function(){tags=JSON.parse(HTMLTags),attributes=JSON.parse(HTMLAttributes);let tagHints=new TagHints,attrHints=new AttrHints,newDocContentProvider=new NewDocContentProvider;CodeHintManager.registerHintProvider(tagHints,["html"],0),CodeHintManager.registerHintProvider(attrHints,["html"],0),NewFileContentManager.registerContentProvider(newDocContentProvider,["html"],0),PreferencesManager.on("change","emmet",preferenceChanged),preferenceChanged();var emmetMarkupHints=new EmmetMarkupHints;CodeHintManager.registerHintProvider(emmetMarkupHints,["html","php"],0),exports.emmetHintProvider=emmetMarkupHints,exports.tagHintProvider=tagHints,exports.attrHintProvider=attrHints})});