Skip to content

Commit fd749ec

Browse files
committed
deploy: 606b7d0
1 parent 82fc847 commit fd749ec

File tree

120 files changed

+3191
-648
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+3191
-648
lines changed

LiveDevelopment/LiveDevMultiBrowser.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ define(function (require, exports, module) {
604604
* @param {Document} doc
605605
*/
606606
function _onDirtyFlagChange(event, doc) {
607-
if (!isActive() || !_server || !_liveDocument) {
607+
if (!isActive() || !_server || !_liveDocument || !_liveDocument.isRelated) {
608608
return;
609609
}
610610

appConfig.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ window.AppConfig = {
2424
"app_notification_url": "assets/notifications/dev/",
2525
"app_update_url": "https://updates.phcode.io/tauri/update-latest-experimental-build.json",
2626
"linting.enabled_by_default": true,
27-
"build_timestamp": "2024-04-19T09:07:00.923Z",
27+
"build_timestamp": "2024-04-20T14:55:50.959Z",
2828
"googleAnalyticsID": "G-P4HJFPDB76",
2929
"googleAnalyticsIDDesktop": "G-VE5BXWJ0HF",
3030
"mixPanelID": "49c4d164b592be2350fc7af06a259bf3",
@@ -36,7 +36,7 @@ window.AppConfig = {
3636
"bugsnagEnv": "development"
3737
},
3838
"name": "Phoenix Code",
39-
"version": "3.6.1-20159",
39+
"version": "3.6.1-20176",
4040
"apiVersion": "3.6.1",
4141
"homepage": "https://core.ai",
4242
"issues": {

assets/default-project/en.zip

0 Bytes
Binary file not shown.

assets/sample-projects/HTML5.zip

0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

assets/sample-projects/explore.zip

0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

brackets-min.js

Lines changed: 214 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3950,7 +3950,7 @@ define("LiveDevelopment/LiveDevMultiBrowser", function (require, exports, module
39503950
* @param {Document} doc
39513951
*/
39523952
function _onDirtyFlagChange(event, doc) {
3953-
if (!isActive() || !_server || !_liveDocument) {
3953+
if (!isActive() || !_server || !_liveDocument || !_liveDocument.isRelated) {
39543954
return;
39553955
}
39563956

@@ -15704,6 +15704,12 @@ define("document/DocumentCommandHandlers", function (require, exports, module) {
1570415704
_$dirtydot = $(".dirty-dot", _$titleWrapper);
1570515705
});
1570615706

15707+
if(Phoenix.isSpecRunnerWindow){
15708+
_$titleContainerToolbar = $("#titlebar");
15709+
_$titleWrapper = $(".title-wrapper");
15710+
_$title = $(".title");
15711+
_$dirtydot = $(".dirty-dot");
15712+
}
1570715713

1570815714
let firstProjectOpenHandled = false;
1570915715
ProjectManager.on(ProjectManager.EVENT_AFTER_PROJECT_OPEN, ()=>{
@@ -25151,7 +25157,7 @@ define("editor/EditorStatusBar", function (require, exports, module) {
2515125157
fullPath = document.file.fullPath;
2515225158

2515325159
var fileType = (document.file instanceof InMemoryFile) ? "newFile" : "existingFile",
25154-
filelanguageName = lang ? lang._name : "";
25160+
filelanguageName = lang ? lang._name||"" : "";
2515525161

2515625162
Metrics.countEvent(
2515725163
Metrics.EVENT_TYPE.EDITOR,
@@ -48886,6 +48892,7 @@ define("help/HelpCommandHandlers", function (require, exports, module) {
4888648892
*/
4888748893

4888848894
/*jslint regexp: true */
48895+
/*global jsPromise*/
4888948896

4889048897
/**
4889148898
* Set of utilities for simple parsing of CSS text.
@@ -48896,11 +48903,13 @@ define("language/CSSUtils", function (require, exports, module) {
4889648903
var CodeMirror = require("thirdparty/CodeMirror/lib/codemirror"),
4889748904
Async = require("utils/Async"),
4889848905
DocumentManager = require("document/DocumentManager"),
48906+
AppInit = require("utils/AppInit"),
4889948907
EditorManager = require("editor/EditorManager"),
4890048908
HTMLUtils = require("language/HTMLUtils"),
4890148909
LanguageManager = require("language/LanguageManager"),
4890248910
ProjectManager = require("project/ProjectManager"),
4890348911
TokenUtils = require("utils/TokenUtils"),
48912+
IndexingWorker = require("worker/IndexingWorker"),
4890448913
_ = require("thirdparty/lodash");
4890548914

4890648915
// Constants
@@ -50673,6 +50682,208 @@ define("language/CSSUtils", function (require, exports, module) {
5067350682
return (allSelectors.length ? allSelectors[0].selectorGroup || allSelectors[0].selector : "");
5067450683
}
5067550684

50685+
function _extractSelectorSet(selectorList) {
50686+
const regex = /[{}!]/;
50687+
const selectors = new Set();
50688+
if(!selectorList){
50689+
return selectors;
50690+
}
50691+
for(let item of selectorList) {
50692+
if(regex.test(item) || !item.trim()){
50693+
// this happens for scss selectors like #${var}-something. we ignore that for now instead of resolving
50694+
continue;
50695+
}
50696+
const extracted = extractSelectorBase(item);
50697+
extracted.trim() && selectors.add(extracted); // x:hover or x::some -> x
50698+
}
50699+
return selectors;
50700+
}
50701+
50702+
const CSSSelectorCache = new Map();
50703+
50704+
function _projectFileChanged(_evt, entry) {
50705+
if(!entry){
50706+
return;
50707+
}
50708+
let changedPath = entry.fullPath;
50709+
if(entry.isFile) {
50710+
CSSSelectorCache.delete(changedPath);
50711+
} else if(entry.isDirectory) {
50712+
changedPath = Phoenix.VFS.ensureTrailingSlash(changedPath);
50713+
const cachedFilePaths = Array.from(CSSSelectorCache.keys());
50714+
for(let filePath of cachedFilePaths) {
50715+
if(filePath.startsWith(changedPath)){
50716+
CSSSelectorCache.delete(filePath);
50717+
}
50718+
}
50719+
}
50720+
}
50721+
50722+
const MODE_MAP = {
50723+
css: "CSS",
50724+
less: "LESS",
50725+
scss: "SCSS"
50726+
};
50727+
50728+
function _loadFileAndScanCSSSelectorCached(fullPath) {
50729+
return new Promise(resolve=>{
50730+
DocumentManager.getDocumentForPath(fullPath)
50731+
.done(function (doc) {
50732+
// Find all matching rules for the given CSS file's content, and add them to the
50733+
// overall search result
50734+
let selectors = new Set();
50735+
const cachedSelectors = CSSSelectorCache.get(fullPath);
50736+
if(cachedSelectors){
50737+
resolve(cachedSelectors);
50738+
return;
50739+
}
50740+
const langID = doc.getLanguage().getId();
50741+
if(!MODE_MAP[langID]){
50742+
console.log("Cannot parse CSS for mode :", langID, "ignoring", fullPath);
50743+
resolve(selectors);
50744+
return;
50745+
}
50746+
console.log("scanning file for css selector collation: ", fullPath);
50747+
IndexingWorker.execPeer("css_getAllSymbols",
50748+
{text: doc.getText(), cssMode: "CSS", filePath: fullPath})
50749+
.then((selectorArray)=>{
50750+
selectors = _extractSelectorSet(selectorArray);
50751+
CSSSelectorCache.set(fullPath, selectors);
50752+
resolve(selectors);
50753+
}).catch(err=>{
50754+
console.warn("CSS language service unable to get selectors for" + fullPath, err);
50755+
resolve(selectors); // still resolve, so the overall result doesn't reject
50756+
});
50757+
})
50758+
.fail(function (error) {
50759+
console.warn("Unable to read " + fullPath + " during CSS selector search:", error);
50760+
resolve(new Set()); // still resolve, so the overall result doesn't reject
50761+
});
50762+
});
50763+
}
50764+
50765+
function extractSelectorBase(selector) {
50766+
// Use a regular expression to find the base part of the selector before any spaces, combinators,
50767+
// pseudo-classes, or attribute selectors
50768+
const match = selector.match(/^[^\s>+~:\[]+/);
50769+
// Return the match if found, otherwise return the original selector if no ':' or '::' is present
50770+
selector = match ? match[0] : selector;
50771+
if(selector.startsWith(".")) {
50772+
// Eg .class1.class2 type selector, we have to consider this too, so we always take the first segment only
50773+
selector = "." + selector.split(".")[1];
50774+
}
50775+
return selector;
50776+
}
50777+
50778+
const _htmlLikeFileExts = ["htm", "html", "xhtml", "php"];
50779+
function _isHtmlLike(editor) {
50780+
const fullPath = editor && editor.document.file.fullPath;
50781+
if (!editor || !LanguageManager.getLanguageForPath(fullPath)) {
50782+
return false;
50783+
}
50784+
50785+
return (_htmlLikeFileExts.indexOf(LanguageManager.getLanguageForPath(fullPath).getId() || "") !== -1);
50786+
}
50787+
50788+
function _getAllSelectorsInCurrentHTMLEditor() {
50789+
return new Promise(resolve=>{
50790+
let selectors = new Set();
50791+
const htmlEditor = EditorManager.getCurrentFullEditor();
50792+
if (!htmlEditor || !_isHtmlLike(htmlEditor) ) {
50793+
resolve(selectors);
50794+
return;
50795+
}
50796+
50797+
// Find all <style> blocks in the HTML file
50798+
const styleBlocks = HTMLUtils.findStyleBlocks(htmlEditor);
50799+
let cssText = "";
50800+
50801+
styleBlocks.forEach(function (styleBlockInfo) {
50802+
// Search this one <style> block's content
50803+
cssText += styleBlockInfo.text;
50804+
});
50805+
const fullPath = htmlEditor.document.file.fullPath;
50806+
IndexingWorker.execPeer("css_getAllSymbols", {text: cssText, cssMode: "CSS", filePath: fullPath})
50807+
.then((selectorArray)=>{
50808+
selectors = _extractSelectorSet(selectorArray);
50809+
CSSSelectorCache.set(fullPath, selectors);
50810+
resolve(selectors);
50811+
}).catch(err=>{
50812+
console.warn("CSS language service unable to get selectors for" + fullPath, err);
50813+
resolve(selectors); // still resolve, so the overall result doesn't reject
50814+
});
50815+
});
50816+
}
50817+
50818+
let globalPrecacheRun = 0;
50819+
function getAllCssSelectorsInProject(options = {
50820+
includeClasses: true,
50821+
includeIDs: true,
50822+
scanCurrentHtml: true
50823+
}) {
50824+
globalPrecacheRun ++; // we need to stop the pre cache logic from doing the same cache again
50825+
return new Promise(resolve=>{
50826+
ProjectManager.getAllFiles(ProjectManager.getLanguageFilter(["css", "less", "scss"]))
50827+
.done(function (cssFiles) {
50828+
// Create an array of promises from the array of cssFiles
50829+
const promises = cssFiles.map(fileInfo => _loadFileAndScanCSSSelectorCached(fileInfo.fullPath));
50830+
if(options.scanCurrentHtml){
50831+
promises.push(_getAllSelectorsInCurrentHTMLEditor());
50832+
}
50833+
const mergedSets = new Set();
50834+
// Use Promise.allSettled to handle all promises
50835+
Promise.allSettled(promises)
50836+
.then(results => {
50837+
results.forEach((result, index) => {
50838+
if (result.status === 'fulfilled') {
50839+
result.value.forEach(value => {
50840+
if((options.includeClasses && value.startsWith(".")) ||
50841+
(options.includeIDs && value.startsWith("#"))) {
50842+
mergedSets.add(value);
50843+
}
50844+
});
50845+
} else {
50846+
console.error(`Error collect css selectors from file ${cssFiles[index].fullPath}:`,
50847+
result.reason);
50848+
}
50849+
});
50850+
resolve(Array.from(mergedSets.keys()));
50851+
});
50852+
});
50853+
});
50854+
}
50855+
50856+
async function _populateSelectorCache() {
50857+
globalPrecacheRun ++;
50858+
const currentCacheRun = globalPrecacheRun;
50859+
const cssFiles = await jsPromise(ProjectManager.getAllFiles(
50860+
ProjectManager.getLanguageFilter(["css", "less", "scss"])));
50861+
for(let cssFile of cssFiles){
50862+
if(currentCacheRun !== globalPrecacheRun) {
50863+
// this is for cases in very large projects where the project switches while a
50864+
// project wide css parse was in progress.
50865+
break;
50866+
}
50867+
await _loadFileAndScanCSSSelectorCached(cssFile.fullPath); // this is serial to not hog processor
50868+
}
50869+
}
50870+
50871+
AppInit.appReady(function () {
50872+
if(Phoenix.isSpecRunnerWindow){
50873+
// no unit tests event handlers
50874+
return;
50875+
}
50876+
ProjectManager.on(ProjectManager.EVENT_PROJECT_FILE_CHANGED, _projectFileChanged);
50877+
ProjectManager.on(ProjectManager.EVENT_PROJECT_OPEN, ()=>{
50878+
CSSSelectorCache.clear();
50879+
setTimeout(_populateSelectorCache, 2000);
50880+
});
50881+
setTimeout(_populateSelectorCache, 2000);
50882+
DocumentManager.on(DocumentManager.EVENT_DOCUMENT_CHANGE, function (event, doc, _changelist) {
50883+
CSSSelectorCache.delete(doc.file.fullPath);
50884+
});
50885+
});
50886+
5067650887
exports._findAllMatchingSelectorsInText = _findAllMatchingSelectorsInText; // For testing only
5067750888
exports.findMatchingRules = findMatchingRules;
5067850889
exports.extractAllSelectors = extractAllSelectors;
@@ -50683,6 +50894,7 @@ define("language/CSSUtils", function (require, exports, module) {
5068350894
exports.getRangeSelectors = getRangeSelectors;
5068450895
exports.getCompleteSelectors = getCompleteSelectors;
5068550896
exports.isCSSPreprocessorFile = isCSSPreprocessorFile;
50897+
exports.getAllCssSelectorsInProject = getAllCssSelectorsInProject;
5068650898

5068750899
exports.SELECTOR = SELECTOR;
5068850900
exports.PROP_NAME = PROP_NAME;

0 commit comments

Comments
 (0)