├── .stylelintrc.json ├── .eslintrc.json ├── i18n └── aposFavicon │ ├── de.json │ ├── en.json │ ├── sk.json │ ├── fr.json │ ├── pt-BR.json │ ├── es.json │ └── it.json ├── .gitignore ├── .editorconfig ├── CHANGELOG.md ├── modules └── @apostrophecms │ └── favicon-global │ └── index.js ├── LICENSE.md ├── package.json ├── .github └── workflows │ └── main.yml ├── index.js └── README.md /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-apostrophe" 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ "apostrophe", "plugin:vue/vue3-recommended" ] 3 | } 4 | -------------------------------------------------------------------------------- /i18n/aposFavicon/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "faviconFieldLabel": "Favicon (Browser-Tab-Symbol)", 3 | "faviconGroupLabel": "Favicon" 4 | } 5 | -------------------------------------------------------------------------------- /i18n/aposFavicon/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "faviconFieldLabel": "Favicon (browser tab icon)", 3 | "faviconGroupLabel": "Favicon" 4 | } 5 | -------------------------------------------------------------------------------- /i18n/aposFavicon/sk.json: -------------------------------------------------------------------------------- 1 | { 2 | "faviconFieldLabel": "Favicon (ikona prehliadača)", 3 | "faviconGroupLabel": "Favicon" 4 | } 5 | -------------------------------------------------------------------------------- /i18n/aposFavicon/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "faviconFieldLabel": "Favicon (icône d'onglet du navigateur)", 3 | "faviconGroupLabel": "Favicon" 4 | } 5 | -------------------------------------------------------------------------------- /i18n/aposFavicon/pt-BR.json: -------------------------------------------------------------------------------- 1 | { 2 | "faviconFieldLabel": "Favicon (ícone da aba do navegador)", 3 | "faviconGroupLabel": "Favicon" 4 | } 5 | -------------------------------------------------------------------------------- /i18n/aposFavicon/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "faviconFieldLabel": "Favicon (icono de la pestaña del navegador)", 3 | "faviconGroupLabel": "Favicon" 4 | } 5 | -------------------------------------------------------------------------------- /i18n/aposFavicon/it.json: -------------------------------------------------------------------------------- 1 | { 2 | "faviconFieldLabel": "Favicon (icona della scheda del browser)", 3 | "faviconGroupLabel": "Favicon" 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore MacOS X metadata forks (fusefs) 2 | ._* 3 | package-lock.json 4 | *.DS_Store 5 | node_modules 6 | 7 | # Never commit a CSS map file, anywhere 8 | *.css.map 9 | 10 | # vim swp files 11 | .*.sw* 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | indent_size = 2 9 | indent_style = space 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.md] 14 | trim_trailing_whitespace = false 15 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.1.3 (2025-08-06) 4 | 5 | * Inject nodes rather than async Nunjucks components, to support external frontends. 6 | 7 | ## 1.1.2 (2024-10-04) 8 | 9 | * Fixes typo in README, no code changes. 10 | 11 | ## 1.1.1 (2024-10-03) 12 | 13 | * Adds translation strings. 14 | 15 | ## 1.1.0 (2024-07-10) 16 | 17 | ### Adds 18 | 19 | * Add i18n support and UI translation keys. 20 | 21 | ## 1.0.0 (2024-02-15) 22 | 23 | Initial release. 24 | -------------------------------------------------------------------------------- /modules/@apostrophecms/favicon-global/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | improve: '@apostrophecms/global', 3 | fields: { 4 | add: { 5 | favicon: { 6 | label: 'aposFavicon:faviconFieldLabel', 7 | type: 'area', 8 | options: { 9 | widgets: { 10 | '@apostrophecms/image': { 11 | minSize: [ 192, 192 ], 12 | aspectRatio: [ 1, 1 ] 13 | } 14 | }, 15 | max: 1 16 | } 17 | } 18 | }, 19 | group: { 20 | favicon: { 21 | label: 'aposFavicon:faviconGroupLabel', 22 | fields: [ 'favicon' ] 23 | } 24 | } 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 Apostrophe Technologies, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apostrophecms/favicon", 3 | "version": "1.1.3", 4 | "description": "Edit the favicon (the icon in the browser tab) within ApostropheCMS", 5 | "main": "index.js", 6 | "scripts": { 7 | "eslint": "eslint --ext .js,.vue .", 8 | "lint": "npm run eslint", 9 | "test": "npm run lint" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/apostrophecms/favicon.git" 14 | }, 15 | "homepage": "https://github.com/apostrophecms/favicon#readme", 16 | "author": "Apostrophe Technologies", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "eslint": "^8.44.0", 20 | "eslint-config-apostrophe": "^4.0.0", 21 | "eslint-config-standard": "^17.1.0", 22 | "eslint-plugin-import": "^2.22.0", 23 | "eslint-plugin-node": "^11.1.0", 24 | "eslint-plugin-promise": "^6.1.1", 25 | "eslint-plugin-standard": "^5.0.0", 26 | "eslint-plugin-vue": "^9.15.1", 27 | "stylelint": "^15.9.0", 28 | "stylelint-config-apostrophe": "^3.0.0", 29 | "vue-eslint-parser": "^9.3.1" 30 | } 31 | } -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: tests 4 | 5 | # Controls when the action will run. 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | pull_request: 10 | branches: [ '*' ] 11 | 12 | # Allows you to run this workflow manually from the Actions tab 13 | workflow_dispatch: 14 | 15 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 16 | jobs: 17 | # This workflow contains a single job called "build" 18 | build: 19 | # The type of runner that the job will run on 20 | runs-on: ubuntu-latest 21 | strategy: 22 | matrix: 23 | node-version: [16, 18, 20] 24 | mongodb-version: ['4.4', '5.0', '6.0'] 25 | 26 | # Steps represent a sequence of tasks that will be executed as part of the job 27 | steps: 28 | - name: Git checkout 29 | uses: actions/checkout@v3 30 | 31 | - name: Use Node.js ${{ matrix.node-version }} 32 | uses: actions/setup-node@v3 33 | with: 34 | node-version: ${{ matrix.node-version }} 35 | 36 | - name: Start MongoDB 37 | uses: supercharge/mongodb-github-action@1.8.0 38 | with: 39 | mongodb-version: ${{ matrix.mongodb-version }} 40 | 41 | - run: npm install 42 | 43 | - run: npm test 44 | env: 45 | CI: true 46 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | i18n: { 6 | aposFavicon: { 7 | browser: true 8 | } 9 | }, 10 | bundle: { 11 | directory: 'modules', 12 | modules: getBundleModuleNames() 13 | }, 14 | init(self) { 15 | self.appendNodes('head', 'head'); 16 | }, 17 | methods(self) { 18 | return { 19 | head(req) { 20 | const doc = req.data.global; 21 | const attachment = self.apos.image.first(doc.favicon); 22 | if (!attachment) { 23 | return []; 24 | } 25 | const href = self.apos.attachment.url(attachment, { size: 'one-third' }); 26 | if (!href) { 27 | return []; 28 | } 29 | return [ 30 | // Android 31 | { 32 | name: 'link', 33 | attrs: { 34 | rel: 'icon', 35 | href 36 | } 37 | }, 38 | // iOS 39 | { 40 | name: 'link', 41 | attrs: { 42 | rel: 'apple-touch-icon', 43 | href 44 | } 45 | } 46 | ]; 47 | } 48 | }; 49 | } 50 | }; 51 | 52 | function getBundleModuleNames() { 53 | const source = path.join(__dirname, './modules/@apostrophecms'); 54 | return fs 55 | .readdirSync(source, { withFileTypes: true }) 56 | .filter(dirent => dirent.isDirectory()) 57 | .map(dirent => `@apostrophecms/${dirent.name}`); 58 | } 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
14 | 15 | This module allows users to edit the "favicon" (browser tab icon) of the site via the global settings of the site. 16 | As such, it pairs well with the Apostrophe palette and multisite modules. 17 | 18 | ## Compatibility 19 | This version requires the latest ApostropheCMS. When adding this module to an existing project, run `npm update` to ensure all ApostropheCMS modules are up-to-date. 20 | 21 | ## Installation 22 | 23 | To install the module, use the command line to run this command in an Apostrophe project's root directory: 24 | 25 | ``` 26 | npm install @apostrophecms/favicon 27 | ``` 28 | 29 | ## Usage 30 | 31 | Configure the `@apostrophecms/favicon` module in the `app.js` file: 32 | 33 | ```javascript 34 | require('apostrophe')({ 35 | shortName: 'my-project', 36 | modules: { 37 | '@apostrophecms/favicon': {} 38 | } 39 | }); 40 | ``` 41 | 42 | You do not have to do anything else. You can access the global settings of the site 43 | via the "Gear" button in the upper right. Once there, select the "Favicon" tab and 44 | choose your preferred image. Note that a square portion of the image is automatically 45 | cropped if you do not use the cropping interface manually. 46 | 47 | There are no special requirements for images uploaded for this purpose, however you may 48 | wish to use a PNG file in order to achieve transparency effects. 49 | 50 | > Browsers vary in terms of how quickly you will see the new favicon image, but a 51 | > page refresh usually suffices. 52 | --------------------------------------------------------------------------------