diff --git a/.gitignore b/.gitignore
index 2ef99613b67..4f56364e481 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,7 +54,6 @@ bootsnap-compile-cache/
!/plugins/discourse-narrative-bot
!/plugins/discourse-presence
!/plugins/discourse-local-dates
-!/plugins/discourse-unsupported-browser
/plugins/*/auto_generated/
/spec/fixtures/plugins/my_plugin/auto_generated
diff --git a/app/assets/javascripts/discourse/app/components/quote-button.js b/app/assets/javascripts/discourse/app/components/quote-button.js
index 8f7d464543b..2b932be2d67 100644
--- a/app/assets/javascripts/discourse/app/components/quote-button.js
+++ b/app/assets/javascripts/discourse/app/components/quote-button.js
@@ -97,7 +97,7 @@ export default Component.extend({
// on Desktop, shows the button at the beginning of the selection
// on Mobile, shows the button at the end of the selection
const isMobileDevice = this.site.isMobileDevice;
- const { isIOS, isAndroid, isSafari, isOpera, isIE11 } = this.capabilities;
+ const { isIOS, isAndroid, isSafari, isOpera } = this.capabilities;
const showAtEnd = isMobileDevice || isIOS || isAndroid || isOpera;
// Don't mess with the original range as it results in weird behaviours
@@ -125,10 +125,7 @@ export default Component.extend({
const parent = markerElement.parentNode;
parent.removeChild(markerElement);
// merge back all text nodes so they don't get messed up
- if (!isIE11) {
- // Skip this fix in IE11 - .normalize causes the selection to change
- parent.normalize();
- }
+ parent.normalize();
// work around Safari that would sometimes lose the selection
if (isSafari) {
diff --git a/app/assets/javascripts/discourse/app/initializers/copy-codeblocks.js b/app/assets/javascripts/discourse/app/initializers/copy-codeblocks.js
index f6fcef5e17e..3d8ee45ee7a 100644
--- a/app/assets/javascripts/discourse/app/initializers/copy-codeblocks.js
+++ b/app/assets/javascripts/discourse/app/initializers/copy-codeblocks.js
@@ -113,8 +113,7 @@ export default {
}
const siteSettings = container.lookup("site-settings:main");
- const { isIE11 } = container.lookup("capabilities:main");
- if (!siteSettings.show_copy_button_on_codeblocks || isIE11) {
+ if (!siteSettings.show_copy_button_on_codeblocks) {
return;
}
diff --git a/app/assets/javascripts/discourse/app/pre-initializers/sniff-capabilities.js b/app/assets/javascripts/discourse/app/pre-initializers/sniff-capabilities.js
index c8c35032ce2..a3a3f76153d 100644
--- a/app/assets/javascripts/discourse/app/pre-initializers/sniff-capabilities.js
+++ b/app/assets/javascripts/discourse/app/pre-initializers/sniff-capabilities.js
@@ -30,7 +30,6 @@ export default {
return p.toString() === "[object SafariRemoteNotification]";
})(!window["safari"] || safari.pushNotification);
caps.isChrome = !!window.chrome && !caps.isOpera;
- caps.isIE11 = !!ua.match(/Trident.*rv\:11\./);
caps.canPasteImages = caps.isChrome || caps.isFirefox;
}
diff --git a/app/assets/javascripts/polyfills.js b/app/assets/javascripts/polyfills.js
index 0fe25c8bdbc..5913ad0e5e2 100644
--- a/app/assets/javascripts/polyfills.js
+++ b/app/assets/javascripts/polyfills.js
@@ -1,7 +1,5 @@
/* eslint-disable */
-// Any IE only polyfill should be moved in discourse-unsupported-browser plugin
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/flags#Polyfill
// IE and EDGE
if (RegExp.prototype.flags === undefined) {
diff --git a/lib/plugin/metadata.rb b/lib/plugin/metadata.rb
index d2de1ffd63d..9f8eec74c51 100644
--- a/lib/plugin/metadata.rb
+++ b/lib/plugin/metadata.rb
@@ -75,7 +75,6 @@ class Plugin::Metadata
"docker_manager",
"lazy-yt",
"poll",
- "discourse-unsupported-browser",
"discourse-fontawesome-pro",
"discourse-staff-alias",
])
diff --git a/plugins/discourse-unsupported-browser/assets/javascripts/initializers/discourse-unsupported-browser.js.es6 b/plugins/discourse-unsupported-browser/assets/javascripts/initializers/discourse-unsupported-browser.js.es6
deleted file mode 100644
index 59cdbb15920..00000000000
--- a/plugins/discourse-unsupported-browser/assets/javascripts/initializers/discourse-unsupported-browser.js.es6
+++ /dev/null
@@ -1,24 +0,0 @@
-import I18n from "I18n";
-import { withPluginApi } from "discourse/lib/plugin-api";
-
-function initializeInternetExplorerDeprecation(api) {
- const siteSettings = api.container.lookup("site-settings:main");
- if (siteSettings.browser_deprecation_warning) {
- const { isIE11 } = api.container.lookup("capabilities:main");
- if (isIE11) {
- api.addGlobalNotice(
- I18n.t("discourse_unsupported_browser.deprecation_warning"),
- "browser-deprecation-warning",
- { dismissable: true, dismissDuration: moment.duration(1, "week") }
- );
- }
- }
-}
-
-export default {
- name: "discourse-unsupported-browser",
-
- initialize() {
- withPluginApi("0.8.37", initializeInternetExplorerDeprecation);
- }
-};
diff --git a/plugins/discourse-unsupported-browser/assets/stylesheets/ie.scss b/plugins/discourse-unsupported-browser/assets/stylesheets/ie.scss
deleted file mode 100644
index 00d91c889d2..00000000000
--- a/plugins/discourse-unsupported-browser/assets/stylesheets/ie.scss
+++ /dev/null
@@ -1,444 +0,0 @@
-@media screen and (max-width: 767px) {
- table.staff-logs tr {
- display: -ms-grid;
- -ms-grid-columns: 1fr 1fr 1fr 0.5fr;
- -ms-grid-rows: auto auto;
- td {
- display: -ms-grid;
- &.staff-users {
- -ms-grid-row: 1;
- -ms-grid-column: 1;
- -ms-grid-column-span: 2;
- }
- &.created-at {
- -ms-grid-row: 1;
- -ms-grid-column: 4;
- }
- &.action {
- -ms-grid-row: 2;
- -ms-grid-column: 1;
- }
- &.subject {
- -ms-grid-row: 2;
- -ms-grid-column: 2;
- -ms-grid-column-span: 3;
- }
- &.details {
- -ms-grid-row: 3;
- -ms-grid-column: 1;
- -ms-grid-column-span: 3;
- }
- &.context {
- -ms-grid-row: 4;
- -ms-grid-column: 1;
- -ms-grid-column-span: 3;
- }
- }
- }
-}
-
-// desktop/login.scss
-.d-modal.create-account {
- .login-form {
- form,
- table {
- display: block; //IE11
- }
- }
-}
-
-// common/admin/dashboard.scss
-.dashboard,
-.dashboard-next {
- .charts {
- display: -ms-grid;
- -ms-grid-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
- -ms-grid-rows: 1fr 1fr;
- .admin-report {
- -ms-grid-column-span: 4;
-
- &:nth-of-type(1) {
- -ms-grid-row: 1;
- -ms-grid-column: 1;
- }
- &:nth-of-type(2) {
- -ms-grid-row: 2;
- -ms-grid-column: 1;
- }
- &:nth-of-type(3) {
- -ms-grid-row: 2;
- -ms-grid-column: 5;
- }
- &:nth-of-type(4) {
- -ms-grid-row: 2;
- -ms-grid-column: 9;
- }
- &:nth-of-type(5) {
- -ms-grid-row: 3;
- -ms-grid-column: 1;
- }
- &:nth-of-type(6) {
- -ms-grid-row: 3;
- -ms-grid-column: 5;
- }
- &:nth-of-type(7) {
- -ms-grid-row: 3;
- -ms-grid-column: 9;
- }
- }
-
- .admin-report {
- &.consolidated-page-views {
- -ms-grid-column-span: 12;
- }
- }
- }
-}
-.counters-list {
- .counters-header {
- display: -ms-grid;
- -ms-grid-columns: 2fr 1fr 1fr 1fr 1fr;
- .counters-cell {
- -ms-grid-row: 1;
- -ms-grid-column-span: 1;
- &:nth-of-type(1) {
- -ms-grid-column: 1;
- }
- &:nth-of-type(2) {
- -ms-grid-column: 2;
- }
- &:nth-of-type(3) {
- -ms-grid-column: 3;
- }
- &:nth-of-type(4) {
- -ms-grid-column: 4;
- }
- &:nth-of-type(5) {
- -ms-grid-column: 5;
- }
- }
- }
-}
-
-// common/admin/api.scss
-table.web-hooks.grid {
- @media screen and (max-width: 767px) {
- tr {
- display: -ms-grid;
- -ms-grid-columns: 0.5fr 1fr 1fr 0.5fr;
- td {
- display: -ms-grid;
- &.delivery-status {
- -ms-grid-row: 1;
- -ms-grid-column: 1;
- }
- &.payload-url {
- -ms-grid-row: 1;
- -ms-grid-column: 2;
- }
- &.description {
- -ms-grid-row: 1;
- -ms-grid-column: 3;
- }
- &.controls {
- -ms-grid-row: 1;
- -ms-grid-column: 4;
- }
- }
- }
- }
-}
-table.api-keys {
- @media screen and (max-width: 767px) {
- tr {
- display: -ms-grid;
- -ms-grid-columns: 0.25fr 1fr 1fr;
- -ms-grid-rows: auto auto;
- td {
- display: -ms-grid;
-
- &.key {
- -ms-grid-row: 1;
- -ms-grid-column: 1;
- -ms-grid-column-span: 3;
- }
- &.key-user {
- -ms-grid-row: 2;
- -ms-grid-column: 1;
- }
- &.key-controls {
- -ms-grid-row: 2;
- -ms-grid-column: 2;
- -ms-grid-column-span: 2;
- display: -ms-grid;
- -ms-grid-columns: 125px 125px;
- button:first-of-type {
- -ms-grid-column: 1;
- }
- button:last-of-type {
- -ms-grid-column: 2;
- }
- }
- }
- }
- }
-}
-
-// common/admin/staff_logs.scss
-table.search-logs-list {
- @media screen and (max-width: 767px) {
- tr {
- display: -ms-grid;
- -ms-grid-columns: 1fr 1fr 1fr;
- -ms-grid-rows: auto 2em;
- td {
- display: -ms-grid;
- -ms-grid-rows: auto auto;
- .label {
- -ms-grid-row: 2;
- }
- &.term {
- -ms-grid-row: 1;
- -ms-grid-column: 1;
- -ms-grid-column-span: 3;
- }
- &.col:nth-of-type(2) {
- -ms-grid-row: 2;
- -ms-grid-column: 1;
- }
- &.col:nth-of-type(3) {
- -ms-grid-row: 2;
- -ms-grid-column: 2;
- }
- &.col:nth-of-type(4) {
- -ms-grid-row: 2;
- -ms-grid-column: 3;
- }
- }
- }
- }
-}
-
-// common/admin/admin_report_counters.scss
-.admin-report {
- .admin-report-counters {
- display: -ms-grid;
- -ms-grid-columns: 2fr 1fr 1fr 1fr 1fr;
- .cell {
- -ms-grid-row: 1;
- -ms-grid-column-span: 1;
-
- &:nth-of-type(1) {
- -ms-grid-column: 1;
- }
- &:nth-of-type(2) {
- -ms-grid-column: 2;
- }
- &:nth-of-type(3) {
- -ms-grid-column: 3;
- }
- &:nth-of-type(4) {
- -ms-grid-column: 4;
- }
- &:nth-of-type(5) {
- -ms-grid-column: 5;
- }
- }
- }
-}
-
-// common/admin/users.scss
-.admin-users-list {
- @media screen and (max-width: 767px) {
- tr.user {
- display: -ms-grid;
- -ms-grid-columns: 1fr 1fr 1fr;
- -ms-grid-rows: 2em 1fr 3em 3em;
- td {
- display: -ms-grid;
- -ms-grid-columns: 1fr;
- -ms-grid-rows: 1fr 1fr;
- .label {
- -ms-grid-row: 1;
- -ms-grid-column: 1;
- }
- div:not(.label) {
- -ms-grid-row: 2;
- -ms-grid-column: 1;
- align-self: center;
- }
- &.username {
- -ms-grid-row: 1;
- -ms-grid-column: 1;
- -ms-grid-column-span: 2;
- }
- &.user-status {
- -ms-grid-row: 1;
- -ms-grid-column: 3;
- }
- &.email {
- -ms-grid-row: 2;
- -ms-grid-column: 1;
- -ms-grid-column-span: 3;
- }
- &.last-emailed {
- -ms-grid-row: 3;
- -ms-grid-column: 1;
- }
- &.last-seen {
- -ms-grid-row: 3;
- -ms-grid-column: 2;
- }
- &.topics-entered {
- -ms-grid-row: 3;
- -ms-grid-column: 3;
- }
- &.posts-read {
- -ms-grid-row: 4;
- -ms-grid-column: 1;
- }
- &.time-read {
- -ms-grid-row: 4;
- -ms-grid-column: 2;
- }
- &.created {
- -ms-grid-row: 4;
- -ms-grid-column: 3;
- }
- }
- }
- }
-}
-
-// common/base/groups.scss
-.groups-boxes {
- display: flex;
- flex-wrap: wrap;
- justify-content: space-between;
-
- .group-box {
- flex: 1 1 24%;
- margin: 1%;
- }
-}
-
-// common/base/_topic-list.scss
-.list-controls {
- .combo-box .combo-box-header {
- height: 10px;
- }
-}
-.topic-list {
- .link-bottom-line {
- .discourse-tags {
- -ms-flex: 1 0 0px;
- }
- }
-}
-
-// common/base/user.scss
-.user-content-wrapper {
- display: -ms-grid;
- -ms-grid-columns: 1fr 5fr;
- -ms-grid-rows: auto auto 1fr auto;
- .user-primary-navigation {
- -ms-grid-row: 1;
- -ms-grid-column: 1;
- -ms-grid-column-span: 2;
- }
- .user-secondary-navigation {
- -ms-grid-row: 2;
- -ms-grid-column: 1;
- }
- .solo-preference,
- .user-content,
- .spinner {
- -ms-grid-row: 2;
- -ms-grid-column: 2;
- -ms-grid-column-span: 2;
- }
- .user-secondary-navigation + .user-content {
- -ms-grid-column: 2;
- -ms-grid-column-span: 1;
- }
- .user-additional-controls {
- -ms-grid-row: 3;
- -ms-grid-column-align: start;
- -ms-grid-row-align: start;
- }
-}
-.avatar-selector {
- .avatar-choice {
- display: -ms-grid;
- -ms-grid-columns: 2em 1fr auto;
- -ms-grid-rows: auto auto;
- input[type="radio"] {
- -ms-grid-row: 1;
- -ms-grid-column: 1;
- }
- label.radio {
- -ms-grid-row: 1;
- -ms-grid-column: 2;
- }
- span.avatar-uploader {
- -ms-grid-row: 1;
- -ms-grid-column: 3;
- }
- .error {
- -ms-grid-row: 2;
- -ms-grid-column-span: 3;
- }
- }
-}
-
-// common/base/topic-post.scss
-aside.quote {
- .title {
- padding: 12px 12px 1px 12px;
- }
-}
-
-// common/base/menu-panel.scss
-div.menu-links-header {
- .menu-links-row {
- li {
- &.glyphs {
- max-width: 65%;
- }
- }
- }
-}
-
-// common/base/header.scss
-.extra-info-wrapper {
- flex: 1 1 0%;
-
- .topic-header-extra {
- flex: 1 0 0%;
- min-width: 1px;
- }
-}
-
-// common/select-kit/dropdown-select-box.scss
-.select-kit {
- &.dropdown-select-box {
- .select-kit-row {
- .texts {
- width: 0;
-
- .desc {
- width: 100%;
- }
- }
- }
- }
-}
-
-// common/select-kit/category-row.scss
-.select-kit {
- .category-row {
- .category-desc {
- max-width: 100%;
- }
- }
-}
diff --git a/plugins/discourse-unsupported-browser/config/locales/client.en.yml b/plugins/discourse-unsupported-browser/config/locales/client.en.yml
deleted file mode 100644
index fca8ed0b1e4..00000000000
--- a/plugins/discourse-unsupported-browser/config/locales/client.en.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-en:
- js:
- discourse_unsupported_browser:
- deprecation_warning: This site will soon remove support for Internet Explorer 11 - please update your browser
diff --git a/plugins/discourse-unsupported-browser/config/locales/server.en.yml b/plugins/discourse-unsupported-browser/config/locales/server.en.yml
deleted file mode 100644
index aa0ed026bc3..00000000000
--- a/plugins/discourse-unsupported-browser/config/locales/server.en.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-en:
- site_settings:
- discourse_unsupported_browser_enabled: "Enable temporary support for old browsers. This plugin is an effort to maintain compatibility with older browsers and will be completely removed in the near future."
- browser_deprecation_warning: "Show a warning to deprecated browsers"
diff --git a/plugins/discourse-unsupported-browser/config/settings.yml b/plugins/discourse-unsupported-browser/config/settings.yml
deleted file mode 100644
index 6536eeac8b2..00000000000
--- a/plugins/discourse-unsupported-browser/config/settings.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-plugins:
- discourse_unsupported_browser_enabled:
- default: false
- hidden: true
- browser_deprecation_warning:
- default: true
- client: true
diff --git a/plugins/discourse-unsupported-browser/plugin.rb b/plugins/discourse-unsupported-browser/plugin.rb
deleted file mode 100644
index c27d4420903..00000000000
--- a/plugins/discourse-unsupported-browser/plugin.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-# name: discourse-unsupported-browser
-# about: Attempts to provide support for old and unsupported browser through polyfills
-# version: 1.0
-# authors: Joffrey Jaffeux, David Taylor, Daniel Waterworth, Robin Ward
-# url: https://github.com/discourse/discourse/tree/master/plugins/discourse-unsupported-browser
-
-enabled_site_setting :discourse_unsupported_browser_enabled
-hide_plugin if self.respond_to?(:hide_plugin)
-
-register_asset 'stylesheets/ie.scss'
-
-# We can't use register asset for an optional resource. Instead copy it after plugins have
-# been activated so it can be uploaded to CDNs.
-DiscourseEvent.on(:after_plugin_activation) do ||
- polyfill_path = "#{Plugin::Instance.js_path}/#{self.directory_name}-optional.js"
- FileUtils.cp("#{Rails.root}/public/plugins/discourse-unsupported-browser/js/ie.js", polyfill_path)
- Rails.configuration.assets.precompile << "plugins/discourse-unsupported-browser-optional.js"
-end
-
-after_initialize do
- # Conditionally load the stylesheet
- register_asset_filter do |type, request|
- request.nil? || request.env['HTTP_USER_AGENT'] =~ /MSIE|Trident/
- end
-
- register_anonymous_cache_key(:ie) do
- unless defined?(@is_ie)
- session = @env[self.class::RACK_SESSION]
- # don't initialize params until later
- # otherwise you get a broken params on the request
- params = {}
-
- @is_ie = BrowserDetection.browser(@env[self.class::USER_AGENT]) == :ie
- end
-
- @is_ie
- end
-
- # not using patch on preload_script as js is fine and we need this file
- # to be loaded before other files
- register_html_builder('server:before-script-load') do |controller|
- if BrowserDetection.browser(controller.request.env['HTTP_USER_AGENT']) == :ie
- path = controller.helpers.script_asset_path('plugins/discourse-unsupported-browser-optional')
-
- <<~JAVASCRIPT
-
- JAVASCRIPT
- end
- end
-end
diff --git a/plugins/discourse-unsupported-browser/public/js/ie.js b/plugins/discourse-unsupported-browser/public/js/ie.js
deleted file mode 100644
index 168731d5ffb..00000000000
--- a/plugins/discourse-unsupported-browser/public/js/ie.js
+++ /dev/null
@@ -1,984 +0,0 @@
-/* eslint-disable */
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
-if (!Object.entries) {
- Object.entries = function(obj) {
- var ownProps = Object.keys(obj),
- i = ownProps.length,
- resArray = new Array(i); // preallocate the Array
- while (i--) resArray[i] = [ownProps[i], obj[ownProps[i]]];
-
- return resArray;
- };
-}
-
-// adapted from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
-// missing in ie only
-if (!Object.values) {
- Object.values = function(obj) {
- var ownProps = Object.keys(obj),
- i = ownProps.length,
- resArray = new Array(i); // preallocate the Array
- while (i--) resArray[i] = obj[ownProps[i]];
-
- return resArray;
- };
-}
-
-// https://developer.mozilla.org/fr/docs/Web/API/NodeList/forEach
-if (window.NodeList && !NodeList.prototype.forEach) {
- NodeList.prototype.forEach = function(callback, thisArg) {
- thisArg = thisArg || window;
- for (var i = 0; i < this.length; i++) {
- callback.call(thisArg, this[i], i, this);
- }
- };
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes#Polyfill
-if (!Array.prototype.includes) {
- Object.defineProperty(Array.prototype, "includes", {
- value: function(searchElement, fromIndex) {
- if (this == null) {
- throw new TypeError('"this" is null or not defined');
- }
-
- // 1. Let O be ? ToObject(this value).
- var o = Object(this);
-
- // 2. Let len be ? ToLength(? Get(O, "length")).
- var len = o.length >>> 0;
-
- // 3. If len is 0, return false.
- if (len === 0) {
- return false;
- }
-
- // 4. Let n be ? ToInteger(fromIndex).
- // (If fromIndex is undefined, this step produces the value 0.)
- var n = fromIndex | 0;
-
- // 5. If n ≥ 0, then
- // a. Let k be n.
- // 6. Else n < 0,
- // a. Let k be len + n.
- // b. If k < 0, let k be 0.
- var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
-
- function sameValueZero(x, y) {
- return (
- x === y ||
- (typeof x === "number" &&
- typeof y === "number" &&
- isNaN(x) &&
- isNaN(y))
- );
- }
-
- // 7. Repeat, while k < len
- while (k < len) {
- // a. Let elementK be the result of ? Get(O, ! ToString(k)).
- // b. If SameValueZero(searchElement, elementK) is true, return true.
- if (sameValueZero(o[k], searchElement)) {
- return true;
- }
- // c. Increase k by 1.
- k++;
- }
-
- // 8. Return false
- return false;
- }
- });
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes#Polyfill
-if (!String.prototype.includes) {
- Object.defineProperty(String.prototype, "includes", {
- value: function(search, start) {
- if (typeof start !== "number") {
- start = 0;
- }
-
- if (start + search.length > this.length) {
- return false;
- } else {
- return this.indexOf(search, start) !== -1;
- }
- }
- });
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
-if (!Array.prototype.find) {
- Object.defineProperty(Array.prototype, "find", {
- value: function(predicate) {
- // 1. Let O be ? ToObject(this value).
- if (this == null) {
- throw new TypeError('"this" is null or not defined');
- }
-
- var o = Object(this);
-
- // 2. Let len be ? ToLength(? Get(O, "length")).
- var len = o.length >>> 0;
-
- // 3. If IsCallable(predicate) is false, throw a TypeError exception.
- if (typeof predicate !== "function") {
- throw new TypeError("predicate must be a function");
- }
-
- // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
- var thisArg = arguments[1];
-
- // 5. Let k be 0.
- var k = 0;
-
- // 6. Repeat, while k < len
- while (k < len) {
- // a. Let Pk be ! ToString(k).
- // b. Let kValue be ? Get(O, Pk).
- // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
- // d. If testResult is true, return kValue.
- var kValue = o[k];
- if (predicate.call(thisArg, kValue, k, o)) {
- return kValue;
- }
- // e. Increase k by 1.
- k++;
- }
-
- // 7. Return undefined.
- return undefined;
- },
- configurable: true,
- writable: true
- });
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
-// Production steps of ECMA-262, Edition 6, 22.1.2.1
-if (!Array.from) {
- Array.from = (function() {
- var toStr = Object.prototype.toString;
- var isCallable = function(fn) {
- return typeof fn === "function" || toStr.call(fn) === "[object Function]";
- };
- var toInteger = function(value) {
- var number = Number(value);
- if (isNaN(number)) {
- return 0;
- }
- if (number === 0 || !isFinite(number)) {
- return number;
- }
- return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
- };
- var maxSafeInteger = Math.pow(2, 53) - 1;
- var toLength = function(value) {
- var len = toInteger(value);
- return Math.min(Math.max(len, 0), maxSafeInteger);
- };
-
- // The length property of the from method is 1.
- return function from(arrayLike /*, mapFn, thisArg */) {
- // 1. Let C be the this value.
- var C = this;
-
- // 2. Let items be ToObject(arrayLike).
- var items = Object(arrayLike);
-
- // 3. ReturnIfAbrupt(items).
- if (arrayLike == null) {
- throw new TypeError(
- "Array.from requires an array-like object - not null or undefined"
- );
- }
-
- // 4. If mapfn is undefined, then let mapping be false.
- var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
- var T;
- if (typeof mapFn !== "undefined") {
- // 5. else
- // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
- if (!isCallable(mapFn)) {
- throw new TypeError(
- "Array.from: when provided, the second argument must be a function"
- );
- }
-
- // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
- if (arguments.length > 2) {
- T = arguments[2];
- }
- }
-
- // 10. Let lenValue be Get(items, "length").
- // 11. Let len be ToLength(lenValue).
- var len = toLength(items.length);
-
- // 13. If IsConstructor(C) is true, then
- // 13. a. Let A be the result of calling the [[Construct]] internal method
- // of C with an argument list containing the single item len.
- // 14. a. Else, Let A be ArrayCreate(len).
- var A = isCallable(C) ? Object(new C(len)) : new Array(len);
-
- // 16. Let k be 0.
- var k = 0;
- // 17. Repeat, while k < len… (also steps a - h)
- var kValue;
- while (k < len) {
- kValue = items[k];
- if (mapFn) {
- A[k] =
- typeof T === "undefined"
- ? mapFn(kValue, k)
- : mapFn.call(T, kValue, k);
- } else {
- A[k] = kValue;
- }
- k += 1;
- }
- // 18. Let putStatus be Put(A, "length", len, true).
- A.length = len;
- // 20. Return A.
- return A;
- };
- })();
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
-if (typeof Object.assign !== "function") {
- // Must be writable: true, enumerable: false, configurable: true
- Object.defineProperty(Object, "assign", {
- value: function assign(target) {
- // .length of function is 2
- "use strict";
- if (target == null) {
- // TypeError if undefined or null
- throw new TypeError("Cannot convert undefined or null to object");
- }
-
- var to = Object(target);
-
- for (var index = 1; index < arguments.length; index++) {
- var nextSource = arguments[index];
-
- if (nextSource != null) {
- // Skip over if undefined or null
- for (var nextKey in nextSource) {
- // Avoid bugs when hasOwnProperty is shadowed
- if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
- to[nextKey] = nextSource[nextKey];
- }
- }
- }
- }
- return to;
- },
- writable: true,
- configurable: true
- });
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat#Polyfill
-if (!String.prototype.repeat) {
- String.prototype.repeat = function(count) {
- "use strict";
- if (this == null)
- throw new TypeError("can't convert " + this + " to object");
-
- var str = "" + this;
- // To convert string to integer.
- count = +count;
- // Check NaN
- if (count != count) count = 0;
-
- if (count < 0) throw new RangeError("repeat count must be non-negative");
-
- if (count == Infinity)
- throw new RangeError("repeat count must be less than infinity");
-
- count = Math.floor(count);
- if (str.length == 0 || count == 0) return "";
-
- // Ensuring count is a 31-bit integer allows us to heavily optimize the
- // main part. But anyway, most current (August 2014) browsers can't handle
- // strings 1 << 28 chars or longer, so:
- if (str.length * count >= 1 << 28)
- throw new RangeError(
- "repeat count must not overflow maximum string size"
- );
-
- var maxCount = str.length * count;
- count = Math.floor(Math.log(count) / Math.log(2));
- while (count) {
- str += str;
- count--;
- }
- str += str.substring(0, maxCount - str.length);
- return str;
- };
-}
-
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith#Polyfill
-if (!String.prototype.startsWith) {
- Object.defineProperty(String.prototype, "startsWith", {
- value: function(search, rawPos) {
- var pos = rawPos > 0 ? rawPos | 0 : 0;
- return this.substring(pos, pos + search.length) === search;
- }
- });
-}
-
-/*!
- * Symbol-ES6 v0.1.2
- * ES6 Symbol polyfill in pure ES5.
- *
- * @license Copyright (c) 2017-2018 Rousan Ali, MIT License
- *
- * Codebase: https://github.com/rousan/symbol-es6
- * Date: 28th Jan, 2018
- */
-
-(function(global, factory) {
- "use strict";
-
- if (typeof module === "object" && typeof module.exports === "object") {
- // For the environment like NodeJS, CommonJS etc where module or
- // module.exports objects are available
- module.exports = factory(global);
- } else {
- // For browser context, where global object is window
- factory(global);
- }
-
- /* window is for browser environment and global is for NodeJS environment */
-})(typeof window !== "undefined" ? window : global, function(global) {
- "use strict";
-
- var defineProperty = Object.defineProperty;
-
- var defineProperties = Object.defineProperties;
-
- var symbolHiddenCounter = 0;
-
- var globalSymbolRegistry = [];
-
- var slice = Array.prototype.slice;
-
- var ES6 = typeof global.ES6 === "object" ? global.ES6 : (global.ES6 = {});
-
- var isArray = Array.isArray;
-
- var objectToString = Object.prototype.toString;
-
- var push = Array.prototype.push;
-
- var emptyFunction = function() {};
-
- var simpleFunction = function(arg) {
- return arg;
- };
-
- var isCallable = function(fn) {
- return typeof fn === "function";
- };
-
- var isConstructor = function(fn) {
- return isCallable(fn);
- };
-
- var Iterator = function() {};
-
- var ArrayIterator = function ArrayIterator(array, flag) {
- this._array = array;
- this._flag = flag;
- this._nextIndex = 0;
- };
-
- var StringIterator = function StringIterator(string, flag) {
- this._string = string;
- this._flag = flag;
- this._nextIndex = 0;
- };
-
- var isES6Running = function() {
- return false; /* Now 'false' for testing purpose */
- };
-
- var isObject = function(value) {
- return (
- value !== null &&
- (typeof value === "object" || typeof value === "function")
- );
- };
-
- var es6FunctionPrototypeHasInstanceSymbol = function(instance) {
- if (typeof this !== "function") return false;
- return instance instanceof this;
- };
-
- var es6InstanceOfOperator = function(object, constructor) {
- if (!isObject(constructor))
- throw new TypeError("Right-hand side of 'instanceof' is not an object");
-
- var hasInstanceSymbolProp = constructor[Symbol.hasInstance];
- if (typeof hasInstanceSymbolProp === "undefined") {
- return object instanceof constructor;
- } else if (typeof hasInstanceSymbolProp !== "function") {
- throw new TypeError(typeof hasInstanceSymbolProp + " is not a function");
- } else {
- return hasInstanceSymbolProp.call(constructor, object);
- }
- };
-
- // Generates name for a symbol instance and this name will be used as
- // property key for property symbols internally.
- var generateSymbolName = function(id) {
- return "@@_____" + id + "_____";
- };
-
- // Generates id for next Symbol instance
- var getNextSymbolId = function() {
- return symbolHiddenCounter++;
- };
-
- var setupSymbolInternals = function(symbol, desc) {
- defineProperties(symbol, {
- _description: {
- value: desc
- },
- _isSymbol: {
- value: true
- },
- _id: {
- value: getNextSymbolId()
- }
- });
- return symbol;
- };
-
- var checkSymbolInternals = function(symbol) {
- return (
- symbol._isSymbol === true &&
- typeof symbol._id === "number" &&
- typeof symbol._description === "string"
- );
- };
-
- var isSymbol = function(symbol) {
- return symbol instanceof Symbol && checkSymbolInternals(symbol);
- };
-
- var symbolFor = function(key) {
- key = String(key);
- var registryLength = globalSymbolRegistry.length,
- record,
- i = 0;
-
- for (; i < registryLength; ++i) {
- record = globalSymbolRegistry[i];
- if (record.key === key) return record.symbol;
- }
-
- record = {
- key: key,
- symbol: Symbol(key)
- };
- globalSymbolRegistry.push(record);
- return record.symbol;
- };
-
- var symbolKeyFor = function(symbol) {
- if (!ES6.isSymbol(symbol))
- throw new TypeError(String(symbol) + " is not a symbol");
- var registryLength = globalSymbolRegistry.length,
- record,
- i = 0;
-
- for (; i < registryLength; ++i) {
- record = globalSymbolRegistry[i];
- if (record.symbol === symbol) return record.key;
- }
- };
-
- /* It affects array1 and appends array2 at the end of array1 */
- var appendArray = function(array1, array2) {
- // Returns immediately if these are not array or not array-like objects
- if (
- !(
- typeof array1.length === "number" &&
- array1.length >= 0 &&
- typeof array2.length === "number" &&
- array2.length >= 0
- )
- )
- return;
- var length1 = Math.floor(array1.length),
- length2 = Math.floor(array2.length),
- i = 0;
-
- array1.length = length1 + length2;
- for (; i < length2; ++i)
- if (array2.hasOwnProperty(i)) array1[length1 + i] = array2[i];
- };
-
- var es6ObjectPrototypeToString = function toString() {
- if (this === undefined || this === null) return objectToString.call(this);
- // Add support for @@toStringTag symbol
- if (typeof this[Symbol.toStringTag] === "string")
- return "[object " + this[Symbol.toStringTag] + "]";
- else return objectToString.call(this);
- };
-
- var es6ArrayPrototypeConcat = function concat() {
- if (this === undefined || this === null)
- throw new TypeError("Array.prototype.concat called on null or undefined");
-
- // Boxing 'this' value to wrapper object
- var self = Object(this),
- targets = slice.call(arguments),
- outputs = []; // Later it may affected by Symbol
-
- targets.unshift(self);
-
- targets.forEach(function(target) {
- // If target is primitive then just push
- if (!isObject(target)) outputs.push(target);
- // Here Symbol.isConcatSpreadable support is added
- else if (typeof target[Symbol.isConcatSpreadable] !== "undefined") {
- if (target[Symbol.isConcatSpreadable]) {
- appendArray(outputs, target);
- } else {
- outputs.push(target);
- }
- } else if (isArray(target)) {
- appendArray(outputs, target);
- } else {
- outputs.push(target);
- }
- });
- return outputs;
- };
-
- var es6ForOfLoop = function(iterable, callback, thisArg) {
- callback = typeof callback !== "function" ? emptyFunction : callback;
- if (typeof iterable[Symbol.iterator] !== "function")
- throw new TypeError("Iterable[Symbol.iterator] is not a function");
- var iterator = iterable[Symbol.iterator](),
- iterationResult;
- if (typeof iterator.next !== "function")
- throw new TypeError(".iterator.next is not a function");
- while (true) {
- iterationResult = iterator.next();
- if (!isObject(iterationResult))
- throw new TypeError(
- "Iterator result " + iterationResult + " is not an object"
- );
- if (iterationResult.done) break;
- callback.call(thisArg, iterationResult.value);
- }
- };
-
- // Provides simple inheritance functionality
- var simpleInheritance = function(child, parent) {
- if (typeof child !== "function" || typeof parent !== "function")
- throw new TypeError("Child and Parent must be function type");
-
- child.prototype = Object.create(parent.prototype);
- child.prototype.constructor = child;
- };
-
- // Behaves as Symbol function in ES6, take description and returns an unique object,
- // but in ES6 this function returns 'symbol' primitive typed value.
- // Its type is 'object' not 'symbol'.
- // There is no wrapping in this case i.e. Object(sym) = sym.
- var Symbol = function Symbol(desc) {
- desc = typeof desc === "undefined" ? "" : String(desc);
-
- if (this instanceof Symbol)
- throw new TypeError("Symbol is not a constructor");
-
- return setupSymbolInternals(Object.create(Symbol.prototype), desc);
- };
-
- defineProperties(Symbol, {
- for: {
- value: symbolFor,
- writable: true,
- configurable: true
- },
-
- keyFor: {
- value: symbolKeyFor,
- writable: true,
- configurable: true
- },
-
- hasInstance: {
- value: Symbol("Symbol.hasInstance")
- },
-
- isConcatSpreadable: {
- value: Symbol("Symbol.isConcatSpreadable")
- },
-
- iterator: {
- value: Symbol("Symbol.iterator")
- },
-
- toStringTag: {
- value: Symbol("Symbol.toStringTag")
- }
- });
-
- // In ES6, this function returns like 'Symbol()', but in this case
- // this function returns the symbol's internal name to work properly.
- Symbol.prototype.toString = function() {
- return generateSymbolName(this._id);
- };
-
- // Returns itself but in ES6 It returns 'symbol' typed value.
- Symbol.prototype.valueOf = function() {
- return this;
- };
-
- // Make Iterator like iterable
- defineProperty(Iterator.prototype, Symbol.iterator.toString(), {
- value: function() {
- return this;
- },
- writable: true,
- configurable: true
- });
-
- simpleInheritance(ArrayIterator, Iterator);
-
- simpleInheritance(StringIterator, Iterator);
-
- defineProperty(ArrayIterator.prototype, Symbol.toStringTag.toString(), {
- value: "Array Iterator",
- configurable: true
- });
-
- defineProperty(StringIterator.prototype, Symbol.toStringTag.toString(), {
- value: "String Iterator",
- configurable: true
- });
-
- // This iterator works on any Array or TypedArray or array-like objects
- ArrayIterator.prototype.next = function next() {
- if (!(this instanceof ArrayIterator))
- throw new TypeError(
- "Method Array Iterator.prototype.next called on incompatible receiver " +
- String(this)
- );
-
- var self = this,
- nextValue;
-
- if (self._nextIndex === -1) {
- return {
- done: true,
- value: undefined
- };
- }
-
- if (!(typeof self._array.length === "number" && self._array.length >= 0)) {
- self._nextIndex = -1;
- return {
- done: true,
- value: undefined
- };
- }
-
- // _flag = 1 for [index, value]
- // _flag = 2 for [value]
- // _flag = 3 for [index]
- if (self._nextIndex < Math.floor(self._array.length)) {
- if (self._flag === 1)
- nextValue = [self._nextIndex, self._array[self._nextIndex]];
- else if (self._flag === 2) nextValue = self._array[self._nextIndex];
- else if (self._flag === 3) nextValue = self._nextIndex;
- self._nextIndex++;
- return {
- done: false,
- value: nextValue
- };
- } else {
- self._nextIndex = -1;
- return {
- done: true,
- value: undefined
- };
- }
- };
-
- StringIterator.prototype.next = function next() {
- if (!(this instanceof StringIterator))
- throw new TypeError(
- "Method String Iterator.prototype.next called on incompatible receiver " +
- String(this)
- );
-
- var self = this,
- stringObject = new String(this._string),
- nextValue;
-
- if (self._nextIndex === -1) {
- return {
- done: true,
- value: undefined
- };
- }
-
- if (self._nextIndex < stringObject.length) {
- nextValue = stringObject[self._nextIndex];
- self._nextIndex++;
- return {
- done: false,
- value: nextValue
- };
- } else {
- self._nextIndex = -1;
- return {
- done: true,
- value: undefined
- };
- }
- };
-
- var es6ArrayPrototypeIteratorSymbol = function values() {
- if (this === undefined || this === null)
- throw new TypeError("Cannot convert undefined or null to object");
-
- var self = Object(this);
- return new ArrayIterator(self, 2);
- };
-
- var es6StringPrototypeIteratorSymbol = function values() {
- if (this === undefined || this === null)
- throw new TypeError(
- "String.prototype[Symbol.iterator] called on null or undefined"
- );
- return new StringIterator(String(this), 0);
- };
-
- var es6ArrayPrototypeEntries = function entries() {
- if (this === undefined || this === null)
- throw new TypeError("Cannot convert undefined or null to object");
-
- var self = Object(this);
- return new ArrayIterator(self, 1);
- };
-
- var es6ArrayPrototypeKeys = function keys() {
- if (this === undefined || this === null)
- throw new TypeError("Cannot convert undefined or null to object");
- var self = Object(this);
- return new ArrayIterator(self, 3);
- };
-
- var SpreadOperatorImpl = function(target, thisArg) {
- this._target = target;
- this._values = [];
- this._thisArg = thisArg;
- };
- // All the arguments must be iterable
- SpreadOperatorImpl.prototype.spread = function() {
- var self = this;
- slice.call(arguments).forEach(function(iterable) {
- ES6.forOf(iterable, function(value) {
- self._values.push(value);
- });
- });
- return self;
- };
-
- SpreadOperatorImpl.prototype.add = function() {
- var self = this;
- slice.call(arguments).forEach(function(value) {
- self._values.push(value);
- });
- return self;
- };
-
- SpreadOperatorImpl.prototype.call = function(thisArg) {
- if (typeof this._target !== "function")
- throw new TypeError("Target is not a function");
- thisArg = arguments.length <= 0 ? this._thisArg : thisArg;
- return this._target.apply(thisArg, this._values);
- };
-
- SpreadOperatorImpl.prototype.new = function() {
- if (typeof this._target !== "function")
- throw new TypeError("Target is not a constructor");
-
- var temp, returnValue;
- temp = Object.create(this._target.prototype);
- returnValue = this._target.apply(temp, this._values);
- return isObject(returnValue) ? returnValue : temp;
- };
-
- // Affects the target array
- SpreadOperatorImpl.prototype.array = function() {
- if (!isArray(this._target)) throw new TypeError("Target is not a array");
- push.apply(this._target, this._values);
- return this._target;
- };
-
- // Target must be Array or function
- var es6SpreadOperator = function spreadOperator(target, thisArg) {
- if (!(typeof target === "function" || isArray(target)))
- throw new TypeError(
- "Spread operator only supports on array and function objects at this moment"
- );
- return new SpreadOperatorImpl(target, thisArg);
- };
-
- var es6ArrayFrom = function from(arrayLike, mapFn, thisArg) {
- var constructor,
- i = 0,
- length,
- outputs;
- // Use the generic constructor
- constructor = !isConstructor(this) ? Array : this;
- if (arrayLike === undefined || arrayLike === null)
- throw new TypeError("Cannot convert undefined or null to object");
-
- arrayLike = Object(arrayLike);
- if (mapFn === undefined) mapFn = simpleFunction;
- else if (!isCallable(mapFn))
- throw new TypeError(mapFn + " is not a function");
-
- if (typeof arrayLike[Symbol.iterator] === "undefined") {
- if (!(typeof arrayLike.length === "number" && arrayLike.length >= 0)) {
- outputs = new constructor(0);
- outputs.length = 0;
- return outputs;
- }
- length = Math.floor(arrayLike.length);
- outputs = new constructor(length);
- outputs.length = length;
- for (; i < length; ++i) outputs[i] = mapFn.call(thisArg, arrayLike[i]);
- } else {
- outputs = new constructor();
- outputs.length = 0;
- ES6.forOf(arrayLike, function(value) {
- outputs.length++;
- outputs[outputs.length - 1] = mapFn.call(thisArg, value);
- });
- }
- return outputs;
- };
-
- // Export ES6 APIs and add all the patches to support Symbol in ES5
- // If the running environment already supports ES6 then no patches will be applied,
- if (isES6Running()) return ES6;
- else {
- // Some ES6 APIs can't be implemented in pure ES5, so this 'ES6' object provides
- // some equivalent functionality of these features.
- defineProperties(ES6, {
- // Checks if a JS value is a symbol
- // It can be used as equivalent api in ES6: typeof symbol === 'symbol'
- isSymbol: {
- value: isSymbol,
- writable: true,
- configurable: true
- },
-
- // Native ES5 'instanceof' operator does not support @@hasInstance symbol,
- // this method provides same functionality of ES6 'instanceof' operator.
- instanceOf: {
- value: es6InstanceOfOperator,
- writable: true,
- configurable: true
- },
-
- // This method behaves exactly same as ES6 for...of loop.
- forOf: {
- value: es6ForOfLoop,
- writable: true,
- configurable: true
- },
-
- // This method gives same functionality of the spread operator of ES6
- // It works on only functions and arrays.
- // Limitation: You can't create array like this [...iterable, , , , 33] by this method,
- // to achieve this you have to do like this [...iterable, undefined, undefined, undefined, 33]
- spreadOperator: {
- value: es6SpreadOperator,
- writable: true,
- configurable: true
- }
- });
-
- defineProperty(global, "Symbol", {
- value: Symbol,
- writable: true,
- configurable: true
- });
-
- defineProperty(Function.prototype, Symbol.hasInstance.toString(), {
- value: es6FunctionPrototypeHasInstanceSymbol
- });
-
- defineProperty(Array.prototype, "concat", {
- value: es6ArrayPrototypeConcat,
- writable: true,
- configurable: true
- });
-
- defineProperty(Object.prototype, "toString", {
- value: es6ObjectPrototypeToString,
- writable: true,
- configurable: true
- });
-
- defineProperty(Array.prototype, Symbol.iterator.toString(), {
- value: es6ArrayPrototypeIteratorSymbol,
- writable: true,
- configurable: true
- });
-
- defineProperty(Array, "from", {
- value: es6ArrayFrom,
- writable: true,
- configurable: true
- });
-
- defineProperty(Array.prototype, "entries", {
- value: es6ArrayPrototypeEntries,
- writable: true,
- configurable: true
- });
-
- defineProperty(Array.prototype, "keys", {
- value: es6ArrayPrototypeKeys,
- writable: true,
- configurable: true
- });
-
- defineProperty(String.prototype, Symbol.iterator.toString(), {
- value: es6StringPrototypeIteratorSymbol,
- writable: true,
- configurable: true
- });
- }
-
- return ES6;
-});
-/* eslint-enable */
-
-// Polyfill Promise - used by popper.js
-if (!window.Promise) {
- window.Promise = true;
-}
-window.addEventListener(
- "load",
- function() {
- window.Promise = require("rsvp").Promise;
- },
- false
-);
diff --git a/plugins/discourse-unsupported-browser/spec/middleware/anonymous_cache_spec.rb b/plugins/discourse-unsupported-browser/spec/middleware/anonymous_cache_spec.rb
deleted file mode 100644
index 5c849664afc..00000000000
--- a/plugins/discourse-unsupported-browser/spec/middleware/anonymous_cache_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-require "rails_helper"
-
-describe Middleware::AnonymousCache::Helper do
- before { SiteSetting.discourse_unsupported_browser_enabled = true }
-
- def env(opts = {})
- {
- "HTTP_HOST" => "http://test.com",
- "REQUEST_URI" => "/path?bla=1",
- "REQUEST_METHOD" => "GET",
- "rack.input" => ""
- }.merge(opts)
- end
-
- def new_helper(opts = {})
- Middleware::AnonymousCache::Helper.new(env(opts))
- end
-
- it "includes ie in cache key" do
- helper = new_helper
- expect(helper.cache_key).to include("ie=false")
-
- helper = new_helper("HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko")
- expect(helper.cache_key).to include("ie=true")
- end
-end
diff --git a/plugins/discourse-unsupported-browser/spec/requests/bootstrap_request_spec.rb b/plugins/discourse-unsupported-browser/spec/requests/bootstrap_request_spec.rb
deleted file mode 100644
index 036e1ced506..00000000000
--- a/plugins/discourse-unsupported-browser/spec/requests/bootstrap_request_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-require 'rails_helper'
-
-describe 'Bootstrapping the Discourse App' do
- let(:ie_agent) { "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko" }
-
- context "when disabled" do
- before do
- SiteSetting.discourse_unsupported_browser_enabled = false
- end
-
- it "does not include the IE stylesheet or Javascript" do
- get "/categories", headers: { "HTTP_USER_AGENT" => ie_agent }
- expect(response.body).not_to match(/discourse-unsupported-browser-optional.js/)
- expect(response.body).not_to match(/stylesheets\/discourse-unsupported-browser/)
- end
- end
-
- context "when enabled" do
- before do
- SiteSetting.discourse_unsupported_browser_enabled = true
- end
-
- it "includes the IE js and css" do
- get "/categories", headers: { "HTTP_USER_AGENT" => ie_agent }
- expect(response.body).to match(/discourse-unsupported-browser-optional.js/)
- expect(response.body).to match(/stylesheets\/discourse-unsupported-browser/)
- end
-
- it "doesn't include IE stuff for non-IE browsers" do
- get "/categories", headers: { "HTTP_USER_AGENT" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36" }
- expect(response.body).not_to match(/discourse-unsupported-browser-optional.js/)
- expect(response.body).not_to match(/stylesheets\/discourse-unsupported-browser/)
- end
- end
-end
diff --git a/translator.yml b/translator.yml
index 9138a899a5d..d8e0c80c622 100644
--- a/translator.yml
+++ b/translator.yml
@@ -38,11 +38,6 @@ files:
- source_path: plugins/discourse-presence/config/locales/server.en.yml
destination_path: plugins/presence/server.yml
- - source_path: plugins/discourse-unsupported-browser/config/locales/client.en.yml
- destination_path: plugins/unsupported-browser/client.yml
- - source_path: plugins/discourse-unsupported-browser/config/locales/server.en.yml
- destination_path: plugins/unsupported-browser/server.yml
-
- source_path: plugins/poll/config/locales/client.en.yml
destination_path: plugins/poll/client.yml
- source_path: plugins/poll/config/locales/server.en.yml