diff --git a/util/gh-pages/index.html b/util/gh-pages/index.html
index 8791debad723..99e211654d19 100644
--- a/util/gh-pages/index.html
+++ b/util/gh-pages/index.html
@@ -501,9 +501,11 @@ Otherwise, have a great day =^.^=
-
+
-
@@ -517,7 +519,8 @@ Otherwise, have a great day =^.^=
{{lint.id}}
- ¶
+ ¶
📋
diff --git a/util/gh-pages/script.js b/util/gh-pages/script.js
index 1c16ecd6b0b1..f59245e556cd 100644
--- a/util/gh-pages/script.js
+++ b/util/gh-pages/script.js
@@ -24,9 +24,9 @@
target.scrollIntoView();
}
- function scrollToLintByURL($scope) {
- var removeListener = $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
- scrollToLint(window.location.hash.slice(1));
+ function scrollToLintByURL($scope, $location) {
+ var removeListener = $scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) {
+ scrollToLint($location.path().substring(1));
removeListener();
});
}
@@ -106,10 +106,10 @@
}
};
})
- .controller("lintList", function ($scope, $http, $timeout) {
+ .controller("lintList", function ($scope, $http, $location, $timeout) {
// Level filter
var LEVEL_FILTERS_DEFAULT = {allow: true, warn: true, deny: true, none: true};
- $scope.levels = LEVEL_FILTERS_DEFAULT;
+ $scope.levels = { ...LEVEL_FILTERS_DEFAULT };
$scope.byLevels = function (lint) {
return $scope.levels[lint.level];
};
@@ -146,6 +146,165 @@
"=": {enabled: false, minorVersion: null },
};
+ // Map the versionFilters to the query parameters in a way that is easier to work with in a URL
+ const versionFilterKeyMap = {
+ "≥": "gte",
+ "≤": "lte",
+ "=": "eq"
+ };
+ const reverseVersionFilterKeyMap = Object.fromEntries(
+ Object.entries(versionFilterKeyMap).map(([key, value]) => [value, key])
+ );
+
+ // loadFromURLParameters retrieves filter settings from the URL parameters and assigns them
+ // to corresponding $scope variables.
+ function loadFromURLParameters() {
+ // Extract parameters from URL
+ const urlParameters = $location.search();
+
+ // Define a helper function that assigns URL parameters to a provided scope variable
+ const handleParameter = (parameter, scopeVariable, defaultValues) => {
+ if (urlParameters[parameter]) {
+ const items = urlParameters[parameter].split(',');
+ for (const key in scopeVariable) {
+ if (scopeVariable.hasOwnProperty(key)) {
+ scopeVariable[key] = items.includes(key);
+ }
+ }
+ } else if (defaultValues) {
+ for (const key in defaultValues) {
+ if (scopeVariable.hasOwnProperty(key)) {
+ scopeVariable[key] = defaultValues[key];
+ }
+ }
+ }
+ };
+
+ handleParameter('levels', $scope.levels, LEVEL_FILTERS_DEFAULT);
+ handleParameter('groups', $scope.groups, GROUPS_FILTER_DEFAULT);
+
+ // Handle 'versions' parameter separately because it needs additional processing
+ if (urlParameters.versions) {
+ const versionFilters = urlParameters.versions.split(',');
+ for (const versionFilter of versionFilters) {
+ const [key, minorVersion] = versionFilter.split(':');
+ const parsedMinorVersion = parseInt(minorVersion);
+
+ // Map the key from the URL parameter to its original form
+ const originalKey = reverseVersionFilterKeyMap[key];
+
+ if (originalKey in $scope.versionFilters && !isNaN(parsedMinorVersion)) {
+ $scope.versionFilters[originalKey].enabled = true;
+ $scope.versionFilters[originalKey].minorVersion = parsedMinorVersion;
+ }
+ }
+ }
+
+ // Load the search parameter from the URL path
+ const searchParameter = $location.path().substring(1); // Remove the leading slash
+ if (searchParameter) {
+ $scope.search = searchParameter;
+ $scope.open[searchParameter] = true;
+ scrollToLintByURL($scope, $location);
+ }
+ }
+
+ // updateURLParameter updates the URL parameter with the given key to the given value
+ function updateURLParameter(filterObj, urlKey, defaultValue = {}, processFilter = filter => filter) {
+ const parameter = Object.keys(filterObj)
+ .filter(filter => filterObj[filter])
+ .sort()
+ .map(processFilter)
+ .filter(Boolean) // Filters out any falsy values, including null
+ .join(',');
+
+ const defaultParameter = Object.keys(defaultValue)
+ .filter(filter => defaultValue[filter])
+ .sort()
+ .map(processFilter)
+ .filter(Boolean) // Filters out any falsy values, including null
+ .join(',');
+
+ // if we ended up back at the defaults, just remove it from the URL
+ if (parameter === defaultParameter) {
+ $location.search(urlKey, null);
+ } else {
+ $location.search(urlKey, parameter || null);
+ }
+ }
+
+ // updateVersionURLParameter updates the version URL parameter with the given version filters
+ function updateVersionURLParameter(versionFilters) {
+ updateURLParameter(
+ versionFilters,
+ 'versions', {},
+ versionFilter => versionFilters[versionFilter].enabled && versionFilters[versionFilter].minorVersion != null
+ ? `${versionFilterKeyMap[versionFilter]}:${versionFilters[versionFilter].minorVersion}`
+ : null
+ );
+ }
+
+ // updateAllURLParameters updates all the URL parameters with the current filter settings
+ function updateAllURLParameters() {
+ updateURLParameter($scope.levels, 'levels', LEVEL_FILTERS_DEFAULT);
+ updateURLParameter($scope.groups, 'groups', GROUPS_FILTER_DEFAULT);
+ updateVersionURLParameter($scope.versionFilters);
+ }
+
+ // Add $watches to automatically update URL parameters when the data changes
+ $scope.$watch('levels', function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ updateURLParameter(newVal, 'levels', LEVEL_FILTERS_DEFAULT);
+ }
+ }, true);
+
+ $scope.$watch('groups', function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ updateURLParameter(newVal, 'groups', GROUPS_FILTER_DEFAULT);
+ }
+ }, true);
+
+ $scope.$watch('versionFilters', function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ updateVersionURLParameter(newVal);
+ }
+ }, true);
+
+ // Watch for changes in the URL path and update the search and lint display
+ $scope.$watch(function () { return $location.path(); }, function (newPath) {
+ const searchParameter = newPath.substring(1);
+ if ($scope.search !== searchParameter) {
+ $scope.search = searchParameter;
+ $scope.open[searchParameter] = true;
+ scrollToLintByURL($scope, $location);
+ }
+ });
+
+ let debounceTimeout;
+ $scope.$watch('search', function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ if (debounceTimeout) {
+ $timeout.cancel(debounceTimeout);
+ }
+
+ debounceTimeout = $timeout(function () {
+ $location.path(newVal);
+ }, 1000);
+ }
+ });
+
+ $scope.$watch(function () { return $location.search(); }, function (newParameters) {
+ loadFromURLParameters();
+ }, true);
+
+ $scope.updatePath = function () {
+ if (debounceTimeout) {
+ $timeout.cancel(debounceTimeout);
+ }
+
+ $location.path($scope.search);
+ }
+
$scope.selectTheme = function (theme) {
setTheme(theme, true);
}
@@ -169,10 +328,9 @@
};
$scope.resetGroupsToDefault = function () {
- const groups = $scope.groups;
- for (const [key, value] of Object.entries(GROUPS_FILTER_DEFAULT)) {
- groups[key] = value;
- }
+ $scope.groups = {
+ ...GROUPS_FILTER_DEFAULT
+ };
};
$scope.selectedValuesCount = function (obj) {
@@ -272,6 +430,12 @@
return true;
}
+ // Show details for one lint
+ $scope.openLint = function (lint) {
+ $scope.open[lint.id] = true;
+ $location.path(lint.id);
+ };
+
$scope.copyToClipboard = function (lint) {
const clipboard = document.getElementById("clipboard-" + lint.id);
if (clipboard) {
@@ -296,14 +460,12 @@
// Get data
$scope.open = {};
$scope.loading = true;
+
// This will be used to jump into the source code of the version that this documentation is for.
$scope.docVersion = window.location.pathname.split('/')[2] || "master";
- if (window.location.hash.length > 1) {
- $scope.search = window.location.hash.slice(1);
- $scope.open[window.location.hash.slice(1)] = true;
- scrollToLintByURL($scope);
- }
+ // Set up the filters from the URL parameters before we start loading the data
+ loadFromURLParameters();
$http.get('./lints.json')
.success(function (data) {
@@ -315,7 +477,7 @@
selectGroup($scope, selectedGroup.toLowerCase());
}
- scrollToLintByURL($scope);
+ scrollToLintByURL($scope, $location);
setTimeout(function () {
var el = document.getElementById('filter-input');
@@ -326,18 +488,6 @@
$scope.error = data;
$scope.loading = false;
});
-
- window.addEventListener('hashchange', function () {
- // trigger re-render
- $timeout(function () {
- $scope.levels = LEVEL_FILTERS_DEFAULT;
- $scope.search = window.location.hash.slice(1);
- $scope.open[window.location.hash.slice(1)] = true;
-
- scrollToLintByURL($scope);
- });
- return true;
- }, false);
});
})();