mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-20 04:34:08 +01:00
embed free font awesome svg instead of i tag. pro icons will still work with i tag
This commit is contained in:
@@ -68,6 +68,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@braintree/sanitize-url": "^7.0.1",
|
"@braintree/sanitize-url": "^7.0.1",
|
||||||
|
"@fortawesome/fontawesome-svg-core": "^6.7.2",
|
||||||
|
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||||
|
"@fortawesome/free-regular-svg-icons": "^6.7.2",
|
||||||
|
"@fortawesome/free-solid-svg-icons": "^6.7.2",
|
||||||
"@iconify/utils": "^2.1.32",
|
"@iconify/utils": "^2.1.32",
|
||||||
"@mermaid-js/parser": "workspace:^",
|
"@mermaid-js/parser": "workspace:^",
|
||||||
"@types/d3": "^7.4.3",
|
"@types/d3": "^7.4.3",
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { replaceIconSubstring } from './createText.js';
|
import { replaceIconSubstring } from './createText.js';
|
||||||
|
import { icon } from '@fortawesome/fontawesome-svg-core';
|
||||||
|
import { faUser, faArrowRight, faHome } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { faGithub } from '@fortawesome/free-brands-svg-icons';
|
||||||
|
|
||||||
describe('replaceIconSubstring', () => {
|
describe('replaceIconSubstring', () => {
|
||||||
it('converts FontAwesome icon notations to HTML tags', () => {
|
it('converts FontAwesome icon notations to HTML tags', () => {
|
||||||
const input = 'This is an icon: fa:fa-user and fab:fa-github';
|
const input = 'This is an icon: fa:fa-user and fab:fa-github';
|
||||||
const output = replaceIconSubstring(input);
|
const output = replaceIconSubstring(input);
|
||||||
const expected =
|
const expected = `This is an icon: ${icon(faUser).html.join('')} and ${icon(faGithub).html.join('')}`;
|
||||||
"This is an icon: <i class='fa fa-user'></i> and <i class='fab fa-github'></i>";
|
|
||||||
expect(output).toEqual(expected);
|
expect(output).toEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -19,8 +21,7 @@ describe('replaceIconSubstring', () => {
|
|||||||
it('correctly processes multiple FontAwesome icon notations in one string', () => {
|
it('correctly processes multiple FontAwesome icon notations in one string', () => {
|
||||||
const input = 'Icons galore: fa:fa-arrow-right, fak:fa-truck, fas:fa-home';
|
const input = 'Icons galore: fa:fa-arrow-right, fak:fa-truck, fas:fa-home';
|
||||||
const output = replaceIconSubstring(input);
|
const output = replaceIconSubstring(input);
|
||||||
const expected =
|
const expected = `Icons galore: ${icon(faArrowRight).html.join()}, <i class='fak fa-truck'></i>, ${icon(faHome).html.join()}`;
|
||||||
"Icons galore: <i class='fa fa-arrow-right'></i>, <i class='fak fa-truck'></i>, <i class='fas fa-home'></i>";
|
|
||||||
expect(output).toEqual(expected);
|
expect(output).toEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,22 @@ import { markdownToHTML, markdownToLines } from '../rendering-util/handle-markdo
|
|||||||
import { decodeEntities } from '../utils.js';
|
import { decodeEntities } from '../utils.js';
|
||||||
import { splitLineToFitWidth } from './splitText.js';
|
import { splitLineToFitWidth } from './splitText.js';
|
||||||
import type { MarkdownLine, MarkdownWord } from './types.js';
|
import type { MarkdownLine, MarkdownWord } from './types.js';
|
||||||
|
import { library, icon } from '@fortawesome/fontawesome-svg-core';
|
||||||
|
import * as fab from '@fortawesome/free-brands-svg-icons';
|
||||||
|
import * as fas from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import * as far from '@fortawesome/free-regular-svg-icons';
|
||||||
|
|
||||||
|
const iconListFab = Object.keys(fab)
|
||||||
|
.filter((key) => key !== 'fab' && key !== 'prefix')
|
||||||
|
.map((icon) => fab[icon]);
|
||||||
|
const iconListFas = Object.keys(fas)
|
||||||
|
.filter((key) => key !== 'fas' && key !== 'prefix')
|
||||||
|
.map((icon) => fas[icon]);
|
||||||
|
const iconListFar = Object.keys(far)
|
||||||
|
.filter((key) => key !== 'far' && key !== 'prefix')
|
||||||
|
.map((icon) => far[icon]);
|
||||||
|
|
||||||
|
library.add(...iconListFab, ...iconListFas, ...iconListFar);
|
||||||
|
|
||||||
function applyStyle(dom, styleFn) {
|
function applyStyle(dom, styleFn) {
|
||||||
if (styleFn) {
|
if (styleFn) {
|
||||||
@@ -180,14 +196,36 @@ function updateTextContentAndStyles(tspan: any, wrappedLine: MarkdownWord[]) {
|
|||||||
/**
|
/**
|
||||||
* Convert fontawesome labels into fontawesome icons by using a regex pattern
|
* Convert fontawesome labels into fontawesome icons by using a regex pattern
|
||||||
* @param text - The raw string to convert
|
* @param text - The raw string to convert
|
||||||
* @returns string with fontawesome icons as i tags
|
* @returns string with fontawesome icons as i tags if they are from pro pack and as svg if they are from free pack
|
||||||
*/
|
*/
|
||||||
export function replaceIconSubstring(text: string) {
|
export function replaceIconSubstring(text) {
|
||||||
// The letters 'bklrs' stand for possible endings of the fontawesome prefix (e.g. 'fab' for brands, 'fak' for fa-kit) // cspell: disable-line
|
const iconRegex = /(fas|fab|far|fa|fal|fak|fad):fa-([a-z-]+)/g;
|
||||||
return text.replace(
|
const classNameMap = {
|
||||||
/fa[bklrs]?:fa-[\w-]+/g, // cspell: disable-line
|
fas: 'fa-solid',
|
||||||
(s) => `<i class='${s.replace(':', ' ')}'></i>`
|
fab: 'fa-brands',
|
||||||
);
|
far: 'fa-regular',
|
||||||
|
fa: 'fa',
|
||||||
|
fal: 'fa-light',
|
||||||
|
fad: 'fa-duotone',
|
||||||
|
fak: 'fak',
|
||||||
|
} as const;
|
||||||
|
const freeIconPack = ['fas', 'fab', 'far', 'fa'];
|
||||||
|
|
||||||
|
return text.replace(iconRegex, (match, prefix, iconName) => {
|
||||||
|
const isFreeIcon = freeIconPack.includes(prefix);
|
||||||
|
const className = classNameMap[prefix];
|
||||||
|
if (!isFreeIcon) {
|
||||||
|
log.warn(`Icon ${prefix}:fa-${iconName} is pro icon.`);
|
||||||
|
return `<i class='${className} fa-${iconName}'></i>`;
|
||||||
|
}
|
||||||
|
const faIcon = icon({ prefix: prefix, iconName: iconName });
|
||||||
|
if (!faIcon) {
|
||||||
|
log.warn(`Icon ${prefix}:fa-${iconName} not found.`);
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
|
return faIcon.html.join('');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note when using from flowcharts converting the API isNode means classes should be set accordingly. When using htmlLabels => to sett classes to'nodeLabel' when isNode=true otherwise 'edgeLabel'
|
// Note when using from flowcharts converting the API isNode means classes should be set accordingly. When using htmlLabels => to sett classes to'nodeLabel' when isNode=true otherwise 'edgeLabel'
|
||||||
|
|||||||
50
pnpm-lock.yaml
generated
50
pnpm-lock.yaml
generated
@@ -217,6 +217,18 @@ importers:
|
|||||||
'@braintree/sanitize-url':
|
'@braintree/sanitize-url':
|
||||||
specifier: ^7.0.1
|
specifier: ^7.0.1
|
||||||
version: 7.1.0
|
version: 7.1.0
|
||||||
|
'@fortawesome/fontawesome-svg-core':
|
||||||
|
specifier: ^6.7.2
|
||||||
|
version: 6.7.2
|
||||||
|
'@fortawesome/free-brands-svg-icons':
|
||||||
|
specifier: ^6.7.2
|
||||||
|
version: 6.7.2
|
||||||
|
'@fortawesome/free-regular-svg-icons':
|
||||||
|
specifier: ^6.7.2
|
||||||
|
version: 6.7.2
|
||||||
|
'@fortawesome/free-solid-svg-icons':
|
||||||
|
specifier: ^6.7.2
|
||||||
|
version: 6.7.2
|
||||||
'@iconify/utils':
|
'@iconify/utils':
|
||||||
specifier: ^2.1.32
|
specifier: ^2.1.32
|
||||||
version: 2.1.33
|
version: 2.1.33
|
||||||
@@ -2225,6 +2237,26 @@ packages:
|
|||||||
'@floating-ui/vue@1.1.5':
|
'@floating-ui/vue@1.1.5':
|
||||||
resolution: {integrity: sha512-ynL1p5Z+woPVSwgMGqeDrx6HrJfGIDzFyESFkyqJKilGW1+h/8yVY29Khn0LaU6wHBRwZ13ntG6reiHWK6jyzw==}
|
resolution: {integrity: sha512-ynL1p5Z+woPVSwgMGqeDrx6HrJfGIDzFyESFkyqJKilGW1+h/8yVY29Khn0LaU6wHBRwZ13ntG6reiHWK6jyzw==}
|
||||||
|
|
||||||
|
'@fortawesome/fontawesome-common-types@6.7.2':
|
||||||
|
resolution: {integrity: sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
'@fortawesome/fontawesome-svg-core@6.7.2':
|
||||||
|
resolution: {integrity: sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
'@fortawesome/free-brands-svg-icons@6.7.2':
|
||||||
|
resolution: {integrity: sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
'@fortawesome/free-regular-svg-icons@6.7.2':
|
||||||
|
resolution: {integrity: sha512-7Z/ur0gvCMW8G93dXIQOkQqHo2M5HLhYrRVC0//fakJXxcF1VmMPsxnG6Ee8qEylA8b8Q3peQXWMNZ62lYF28g==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
'@fortawesome/free-solid-svg-icons@6.7.2':
|
||||||
|
resolution: {integrity: sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
'@hapi/hoek@9.3.0':
|
'@hapi/hoek@9.3.0':
|
||||||
resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
|
resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
|
||||||
|
|
||||||
@@ -12533,6 +12565,24 @@ snapshots:
|
|||||||
- '@vue/composition-api'
|
- '@vue/composition-api'
|
||||||
- vue
|
- vue
|
||||||
|
|
||||||
|
'@fortawesome/fontawesome-common-types@6.7.2': {}
|
||||||
|
|
||||||
|
'@fortawesome/fontawesome-svg-core@6.7.2':
|
||||||
|
dependencies:
|
||||||
|
'@fortawesome/fontawesome-common-types': 6.7.2
|
||||||
|
|
||||||
|
'@fortawesome/free-brands-svg-icons@6.7.2':
|
||||||
|
dependencies:
|
||||||
|
'@fortawesome/fontawesome-common-types': 6.7.2
|
||||||
|
|
||||||
|
'@fortawesome/free-regular-svg-icons@6.7.2':
|
||||||
|
dependencies:
|
||||||
|
'@fortawesome/fontawesome-common-types': 6.7.2
|
||||||
|
|
||||||
|
'@fortawesome/free-solid-svg-icons@6.7.2':
|
||||||
|
dependencies:
|
||||||
|
'@fortawesome/fontawesome-common-types': 6.7.2
|
||||||
|
|
||||||
'@hapi/hoek@9.3.0': {}
|
'@hapi/hoek@9.3.0': {}
|
||||||
|
|
||||||
'@hapi/topo@5.1.0':
|
'@hapi/topo@5.1.0':
|
||||||
|
|||||||
Reference in New Issue
Block a user