@@ -36833,9 +36833,17 @@ table tr{background-color:#fff;border-top:1px solid #c6cbd1}table tr:nth-child(2
3683336833 }
3683436834 }
3683536835
36836+ let headers;
36837+ if(path.endsWith(".htm") || path.endsWith(".html") || path.endsWith(".xhtml") || path.endsWith(".php")) {
36838+ headers = {
36839+ 'Content-Type': 'text/html;charset=UTF-8'
36840+ };
36841+ }
36842+
3683636843 resolve({
3683736844 path,
36838- contents: contents
36845+ contents: contents,
36846+ headers
3683936847 });
3684036848 });
3684136849 };
@@ -38031,9 +38039,17 @@ table tr{background-color:#fff;border-top:1px solid #c6cbd1}table tr:nth-child(2
3803138039 }
3803238040 }
3803338041
38042+ let headers;
38043+ if(path.endsWith(".htm") || path.endsWith(".html") || path.endsWith(".xhtml") || path.endsWith(".php")) {
38044+ headers = {
38045+ 'Content-Type': 'text/html;charset=UTF-8'
38046+ };
38047+ }
38048+
3803438049 resolve({
3803538050 path,
38036- textContents: contents
38051+ textContents: contents,
38052+ headers
3803738053 });
3803838054 });
3803938055 };
@@ -46071,6 +46087,17 @@ define("filesystem/File", function (require, exports, module) {
4607146087 }.bind(this));
4607246088 };
4607346089
46090+ function _insertIfNotPresent(addedList, file) {
46091+ if(!addedList || !addedList.length) {
46092+ return [file];
46093+ }
46094+ const foundEntry = addedList.find(entry => entry.fullPath === file.fullPath);
46095+ if(!foundEntry){
46096+ addedList.push(file);
46097+ }
46098+ return addedList;
46099+ }
46100+
4607446101 /**
4607546102 * Write a file.
4607646103 *
@@ -46110,11 +46137,11 @@ define("filesystem/File", function (require, exports, module) {
4611046137 this._clearCachedData();
4611146138 try {
4611246139 callback(err);
46113- return;
4611446140 } finally {
4611546141 // Always unblock external change events
4611646142 this._fileSystem._endChange();
4611746143 }
46144+ return;
4611846145 }
4611946146
4612046147 // Always store the hash
@@ -46136,6 +46163,7 @@ define("filesystem/File", function (require, exports, module) {
4613646163 if (parent._isWatched()) {
4613746164 // If the write succeeded and the parent directory is watched,
4613846165 // fire a synthetic change event
46166+ added = _insertIfNotPresent(added, this);
4613946167 this._fileSystem._fireChangeEvent(parent, added, removed);
4614046168
4614146169 }
@@ -51893,7 +51921,7 @@ define("language/CodeInspection", function (require, exports, module) {
5189351921 </td>
5189451922 <td>
5189551923 {{#fix.id}}
51896- <button class="btn btn-mini table-fix-err-button ph-fix-problem" title="{{Strings.FIX_ERROR}}"
51924+ <button class="btn btn-mini table-fix-err-button ph-fix-problem"
5189751925 data-fixid="{{fix.id}}">
5189851926 {{Strings.FIX}}
5189951927 </button>
@@ -52298,10 +52326,12 @@ define("language/CodeInspection", function (require, exports, module) {
5229852326 */
5229952327 function _createMarkerElement(editor, line, ch, type, message, isFixable) {
5230052328 let $marker = $('<div><span>')
52301- .attr('title', message)
52329+ .attr('title', ( message || "").trim() )
5230252330 .addClass(CODE_INSPECTION_GUTTER);
5230352331 $marker.click(function (){
5230452332 editor.setCursorPos(line, ch);
52333+ toggleCollapsed(false);
52334+ scrollToProblem(line);
5230552335 });
5230652336 $marker.find('span')
5230752337 .addClass(_getIconClassForType(type, isFixable))
@@ -52386,17 +52416,23 @@ define("language/CodeInspection", function (require, exports, module) {
5238652416 return new Promise((resolve, reject)=>{
5238752417 let codeInspectionMarks = editor.findMarksAt(pos, CODE_MARK_TYPE_INSPECTOR) || [];
5238852418 let $hoverMessage = $(`<div class="code-inspection-item"></div>`);
52389- let $problemView, quickViewPresent;
52419+ let quickViewPresent;
5239052420 let startPos = {line: pos.line, ch: token.start},
5239152421 endPos = {line: pos.line, ch: token.end};
5239252422 for(let mark of codeInspectionMarks){
52423+ let $problemView;
5239352424 quickViewPresent = true;
5239452425 const fixID = `${mark.metadata}`;
52426+ let errorMessageHTML = `<a style="cursor:pointer;color: unset;">${_.escape(mark.message)}</a>`;
5239552427 if(documentFixes.get(fixID)){
52396- $problemView = $(`<div>
52397- <i class="${_getIconClassForType(mark.type, mark.isFixable)}" style="margin-right: 3px;"></i>
52398- <button class="btn btn-mini fix-problem-btn" style="margin-right: 5px;">Fix</button>
52399- <a style="cursor:pointer;">${mark.message}</a>
52428+ $problemView = $(`<div class="code-inspection-quick-view-item">
52429+ <i title="${Strings.CLICK_VIEW_PROBLEM}" style="margin-right: 3px;cursor: pointer;"
52430+ class="${_getIconClassForType(mark.type, mark.isFixable)}"></i>
52431+ <button class="btn btn-mini fix-problem-btn" style="margin-right: 5px;">${Strings.FIX}</button>
52432+ ${errorMessageHTML}
52433+ <button class="btn btn-mini copy-qv-error-text-btn" title="${Strings.COPY_ERROR}">
52434+ <i class="fas fa-copy copy-qv-error-text-btn"></i>
52435+ </button>
5240052436 <br/>
5240152437 </div>`);
5240252438 $problemView.find(".fix-problem-btn").click(()=>{
@@ -52406,17 +52442,31 @@ define("language/CodeInspection", function (require, exports, module) {
5240652442 });
5240752443 $hoverMessage.append($problemView);
5240852444 } else {
52409- $problemView = $(`<div>
52410- <i class="${_getIconClassForType(mark.type, mark.isFixable)}" style="margin-right: 5px;"></i>
52411- <a style="cursor: pointer">${mark.message}</a>
52445+ $problemView = $(`<div class="code-inspection-quick-view-item">
52446+ <i title="${Strings.CLICK_VIEW_PROBLEM}" style="margin-right: 5px; cursor: pointer;"
52447+ class="${_getIconClassForType(mark.type, mark.isFixable)}"></i>
52448+ ${errorMessageHTML}
52449+ <button class="btn btn-mini copy-qv-error-text-btn" title="${Strings.COPY_ERROR}">
52450+ <i class="fas fa-copy copy-qv-error-text-btn"></i>
52451+ </button>
5241252452 <br/></div>`);
5241352453 $hoverMessage.append($problemView);
5241452454 }
52415- // eslint-disable-next-line no-loop-func
5241652455 $problemView.click(function () {
52456+ const selection = window.getSelection();
52457+ if(selection && selection.rangeCount > 0 && !selection.isCollapsed) {
52458+ // the user may be trying to select text from the error in quick view, in which case we
52459+ // shouldnt open the problems panel
52460+ return;
52461+ }
5241752462 toggleCollapsed(false);
5241852463 scrollToProblem(pos.line);
5241952464 });
52465+ $problemView.find(".copy-qv-error-text-btn").click(function (evt) {
52466+ evt.preventDefault();
52467+ evt.stopPropagation();
52468+ Phoenix.app.copyToClipboard(mark.message);
52469+ });
5242052470 const markPos = mark.find();
5242152471 if(markPos.from && markPos.from.line < startPos.line){
5242252472 startPos.line = markPos.from.line;
@@ -87712,14 +87762,14 @@ define("nls/root/strings", {
8771287762 "LINT_DISABLED": "Linting is disabled",
8771387763 "NO_LINT_AVAILABLE": "No linter available for {0}",
8771487764 "NOTHING_TO_LINT": "Nothing to lint",
87715- "COPY_ERROR": "Copy Error Message",
87716- "FIX_ERROR": "Fix Problem",
87765+ "COPY_ERROR": "Copy problem",
8771787766 "FIX": "Fix",
8771887767 "CANNOT_FIX_TITLE": "Failed to Apply Fix",
8771987768 "CANNOT_FIX_SOME_TITLE": "Failed to Apply Some Fixes",
8772087769 "CANNOT_FIX_MESSAGE": "The document has been modified since the fix was prepared. Please try again.",
8772187770 "LINTER_TIMED_OUT": "{0} has timed out after waiting for {1} ms",
8772287771 "LINTER_FAILED": "{0} terminated with error: {1}",
87772+ "CLICK_VIEW_PROBLEM": "Click to view problem in panel",
8772387773
8772487774 /**
8772587775 * Command Name Constants
@@ -88188,10 +88238,17 @@ define("nls/root/strings", {
8818888238
8818988239 // extensions/default/JSLint
8819088240 "JSHINT_NAME": "JSHint",
88241+ "JSHINT_CONFIG_ERROR": "Error reading JSHint config file: {0}",
88242+ "JSHINT_CONFIG_JSON_ERROR": "Error: JSHint config file `{0}` is not valid JSON",
8819188243 "ESLINT_NAME": "ESLint",
8819288244
8819388245 // extension css code hints
88194- "CSS_LINT_NAME": "{0} Lint",
88246+ "CSS_LINT_NAME": "{0}",
88247+
88248+ // html lint
88249+ "HTML_LINT_NAME": "HTML",
88250+ "HTML_LINT_CONFIG_JSON_ERROR": "Error: HTML Validator config file `{0}` is not valid JSON",
88251+ "HTML_LINT_CONFIG_UNSUPPORTED": "Error: Unsupported config format `{0}`. Use JSON config `.htmlvalidate.json`",
8819588252
8819688253 // Features/QuickView and quick view extensions
8819788254 "CMD_ENABLE_QUICK_VIEW": "Quick View on Hover",
@@ -88257,6 +88314,7 @@ define("nls/root/strings", {
8825788314 "DESCRIPTION_NO_HINTS_ON_DOT": "true to not automatically show JS code hints when . is typed",
8825888315 "DESCRIPTION_JSHINT_DISABLE": "true to disable JSHints linter in problems panel",
8825988316 "DESCRIPTION_ESLINT_DISABLE": "true to disable ESLint linter in problems panel",
88317+ "DESCRIPTION_HTML_LINT_DISABLE": "true to disable HTML linter in problems panel",
8826088318 "DESCRIPTION_ESLINT_FAILED": "ESLint Failed ({0}). Make sure the project contains valid <a href='https://eslint.org/docs/latest/use/configure/configuration-files'>Configuration Files</a>",
8826188319 "DESCRIPTION_ESLINT_USE_NATIVE_APP": "ESLint is only available in the Desktop app. Download it from <a href='https://phcode.io'>phcode.io</a>",
8826288320 "DESCRIPTION_ESLINT_LOAD_FAILED": "Failed to load ESLint for this project. {APP_NAME} supports only ESLint versions above 7.",
@@ -124156,8 +124214,12 @@ define("project/ProjectManager", function (require, exports, module) {
124156124214 EVENT_AFTER_STARTUP_FILES_LOADED = "startupFilesLoaded",
124157124215 EVENT_PROJECT_REFRESH = "projectRefresh",
124158124216 EVENT_CONTENT_CHANGED = "contentChanged",
124217+ // This will capture all file/folder changes in projects except renames. If you want to track renames,
124218+ // use EVENT_PROJECT_PATH_CHANGED_OR_RENAMED to track all changes or EVENT_PROJECT_FILE_RENAMED too.
124159124219 EVENT_PROJECT_FILE_CHANGED = "projectFileChanged",
124160- EVENT_PROJECT_FILE_RENAMED = "projectFileRenamed";
124220+ EVENT_PROJECT_FILE_RENAMED = "projectFileRenamed",
124221+ // the path changed event differs in the sense that all events returned by this will be a path.
124222+ EVENT_PROJECT_CHANGED_OR_RENAMED_PATH = "projectChangedPath";
124161124223
124162124224 EventDispatcher.setLeakThresholdForEvent(EVENT_PROJECT_OPEN, 25);
124163124225
@@ -124644,6 +124706,19 @@ define("project/ProjectManager", function (require, exports, module) {
124644124706 return model.makeProjectRelativeIfPossible(absPath);
124645124707 }
124646124708
124709+ /**
124710+ * Gets a generally displayable path that can be shown to the user in most cases.
124711+ * Gets the project relative path if possible. If paths is not in project, then if its a platform path(Eg. in tauri)
124712+ * it will return the full platform path. If not, then it will return a mount relative path for fs access mount
124713+ * folders opened in the bowser. at last, falling back to vfs path. This should only be used for display purposes
124714+ * as this path will be changed by phcode depending on the situation in the future.
124715+ * @param fullPath
124716+ * @returns {string}
124717+ */
124718+ function getProjectRelativeOrDisplayPath(fullPath) {
124719+ return Phoenix.app.getDisplayPath(makeProjectRelativeIfPossible(fullPath));
124720+ }
124721+
124647124722 /**
124648124723 * Returns the root folder of the currently loaded project, or null if no project is open (during
124649124724 * startup, or running outside of app shell).
@@ -126072,6 +126147,41 @@ define("project/ProjectManager", function (require, exports, module) {
126072126147 return !unsafeExit;
126073126148 }
126074126149
126150+ function _entryToPathSet(entryArray) {
126151+ if (!entryArray || !entryArray.length) {
126152+ return new Set();
126153+ }
126154+ return new Set(entryArray.map(entry => path.normalize(entry.fullPath)));
126155+ }
126156+
126157+ exports.on(EVENT_PROJECT_FILE_CHANGED, (_evt, entry, addedInProject, removedInProject)=>{
126158+ if(!entry && !addedInProject && !removedInProject){
126159+ // when clearing the cached files forcefully, empty change events may get trigerred, in which case ignore.
126160+ return;
126161+ }
126162+ const addedSet = _entryToPathSet(addedInProject);
126163+ const removedSet = _entryToPathSet(removedInProject);
126164+ if(!entry && !addedSet.size && !removedSet.size){
126165+ return;
126166+ }
126167+ exports.trigger(EVENT_PROJECT_CHANGED_OR_RENAMED_PATH, entry && path.normalize(entry.fullPath),
126168+ addedSet, removedSet);
126169+ });
126170+ exports.on(EVENT_PROJECT_FILE_RENAMED, (_evt, oldPath, newPath)=>{
126171+ oldPath = path.normalize(oldPath);
126172+ newPath = path.normalize(newPath);
126173+ if(oldPath === newPath){
126174+ return; // no change
126175+ }
126176+ const oldParent = path.dirname(oldPath), newParent = path.dirname(newPath);
126177+ if(oldParent === newParent) {
126178+ exports.trigger(EVENT_PROJECT_CHANGED_OR_RENAMED_PATH, newParent, new Set([newPath]), new Set([oldPath]));
126179+ } else {
126180+ exports.trigger(EVENT_PROJECT_CHANGED_OR_RENAMED_PATH, oldParent, new Set(), new Set([oldPath]));
126181+ exports.trigger(EVENT_PROJECT_CHANGED_OR_RENAMED_PATH, newParent, new Set([newPath]), new Set());
126182+ }
126183+ });
126184+
126075126185 exports.on(EVENT_PROJECT_OPEN, (_evt, projectRoot)=>{
126076126186 _reloadProjectPreferencesScope();
126077126187 _saveProjectPath();
@@ -126303,6 +126413,7 @@ define("project/ProjectManager", function (require, exports, module) {
126303126413 exports.getInitialProjectPath = getInitialProjectPath;
126304126414 exports.getStartupProjectPath = getStartupProjectPath;
126305126415 exports.getProjectRelativePath = getProjectRelativePath;
126416+ exports.getProjectRelativeOrDisplayPath = getProjectRelativeOrDisplayPath;
126306126417 exports.getWelcomeProjectPath = getWelcomeProjectPath;
126307126418 exports.getPlaceholderProjectPath = getPlaceholderProjectPath;
126308126419 exports.getExploreProjectPath = getExploreProjectPath;
@@ -126335,6 +126446,7 @@ define("project/ProjectManager", function (require, exports, module) {
126335126446 exports.EVENT_CONTENT_CHANGED = EVENT_CONTENT_CHANGED;
126336126447 exports.EVENT_PROJECT_FILE_CHANGED = EVENT_PROJECT_FILE_CHANGED;
126337126448 exports.EVENT_PROJECT_FILE_RENAMED = EVENT_PROJECT_FILE_RENAMED;
126449+ exports.EVENT_PROJECT_CHANGED_OR_RENAMED_PATH = EVENT_PROJECT_CHANGED_OR_RENAMED_PATH;
126338126450 exports.EVENT_PROJECT_OPEN_FAILED = EVENT_PROJECT_OPEN_FAILED;
126339126451});
126340126452
@@ -127723,9 +127835,12 @@ define("project/ProjectModel", function (require, exports, module) {
127723127835 }
127724127836
127725127837 if (added) {
127726- changes.added = added.map(function (entry) {
127727- return self.makeProjectRelativeIfPossible(entry.fullPath);
127728- });
127838+ changes.added = added
127839+ .filter(function(entry) {
127840+ return _shouldShowName(entry.name);
127841+ }).map(function (entry) {
127842+ return self.makeProjectRelativeIfPossible(entry.fullPath);
127843+ });
127729127844 }
127730127845
127731127846 if (removed) {
0 commit comments