Skip to content

Commit 9f14cb3

Browse files
committed
feat: emmet integration for stylesheets
1 parent 28a3742 commit 9f14cb3

File tree

1 file changed

+76
-2
lines changed
  • src/extensions/default/CSSCodeHints

1 file changed

+76
-2
lines changed

src/extensions/default/CSSCodeHints/main.js

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ define(function (require, exports, module) {
3838
CSSProperties = require("text!CSSProperties.json"),
3939
properties = JSON.parse(CSSProperties);
4040

41+
/**
42+
* Emmet API:
43+
* This provides a function to expand abbreviations into full CSS properties.
44+
*/
45+
const EXPAND_ABBR = Phoenix.libs.Emmet.expand;
46+
4147
require("./css-lint");
4248

4349
const BOOSTED_PROPERTIES = [
@@ -248,7 +254,7 @@ define(function (require, exports, module) {
248254
}
249255

250256
/**
251-
* Returns a list of availble CSS propertyname or -value hints if possible for the current
257+
* Returns a list of available CSS property name or -value hints if possible for the current
252258
* editor context.
253259
*
254260
* @param {Editor} implicitChar
@@ -377,8 +383,48 @@ define(function (require, exports, module) {
377383
}
378384
}
379385

386+
// pushedHints stores all the hints that will be displayed to the user
387+
// up until this much is the normal working of css code hints
388+
let pushedHints = formatHints(result);
389+
390+
// needle gives the current word before cursor, make sure that it exists
391+
// also needle shouldn't contain `-`, because for example if user typed:
392+
// `box-siz` then in that case it is very obvious that user wants to type `box-sizing`
393+
// but emmet expands it `box: siz;`. So we prevent calling emmet when needle has `-`.
394+
if(needle && !needle.includes('-')) {
395+
let expandedAbbr = EXPAND_ABBR(needle, { syntax: "css", type: "stylesheet" });
396+
if(expandedAbbr && isEmmetExpandable(needle, expandedAbbr)) {
397+
398+
// if the expandedAbbr doesn't have any numbers, we should split the expandedAbbr to,
399+
// get its first word before `:`.
400+
// For instance, `m` expands to `margin: ;`. Here the `: ;` is unnecessary.
401+
// Also, `bgc` expands to `background-color: #fff;`. Here we don't need the `: #fff;`
402+
// as we have cssIntelligence to display hints based on the property
403+
if(!isEmmetAbbrNumeric(expandedAbbr)) {
404+
expandedAbbr = expandedAbbr.split(':')[0];
405+
}
406+
407+
if(pushedHints) {
408+
409+
// to remove duplicate hints. one comes from emmet and other from default css hints.
410+
// we remove the default css hints and push emmet hint at the beginning.
411+
for(let i = 0; i < pushedHints.length; i++) {
412+
if(pushedHints[i][0].getAttribute('data-val') === expandedAbbr) {
413+
pushedHints.splice(i, 1);
414+
break;
415+
}
416+
}
417+
pushedHints.unshift(expandedAbbr);
418+
} else {
419+
pushedHints = expandedAbbr;
420+
}
421+
}
422+
}
423+
424+
425+
380426
return {
381-
hints: formatHints(result),
427+
hints: pushedHints,
382428
match: null, // the CodeHintManager should not format the results
383429
selectInitial: selectInitial,
384430
handleWideResults: false
@@ -387,6 +433,34 @@ define(function (require, exports, module) {
387433
return null;
388434
};
389435

436+
/**
437+
* Checks whether the emmet abbr should be expanded or not.
438+
* For instance: EXPAND_ABBR function always expands a value passed to it.
439+
* if we pass 'xyz', then there's no CSS property matching to it, but it still expands this to `xyz: ;`.
440+
* So, make sure that `needle + ': ;'` doesn't add to expandedAbbr
441+
*
442+
* @param {String} needle the word before the cursor
443+
* @param {String} expandedAbbr the expanded abbr returned by EXPAND_ABBR emmet api
444+
* @returns {boolean} true if emmet should be expanded, otherwise false
445+
*/
446+
function isEmmetExpandable(needle, expandedAbbr) {
447+
return needle + ': ;' !== expandedAbbr;
448+
}
449+
450+
/**
451+
* Checks whether the expandedAbbr has any number.
452+
* For instance: `m0` expands to `margin: 0;`, so we need to display the whole thing in the code hint
453+
* Here, we also make sure that abbreviations which has `#`, `,` should not be included, because
454+
* * `color` expands to `color: #000;` or `color: rgb(0, 0, 0)`. So this actually has numbers, but we don't want to display this.
455+
*
456+
* @param {String} expandedAbbr the expanded abbr returned by EXPAND_ABBR emmet api
457+
* @returns {boolean} true if expandedAbbr has numbers (and doesn't include '#') otherwise false.
458+
*/
459+
function isEmmetAbbrNumeric(expandedAbbr) {
460+
return expandedAbbr.match(/\d/) !== null && !expandedAbbr.includes('#') && !expandedAbbr.includes(',');
461+
}
462+
463+
390464
const HISTORY_PREFIX = "Live_hint_";
391465
let hintSessionId = 0, isInLiveHighlightSession = false;
392466

0 commit comments

Comments
 (0)