diff --git a/src/extensions/default/QuickView/main.js b/src/extensions/default/QuickView/main.js index 302cded10ab..01c252c7513 100644 --- a/src/extensions/default/QuickView/main.js +++ b/src/extensions/default/QuickView/main.js @@ -49,7 +49,8 @@ define(function (require, exports, module) { $previewContainer, // Preview container $previewContent, // Preview content holder lastMousePos, // Last mouse position - animationRequest; // Request for animation frame + animationRequest, // Request for animation frame + extensionlessImagePreview; // Whether to try and preview extensionless URLs // Constants var CMD_ENABLE_QUICK_VIEW = "view.enableQuickView", @@ -61,6 +62,9 @@ define(function (require, exports, module) { prefs = PreferencesManager.getExtensionPrefs("quickview"); prefs.definePreference("enabled", "boolean", true); + // Whether or not to try and show image previews for URLs missing extensions + // (e.g., https://avatars2.githubusercontent.com/u/476009?v=3&s=200) + prefs.definePreference("extensionlessImagePreview", "boolean", true); /** * There are three states for this var: @@ -472,14 +476,17 @@ define(function (require, exports, module) { // Use this URL if this is an absolute URL and either points to a // filename with a known image extension, or lacks an extension (e.g., - // a web service that returns an image). - if (hasProtocol && (isImage || !ext)) { + // a web service that returns an image). Honour the extensionlessImagePreview + // preference as well in the latter case. + if (hasProtocol && (isImage || (!ext && extensionlessImagePreview))) { imgPath = tokenString; } // Use this filename if this is a path with a known image extension. else if (!hasProtocol && isImage) { imgPath = "file:///" + FileUtils.getDirectoryPath(docPath) + tokenString; - } else { + } + + if (!imgPath) { return null; } @@ -536,7 +543,6 @@ define(function (require, exports, module) { * Lacks only hoverTimer (supplied by handleMouseMove()) and marker (supplied by showPreview()). */ function queryPreviewProviders(editor, pos, token) { - var line = editor.document.getLine(pos.line); // FUTURE: Support plugin providers. For now we just hard-code... @@ -733,6 +739,14 @@ define(function (require, exports, module) { CommandManager.get(CMD_ENABLE_QUICK_VIEW).setChecked(enabled); } + function setExtensionlessImagePreview(_extensionlessImagePreview) { + if(extensionlessImagePreview !== _extensionlessImagePreview) { + extensionlessImagePreview = _extensionlessImagePreview; + prefs.set("extensionlessImagePreview", enabled); + prefs.save(); + } + } + function setEnabled(_enabled, doNotSave) { if (enabled !== _enabled) { enabled = _enabled; @@ -800,10 +814,15 @@ define(function (require, exports, module) { // Setup initial UI state setEnabled(prefs.get("enabled"), true); + setExtensionlessImagePreview(prefs.get("extensionlessImagePreview")); prefs.on("change", "enabled", function () { setEnabled(prefs.get("enabled"), true); }); + + prefs.on("change", "extensionlessImagePreview", function () { + setExtensionlessImagePreview(prefs.get("extensionlessImagePreview")); + }); // For unit testing exports._queryPreviewProviders = queryPreviewProviders; diff --git a/src/extensions/default/QuickView/unittest-files/test.css b/src/extensions/default/QuickView/unittest-files/test.css index 9324dd21172..b40c2ffc0d4 100644 --- a/src/extensions/default/QuickView/unittest-files/test.css +++ b/src/extensions/default/QuickView/unittest-files/test.css @@ -190,3 +190,34 @@ background: -ms-linear-gradient(top, #d2dfed 0%,#c8d7eb 26%,#bed0ea 51%,#a6c0e3 background-image: linear-gradient(to bottom, #333, #CCC; background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(51,51,51)), to(rgb(204,204,204)); } + +.good-preview-image-urls { + background: "http://example.com/image.gif"; + background: "http://example.com/image.png"; + background: "http://example.com/image.jpe"; + background: "http://example.com/image.jpeg"; + background: "http://example.com/image.jpg"; + background: "http://example.com/image.ico"; + background: "http://example.com/image.bmp"; + background: "http://example.com/image.svg"; + + background: "https://image.service.com/id/1234513"; + background: "http://image.service.com/id/1234513"; + background: "https://image.service.com/id/1234513?w=300&h=400"; +} + +.ignored-preview-image-urls { + background: "https://website.com/index.html"; + background: "https://website.com/style.css"; + background: "https://website.com/script.js"; + background: "https://website.com/package.json"; + background: "https://website.com/readme.md"; + background: "https://website.com/data.xml"; + background: "https://website.com/music.mp3"; + background: "https://website.com/video.ogv"; + background: "https://website.com/video.mp4"; + background: "https://website.com/video.mpeg"; + background: "https://website.com/video.webm"; + background: "https://website.com/archive.zip"; + background: "https://website.com/archive.tgz"; +} diff --git a/src/extensions/default/QuickView/unittests.js b/src/extensions/default/QuickView/unittests.js index 39c78518cab..261b7dd52bf 100644 --- a/src/extensions/default/QuickView/unittests.js +++ b/src/extensions/default/QuickView/unittests.js @@ -27,8 +27,10 @@ define(function (require, exports, module) { "use strict"; - var SpecRunnerUtils = brackets.getModule("spec/SpecRunnerUtils"), - FileUtils = brackets.getModule("file/FileUtils"); + var SpecRunnerUtils = brackets.getModule("spec/SpecRunnerUtils"), + FileUtils = brackets.getModule("file/FileUtils"), + PreferencesManager = brackets.getModule("preferences/PreferencesManager"), + prefs = PreferencesManager.getExtensionPrefs("quickview"); describe("Quick View", function () { var testFolder = FileUtils.getNativeModuleDirectoryPath(module) + "/unittest-files/"; @@ -472,6 +474,57 @@ define(function (require, exports, module) { checkImagePathAtPos("img/don't.png", 184, 26); // url("") containing ' checkImageDataAtPos("data:image/svg+xml;utf8, ", 185, 26); // data url("") containing ' }); + + it("Should show image preview for URLs with known image extensions", function() { + checkImageDataAtPos("http://example.com/image.gif", 194, 20); + checkImageDataAtPos("http://example.com/image.png", 195, 20); + checkImageDataAtPos("http://example.com/image.jpe", 196, 20); + checkImageDataAtPos("http://example.com/image.jpeg", 197, 20); + checkImageDataAtPos("http://example.com/image.jpg", 198, 20); + checkImageDataAtPos("http://example.com/image.ico", 199, 20); + checkImageDataAtPos("http://example.com/image.bmp", 200, 20); + checkImageDataAtPos("http://example.com/image.svg", 201, 20); + }); + + it("Should show image preview for extensionless URLs (with protocol) with pref set", function() { + // Flip the pref on and restore when done + var original = prefs.get("extensionlessImagePreview"); + prefs.set("extensionlessImagePreview", true); + + checkImageDataAtPos("https://image.service.com/id/1234513", 203, 20); // https + checkImageDataAtPos("http://image.service.com/id/1234513", 204, 20); // http + checkImageDataAtPos("https://image.service.com/id/1234513?w=300&h=400", 205, 20); // qs params + + prefs.set("extensionlessImagePreview", original); + }); + + it("Should not show image preview for extensionless URLs (with protocol) without pref set", function() { + // Flip the pref off and restore when done + var original = prefs.get("extensionlessImagePreview"); + prefs.set("extensionlessImagePreview", false); + + checkImageDataAtPos("https://image.service.com/id/1234513", 203, 20); // https + checkImageDataAtPos("http://image.service.com/id/1234513", 204, 20); // http + checkImageDataAtPos("https://image.service.com/id/1234513?w=300&h=400", 205, 20); // qs params + + prefs.set("extensionlessImagePreview", original); + }); + + it("Should ignore URLs for common non-image extensions", function() { + expectNoPreviewAtPos(209, 20); // .html + expectNoPreviewAtPos(210, 20); // .css + expectNoPreviewAtPos(211, 20); // .js + expectNoPreviewAtPos(212, 20); // .json + expectNoPreviewAtPos(213, 20); // .md + expectNoPreviewAtPos(214, 20); // .xml + expectNoPreviewAtPos(215, 20); // .mp3 + expectNoPreviewAtPos(216, 20); // .ogv + expectNoPreviewAtPos(217, 20); // .mp4 + expectNoPreviewAtPos(218, 20); // .mpeg + expectNoPreviewAtPos(219, 20); // .webm + expectNoPreviewAtPos(220, 20); // .zip + expectNoPreviewAtPos(221, 20); // .tgz + }); it("Should show image preview for a data URI inside url()", function () { runs(function () {