docs: Add Firefox Add-on support to homepage showcase (#2208)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Aaron <aaronklinker1@gmail.com>
This commit is contained in:
@@ -1,174 +1,651 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import useListExtensionDetails, {
|
||||
ChromeExtension,
|
||||
} from '../composables/useListExtensionDetails';
|
||||
import useListExtensionDetails from '../composables/useListExtensionDetails';
|
||||
|
||||
// Add extension IDs to end of the list. On the website, extensions will be sorted by a combination of weekly active users and rating.
|
||||
// Change the commit message or PR title to: "docs: Added "[extension name]" to the homepage"
|
||||
const chromeExtensionIds = [
|
||||
'ocfdgncpifmegplaglcnglhioflaimkd', // GitHub: Better Line Counts
|
||||
'mgmdkjcljneegjfajchedjpdhbadklcf', // Anime Skip Player
|
||||
'bfbnagnphiehemkdgmmficmjfddgfhpl', // UltraWideo
|
||||
'elfaihghhjjoknimpccccmkioofjjfkf', // StayFree - Website Blocker & Web Analytics
|
||||
'okifoaikfmpfcamplcfjkpdnhfodpkil', // Doozy: Ai Made Easy
|
||||
'lknmjhcajhfbbglglccadlfdjbaiifig', // tl;dv - Record, Transcribe & ChatGPT for Google Meet
|
||||
'oglffgiaiekgeicdgkdlnlkhliajdlja', // Youtube中文配音
|
||||
'agjnjboanicjcpenljmaaigopkgdnihi', // PreMiD
|
||||
'aiakblgmlabokilgljkglggnpflljdgp', // Markdown Sticky Notes
|
||||
'nomnkbngkijpffepcgbbofhcnafpkiep', // DocVersionRedirector
|
||||
'ceicccfeikoipigeghddpocceifjelph', // Plex Skipper
|
||||
'aelkipgppclpfimeamgmlonimflbhlgf', // GitHub Custom Notifier
|
||||
'djnlaiohfaaifbibleebjggkghlmcpcj', // Fluent Read
|
||||
'nhclljcpfmmaiojbhhnkpjcfmacfcian', // Facebook Video Controls
|
||||
'mblkhbaakhbhiimkbcnmeciblfhmafna', // ElemSnap - Quick capture of webpage elements and conversion to images,
|
||||
'oajalfneblkfiejoadecnmodfpnaeblh', // MS Edge TTS (Text to Speech)
|
||||
'nedcanggplmbbgmlpcjiafgjcpdimpea', // YTBlock - Block any content from YouTube™
|
||||
'oadbjpccljkplmhnjekgjamejnbadlne', // demo.fun - Interactive product demos that convert
|
||||
'iopdafdcollfgaoffingmahpffckmjni', // SmartEReply: Elevate Your LinkedIn™ Engagement with AI 🚀📈
|
||||
'khjdmjcmpolknpccmaaipmidphjokhdf', // WorkFlowy MultiFlow
|
||||
'fencadnndhdeggodopebjgdfdlhcimfk', // 香草布丁🌿🍮- https://github.com/Xdy1579883916/vanilla-pudding
|
||||
'bnacincmbaknlbegecpioobkfgejlojp', // MaxFocus: Link Preview
|
||||
'bcpgdpedphodjcjlminjbdeejccjbimp', // 汇率转换-中文版本
|
||||
'loeilaonggnalkaiiaepbegccilkmjjp', // Currency Converter Plus
|
||||
'npcnninnjghigjfiecefheeibomjpkak', // Respond Easy
|
||||
'cfkdcideecefncbglkhneoflfnmhoicc', // mindful - stay focused on your goals
|
||||
'lnhejcpclabmbgpiiomjbhalblnnbffg', // 1Proompt
|
||||
'fonflmjnjbkigocpoommgmhljdpljain', // NiceTab - https://github.com/web-dahuyou/NiceTab
|
||||
'fcffekbnfcfdemeekijbbmgmkognnmkd', // Draftly for LinkedIn
|
||||
'nkndldfehcidpejfkokbeghpnlbppdmo', // YouTube Summarized - Summarize any YouTube video
|
||||
'dbichmdlbjdeplpkhcejgkakobjbjalc', // 社媒助手 - https://github.com/iszhouhua/social-media-copilot
|
||||
'opepfpjeogkbgeigkbepobceinnfmjdd', // Dofollow Links for SEO
|
||||
'pdnenlnelpdomajfejgapbdpmjkfpjkp', // ChatGPT Writer: Use AI on Any Site (GPT-4o, Claude, Gemini, and More)
|
||||
'jobnhifpphkgoelnhnopgkdhbdkiadmj', // discord message translator
|
||||
'ncokhechhpjgjonhjnlaneglmdkfkcbj', // Habit Tracker app widget for daily habit tracking
|
||||
'lnjaiaapbakfhlbjenjkhffcdpoompki', // Catppuccin for GitHub File Explorer Icons
|
||||
'cpaedhbidlpnbdfegakhiamfpndhjpgf', // WebChat: Chat with anyone on any website
|
||||
'fcphghnknhkimeagdglkljinmpbagone', // YouTube Auto HD + FPS
|
||||
'lpomjgbicdemjkgmbnkjncgdebogkhlb', // MultiViewer Companion
|
||||
'ggiafipgeeaaahnjamgpjcgkdpanhddg', // Sync Watch - Watch videos together on any site
|
||||
'nmldnjcblcihmegipecakhmnieiofmgl', // Keyword Rank Checker
|
||||
'gppllamhaciichleihemgilcpledblpn', // YouTube Simple View - Hide distractions & more
|
||||
'pccbghdfdnnkkbcdcibchpbffdgednkf', // Propbar - Property Data Enhancer
|
||||
'lfknakglefggmdkjdfhhofkjnnolffkh', // Text Search Pro - Search by case and whole-word match!
|
||||
'mbenhbocjckkbaojacmaepiameldglij', // Invoice Generator
|
||||
'phlfhkmdofajnbhgmbmjkbkdgppgoppb', // Monthly Bill Tracker
|
||||
'macmkmchfoclhpbncclinhjflmdkaoom', // Wandpen - Instantly improve your writing with AI
|
||||
'lhmgechokhmdekdpgkkemoeecelcaonm', // YouTube Hider - Remove Comments By Keywords, Usernames & Tools
|
||||
'imgheieooppmahcgniieddodaliodeeg', // QA Compass - Record standardized bug reports easily
|
||||
'npgghjedpchajflknnbngajkjkdhncdo', // aesthetic Notion, styled
|
||||
'hmdcmlfkchdmnmnmheododdhjedfccka', // Eye Dropper
|
||||
'eihpmapodnppeemkhkbhikmggfojdkjd', // Cursorful - Screen Recorder with Auto Zoom
|
||||
'hjjkgbibknbahijglkffklflidncplkn', // Show IP – Live View of Website IPs for Developers
|
||||
'ilbikcehnpkmldojkcmlldkoelofnbde', // Strong Password Generator
|
||||
'ocllfkhcdopiafndigclebelbecaiocp', // ZenGram: Mindful Instagram, Your Way
|
||||
'odffpjnpocjfcaclnenaaaddghkgijdb', // Blync: Preview Links, Selection Search, AI Assistant
|
||||
'kofbbilhmnkcmibjbioafflgmpkbnmme', // HTML to Markdown - Convert webpages to markdown
|
||||
'boecmgggeigllcdocgioijmleimjbfkg', // Walmart WFS Profit Calculator
|
||||
'dlnjcbkmomenmieechnmgglgcljhoepd', // Youtube Live Chat Fullscreen
|
||||
'keiealdacakpnbbljlmhfgcebmaadieg', // Python Code Runner
|
||||
'hafcajcllbjnoolpfngclfmmgpikdhlm', // Monochromate
|
||||
'bmoggiinmnodjphdjnmpcnlleamkfedj', // AliasVault - Open-Source Password & (Email) Alias Manager
|
||||
'hlnhhamckimoaiekbglafiebkfimhapb', // SnapThePrice: AI-Powered Real-time Lowest Price Finder
|
||||
'gdjampjdgjmbifnhldgcnccdjkcoicmg', // radiofrance - news & broadcasts (French), music (international)
|
||||
'jlnhphlghikichhgbnkepenehbmloenb', // Blens - Time Tracker and AI Insight
|
||||
'njnammmpdodmfkodnfpammnpdcbhnlcm', // Always Light Mode - Setting website always in light mode
|
||||
'lblmfclcfniabobmamfkdogcgdagbhhb', // DesignPicker - Color Picker & Font Detector
|
||||
'pamnlaoeobcmhkliljfaofekeddpmfoh', // Web to PDF
|
||||
'jmbcbeepjfenihlocplnbmbhimcoooka', // Online CSV Viewer
|
||||
'nkjcoophmpcmmgadnljnlpbpfdfacgbo', // YouTube Video Transcript
|
||||
'lcaieahkjgeggeiihblhcjbbjlppgieh', // NetSuite Record Scripts
|
||||
'gmocfknjllodfiomnljmaehcplnekhlo', // VueTracker
|
||||
'ggcfemmoabhhelfkhknhbnkmeahloiod', // CanCopy - A web extension that allow you to copy any content from website
|
||||
'modkelfkcfjpgbfmnbnllalkiogfofhb', // Language Learning with AI
|
||||
'npfopljnjbamegincfjelhjhnonnjloo', // Bilibili Feed History Helper
|
||||
'edkhpdceeinkcacjdgebjehipmnbomce', // NZBDonkey - The ultimate NZB file download tool
|
||||
'cckggnbnimdbbpmdinkkgbbncopbloob', // WeChat Markdown Editor(微信 Markdown 编辑器)
|
||||
'jcblcjolcojmfopefcighfmkkefbaofg', // Tab Grab
|
||||
'eehmoikadcijkapfjocnhjclpbaindlb', // BrowserLens - https://browserlens.com/
|
||||
'hfhellofkjebbchcdffmicekjdomkcmc', // Epic Games Library Extension
|
||||
'gknigcbhlammoakmmdddkblknanpjiac', // Zen Analytics Pixel Tracker - zapt.web.app
|
||||
'cnklededohhcbmjjdlbjdkkihkgoggol', // Crypto Pulse - Compose your newtab with nature images, widgets & realtime Crypto Price & Bitcoin RSS.
|
||||
'miponnamafdenpgjemkknimgjfibicdc', // Youtube Video Scheduler
|
||||
'nhmbcmalgpkjbomhlhgdicanmkkaajmg', // Chatslator: Livestream Chat Translator
|
||||
'mbamjfdjbcdgpopfnkkmlohadbbnplhm', // 公众号阅读增强器 - https://wxreader.honwhy.wang
|
||||
'hannhecbnjnnbbafffmogdlnajpcomek', // 토탐정
|
||||
'ehboaofjncodknjkngdggmpdinhdoijp', // 2FAS Pass - https://2fas.com/
|
||||
'hnjamiaoicaepbkhdoknhhcedjdocpkd', // Quick Prompt - https://github.com/wenyuanw/quick-prompt
|
||||
'kacblhilkacgfnkjfodalohcnllcgmjd', // Add QR Code Generator Icon Back To Address Bar
|
||||
'fkbdlogfdjmpfepbbbjcgcfbgbcfcnne', // Piwik PRO Tracking Helper
|
||||
'nkbikckldmljjiiajklecmgmajgapbfl', // PIPX - Take Control of Picture-in-Picture, Automatically
|
||||
'hgppdobcpkfkmiegekaglonjajeojmdd', // Browsely - AI-powered browser extension
|
||||
'ehmoihnjgkdimihkhokkmfjdgomohjgm', // Filmbudd Pro - Simple, private – and synced ratings and watch notes across all your devices
|
||||
'alglchohmdikgdjhafiicilegegieafa', // MultiField CopyCat - Copy, Paste & Autofill Web Forms Instantly
|
||||
'aamihahiiogceidpbnfgehacgiecephe', // ChatSight - Add Table of Contents to ChatGPT
|
||||
'cndibmoanboadcifjkjbdpjgfedanolh', // BetterCampus (prev. BetterCanvas)
|
||||
'hinfimgacobnellbncbcpdlpaapcofaa', // Leetcode Fonts - Change fonts in leetcode effortlessly
|
||||
'kbkbfefhhabpkibojinapkkgciiacggg', // TranslateManga - Manga Translator & Manga Tracker
|
||||
'emeakbgdecgmdjgegnejpppcnkcnoaen', // SiteData - Free Website Traffic Checker & Reverse AdSense Tool
|
||||
'gpnckbhgpnjciklpoehkmligeaebigaa', // Livestream Chat Reader - Text-to-Speech for YouTube/Twitch chat
|
||||
'fjlalaedpfcojcfpkgkglbjjbbkofgnl', // ChatGPT Token Counter - Count tokens in real time on chatgpt conversation
|
||||
'fbgblmjbeebanackldpbmpacppflgmlj', // LinuxDo Scripts - 为 linux.do 用户提供了一些增强功能
|
||||
'dfacnjidgbagicaekenjgclfnhdnjjdi', // Zen Virtual Piano - https://zen-piano.web.app/
|
||||
'naeibcegmgpofimedkmfgjgphfhfhlab', // Crypto Pulse price tracker - https://get-crypto-pulse.web.app/
|
||||
'ffglckbhfbfmdkefdmjbhpnffkcmlhdh', // Redirect Web - Automatically redirect pages or open them in another app
|
||||
'eglpfhbhmelampoihamjomgkeobgdofl', // Capture It - Capture & Edit Screenshots
|
||||
'jmghclbfbbapimhbgnpffbimphlpolnm', // Teams Chat Exporter
|
||||
'jdcppdokgfbnhiacbeplahgnciahnhck', // Lofi BGM Player - Free lofi focus music for work & study
|
||||
'cgpmbiiagnehkikhcbnhiagfomajncpa', // Margin - Annotate and highlight any webpage, with your notes saved to the decentralized AT Protocol.
|
||||
'mfjdonmgmgcijagclnkfhmjiblbfjaid', // KeyFloat - Floating multilingual keyboard with native key mappings, drag, dark mode, sounds, and dynamic layouts for macOS & Windows
|
||||
'dhiekgdaipindoapjmcnpompdknjeijf', // Glossy New Tab - Say Goodbye to Boring Tabs with live wallpapers
|
||||
'lapnciffpekdengooeolaienkeoilfeo', // All API Hub – AI Relay & New API Manager - https://github.com/qixing-jk/all-api-hub
|
||||
'bhgobenflkkhfcgkikejaaejenoddcmo', // Scrape Similar - Extract data from websites into spreadsheets - https://github.com/zizzfizzix/scrape-similar
|
||||
'kinlknncggaihnhdcalijdmpbhbflalm', // isTrust - https://github.com/Internet-Society-Belgium/isTrust/
|
||||
'ojpakgiekphppgkcdihbjpafobhnhlkp', // Dymo
|
||||
'pmgehhllikbjmadpenhabejhpemplhmd', // Extension Rank Checker - Extension Ranker
|
||||
/** At least one of `chromeId` or `firefoxSlug` must be set. */
|
||||
type ExtensionEntry =
|
||||
| { chromeId: string; firefoxSlug?: string }
|
||||
| { firefoxSlug: string; chromeId?: string };
|
||||
|
||||
interface StoreLink {
|
||||
label: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
interface ListedExtension {
|
||||
id: string;
|
||||
name: string;
|
||||
iconUrl: string;
|
||||
shortDescription: string;
|
||||
users: number;
|
||||
rating: number | undefined;
|
||||
stores: StoreLink[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add extension entries to end of the list. On the website, extensions will be
|
||||
* sorted by a combination of users and rating.
|
||||
*
|
||||
* Change the commit message or PR title to:
|
||||
*
|
||||
* > "docs: Added "[extension name]" to showcase"
|
||||
*
|
||||
* Use:
|
||||
*
|
||||
* - `chromeId` for the Chrome Web Store listing,
|
||||
* - `firefoxSlug` for Firefox Add-ons (slug from
|
||||
* https://addons.mozilla.org/firefox/addon/{slug}/)
|
||||
*
|
||||
* You may set one or both.
|
||||
*/
|
||||
const extensionEntries: ExtensionEntry[] = [
|
||||
{
|
||||
// GitHub: Better Line Counts
|
||||
chromeId: 'ocfdgncpifmegplaglcnglhioflaimkd',
|
||||
firefoxSlug: 'github-better-line-counts',
|
||||
},
|
||||
{
|
||||
// Anime Skip Player
|
||||
chromeId: 'mgmdkjcljneegjfajchedjpdhbadklcf',
|
||||
firefoxSlug: 'anime-skip',
|
||||
},
|
||||
{
|
||||
// UltraWideo
|
||||
chromeId: 'bfbnagnphiehemkdgmmficmjfddgfhpl',
|
||||
firefoxSlug: 'ultrawideo',
|
||||
},
|
||||
{
|
||||
// StayFree - Website Blocker & Web Analytics
|
||||
chromeId: 'elfaihghhjjoknimpccccmkioofjjfkf',
|
||||
firefoxSlug: 'stayfree',
|
||||
},
|
||||
{
|
||||
// Doozy: Ai Made Easy
|
||||
chromeId: 'okifoaikfmpfcamplcfjkpdnhfodpkil',
|
||||
},
|
||||
{
|
||||
// tl;dv - Record, Transcribe & ChatGPT for Google Meet
|
||||
chromeId: 'lknmjhcajhfbbglglccadlfdjbaiifig',
|
||||
},
|
||||
{
|
||||
// Youtube中文配音
|
||||
chromeId: 'oglffgiaiekgeicdgkdlnlkhliajdlja',
|
||||
},
|
||||
{
|
||||
// PreMiD
|
||||
chromeId: 'agjnjboanicjcpenljmaaigopkgdnihi',
|
||||
},
|
||||
{
|
||||
// Markdown Sticky Notes
|
||||
chromeId: 'aiakblgmlabokilgljkglggnpflljdgp',
|
||||
firefoxSlug: 'markdown-sticky-notes',
|
||||
},
|
||||
{
|
||||
// DocVersionRedirector
|
||||
chromeId: 'nomnkbngkijpffepcgbbofhcnafpkiep',
|
||||
},
|
||||
{
|
||||
// Plex Skipper
|
||||
chromeId: 'ceicccfeikoipigeghddpocceifjelph',
|
||||
firefoxSlug: 'plex-skipper',
|
||||
},
|
||||
{
|
||||
// GitHub Custom Notifier
|
||||
chromeId: 'aelkipgppclpfimeamgmlonimflbhlgf',
|
||||
firefoxSlug: 'github-custom-notifier',
|
||||
},
|
||||
{
|
||||
// Fluent Read
|
||||
chromeId: 'djnlaiohfaaifbibleebjggkghlmcpcj',
|
||||
},
|
||||
{
|
||||
// Facebook Video Controls
|
||||
chromeId: 'nhclljcpfmmaiojbhhnkpjcfmacfcian',
|
||||
firefoxSlug: 'facebook-video-controls',
|
||||
},
|
||||
{
|
||||
// ElemSnap - Quick capture of webpage elements and conversion to images,
|
||||
chromeId: 'mblkhbaakhbhiimkbcnmeciblfhmafna',
|
||||
},
|
||||
{
|
||||
// MS Edge TTS (Text to Speech)
|
||||
chromeId: 'oajalfneblkfiejoadecnmodfpnaeblh',
|
||||
firefoxSlug: 'ms-edge-tts-text-to-speech',
|
||||
},
|
||||
{
|
||||
// YTBlock - Block any content from YouTube™
|
||||
chromeId: 'nedcanggplmbbgmlpcjiafgjcpdimpea',
|
||||
},
|
||||
{
|
||||
// demo.fun - Interactive product demos that convert
|
||||
chromeId: 'oadbjpccljkplmhnjekgjamejnbadlne',
|
||||
},
|
||||
{
|
||||
// SmartEReply: Elevate Your LinkedIn™ Engagement with AI 🚀📈
|
||||
chromeId: 'iopdafdcollfgaoffingmahpffckmjni',
|
||||
},
|
||||
{
|
||||
// WorkFlowy MultiFlow
|
||||
chromeId: 'khjdmjcmpolknpccmaaipmidphjokhdf',
|
||||
},
|
||||
{
|
||||
// 香草布丁🌿🍮- https://github.com/Xdy1579883916/vanilla-pudding
|
||||
chromeId: 'fencadnndhdeggodopebjgdfdlhcimfk',
|
||||
},
|
||||
{
|
||||
// MaxFocus: Link Preview
|
||||
chromeId: 'bnacincmbaknlbegecpioobkfgejlojp',
|
||||
firefoxSlug: 'maxfocus-link-preview',
|
||||
},
|
||||
{
|
||||
// 汇率转换-中文版本
|
||||
chromeId: 'bcpgdpedphodjcjlminjbdeejccjbimp',
|
||||
},
|
||||
{
|
||||
// Currency Converter Plus
|
||||
chromeId: 'loeilaonggnalkaiiaepbegccilkmjjp',
|
||||
firefoxSlug: 'currency-converter-plus',
|
||||
},
|
||||
{
|
||||
// Respond Easy
|
||||
chromeId: 'npcnninnjghigjfiecefheeibomjpkak',
|
||||
},
|
||||
{
|
||||
// mindful - stay focused on your goals
|
||||
chromeId: 'cfkdcideecefncbglkhneoflfnmhoicc',
|
||||
},
|
||||
{
|
||||
// 1Proompt
|
||||
chromeId: 'lnhejcpclabmbgpiiomjbhalblnnbffg',
|
||||
},
|
||||
{
|
||||
// NiceTab - https://github.com/web-dahuyou/NiceTab
|
||||
chromeId: 'fonflmjnjbkigocpoommgmhljdpljain',
|
||||
},
|
||||
{
|
||||
// Draftly for LinkedIn
|
||||
chromeId: 'fcffekbnfcfdemeekijbbmgmkognnmkd',
|
||||
},
|
||||
{
|
||||
// YouTube Summarized - Summarize any YouTube video
|
||||
chromeId: 'nkndldfehcidpejfkokbeghpnlbppdmo',
|
||||
},
|
||||
{
|
||||
// 社媒助手 - https://github.com/iszhouhua/social-media-copilot
|
||||
chromeId: 'dbichmdlbjdeplpkhcejgkakobjbjalc',
|
||||
},
|
||||
{
|
||||
// Dofollow Links for SEO
|
||||
chromeId: 'opepfpjeogkbgeigkbepobceinnfmjdd',
|
||||
},
|
||||
{
|
||||
// ChatGPT Writer: Use AI on Any Site (GPT-4o, Claude, Gemini, and More)
|
||||
chromeId: 'pdnenlnelpdomajfejgapbdpmjkfpjkp',
|
||||
},
|
||||
{
|
||||
// discord message translator
|
||||
chromeId: 'jobnhifpphkgoelnhnopgkdhbdkiadmj',
|
||||
},
|
||||
{
|
||||
// Habit Tracker app widget for daily habit tracking
|
||||
chromeId: 'ncokhechhpjgjonhjnlaneglmdkfkcbj',
|
||||
},
|
||||
{
|
||||
// Catppuccin for GitHub File Explorer Icons
|
||||
chromeId: 'lnjaiaapbakfhlbjenjkhffcdpoompki',
|
||||
firefoxSlug: 'catppuccin-web-file-icons',
|
||||
},
|
||||
{
|
||||
// WebChat: Chat with anyone on any website
|
||||
chromeId: 'cpaedhbidlpnbdfegakhiamfpndhjpgf',
|
||||
},
|
||||
{
|
||||
// YouTube Auto HD + FPS
|
||||
chromeId: 'fcphghnknhkimeagdglkljinmpbagone',
|
||||
firefoxSlug: 'youtube-auto-hd-fps',
|
||||
},
|
||||
{
|
||||
// MultiViewer Companion
|
||||
chromeId: 'lpomjgbicdemjkgmbnkjncgdebogkhlb',
|
||||
firefoxSlug: 'multiviewer-companion',
|
||||
},
|
||||
{
|
||||
// Sync Watch - Watch videos together on any site
|
||||
chromeId: 'ggiafipgeeaaahnjamgpjcgkdpanhddg',
|
||||
firefoxSlug: 'syncwatch',
|
||||
},
|
||||
{
|
||||
// Keyword Rank Checker
|
||||
chromeId: 'nmldnjcblcihmegipecakhmnieiofmgl',
|
||||
firefoxSlug: 'keyword-rank-checker-sa',
|
||||
},
|
||||
{
|
||||
// YouTube Simple View - Hide distractions & more
|
||||
chromeId: 'gppllamhaciichleihemgilcpledblpn',
|
||||
firefoxSlug: 'youtube-simple-view',
|
||||
},
|
||||
{
|
||||
// Propbar - Property Data Enhancer
|
||||
chromeId: 'pccbghdfdnnkkbcdcibchpbffdgednkf',
|
||||
},
|
||||
{
|
||||
// Text Search Pro - Search by case and whole-word match!
|
||||
chromeId: 'lfknakglefggmdkjdfhhofkjnnolffkh',
|
||||
firefoxSlug: 'text-search-pro-ext',
|
||||
},
|
||||
{
|
||||
// Invoice Generator
|
||||
chromeId: 'mbenhbocjckkbaojacmaepiameldglij',
|
||||
firefoxSlug: 'quick-invoice-generator',
|
||||
},
|
||||
{
|
||||
// Monthly Bill Tracker
|
||||
chromeId: 'phlfhkmdofajnbhgmbmjkbkdgppgoppb',
|
||||
},
|
||||
{
|
||||
// Wandpen - Instantly improve your writing with AI
|
||||
chromeId: 'macmkmchfoclhpbncclinhjflmdkaoom',
|
||||
},
|
||||
{
|
||||
// YouTube Hider - Remove Comments By Keywords, Usernames & Tools
|
||||
chromeId: 'lhmgechokhmdekdpgkkemoeecelcaonm',
|
||||
},
|
||||
{
|
||||
// QA Compass - Record standardized bug reports easily
|
||||
chromeId: 'imgheieooppmahcgniieddodaliodeeg',
|
||||
},
|
||||
{
|
||||
// aesthetic Notion, styled
|
||||
chromeId: 'npgghjedpchajflknnbngajkjkdhncdo',
|
||||
},
|
||||
{
|
||||
// Eye Dropper
|
||||
chromeId: 'hmdcmlfkchdmnmnmheododdhjedfccka',
|
||||
firefoxSlug: 'eye_dropper',
|
||||
},
|
||||
{
|
||||
// Cursorful - Screen Recorder with Auto Zoom
|
||||
chromeId: 'eihpmapodnppeemkhkbhikmggfojdkjd',
|
||||
},
|
||||
{
|
||||
// Show IP – Live View of Website IPs for Developers
|
||||
chromeId: 'hjjkgbibknbahijglkffklflidncplkn',
|
||||
},
|
||||
{
|
||||
// Strong Password Generator
|
||||
chromeId: 'ilbikcehnpkmldojkcmlldkoelofnbde',
|
||||
firefoxSlug: 'strongpasswordgenerator',
|
||||
},
|
||||
{
|
||||
// ZenGram: Mindful Instagram, Your Way
|
||||
chromeId: 'ocllfkhcdopiafndigclebelbecaiocp',
|
||||
},
|
||||
{
|
||||
// Blync: Preview Links, Selection Search, AI Assistant
|
||||
chromeId: 'odffpjnpocjfcaclnenaaaddghkgijdb',
|
||||
},
|
||||
{
|
||||
// HTML to Markdown - Convert webpages to markdown
|
||||
chromeId: 'kofbbilhmnkcmibjbioafflgmpkbnmme',
|
||||
},
|
||||
{
|
||||
// Walmart WFS Profit Calculator
|
||||
chromeId: 'boecmgggeigllcdocgioijmleimjbfkg',
|
||||
firefoxSlug: 'walmart-wfs-profit-calculator',
|
||||
},
|
||||
{
|
||||
// Youtube Live Chat Fullscreen
|
||||
chromeId: 'dlnjcbkmomenmieechnmgglgcljhoepd',
|
||||
firefoxSlug: 'youtube-live-chat-fullscreen',
|
||||
},
|
||||
{
|
||||
// Python Code Runner
|
||||
chromeId: 'keiealdacakpnbbljlmhfgcebmaadieg',
|
||||
firefoxSlug: 'code-runner-manager',
|
||||
},
|
||||
{
|
||||
// Monochromate
|
||||
chromeId: 'hafcajcllbjnoolpfngclfmmgpikdhlm',
|
||||
},
|
||||
{
|
||||
// AliasVault - Open-Source Password & (Email) Alias Manager
|
||||
chromeId: 'bmoggiinmnodjphdjnmpcnlleamkfedj',
|
||||
},
|
||||
{
|
||||
// SnapThePrice: AI-Powered Real-time Lowest Price Finder
|
||||
chromeId: 'hlnhhamckimoaiekbglafiebkfimhapb',
|
||||
},
|
||||
{
|
||||
// radiofrance - news & broadcasts (French), music (international)
|
||||
chromeId: 'gdjampjdgjmbifnhldgcnccdjkcoicmg',
|
||||
},
|
||||
{
|
||||
// Blens - Time Tracker and AI Insight
|
||||
chromeId: 'jlnhphlghikichhgbnkepenehbmloenb',
|
||||
firefoxSlug: 'blens-timetracker-ai-insight',
|
||||
},
|
||||
{
|
||||
// Always Light Mode - Setting website always in light mode
|
||||
chromeId: 'njnammmpdodmfkodnfpammnpdcbhnlcm',
|
||||
},
|
||||
{
|
||||
// DesignPicker - Color Picker & Font Detector
|
||||
chromeId: 'lblmfclcfniabobmamfkdogcgdagbhhb',
|
||||
firefoxSlug: 'design-colorpicker-fontdetect',
|
||||
},
|
||||
{
|
||||
// Web to PDF
|
||||
chromeId: 'pamnlaoeobcmhkliljfaofekeddpmfoh',
|
||||
firefoxSlug: 'export-web-to-pdf',
|
||||
},
|
||||
{
|
||||
// Online CSV Viewer
|
||||
chromeId: 'jmbcbeepjfenihlocplnbmbhimcoooka',
|
||||
firefoxSlug: 'csv-viewer',
|
||||
},
|
||||
{
|
||||
// YouTube Video Transcript
|
||||
chromeId: 'nkjcoophmpcmmgadnljnlpbpfdfacgbo',
|
||||
firefoxSlug: 'youtube-transcript-copy',
|
||||
},
|
||||
{
|
||||
// NetSuite Record Scripts
|
||||
chromeId: 'lcaieahkjgeggeiihblhcjbbjlppgieh',
|
||||
firefoxSlug: 'netsuite-scripts-manager',
|
||||
},
|
||||
{
|
||||
// VueTracker
|
||||
chromeId: 'gmocfknjllodfiomnljmaehcplnekhlo',
|
||||
},
|
||||
{
|
||||
// CanCopy - A web extension that allow you to copy any content from website
|
||||
chromeId: 'ggcfemmoabhhelfkhknhbnkmeahloiod',
|
||||
},
|
||||
{
|
||||
// Language Learning with AI
|
||||
chromeId: 'modkelfkcfjpgbfmnbnllalkiogfofhb',
|
||||
firefoxSlug: 'intersub',
|
||||
},
|
||||
{
|
||||
// Bilibili Feed History Helper
|
||||
chromeId: 'npfopljnjbamegincfjelhjhnonnjloo',
|
||||
},
|
||||
{
|
||||
// NZBDonkey - The ultimate NZB file download tool
|
||||
chromeId: 'edkhpdceeinkcacjdgebjehipmnbomce',
|
||||
},
|
||||
{
|
||||
// WeChat Markdown Editor(微信 Markdown 编辑器)
|
||||
chromeId: 'cckggnbnimdbbpmdinkkgbbncopbloob',
|
||||
},
|
||||
{
|
||||
// Tab Grab
|
||||
chromeId: 'jcblcjolcojmfopefcighfmkkefbaofg',
|
||||
firefoxSlug: 'tab-grab',
|
||||
},
|
||||
{
|
||||
// BrowserLens - https://browserlens.com/
|
||||
chromeId: 'eehmoikadcijkapfjocnhjclpbaindlb',
|
||||
firefoxSlug: 'browserlens',
|
||||
},
|
||||
{
|
||||
// Epic Games Library Extension
|
||||
chromeId: 'hfhellofkjebbchcdffmicekjdomkcmc',
|
||||
firefoxSlug: 'epic-games-library-extension',
|
||||
},
|
||||
{
|
||||
// Zen Analytics Pixel Tracker - zapt.web.app
|
||||
chromeId: 'gknigcbhlammoakmmdddkblknanpjiac',
|
||||
},
|
||||
{
|
||||
// Crypto Pulse - Compose your newtab with nature images, widgets & realtime Crypto Price & Bitcoin RSS.
|
||||
chromeId: 'cnklededohhcbmjjdlbjdkkihkgoggol',
|
||||
},
|
||||
{
|
||||
// Youtube Video Scheduler
|
||||
chromeId: 'miponnamafdenpgjemkknimgjfibicdc',
|
||||
firefoxSlug: 'youtube-video-scheduler',
|
||||
},
|
||||
{
|
||||
// Chatslator: Livestream Chat Translator
|
||||
chromeId: 'nhmbcmalgpkjbomhlhgdicanmkkaajmg',
|
||||
firefoxSlug: 'chatslator',
|
||||
},
|
||||
{
|
||||
// 公众号阅读增强器 - https://wxreader.honwhy.wang
|
||||
chromeId: 'mbamjfdjbcdgpopfnkkmlohadbbnplhm',
|
||||
},
|
||||
{
|
||||
// 토탐정
|
||||
chromeId: 'hannhecbnjnnbbafffmogdlnajpcomek',
|
||||
firefoxSlug: '토탐정',
|
||||
},
|
||||
{
|
||||
// 2FAS Pass - https://2fas.com/
|
||||
chromeId: 'ehboaofjncodknjkngdggmpdinhdoijp',
|
||||
firefoxSlug: '2fas-pass-browser-extension',
|
||||
},
|
||||
{
|
||||
// Quick Prompt - https://github.com/wenyuanw/quick-prompt
|
||||
chromeId: 'hnjamiaoicaepbkhdoknhhcedjdocpkd',
|
||||
firefoxSlug: 'quick-prompt',
|
||||
},
|
||||
{
|
||||
// Add QR Code Generator Icon Back To Address Bar
|
||||
chromeId: 'kacblhilkacgfnkjfodalohcnllcgmjd',
|
||||
},
|
||||
{
|
||||
// Piwik PRO Tracking Helper
|
||||
chromeId: 'fkbdlogfdjmpfepbbbjcgcfbgbcfcnne',
|
||||
firefoxSlug: 'piwik-pro-tracking-helper',
|
||||
},
|
||||
{
|
||||
// PIPX - Take Control of Picture-in-Picture, Automatically
|
||||
chromeId: 'nkbikckldmljjiiajklecmgmajgapbfl',
|
||||
},
|
||||
{
|
||||
// Browsely - AI-powered browser extension
|
||||
chromeId: 'hgppdobcpkfkmiegekaglonjajeojmdd',
|
||||
},
|
||||
{
|
||||
// Filmbudd Pro - Simple, private – and synced ratings and watch notes across all your devices
|
||||
chromeId: 'ehmoihnjgkdimihkhokkmfjdgomohjgm',
|
||||
},
|
||||
{
|
||||
// MultiField CopyCat - Copy, Paste & Autofill Web Forms Instantly
|
||||
chromeId: 'alglchohmdikgdjhafiicilegegieafa',
|
||||
},
|
||||
{
|
||||
// ChatSight - Add Table of Contents to ChatGPT
|
||||
chromeId: 'aamihahiiogceidpbnfgehacgiecephe',
|
||||
},
|
||||
{
|
||||
// BetterCampus (prev. BetterCanvas)
|
||||
chromeId: 'cndibmoanboadcifjkjbdpjgfedanolh',
|
||||
firefoxSlug: 'better-canvas',
|
||||
},
|
||||
{
|
||||
// Leetcode Fonts - Change fonts in leetcode effortlessly
|
||||
chromeId: 'hinfimgacobnellbncbcpdlpaapcofaa',
|
||||
},
|
||||
{
|
||||
// TranslateManga - Manga Translator & Manga Tracker
|
||||
chromeId: 'kbkbfefhhabpkibojinapkkgciiacggg',
|
||||
},
|
||||
{
|
||||
// SiteData - Free Website Traffic Checker & Reverse AdSense Tool
|
||||
chromeId: 'emeakbgdecgmdjgegnejpppcnkcnoaen',
|
||||
firefoxSlug: 'sitedata',
|
||||
},
|
||||
{
|
||||
// Livestream Chat Reader - Text-to-Speech for YouTube/Twitch chat
|
||||
chromeId: 'gpnckbhgpnjciklpoehkmligeaebigaa',
|
||||
},
|
||||
{
|
||||
// ChatGPT Token Counter - Count tokens in real time on chatgpt conversation
|
||||
chromeId: 'fjlalaedpfcojcfpkgkglbjjbbkofgnl',
|
||||
firefoxSlug: 'chatgpt-token-counter',
|
||||
},
|
||||
{
|
||||
// LinuxDo Scripts - 为 linux.do 用户提供了一些增强功能
|
||||
chromeId: 'fbgblmjbeebanackldpbmpacppflgmlj',
|
||||
firefoxSlug: 'linux_do-scripts',
|
||||
},
|
||||
{
|
||||
// Zen Virtual Piano - https://zen-piano.web.app/
|
||||
chromeId: 'dfacnjidgbagicaekenjgclfnhdnjjdi',
|
||||
},
|
||||
{
|
||||
// Crypto Pulse price tracker - https://get-crypto-pulse.web.app/
|
||||
chromeId: 'naeibcegmgpofimedkmfgjgphfhfhlab',
|
||||
},
|
||||
{
|
||||
// Redirect Web - Automatically redirect pages or open them in another app
|
||||
chromeId: 'ffglckbhfbfmdkefdmjbhpnffkcmlhdh',
|
||||
},
|
||||
{
|
||||
// Capture It - Capture & Edit Screenshots
|
||||
chromeId: 'eglpfhbhmelampoihamjomgkeobgdofl',
|
||||
},
|
||||
{
|
||||
// Teams Chat Exporter
|
||||
chromeId: 'jmghclbfbbapimhbgnpffbimphlpolnm',
|
||||
firefoxSlug: 'teams-chat-exporter',
|
||||
},
|
||||
{
|
||||
// Lofi BGM Player - Free lofi focus music for work & study
|
||||
chromeId: 'jdcppdokgfbnhiacbeplahgnciahnhck',
|
||||
firefoxSlug: 'lofi-bgm-player',
|
||||
},
|
||||
{
|
||||
// Margin - Annotate and highlight any webpage, with your notes saved to the decentralized AT Protocol.
|
||||
chromeId: 'cgpmbiiagnehkikhcbnhiagfomajncpa',
|
||||
},
|
||||
{
|
||||
// KeyFloat - Floating multilingual keyboard with native key mappings, drag, dark mode, sounds, and dynamic layouts for macOS & Windows
|
||||
chromeId: 'mfjdonmgmgcijagclnkfhmjiblbfjaid',
|
||||
},
|
||||
{
|
||||
// Glossy New Tab - Say Goodbye to Boring Tabs with live wallpapers
|
||||
chromeId: 'dhiekgdaipindoapjmcnpompdknjeijf',
|
||||
firefoxSlug: 'glossy-new-tab',
|
||||
},
|
||||
{
|
||||
// All API Hub – AI Relay & New API Manager - https://github.com/qixing-jk/all-api-hub
|
||||
chromeId: 'lapnciffpekdengooeolaienkeoilfeo',
|
||||
firefoxSlug: 'all-api-hub',
|
||||
},
|
||||
{
|
||||
// Scrape Similar - Extract data from websites into spreadsheets - https://github.com/zizzfizzix/scrape-similar
|
||||
chromeId: 'bhgobenflkkhfcgkikejaaejenoddcmo',
|
||||
},
|
||||
{
|
||||
// isTrust - https://github.com/Internet-Society-Belgium/isTrust/
|
||||
chromeId: 'kinlknncggaihnhdcalijdmpbhbflalm',
|
||||
},
|
||||
{
|
||||
// Dymo
|
||||
chromeId: 'ojpakgiekphppgkcdihbjpafobhnhlkp',
|
||||
},
|
||||
{
|
||||
// Extension Rank Checker - Extension Ranker
|
||||
chromeId: 'pmgehhllikbjmadpenhabejhpemplhmd',
|
||||
firefoxSlug: 'rank-checker',
|
||||
},
|
||||
];
|
||||
|
||||
const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds);
|
||||
const sortedExtensions = computed(() => {
|
||||
if (!data.value?.length) return [];
|
||||
const chromeIds = extensionEntries.flatMap((e) =>
|
||||
e.chromeId ? [e.chromeId] : [],
|
||||
);
|
||||
const firefoxSlugs = [
|
||||
...new Set(
|
||||
extensionEntries.flatMap((e) => (e.firefoxSlug ? [e.firefoxSlug] : [])),
|
||||
),
|
||||
];
|
||||
|
||||
return [...data.value]
|
||||
.filter((item) => item != null)
|
||||
.map((item) => ({
|
||||
...item,
|
||||
// Sort based on the user count weighted by the rating
|
||||
sortKey: ((item.rating ?? 5) / 5) * item.weeklyActiveUsers,
|
||||
}))
|
||||
.filter((item) => !!item)
|
||||
.sort((l, r) => r.sortKey - l.sortKey);
|
||||
});
|
||||
const { data, isLoading } = useListExtensionDetails(chromeIds, firefoxSlugs);
|
||||
|
||||
function getStoreUrl(extension: ChromeExtension) {
|
||||
const url = new URL(extension.storeUrl);
|
||||
function addUtmSource(storeUrl: string): string {
|
||||
const url = new URL(storeUrl);
|
||||
url.searchParams.set('utm_source', 'wxt.dev');
|
||||
return url.href;
|
||||
}
|
||||
|
||||
const sortedExtensions = computed((): ListedExtension[] => {
|
||||
if (!data.value) return [];
|
||||
|
||||
const chromeById = new Map(
|
||||
(data.value.chrome ?? []).filter(Boolean).map((e) => [e.id, e]),
|
||||
);
|
||||
const firefoxBySlug = new Map(
|
||||
(data.value.firefox ?? []).filter(Boolean).map((e) => [e.id, e]),
|
||||
);
|
||||
|
||||
const results: ListedExtension[] = [];
|
||||
|
||||
for (const entry of extensionEntries) {
|
||||
const chrome = entry.chromeId ? chromeById.get(entry.chromeId) : undefined;
|
||||
const firefox = entry.firefoxSlug
|
||||
? firefoxBySlug.get(entry.firefoxSlug)
|
||||
: undefined;
|
||||
|
||||
if (!chrome && !firefox) continue;
|
||||
|
||||
const primary = chrome ?? firefox!;
|
||||
const users = (chrome?.users ?? 0) + (firefox?.users ?? 0);
|
||||
const rating = chrome?.rating ?? firefox?.rating;
|
||||
|
||||
const stores: StoreLink[] = [];
|
||||
if (chrome) {
|
||||
stores.push({ label: 'Chrome', url: addUtmSource(chrome.storeUrl) });
|
||||
}
|
||||
if (firefox) {
|
||||
stores.push({ label: 'Firefox', url: addUtmSource(firefox.storeUrl) });
|
||||
}
|
||||
|
||||
results.push({
|
||||
id: entry.chromeId ?? `firefox:${entry.firefoxSlug}`,
|
||||
name: primary.name,
|
||||
iconUrl: primary.iconUrl,
|
||||
shortDescription: primary.shortDescription,
|
||||
users,
|
||||
rating,
|
||||
stores,
|
||||
});
|
||||
}
|
||||
|
||||
const score = (e: ListedExtension) => ((e.rating ?? 5) / 5) * e.users;
|
||||
return results.sort((a, b) => score(b) - score(a));
|
||||
});
|
||||
|
||||
function formatUsers(n: number): string {
|
||||
return `${n.toLocaleString()} users`;
|
||||
}
|
||||
|
||||
function formatStars(r: number): string {
|
||||
const rounded = Math.round(r * 10) / 10;
|
||||
return `${rounded % 1 === 0 ? rounded.toFixed(0) : rounded.toFixed(1)} stars`;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p v-if="isLoading" style="text-align: center; opacity: 50%">Loading...</p>
|
||||
<p
|
||||
v-else-if="err || sortedExtensions.length === 0"
|
||||
v-else-if="sortedExtensions.length === 0"
|
||||
style="text-align: center; opacity: 50%"
|
||||
>
|
||||
Failed to load extension details.
|
||||
</p>
|
||||
<ul v-else>
|
||||
<li
|
||||
v-for="extension of sortedExtensions"
|
||||
:key="extension.id"
|
||||
class="relative"
|
||||
>
|
||||
<ul v-else class="extension-grid">
|
||||
<li v-for="extension of sortedExtensions" :key="extension.id">
|
||||
<img
|
||||
:src="extension.iconUrl"
|
||||
:alt="`${extension.name} icon`"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<div class="relative">
|
||||
<div class="card-content">
|
||||
<a
|
||||
:href="getStoreUrl(extension)"
|
||||
:href="extension.stores[0]?.url ?? '#'"
|
||||
target="_blank"
|
||||
:title="extension.name"
|
||||
class="extension-name"
|
||||
@@ -177,14 +654,35 @@ function getStoreUrl(extension: ChromeExtension) {
|
||||
<p class="description" :title="extension.shortDescription">
|
||||
{{ extension.shortDescription }}
|
||||
</p>
|
||||
<div v-if="extension.stores.length > 0" class="store-stats">
|
||||
<span class="store-stats-info">
|
||||
<span>{{ formatUsers(extension.users) }}</span>
|
||||
<template v-if="extension.rating">
|
||||
<span class="store-stats-sep" aria-hidden="true">,</span>
|
||||
<span>{{ formatStars(extension.rating) }}</span>
|
||||
</template>
|
||||
</span>
|
||||
<span class="store-stats-sep" aria-hidden="true">·</span>
|
||||
<span class="store-links">
|
||||
<a
|
||||
v-for="(store, i) of extension.stores"
|
||||
:key="store.label"
|
||||
:href="store.url"
|
||||
target="_blank"
|
||||
class="store-link"
|
||||
:title="store.label"
|
||||
>
|
||||
{{ store.label
|
||||
}}<span
|
||||
v-if="i < extension.stores.length - 1"
|
||||
class="store-stats-sep"
|
||||
aria-hidden="true"
|
||||
>, </span
|
||||
>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="user-count">
|
||||
<span>{{ extension.weeklyActiveUsers.toLocaleString() }} users</span
|
||||
><template v-if="extension.rating != null"
|
||||
>,
|
||||
<span>{{ extension.rating }} stars</span>
|
||||
</template>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="centered pr">
|
||||
@@ -198,7 +696,7 @@ function getStoreUrl(extension: ChromeExtension) {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
li img {
|
||||
.extension-grid > li > img {
|
||||
width: 116px;
|
||||
height: 116px;
|
||||
padding: 16px;
|
||||
@@ -206,7 +704,7 @@ li img {
|
||||
background-color: var(--vp-c-default-soft);
|
||||
}
|
||||
|
||||
ul {
|
||||
.extension-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
align-items: stretch;
|
||||
@@ -216,12 +714,12 @@ ul {
|
||||
padding: 0;
|
||||
}
|
||||
@media (min-width: 960px) {
|
||||
ul {
|
||||
.extension-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
.extension-grid > li {
|
||||
margin: 0 !important;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
@@ -229,28 +727,68 @@ li {
|
||||
border-radius: 12px;
|
||||
flex: 1;
|
||||
gap: 24px;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
li a,
|
||||
li .user-count,
|
||||
li .description {
|
||||
.extension-grid > li .description {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
li .user-count {
|
||||
opacity: 70%;
|
||||
font-size: small;
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
right: 16px;
|
||||
|
||||
.extension-grid > li .card-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
li a {
|
||||
.store-stats {
|
||||
margin-top: auto;
|
||||
padding-top: 6px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
align-items: baseline;
|
||||
column-gap: 6px;
|
||||
row-gap: 4px;
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
opacity: 0.72;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.store-stats-info {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.store-stats-sep {
|
||||
opacity: 0.45;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.store-links {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.store-link {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.store-link:hover {
|
||||
color: var(--vp-c-text-1);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.extension-grid > li .extension-name {
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
@@ -259,33 +797,23 @@ li a {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
font-size: large;
|
||||
}
|
||||
li a:hover {
|
||||
|
||||
.extension-grid > li .extension-name:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
li div {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
li .description {
|
||||
.extension-grid > li .description {
|
||||
opacity: 90%;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
li .extension-name {
|
||||
font-size: large;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.pr {
|
||||
opacity: 70%;
|
||||
}
|
||||
|
||||
.relative {
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,39 +1,58 @@
|
||||
import { ref } from 'vue';
|
||||
|
||||
export interface ChromeExtension {
|
||||
export interface Extension {
|
||||
id: string;
|
||||
name: string;
|
||||
iconUrl: string;
|
||||
weeklyActiveUsers: number;
|
||||
shortDescription: string;
|
||||
storeUrl: string;
|
||||
rating: number | undefined;
|
||||
users: number;
|
||||
}
|
||||
|
||||
export interface ExtensionResults {
|
||||
chrome: Extension[];
|
||||
firefox: Extension[];
|
||||
}
|
||||
|
||||
const operationName = 'WxtDocsUsedBy';
|
||||
const query = `query ${operationName}($ids:[String!]!) {
|
||||
chromeExtensions(ids: $ids) {
|
||||
const query = `query ${operationName}($chromeIds: [String!]!, $firefoxIds: [String!]!) {
|
||||
chromeExtensions(ids: $chromeIds) {
|
||||
id
|
||||
name
|
||||
iconUrl
|
||||
weeklyActiveUsers
|
||||
shortDescription
|
||||
storeUrl
|
||||
rating
|
||||
...ExtensionData
|
||||
}
|
||||
firefoxAddons(ids: $firefoxIds) {
|
||||
id: slug
|
||||
...ExtensionData
|
||||
}
|
||||
}
|
||||
|
||||
fragment ExtensionData on Extension {
|
||||
name
|
||||
iconUrl
|
||||
shortDescription
|
||||
storeUrl
|
||||
rating
|
||||
users
|
||||
}`;
|
||||
|
||||
export default function (ids: string[]) {
|
||||
const data = ref<ChromeExtension[]>();
|
||||
export default function (chromeIds: string[], firefoxSlugs: string[]) {
|
||||
const data = ref<ExtensionResults>();
|
||||
const err = ref<unknown>();
|
||||
const isLoading = ref(true);
|
||||
|
||||
if (chromeIds.length === 0 && firefoxSlugs.length === 0) {
|
||||
data.value = { chrome: [], firefox: [] };
|
||||
isLoading.value = false;
|
||||
return { data, err, isLoading };
|
||||
}
|
||||
|
||||
fetch('https://queue.wxt.dev/api', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
operationName,
|
||||
query,
|
||||
variables: { ids },
|
||||
variables: { chromeIds, firefoxIds: firefoxSlugs },
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -41,10 +60,11 @@ export default function (ids: string[]) {
|
||||
})
|
||||
.then(async (res) => {
|
||||
isLoading.value = false;
|
||||
const {
|
||||
data: { chromeExtensions },
|
||||
} = await res.json();
|
||||
data.value = chromeExtensions;
|
||||
const { data: responseData } = await res.json();
|
||||
data.value = {
|
||||
chrome: responseData.chromeExtensions ?? [],
|
||||
firefox: responseData.firefoxAddons ?? [],
|
||||
};
|
||||
err.value = undefined;
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -54,9 +74,5 @@ export default function (ids: string[]) {
|
||||
err.value = error;
|
||||
});
|
||||
|
||||
return {
|
||||
data,
|
||||
err,
|
||||
isLoading,
|
||||
};
|
||||
return { data, err, isLoading };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user