automatic category fallback in style search (#831)
Even better. Seems way more reliable. Thanks tophf.
This commit is contained in:
parent
a3c22325b8
commit
2b985a0a91
|
@ -20,17 +20,7 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
const API_URL = BASE_URL + '/api/v1/styles/';
|
const API_URL = BASE_URL + '/api/v1/styles/';
|
||||||
const UPDATE_URL = 'https://update.userstyles.org/%.md5';
|
const UPDATE_URL = 'https://update.userstyles.org/%.md5';
|
||||||
|
|
||||||
// normal category is just one word like 'github' or 'google'
|
const STYLUS_CATEGORY = 'chrome-extension';
|
||||||
// but for some sites we need a fallback
|
|
||||||
// key: category.tld
|
|
||||||
// value <string>: use as category
|
|
||||||
// value true: fallback to search_terms
|
|
||||||
const CATEGORY_FALLBACK = {
|
|
||||||
'userstyles.org': 'userstyles.org',
|
|
||||||
'last.fm': true,
|
|
||||||
'Stylus': true,
|
|
||||||
};
|
|
||||||
const RX_CATEGORY = /^(?:.*?)([^.]+)(?:\.com?)?\.(\w+)$/;
|
|
||||||
|
|
||||||
const DISPLAY_PER_PAGE = 10;
|
const DISPLAY_PER_PAGE = 10;
|
||||||
// Millisecs to wait before fetching next batch of search results.
|
// Millisecs to wait before fetching next batch of search results.
|
||||||
|
@ -54,7 +44,7 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
|
|
||||||
let searchTotalPages;
|
let searchTotalPages;
|
||||||
let searchCurrentPage = 1;
|
let searchCurrentPage = 1;
|
||||||
let searchExhausted = false;
|
let searchExhausted = 0; // 1: once, 2: twice (first host.jp, then host)
|
||||||
|
|
||||||
// currently active USO requests
|
// currently active USO requests
|
||||||
const xhrSpoofIds = new Set();
|
const xhrSpoofIds = new Set();
|
||||||
|
@ -79,7 +69,7 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
const dom = {};
|
const dom = {};
|
||||||
|
|
||||||
Object.assign($('#find-styles-link'), {
|
Object.assign($('#find-styles-link'), {
|
||||||
href: getSearchPageURL(tabURL),
|
href: BASE_URL + '/styles/browse/' + getCategory(),
|
||||||
onclick(event) {
|
onclick(event) {
|
||||||
if (!prefs.get('popup.findStylesInline') || dom.container) {
|
if (!prefs.get('popup.findStylesInline') || dom.container) {
|
||||||
handleEvent.openURLandHide.call(this, event);
|
handleEvent.openURLandHide.call(this, event);
|
||||||
|
@ -222,7 +212,7 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
* Initializes search results container, starts fetching results.
|
* Initializes search results container, starts fetching results.
|
||||||
*/
|
*/
|
||||||
function load() {
|
function load() {
|
||||||
if (searchExhausted) {
|
if (searchExhausted > 1) {
|
||||||
if (!processedResults.length) {
|
if (!processedResults.length) {
|
||||||
error(404);
|
error(404);
|
||||||
}
|
}
|
||||||
|
@ -233,21 +223,21 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
dom.container.classList.remove('hidden');
|
dom.container.classList.remove('hidden');
|
||||||
dom.error.classList.add('hidden');
|
dom.error.classList.add('hidden');
|
||||||
|
|
||||||
let pass = category ? 1 : 0;
|
|
||||||
category = category || getCategory();
|
category = category || getCategory();
|
||||||
|
|
||||||
search({category})
|
search({category})
|
||||||
.then(function process(results) {
|
.then(function process(results) {
|
||||||
const data = results.data.filter(sameCategory);
|
const data = results.data.filter(sameCategoryNoDupes);
|
||||||
|
|
||||||
pass++;
|
if (!data.length && searchExhausted <= 1) {
|
||||||
if (pass === 1 && !data.length) {
|
const old = category;
|
||||||
category = getCategory({keepTLD: true});
|
const uso = (processedResults[0] || {}).subcategory;
|
||||||
return search({category, restart: true}).then(process);
|
category = uso !== category && uso || getCategory({retry: true});
|
||||||
|
if (category !== old) return search({category, restart: true}).then(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
const numIrrelevant = results.data.length - data.length;
|
const numIrrelevant = results.data.length - data.length;
|
||||||
totalResults = results.current_page === 1 ? results.total_entries : totalResults;
|
totalResults += results.current_page === 1 ? results.total_entries : 0;
|
||||||
totalResults = Math.max(0, totalResults - numIrrelevant);
|
totalResults = Math.max(0, totalResults - numIrrelevant);
|
||||||
totalPages = Math.ceil(totalResults / DISPLAY_PER_PAGE);
|
totalPages = Math.ceil(totalResults / DISPLAY_PER_PAGE);
|
||||||
|
|
||||||
|
@ -258,7 +248,7 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
processNextResult();
|
processNextResult();
|
||||||
} else if (numIrrelevant) {
|
} else if (numIrrelevant) {
|
||||||
load();
|
load();
|
||||||
} else {
|
} else if (!processedResults.length) {
|
||||||
return Promise.reject(404);
|
return Promise.reject(404);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -610,18 +600,10 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
//endregion
|
//endregion
|
||||||
//region USO API wrapper
|
//region USO API wrapper
|
||||||
|
|
||||||
function getSearchPageURL() {
|
|
||||||
const category = getCategory();
|
|
||||||
return BASE_URL +
|
|
||||||
'/styles/browse/' +
|
|
||||||
(category in CATEGORY_FALLBACK ? '?search_terms=' : '') +
|
|
||||||
category;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the Userstyles.org "category" for a given URL.
|
* Resolves the Userstyles.org "category" for a given URL.
|
||||||
*/
|
*/
|
||||||
function getCategory({keepTLD} = {}) {
|
function getCategory({retry} = {}) {
|
||||||
const u = tryCatch(() => new URL(tabURL));
|
const u = tryCatch(() => new URL(tabURL));
|
||||||
if (!u) {
|
if (!u) {
|
||||||
// Invalid URL
|
// Invalid URL
|
||||||
|
@ -629,21 +611,28 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
} else if (u.protocol === 'file:') {
|
} else if (u.protocol === 'file:') {
|
||||||
return 'file:';
|
return 'file:';
|
||||||
} else if (u.protocol === location.protocol) {
|
} else if (u.protocol === location.protocol) {
|
||||||
return 'Stylus';
|
return STYLUS_CATEGORY;
|
||||||
} else {
|
} else {
|
||||||
// Website address, strip TLD & subdomain
|
const parts = u.hostname.replace(/\.(?:com?|org)(\.\w{2,3})$/, '$1').split('.');
|
||||||
const [, category = u.hostname, tld = ''] = u.hostname.match(RX_CATEGORY) || [];
|
const [tld, main = u.hostname, third, fourth] = parts.reverse();
|
||||||
const categoryWithTLD = category + '.' + tld;
|
const keepTld = !retry && !(
|
||||||
const fallback = CATEGORY_FALLBACK[categoryWithTLD];
|
tld === 'com' ||
|
||||||
return fallback === true && categoryWithTLD || fallback || category + (keepTLD ? tld : '');
|
tld === 'org' && main !== 'userstyles'
|
||||||
|
);
|
||||||
|
const keepThird = !retry && (
|
||||||
|
fourth ||
|
||||||
|
third && third !== 'www' && third !== 'm'
|
||||||
|
);
|
||||||
|
return (keepThird && `${third}.` || '') + main + (keepTld ? `.${tld}` : '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sameCategory(result) {
|
function sameCategoryNoDupes(result) {
|
||||||
return result.subcategory && (
|
return (
|
||||||
category === result.subcategory ||
|
result.subcategory &&
|
||||||
category === 'Stylus' && /^(chrome|moz)-extension$/.test(result.subcategory) ||
|
!processedResults.some(pr => pr.id === result.id) &&
|
||||||
category.replace('.', '').toLowerCase() === result.subcategory.replace('.', '').toLowerCase()
|
(category !== STYLUS_CATEGORY || /\bStylus\b/i.test(result.name + result.description)) &&
|
||||||
|
category.split('.')[0] === result.subcategory.split('.')[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,10 +693,10 @@ window.addEventListener('showStyles:done', function _() {
|
||||||
.then(json => {
|
.then(json => {
|
||||||
searchCurrentPage = json.current_page + 1;
|
searchCurrentPage = json.current_page + 1;
|
||||||
searchTotalPages = json.total_pages;
|
searchTotalPages = json.total_pages;
|
||||||
searchExhausted = (searchCurrentPage > searchTotalPages);
|
searchExhausted += searchCurrentPage > searchTotalPages;
|
||||||
return json;
|
return json;
|
||||||
}).catch(reason => {
|
}).catch(reason => {
|
||||||
searchExhausted = true;
|
searchExhausted++;
|
||||||
return Promise.reject(reason);
|
return Promise.reject(reason);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user