Source: plugins/icon.js

/*
** Copyright © 2025 The CTAN Team and individual authors
**
** This file is distributed under the 3-clause BSD license.
** See file LICENSE for details.
*/

/**
 * The icons have logical names.
 * To ensure a certain consistency the following list is sorted by icon name.
 */
const ICON = {
  'attribute.account.account':           'mdi-account',
  'page.account':                        'mdi-account',
  'entity.account':                      'mdi-account',
  'attribute.guestbook.account':         'mdi-account',
  'attribute.upload.uploader':           'mdi-account-arrow-up-outline',
  'attribute.upload.author':             'mdi-account-badge-outline',
  'entity.author':                       'mdi-account-badge-outline',
  'attribute.author.key':                'mdi-account-badge-outline',
  'attribute.account.roles':             'mdi-account-box',
  'page.user.public':                    'mdi-account-box-outline',
  'page.admin.user-stops':               'mdi-account-cancel',
  'button.author.confirm':               'mdi-account-check-outline',
  'page.lugs':                           'mdi-account-group',
  'card.lugs':                           'mdi-account-group',
  'page.community':                      'mdi-account-group-outline',
  'item.team.former':                    'mdi-account-hard-hat',
  'item.team.member':                    'mdi-account-hard-hat-outline',
  'page.team':                           'mdi-account-hard-hat-outline',
  'role.admin':                          'mdi-account-hard-hat-outline',
  'account.unlocked':                    'mdi-account-lock-open-outline',
  'account.locked':                      'mdi-account-lock-outline',
  'button.pkg.orphaned':                 'mdi-account-off',
  'dialog.register':                     'mdi-account-plus',
  'dialog.reset':                        'mdi-account-question',
  'button.account.delete':               'mdi-account-remove',
  'attribute.cdn.contact':               'mdi-account-network-outline',
  'button.user.settings':                'mdi-account-settings',
  'page.admin.users':                    'mdi-account-wrench',
  'info.error':                          'mdi-alert-octagon-outline',
  'info.passwd.fail':                    'mdi-alert-octagon-outline',
  'license.type.nonfree':                'mdi-alert-rhombus-outline',
  'section.note':                        'mdi-alert-rhombus-outline',
  'page.api':                            'mdi-api',
  'section.pkg.docs.source':             'mdi-archive',
  'entity.archive-notes':                'mdi-archive-outline',
  'button.pkg.docs.src':                 'mdi-archive-outline',
  'file.ext.arc':                        'mdi-archive-outline',
  'file.ext.boo':                        'mdi-archive-outline',
  'file.ext.gz':                         'mdi-archive-outline',
  'file.ext.hqx':                        'mdi-archive-outline',
  'file.ext.xz':                         'mdi-archive-outline',
  'file.ext.zip':                        'mdi-archive-outline',
  'button.backward':                     'mdi-arrow-left',
  'button.back':                         'mdi-arrow-left-bold',
  'button.foreward':                     'mdi-arrow-right',
  'button.visit':                        'mdi-arrow-top-right-bold-outline',
  'file.type.l':                         'mdi-arrow-u-right-bottom',
  'gender.x':                            'mdi-baby-face-outline',
  'attribute.account.name':              'mdi-badge-account-outline',
  'tab.pkg.summary':                     'mdi-book',
  'page.admin.guestbook':                'mdi-book-account-outline',
  'page.admin.guestbook.stops':          'mdi-book-cancel-outline',
  'page.help.ctan':                      'mdi-book-open-page-variant-outline',
  'tab.my.pages':                        'mdi-book-open-variant',
  'page.browse':                         'mdi-bookshelf',
  'tab.pkg.docs':                        'mdi-bookshelf',
  'attribute.pkg.bugs':                  'mdi-bug-outline',
  'attribute.upload.bugs':               'mdi-bug-outline',
  'attribute.message.to':                'mdi-calendar-end-outline',
  'attribute.upload.created':            'mdi-calendar-outline',
  'attribute.upload.updated':            'mdi-calendar-outline',
  'attribute.account.created':           'mdi-calendar-start-outline',
  'attribute.guestbook.created':         'mdi-calendar-start-outline',
  'attribute.message.from':              'mdi-calendar-start-outline',
  'page.my.data':                        'mdi-card-account-details-outline',
  'tab.my.data':                         'mdi-card-account-details-outline',
  'page.my.packages':                    'mdi-card-multiple-outline',
  'tab.my.packages':                     'mdi-card-multiple-outline',
  'page.packages':                       'mdi-card-multiple-outline',
  'tab.packages':                        'mdi-card-multiple-outline',
  'label.pkg.bibtex.key':                'mdi-card-text',
  'attribute.upload.description':        'mdi-card-text',
  'attribute.guestbook.text':            'mdi-card-text-outline',
  'attribute.upload.summary':            'mdi-card-text-outline',
  'tab.pkg.abstract':                    'mdi-card-text-outline',
  'attribute.rating.comment':            'mdi-card-text-outline',
  'attribute.rating.expertise':          'mdi-certificate-outline',
  'card.statistics.upload':              'mdi-chart-box-outline',
  'state.ok':                            'mdi-check',
  'account.enabled.true':                'mdi-check-circle-outline',
  'page.cdn.monitor':                    'mdi-check-network-outline',
  'checkbox.off':                        'mdi-checkbox-blank-outline',
  'checkbox.on':                         'mdi-checkbox-marked-outline',
  'breadcrumb.sep':                      'mdi-chevron-right',
  'expertise.full':                      'mdi-circle',
  'carousel.delimiter':                  'mdi-circle-double',
  'page.item':                           'mdi-circle-medium',
  'expertise.empty':                     'mdi-circle-outline',
  'animation.0':                         'mdi-circle-outline',
  'animation.1':                         'mdi-circle-slice-2',
  'animation.2':                         'mdi-circle-slice-4',
  'animation.3':                         'mdi-circle-slice-6',
  'attribute.account.city':              'mdi-city',
  'attribute.cdn.city':                  'mdi-city',
  'markdown.input':                      'mdi-clipboard-edit-outline',
  'page.admin.jobs':                     'mdi-clock-start',
  'button.clear':                        'mdi-close',
  'button.close':                        'mdi-close',
  'attribute.stopword.word':             'mdi-close-octagon-outline',
  'section.json':                        'mdi-code-json',
  'markdown.tab.source':                 'mdi-code-tags',
  'page.admin':                          'mdi-cogs',
  'attribute.upload.note':               'mdi-comment-outline',
  'attribute.guestbook.title':           'mdi-comment-alert',
  'section.ratings.all':                 'mdi-comment-multiple-outline',
  'section.ratings.my':                  'mdi-comment-outline',
  'button.guestbook.add':                'mdi-comment-plus-outline',
  'dialog.guestbook.add':                'mdi-comment-plus-outline',
  'attribute.guestbook.comment':         'mdi-comment-text',
  'page.guestbook':                      'mdi-comment-text-multiple-outline',
  'attribute.guestbook.section':         'mdi-comment-text-outline',
  'button.save':                         'mdi-content-save-outline',
  'attribute.pkg.repository':            'mdi-database-outline',
  'attribute.upload.repository':         'mdi-database-outline',
  'button.delete':                       'mdi-delete-outline',
  'card.dvd':                            'mdi-disc',
  'tab.pkg.install.mactex':              'mdi-disc',
  'tab.pkg.install.miktex':              'mdi-disc',
  'tab.pkg.install.texlive':             'mdi-disc',
  'button.settings':                     'mdi-dots-vertical',
  'button.download':                     'mdi-download',
  'tab.download':                        'mdi-download',
  'tab.pkg.install.download':            'mdi-download',
  'tab.pkg.install':                     'mdi-download',
  'card.distribution.intro':             'mdi-download',
  'card.distribution.mactex':            'mdi-download',
  'card.distribution.miktex':            'mdi-download',
  'card.distribution.texlive':           'mdi-download',
  'attribute.cdn.region':                'mdi-earth',
  'attribute.upload.notify':             'mdi-email-check',
  'button.feedback':                     'mdi-email-fast',
  'page.admin.notifications':            'mdi-email-fast-outline',
  'page.contact':                        'mdi-email-fast-outline',
  'attribute.lug.newsletter':            'mdi-email-multiple-outline',
  'attribute.upload.mailinglist':        'mdi-email-newsletter',
  'tab.pkg.announce':                    'mdi-email-newsletter',
  'attribute.account.email':             'mdi-email-outline',
  'attribute.email':                     'mdi-email-outline',
  'attribute.guestbook.email':           'mdi-email-outline',
  'attribute.lug.email':                 'mdi-email-outline',
  'attribute.cdn.email':                 'mdi-email-outline',
  'attribute.upload.email':              'mdi-email-outline',
  'dialog.register-ack':                 'mdi-email-outline',
  'state.error':                         'mdi-exclamation-thick',
  'button.password.show':                'mdi-eye-outline',
  'field.view':                          'mdi-eye-outline',
  'button.password.hide':                'mdi-eye-off-outline',
  'button.view.settings':                'mdi-eye-settings-outline',
  'file.type.x':                         'mdi-file',
  'file.ext.html':                       'mdi-file-code-outline',
  'file.name.makefile':                  'mdi-file-cog',
  'file.name.Makefile':                  'mdi-file-cog',
  'file.ext.bst':                        'mdi-file-cog-outline',
  'file.ext.cls':                        'mdi-file-cog-outline',
  'file.ext.dtx':                        'mdi-file-cog-outline',
  'file.ext.ist':                        'mdi-file-cog-outline',
  'file.ext.sty':                        'mdi-file-cog-outline',
  'file.ext.dvi':                        'mdi-file-document',
  'file.ext.pdf':                        'mdi-file-document',
  'file.ext.ps':                         'mdi-file-document',
  'file.ext.tex':                        'mdi-file-document',
  'file.ext.latex':                      'mdi-file-document-outline',
  'file.ext.ltx':                        'mdi-file-document-outline',
  'file.ext.tex':                        'mdi-file-document-outline',
  'tab.pkg.bibtex':                      'mdi-file-document-outline',
  'file.ext.eps':                        'mdi-file-image-outline',
  'file.ext.gif':                        'mdi-file-image-outline',
  'file.ext.jpeg':                       'mdi-file-image-outline',
  'file.ext.jpg':                        'mdi-file-image-outline',
  'file.ext.png':                        'mdi-file-image-outline',
  'file.ext.tif':                        'mdi-file-image-outline',
  'page.help.lion.files':                'mdi-file-image-outline',
  'tab.files':                           'mdi-file-multiple-outline', // 
  'file.type.f':                         'mdi-file-outline',
  'field.pkg.bibtex.type':               'mdi-file-star-four-points-outline',
  'page.upload.file':                    'mdi-file-upload-outline',
  'attribute.upload.file':               'mdi-file-upload-outline',
  'button.filter':                       'mdi-filter',
  'attribute.filter':                    'mdi-filter',
  'button.menu.search':                  'mdi-filter-menu-outline',
  'page.filter.none':                    'mdi-filter-off-outline',
  'page.filter.list':                    'mdi-filter-outline',
  'attribute.account.country':           'mdi-flag-outline',
  'attribute.cdn.country':               'mdi-flag-outline',
  'error.message':                       'mdi-flash-triangle-outline',
  'card.tex-archive':                    'mdi-folder-multiple-outline',
  'page.tex-archive':                    'mdi-folder-multiple-outline',
  'file.type.d.open':                    'mdi-folder-open-outline',
  'file.type.directory.open':            'mdi-folder-open-outline',
  'file.type.d':                         'mdi-folder-outline',
  'attribute.upload.path':               'mdi-folder-outline',
  'file.type.directory':                 'mdi-folder-outline',
  'attribute.tex-archive-notes.path':    'mdi-folder-outline',
  'attribute.tex-archive-notes.text.de': 'mdi-folder-text',
  'attribute.tex-archive-notes.text.en': 'mdi-folder-text-outline',
  'page.changelog':                      'mdi-format-list-text',
  'page.changelog.item':                 'mdi-format-list-bulleted-square',
  'attribute.license.text':              'mdi-format-section',
  'entity.license':                      'mdi-gavel',
  'page.licenses':                       'mdi-gavel',
  'card.licenses':                       'mdi-gavel',
  'entity.pkg.obsolete':                 'mdi-hand-front-right-outline',
  'pkg.orphaned':                        'mdi-hand-pointing-up',
  'item.team.role':                      'mdi-hard-hat',
  'tip.title':                           'mdi-head-question',
  'page.help':                           'mdi-help-box-multiple-outline',
  'attribute.pkg.support':               'mdi-help-circle-outline',
  'attribute.upload.support':            'mdi-help-circle-outline',
  'card.wanted':                         'mdi-hand-front-right-outline',
  'page.cover':                          'mdi-home',
  'page.user.home':                      'mdi-home-account',
  'attribute.pkg.home':                  'mdi-home-outline',
  'attribute.upload.home':               'mdi-home-outline',
  'gender.f':                            'mdi-human-female',
  'gender.m':                            'mdi-human-male',
  'gender.g':                            'mdi-human-queue',
  'attribute.license.key':               'mdi-identifier',
  'file.readme':                         'mdi-information',
  'file.name.readme':                    'mdi-information',
  'file.name.README':                    'mdi-information',
  'file.name.Readme':                    'mdi-information',
  'card.tex':                            'mdi-information-outline',
  'info.i':                              'mdi-information-outline',
  'file.name.README.md':                 'mdi-information-outline',
  'page.about':                          'mdi-information-outline',
  'search.message.I':                    'mdi-information-outline',
  'tab.readme':                          'mdi-information-outline',
  'attribute.account.passwd.1':          'mdi-key-variant',
  'attribute.account.passwd.2':          'mdi-key-variant',
  'page.admin.catalogue':                'mdi-library-shelves',
  'file.ext.bib':                        'mdi-library-shelves',
  'file.name.COPYING':                   'mdi-license',
  'file.name.LICENSE':                   'mdi-license',
  'button.search.help':                  'mdi-lifebuoy',
  'page.help.faq':                       'mdi-lightbulb-question-outline',
  'search.message.E':                    'mdi-lightning-bolt-circle',
  'attribute.license.url':               'mdi-link',
  'button.link':                         'mdi-link-variant',
  'button.login':                        'mdi-login-variant',
  'button.logout':                       'mdi-logout',
  'page.search':                         'mdi-magnify',
  'button.search':                       'mdi-magnify',
  'button.search.close':                 'mdi-magnify-minus-outline',
  'button.search.open':                  'mdi-magnify-plus-outline',
  'button.search.reset':                 'mdi-magnify-remove-outline',
  'attribute.lug.address':               'mdi-mail',
  'tab.my.visited':                      'mdi-map-marker-multiple-outline',
  'page.visited':                        'mdi-map-marker-multiple-outline',
  'tab.visited':                         'mdi-map-marker-multiple-outline',
  'indicator.visited':                   'mdi-map-marker-outline',
  'page.sitemap':                        'mdi-map-outline',
  'button.menu.left':                    'mdi-menu-left-outline',
  'button.menu.right':                   'mdi-menu-right-outline',
  'button.menu.down':                    'mdi-menu-down',
  'page.admin.message':                  'mdi-message-fast-outline',
  'page.admin.messages':                 'mdi-message-outline',
  'attribute.upload.announcement':       'mdi-message-outline',
  'attribute.feedback.concern':          'mdi-message-question',
  'attribute.feedback.reply':            'mdi-message-reply-text-outline',
  'attribute.message.title':             'mdi-message-text',
  'card.message':                        'mdi-message-text-fast-outline',
  'attribute.message.text':              'mdi-message-text-outline',
  'card.cdn':                            'mdi-mirror',
  'page.cdn':                            'mdi-mirror',
  'page.cdn.list':                       'mdi-mirror',
  'page.cdn.become':                     'mdi-mirror-variant',
  'markdown.tab.preview':                'mdi-monitor',
  'theme.dark':                          'mdi-moon-waning-crescent',
  'pkg.new':                             'mdi-new-box',
  'page.ctan-ann':                       'mdi-newspaper-variant-multiple-outline',
  'entity.announcement':                 'mdi-newspaper-variant-outline',
  'attribute.ctan-ann.summary':          'mdi-newspaper-variant-outline',
  'attribute.lug.periodical':            'mdi-newspaper-variant-outline',
  'attribute.pkg.announce':              'mdi-newspaper-variant-outline',
  'attribute.upload.announce':           'mdi-newspaper-variant-outline',
  'page.announcement':                   'mdi-newspaper-variant-outline',
  'attribute.pkg.version':               'mdi-numeric',
  'attribute.upload.version':            'mdi-numeric',
  'section.packages':                    'mdi-package',
  'entity.pkg.open':                     'mdi-package-variant',
  'entity.pkg':                          'mdi-package-variant-closed',
  'card.package':                        'mdi-package-variant-closed',
  'tab.package':                         'mdi-package-variant-closed',
  'tab.pkg':                             'mdi-package-variant-closed',
  'pkg.exists':                          'mdi-package-variant-closed-check',
  'tab.install.pkg':                     'mdi-package-variant-closed-plus',
  'section.contributions':               'mdi-package-variant-closed-plus',
  'button.ctrl.pause':                   'mdi-pause',
  'attribute.cdn.notes':                 'mdi-pen',
  'field.edit':                          'mdi-pen',
  'section.my.settings':                 'mdi-pen',
  'field.create':                        'mdi-pen-plus',
  'field.edit.default':                  'mdi-pencil-circle-outline',
  'page.markdown':                       'mdi-pencil-ruler-outline',
  'page.help.markdown':                  'mdi-pencil-ruler-outline',
  'button.ctrl.play':                    'mdi.play',
  'button.create':                       'mdi-plus-circle-outline',
  'button.cdn.submit':                   'mdi-plus-circle-outline',
  'page.cdn.register':                   'mdi-plus-network-outline',
  'attribute.message.type':              'mdi-pound',
  'dialog.login':                        'mdi-power',
  'account.enabled.false':               'mdi-progress-question',
  'page.incoming':                       'mdi-progress-upload',
  'page.upload.incoming':                'mdi-progress-upload',
  'attribute.cdn.ftp':                   'mdi-protocol',
  'attribute.cdn.http':                  'mdi-protocol',
  'attribute.cdn.https':                 'mdi-protocol',
  'attribute.cdn.rsync':                 'mdi-protocol',
  'attribute.upload.type':               'mdi-radar',
  'button.reset':                        'mdi-restore',
  'page.admin.run':                      'mdi-run',
  'page.admin.logs.apache':              'mdi-script-text',
  'page.admin.logs.server':              'mdi-script-text',
  'page.admin.logs.update':              'mdi-script-text',
  'button.search.history':               'mdi-select-search',
  'attribute.cdn.name':                  'mdi-server',
  'attribute.upload.server':             'mdi-server-network',
  'page.privacy':                        'mdi-shield-check',
  'card.password':                       'mdi-shield-key-outline',
  'dialog.password':                     'mdi-shield-key-outline',
  'account.locked.true':                 'mdi-shield-lock-outline',
  'account.locked.false':                'mdi-shield-lock-open-outline',
  'attribute.account.password':          'mdi-shield-lock-open-outline',
  'dialog.passwd':                       'mdi-shield-refresh-outline',
  'attribute.lug.languages':             'mdi-sign-language',
  'button.ctrl.next':                    'mdi-skip-next',
  'button.ctrl.previous':                'mdi-skip-previous',
  'star.full':                           'mdi-star',
  'label.my.rating':                     'mdi-star-box-multiple-outline',
  'tab.pkg.ratings':                     'mdi-star-box-multiple-outline',
  'tab.my.ratings':                      'mdi-star-box-multiple-outline',
  'star.half':                           'mdi-star-half',
  'star.empty':                          'mdi-star-outline',
  'attribute.upload.status':             'mdi-state-machine',
  'list.end':                            'mdi-stop',
  'entity.tex-archive-notes':            'mdi-subtitles-outline',
  'page.credits':                        'mdi-subtitles-outline',
  'attribute.pkg.topics':                'mdi-tag-multiple-outline',
  'attribute.upload.topics':             'mdi-tag-multiple-outline',
  'card.topics':                         'mdi-tag-multiple-outline',
  'page.topics':                         'mdi-tag-multiple-outline',
  'entity.topic':                        'mdi-tag-outline',
  'attribute.license.details':           'mdi-text',
  'attribute.account.description':       'mdi-text-account',
  'page.help.markdown':                  'mdi-text-box',
  'tab.markdown':                        'mdi-text-box',
  'page.admin.logs':                     'mdi-text-box-multiple-outline',
  'attribute.license.name':              'mdi-text-box-outline',
  'page.admin.search':                   'mdi-text-search',
  'button.no':                           'mdi-thumb-down-outline',
  'license.type.free':                   'mdi-thumb-up-outline',
  'button.yes':                          'mdi-thumb-up-outline',
  'info.passwd.ok':                      'mdi-thumb-up-outline',
  'dialog.confirm':                      'mdi-thumbs-up-down-outline',
  'page.admin.tickets':                  'mdi-ticket-confirmation-outline',
  'attribute.ticket.key':                'mdi-ticket-outline',
  'tab.install':                         'mdi-tools',
  'attribute.pkg.development':           'mdi-tools',
  'attribute.upload.development':        'mdi-tools',
  'button.help.on':                      'mdi-tooltip-question',
  'button.help.off':                     'mdi-tooltip-question-outline',
  'button.upload':                       'mdi-upload',
  'card.upload':                         'mdi-upload',
  'page.upload':                         'mdi-upload',
  'page.admin.uploads':                  'mdi-upload-multiple',
  'button.upload.new':                   'mdi-upload-outline',
  'button.view.list':                    'mdi-view-list',
  'button.view-cards':                   'mdi-view-module',
  'entity.rating':                       'mdi-vote-outline',
  'theme.light':                         'mdi-weather-sunny',
  'attribute.lug.site':                  'mdi-web',
  'page.api.xml':                        'mdi-xml',
  'page.help.lion':                      'mdi-zodiac-leo'
}

/**
 * This is the plug-in for accessing the icons with logical names.
 *
 * @author Gerd Neugebauer <gene@ctan.org>
 */
export default defineNuxtPlugin(nuxtApp => {

  /**
   * Map the logical icon name to the mdi name.
   * If the name starts with mdi_ then the argument is returned unchanged.
   */
  nuxtApp.provide('icon', (name) =>  {
    return name.startsWith('mdi-') ? name : ICON[name]
  })

  /**
   * Provide access to the file type information.
   */
  nuxtApp.provide('filetype', {
    /**
     * Provide access to the icon information.
     */
    icon: (name, type) =>  {
      if (type === 'f') {
        const ext = name.replaceAll(/.*\./g, '.')
        let icon = ICON[`file.ext${ext}`]
        if (icon !== undefined) {
          return icon
        }
        icon = ICON[`file.name.${name}`]
        if (icon !== undefined) {
          return icon
        }
      }
      return ICON[`file.type.${type}`]
    },

    /**
     *
     */
    size: (bytes) => {
      if (bytes > 1000000) {
        return `${Math.floor(bytes / 1000000)}MB`
      }
      if (bytes > 1000) {
        return `${Math.floor(bytes / 1000)}kB`
      }
      return `${bytes}B`
    }
  })
})