import.macro.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. const { createMacro, MacroError } = require('babel-plugin-macros')
  2. const { addNamed } = require('@babel/helper-module-imports')
  3. module.exports = createMacro(importer, {
  4. configName: 'fontawesome-svg-core'
  5. })
  6. const styles = [
  7. 'solid',
  8. 'regular',
  9. 'light',
  10. 'thin',
  11. 'duotone',
  12. 'brands'
  13. ]
  14. function importer ({references, state, babel, source, config}) {
  15. const license = (config !== undefined ? config.license : 'free')
  16. if (!['free', 'pro'].includes(license)) {
  17. throw new Error(
  18. "config license must be either 'free' or 'pro'"
  19. )
  20. }
  21. Object.keys(references).forEach((key) => {
  22. replace({
  23. style: key,
  24. license: (key === 'brands' ? 'free' : license),
  25. references: references[key],
  26. state,
  27. babel,
  28. source
  29. })
  30. })
  31. }
  32. function replace ({ style, license, references, state, babel, source }) {
  33. references.forEach((nodePath) => {
  34. if (canBeReplaced({ nodePath, babel, state, style })) {
  35. const iconName = nodePath.parentPath.node.arguments[0].value
  36. const name = `fa${capitalize(camelCase(iconName))}`
  37. const importFrom = `@fortawesome/${license}-${style}-svg-icons/${name}`
  38. const importName = addNamed(nodePath, name, importFrom)
  39. nodePath.parentPath.replaceWith(importName)
  40. }
  41. })
  42. }
  43. function canBeReplaced ({ nodePath, babel, state, style }) {
  44. const { types: t } = babel
  45. const { parentPath } = nodePath
  46. if (!styles.includes(style)) {
  47. throw parentPath.buildCodeFrameError(
  48. `${style} is not a valid style. Use one of ${styles.join(', ')}`,
  49. MacroError
  50. )
  51. }
  52. if (parentPath.node.arguments) {
  53. if (parentPath.node.arguments.length !== 1) {
  54. throw parentPath.buildCodeFrameError(
  55. `Received an invalid number of arguments (must be 1)`,
  56. MacroError
  57. )
  58. }
  59. if (
  60. parentPath.node.arguments.length === 1 &&
  61. t.isStringLiteral(parentPath.node.arguments[0]) &&
  62. nodePath.parentPath.node.arguments[0].value.startsWith('fa-')
  63. ) {
  64. throw parentPath.buildCodeFrameError(
  65. `Don't begin the icon name with fa-, just use ${nodePath.parentPath.node.arguments[0].value.slice(3)}`,
  66. MacroError
  67. )
  68. }
  69. if (parentPath.node.arguments.length === 1 && !t.isStringLiteral(parentPath.node.arguments[0])) {
  70. throw parentPath.buildCodeFrameError(
  71. 'Only string literals are supported when referencing icons (use a string here instead)',
  72. MacroError
  73. )
  74. }
  75. } else {
  76. throw parentPath.buildCodeFrameError(
  77. 'Pass the icon name you would like to import as an argument.',
  78. MacroError
  79. )
  80. }
  81. return true
  82. }
  83. function capitalize (str) {
  84. return str[0].toUpperCase() + str.slice(1)
  85. }
  86. function camelCase (str) {
  87. return str
  88. .split('-')
  89. .map((s, index) => {
  90. return (
  91. (index === 0 ? s[0].toLowerCase() : s[0].toUpperCase()) +
  92. s.slice(1).toLowerCase()
  93. )
  94. })
  95. .join('')
  96. }