зеркало из https://github.com/mozilla/gecko-dev.git
Bug 677930 - Style Inspector: make URLs clickable.
This commit is contained in:
Родитель
c094610e66
Коммит
71085f2b8c
|
@ -744,6 +744,24 @@ CssLogic.isContentStylesheet = function CssLogic_isContentStylesheet(aSheet)
|
|||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a source for a stylesheet, taking into account embedded stylesheets
|
||||
* for which we need to use document.defaultView.location.href rather than
|
||||
* sheet.href
|
||||
*
|
||||
* @param {CSSStyleSheet} aSheet the DOM object for the style sheet.
|
||||
* @return {string} the address of the stylesheet.
|
||||
*/
|
||||
CssLogic.href = function CssLogic_href(aSheet)
|
||||
{
|
||||
let href = aSheet.href;
|
||||
if (!href) {
|
||||
href = aSheet.ownerNode.ownerDocument.location;
|
||||
}
|
||||
|
||||
return href;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a shortened version of a style sheet's source.
|
||||
*
|
||||
|
@ -927,21 +945,17 @@ CssSheet.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Get a source for a stylesheet, taking into account embedded stylesheets
|
||||
* for which we need to use document.defaultView.location.href rather than
|
||||
* sheet.href
|
||||
* Get a source for a stylesheet, using CssLogic.href
|
||||
*
|
||||
* @return {string} the address of the stylesheet.
|
||||
*/
|
||||
get href()
|
||||
{
|
||||
if (!this._href) {
|
||||
this._href = this.domSheet.href;
|
||||
if (!this._href) {
|
||||
this._href = this.domSheet.ownerNode.ownerDocument.location;
|
||||
}
|
||||
if (this._href) {
|
||||
return this._href;
|
||||
}
|
||||
|
||||
this._href = CssLogic.href(this.domSheet);
|
||||
return this._href;
|
||||
},
|
||||
|
||||
|
|
|
@ -24,6 +24,12 @@ const CSS_LINE_RE = /(?:[^;\(]*(?:\([^\)]*?\))?[^;\(]*)*;?/g;
|
|||
// Used to parse a single property line.
|
||||
const CSS_PROP_RE = /\s*([^:\s]*)\s*:\s*(.*?)\s*(?:! (important))?;?$/;
|
||||
|
||||
// Used to parse an external resource from a property value
|
||||
const CSS_RESOURCE_RE = /url\([\'\"]?(.*?)[\'\"]?\)/;
|
||||
|
||||
const IOService = Components.classes["@mozilla.org/network/io-service;1"]
|
||||
.getService(Components.interfaces.nsIIOService);
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/devtools/CssLogic.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
@ -1321,6 +1327,12 @@ function TextPropertyEditor(aRuleEditor, aProperty)
|
|||
this.prop = aProperty;
|
||||
this.prop.editor = this;
|
||||
|
||||
let sheet = this.prop.rule.sheet;
|
||||
let href = sheet ? CssLogic.href(sheet) : null;
|
||||
if (href) {
|
||||
this.sheetURI = IOService.newURI(href, null, null);
|
||||
}
|
||||
|
||||
this._onEnableClicked = this._onEnableClicked.bind(this);
|
||||
this._onExpandClicked = this._onExpandClicked.bind(this);
|
||||
this._onStartEditing = this._onStartEditing.bind(this);
|
||||
|
@ -1436,6 +1448,36 @@ TextPropertyEditor.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Resolve a URI based on the rule stylesheet
|
||||
* @param {string} relativePath the path to resolve
|
||||
* @return {string} the resolved path.
|
||||
*/
|
||||
resolveURI: function(relativePath)
|
||||
{
|
||||
if (this.sheetURI) {
|
||||
relativePath = this.sheetURI.resolve(relativePath);
|
||||
}
|
||||
return relativePath;
|
||||
},
|
||||
|
||||
/**
|
||||
* Check the property value to find an external resource (if any).
|
||||
* @return {string} the URI in the property value, or null if there is no match.
|
||||
*/
|
||||
getResourceURI: function()
|
||||
{
|
||||
let val = this.prop.value;
|
||||
let uriMatch = CSS_RESOURCE_RE.exec(val);
|
||||
let uri = null;
|
||||
|
||||
if (uriMatch && uriMatch[1]) {
|
||||
uri = uriMatch[1];
|
||||
}
|
||||
|
||||
return uri;
|
||||
},
|
||||
|
||||
/**
|
||||
* Populate the span based on changes to the TextProperty.
|
||||
*/
|
||||
|
@ -1464,7 +1506,32 @@ TextPropertyEditor.prototype = {
|
|||
if (this.prop.priority) {
|
||||
val += " !" + this.prop.priority;
|
||||
}
|
||||
this.valueSpan.textContent = val;
|
||||
|
||||
// Treat URLs differently than other properties.
|
||||
// Allow the user to click a link to the resource and open it.
|
||||
let resourceURI = this.getResourceURI();
|
||||
if (resourceURI) {
|
||||
this.valueSpan.textContent = "";
|
||||
|
||||
appendText(this.valueSpan, val.split(resourceURI)[0]);
|
||||
|
||||
let a = createChild(this.valueSpan, "a", {
|
||||
target: "_blank",
|
||||
class: "theme-link",
|
||||
textContent: resourceURI,
|
||||
href: this.resolveURI(resourceURI)
|
||||
});
|
||||
|
||||
a.addEventListener("click", function(aEvent) {
|
||||
// Clicks within the link shouldn't trigger editing.
|
||||
aEvent.stopPropagation();
|
||||
}, false);
|
||||
|
||||
appendText(this.valueSpan, val.split(resourceURI)[1]);
|
||||
} else {
|
||||
this.valueSpan.textContent = val;
|
||||
}
|
||||
|
||||
this.warning.hidden = this._validate();
|
||||
|
||||
let store = this.prop.rule.elementStyle.store;
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.ruleview-propertycontainer a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ruleview-computedlist:not(.styleinspector-open),
|
||||
.ruleview-warning[hidden] {
|
||||
display: none;
|
||||
|
|
|
@ -37,6 +37,7 @@ MOCHITEST_BROWSER_FILES = \
|
|||
browser_bug722691_rule_view_increment.js \
|
||||
browser_computedview_734259_style_editor_link.js \
|
||||
browser_computedview_copy.js\
|
||||
browser_styleinspector_bug_677930_urls_clickable.js \
|
||||
head.js \
|
||||
$(NULL)
|
||||
|
||||
|
@ -50,6 +51,10 @@ MOCHITEST_BROWSER_FILES += \
|
|||
browser_bug705707_is_content_stylesheet.xul \
|
||||
browser_bug705707_is_content_stylesheet_xul.css \
|
||||
browser_bug722196_identify_media_queries.html \
|
||||
browser_styleinspector_bug_677930_urls_clickable.html \
|
||||
browser_styleinspector_bug_677930_urls_clickable \
|
||||
browser_styleinspector_bug_677930_urls_clickable/browser_styleinspector_bug_677930_urls_clickable.css \
|
||||
test-image.png \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<html>
|
||||
<head>
|
||||
|
||||
<link href="./browser_styleinspector_bug_677930_urls_clickable/browser_styleinspector_bug_677930_urls_clickable.css" rel="stylesheet" type="text/css">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="relative">Background image with relative path (loaded from external css)</div>
|
||||
|
||||
<div class="absolute">Background image with absolute path (loaded from external css)</div>
|
||||
|
||||
<div class="base64">Background image with base64 url (loaded from external css)</div>
|
||||
|
||||
<div class="inline" style="background: url(test-image.png);">Background image with relative path (loaded from style attribute)</div>';
|
||||
|
||||
<div class="noimage">No background image :(</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,97 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests to make sure that URLs are clickable in the rule view
|
||||
|
||||
let doc;
|
||||
let computedView;
|
||||
let inspector;
|
||||
|
||||
const BASE_URL = "http://example.com/browser/browser/" +
|
||||
"devtools/styleinspector/test/";
|
||||
const TEST_URI = BASE_URL +
|
||||
"browser_styleinspector_bug_677930_urls_clickable.html";
|
||||
const TEST_IMAGE = BASE_URL + "test-image.png";
|
||||
const BASE_64_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
|
||||
|
||||
function createDocument()
|
||||
{
|
||||
doc.title = "Style Inspector URL Clickable test";
|
||||
|
||||
openInspector(function(aInspector) {
|
||||
inspector = aInspector;
|
||||
executeSoon(selectNode);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function selectNode(aInspector)
|
||||
{
|
||||
let sidebar = inspector.sidebar;
|
||||
let iframe = sidebar._tabbox.querySelector(".iframe-ruleview");
|
||||
let contentDoc = iframe.contentWindow.document;
|
||||
|
||||
let relative = doc.querySelector(".relative");
|
||||
let absolute = doc.querySelector(".absolute");
|
||||
let inline = doc.querySelector(".inline");
|
||||
let base64 = doc.querySelector(".base64");
|
||||
let noimage = doc.querySelector(".noimage");
|
||||
|
||||
ok(relative, "captain, we have the relative div");
|
||||
ok(absolute, "captain, we have the absolute div");
|
||||
ok(inline, "captain, we have the inline div");
|
||||
ok(base64, "captain, we have the base64 div");
|
||||
ok(noimage, "captain, we have the noimage div");
|
||||
|
||||
inspector.selection.setNode(relative);
|
||||
is(inspector.selection.node, relative, "selection matches the relative element");
|
||||
let relativeLink = contentDoc.querySelector(".ruleview-propertycontainer a");
|
||||
ok (relativeLink, "Link exists for relative node");
|
||||
ok (relativeLink.getAttribute("href"), TEST_IMAGE);
|
||||
|
||||
inspector.selection.setNode(absolute);
|
||||
is(inspector.selection.node, absolute, "selection matches the absolute element");
|
||||
let absoluteLink = contentDoc.querySelector(".ruleview-propertycontainer a");
|
||||
ok (absoluteLink, "Link exists for absolute node");
|
||||
ok (absoluteLink.getAttribute("href"), TEST_IMAGE);
|
||||
|
||||
inspector.selection.setNode(inline);
|
||||
is(inspector.selection.node, inline, "selection matches the inline element");
|
||||
let inlineLink = contentDoc.querySelector(".ruleview-propertycontainer a");
|
||||
ok (inlineLink, "Link exists for inline node");
|
||||
ok (inlineLink.getAttribute("href"), TEST_IMAGE);
|
||||
|
||||
inspector.selection.setNode(base64);
|
||||
is(inspector.selection.node, base64, "selection matches the base64 element");
|
||||
let base64Link = contentDoc.querySelector(".ruleview-propertycontainer a");
|
||||
ok (base64Link, "Link exists for base64 node");
|
||||
ok (base64Link.getAttribute("href"), BASE_64_URL);
|
||||
|
||||
inspector.selection.setNode(noimage);
|
||||
is(inspector.selection.node, noimage, "selection matches the inline element");
|
||||
let noimageLink = contentDoc.querySelector(".ruleview-propertycontainer a");
|
||||
ok (!noimageLink, "There is no link for the node with no background image");
|
||||
|
||||
finishUp();
|
||||
}
|
||||
|
||||
function finishUp()
|
||||
{
|
||||
doc = computedView = inspector = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
|
||||
gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
|
||||
doc = content.document;
|
||||
waitForFocus(createDocument, content);
|
||||
}, true);
|
||||
|
||||
content.location = TEST_URI;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
.relative {
|
||||
background-image: url(../test-image.png);
|
||||
}
|
||||
.absolute {
|
||||
background: url("http://example.com/browser/browser/devtools/styleinspector/test/test-image.png");
|
||||
}
|
||||
.base64 {
|
||||
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==');
|
||||
}
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 580 B |
Загрузка…
Ссылка в новой задаче