-
Notifications
You must be signed in to change notification settings - Fork 7.5k
Collect Named CSS Region Flows #4890
Changes from all commits
3f4930c
439cf36
14ab7c6
4b77394
3002e4f
a3880e8
f31c4e1
884523d
3d4cf78
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,7 @@ | |
| */ | ||
|
|
||
|
|
||
| /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */ | ||
| /*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50, regexp: true */ | ||
| /*global define, $, CodeMirror, _parseRuleList: true */ | ||
|
|
||
| // JSLint Note: _parseRuleList() is cyclical dependency, not a global function. | ||
|
|
@@ -48,6 +48,11 @@ define(function (require, exports, module) { | |
| PROP_VALUE = "prop.value", | ||
| IMPORT_URL = "import.url"; | ||
|
|
||
| var RESERVED_FLOW_NAMES = ["content", "element"], | ||
| INVALID_FLOW_NAMES = ["none", "inherit", "default", "auto", "initial"], | ||
| IGNORED_FLOW_NAMES = RESERVED_FLOW_NAMES.concat(INVALID_FLOW_NAMES); | ||
|
|
||
|
|
||
| /** | ||
| * @private | ||
| * Checks if the current cursor position is inside the property name context | ||
|
|
@@ -501,7 +506,7 @@ define(function (require, exports, module) { | |
| declListStartChar: column in line where the declaration list for the rule starts | ||
| declListEndLine: line where the declaration list for the rule ends | ||
| declListEndChar: column in the line where the declaration list for the rule ends | ||
| * @param text {!String} CSS text to extract from | ||
| * @param text {!string} CSS text to extract from | ||
| * @return {Array.<Object>} Array with objects specifying selectors. | ||
| */ | ||
| function extractAllSelectors(text) { | ||
|
|
@@ -851,8 +856,8 @@ define(function (require, exports, module) { | |
| * jquery and ask what matches. If the node that the user's cursor is in comes back from jquery, then | ||
| * we know the selector applies. | ||
| * | ||
| * @param text {!String} CSS text to search | ||
| * @param selector {!String} selector to search for | ||
| * @param text {!string} CSS text to search | ||
| * @param selector {!string} selector to search for | ||
| * @return {Array.<{selectorGroupStartLine:number, declListEndLine:number, selector:string}>} | ||
| * Array of objects containing the start and end line numbers (0-based, inclusive range) for each | ||
| * matched selector. | ||
|
|
@@ -984,7 +989,7 @@ define(function (require, exports, module) { | |
| * div .foo .bar {} | ||
| * .foo.bar {} | ||
| * | ||
| * @param {!String} selector The selector to match. This can be a tag selector, class selector or id selector | ||
| * @param {!string} selector The selector to match. This can be a tag selector, class selector or id selector | ||
| * @param {?Document} htmlDocument An HTML file for context (so we can search <style> blocks) | ||
| * @return {$.Promise} that will be resolved with an Array of objects containing the | ||
| * source document, start line, and end line (0-based, inclusive range) for each matching declaration list. | ||
|
|
@@ -1115,10 +1120,71 @@ define(function (require, exports, module) { | |
| return _stripAtRules(selector); | ||
| } | ||
|
|
||
| /** | ||
| * removes CSS comments from the content | ||
| * @param {!string} content to reduce | ||
| * @return {string} reduced content | ||
| */ | ||
| function _removeComments(content) { | ||
| return content.replace(/\/\*(?:(?!\*\/)[\s\S])*\*\//g, ''); | ||
| } | ||
|
|
||
| /** | ||
| * removes strings from the content | ||
| * @param {!string} content to reduce | ||
| * @return {string} reduced content | ||
| */ | ||
| function _removeStrings(content) { | ||
| return content.replace(/[^\\]\"(.*)[^\\]\"|[^\\]\'(.*)[^\\]\'+/g, ''); | ||
| } | ||
|
|
||
| /** | ||
| * Reduces the style sheet by removing comments and strings | ||
| * so that the content can be parsed using a regular expression | ||
| * @param {!string} content to reduce | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need to add
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not clear about the use of This is confusing because There are valid times when undefined and null could mean different things so doesn't it also mean that type type cannot be null or undefined? JSDoc has It seems that a null parameter isn't one that was omitted and shouldn't be ignored so is isn't Anyway, this comment block was copied from another place in this same file so I assumed it was correct. There are many others like it throughout the codebase (in many, many files) It very well may not be the correct usage but at least it's consistent with the rest of the code so I think leave it for now. I will bring it up at the next architecture review, however, and see if anyone feels strongly about changing it.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see, the problem seems that http://usejsdoc.org/tags-type.html is a bit different than https://developers.google.com/closure/compiler/docs/js-for-compiler#types. According to the Google's JSDocs, functions, booleans, numbers, and strings are non-nullable by default. So if you say But it seems that usejsdoc.org, does not use this convention, so |
||
| * @return {string} reduced content | ||
| */ | ||
| function reduceStyleSheetForRegExParsing(content) { | ||
| return _removeStrings(_removeComments(content)); | ||
| } | ||
|
|
||
| /** | ||
| * Extracts all named flow instances | ||
| * @param {!string} text to extract from | ||
| * @return {Array.<string>} array of unique flow names found in the content (empty if none) | ||
| */ | ||
| function extractAllNamedFlows(text) { | ||
| var namedFlowRegEx = /(?:flow\-(into|from)\:\s*)([\w\-_]+)(?:\s*;)/gi, | ||
| result = [], | ||
| names = {}, | ||
| thisMatch; | ||
|
|
||
| // Reduce the content so that matches | ||
| // inside strings and comments are ignored | ||
| text = reduceStyleSheetForRegExParsing(text); | ||
|
|
||
| // Find the first match | ||
| thisMatch = namedFlowRegEx.exec(text); | ||
|
|
||
| // Iterate over the matches and add them to result | ||
| while (thisMatch) { | ||
| var thisName = thisMatch[2]; | ||
|
|
||
| if (IGNORED_FLOW_NAMES.indexOf(thisName) === -1 && !names.hasOwnProperty(thisName)) { | ||
| names[thisName] = result.push(thisName); | ||
| } | ||
| thisMatch = namedFlowRegEx.exec(text); | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
| exports._findAllMatchingSelectorsInText = _findAllMatchingSelectorsInText; // For testing only | ||
| exports.findMatchingRules = findMatchingRules; | ||
| exports.extractAllSelectors = extractAllSelectors; | ||
| exports.extractAllNamedFlows = extractAllNamedFlows; | ||
| exports.findSelectorAtDocumentPos = findSelectorAtDocumentPos; | ||
| exports.reduceStyleSheetForRegExParsing = reduceStyleSheetForRegExParsing; | ||
|
|
||
| exports.SELECTOR = SELECTOR; | ||
| exports.PROP_NAME = PROP_NAME; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| /* basic tests */ | ||
| article.content { | ||
| flow-into: main; | ||
| } | ||
|
|
||
| section.layout > div { | ||
| flow-from: main; | ||
| } | ||
|
|
||
|
|
||
| #jeff.content { | ||
| flow-into: jeff; | ||
| } | ||
|
|
||
| #jeff.layout > div { | ||
| flow-from: jeff; | ||
| } | ||
|
|
||
| /* exclude matches inside comments tests */ | ||
|
|
||
| /* | ||
| p.content { | ||
| flow-into: carter; | ||
| } | ||
|
|
||
| p.layout > div { | ||
| flow-from: carter; | ||
| } | ||
| */ | ||
|
|
||
| /* exclude matches inside strings tests */ | ||
|
|
||
| div { | ||
| content: "/* p.content { flow-into: carter; } p.layout > div { flow-from: carter; } */"; | ||
| } | ||
|
|
||
|
|
||
| div { | ||
| content: "html.content { flow-into: dexter; } html.layout > div { flow-from: dexter; }"; | ||
| } | ||
|
|
||
|
|
||
| /* | ||
| div.content { | ||
| content: "flow-into: martin;"; | ||
| } | ||
|
|
||
| div.layout > div { | ||
| content: "flow-from: martin;"; | ||
| } | ||
| */ | ||
|
|
||
| /* multi-line property tests */ | ||
|
|
||
| #randy.content { | ||
| flow-into: | ||
| randy | ||
| ; | ||
| } | ||
|
|
||
| #randy.layout > div { | ||
| flow-from: randy; | ||
| } | ||
|
|
||
| /* test to exclude duplicates */ | ||
| #yin.content { | ||
| flow-into: jeff; | ||
| } | ||
|
|
||
| #yin.layout > div { | ||
| flow-from: jeff; | ||
| } | ||
|
|
||
| /* flow-from only tests */ | ||
| #raymond.layout > div { | ||
| flow-from: lim; | ||
| } | ||
|
|
||
| /* underscores and dashes */ | ||
| #ingo.content { | ||
| flow-from: edge-code_now_shipping; | ||
| } | ||
|
|
||
| /* invalid / ignored flows */ | ||
| #test364.content { | ||
| flow-from: default; | ||
| flow-from: none; | ||
| flow-from: inherit; | ||
| flow-from: auto; | ||
| flow-from: initial; | ||
| flow-from: content; | ||
| flow-from: element; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: We use double-quotes for strings. So the second argument should be "". Same for the one on line 1124.