fontFamily.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. "use strict";
  2. const parsers = require("../parsers");
  3. module.exports.parse = function parse(v) {
  4. if (v === "") {
  5. return v;
  6. }
  7. const keywords = [
  8. "serif",
  9. "sans-serif",
  10. "cursive",
  11. "fantasy",
  12. "monospace",
  13. "system-ui",
  14. "math",
  15. "ui-serif",
  16. "ui-sans-serif",
  17. "ui-monospace",
  18. "ui-rounded"
  19. ];
  20. const genericValues = ["fangsong", "kai", "khmer-mul", "nastaliq"];
  21. const val = parsers.splitValue(v, {
  22. delimiter: ","
  23. });
  24. const font = [];
  25. let valid = false;
  26. for (const i of val) {
  27. const str = parsers.parseString(i);
  28. if (str) {
  29. font.push(str);
  30. valid = true;
  31. continue;
  32. }
  33. const key = parsers.parseKeyword(i, keywords);
  34. if (key) {
  35. font.push(key);
  36. valid = true;
  37. continue;
  38. }
  39. const obj = parsers.parseFunction(i);
  40. if (obj) {
  41. const { name, value } = obj;
  42. if (name === "generic" && genericValues.includes(value)) {
  43. font.push(`${name}(${value})`);
  44. valid = true;
  45. continue;
  46. }
  47. }
  48. // This implementation does not strictly follow the specification.
  49. // The spec does not require the first letter of the font-family to be
  50. // capitalized, and unquoted font-family names are not restricted to ASCII.
  51. // However, in the real world, the first letter of the ASCII font-family
  52. // names are capitalized, and unquoted font-family names do not contain
  53. // spaces, e.g. `Times`. And non-ASCII font-family names are quoted even
  54. // without spaces, e.g. `"メイリオ"`.
  55. // @see https://drafts.csswg.org/css-fonts/#font-family-prop
  56. if (
  57. i !== "undefined" &&
  58. /^(?:[A-Z][A-Za-z\d-]+(?:\s+[A-Z][A-Za-z\d-]+)*|-?[a-z][a-z-]+)$/.test(i)
  59. ) {
  60. font.push(i.trim());
  61. valid = true;
  62. continue;
  63. }
  64. if (!valid) {
  65. return;
  66. }
  67. }
  68. return font.join(", ");
  69. };
  70. module.exports.isValid = function isValid(v) {
  71. if (v === "") {
  72. return true;
  73. }
  74. return typeof module.exports.parse(v) === "string";
  75. };
  76. module.exports.definition = {
  77. set(v) {
  78. v = parsers.prepareValue(v, this._global);
  79. if (parsers.hasVarFunc(v)) {
  80. this._setProperty("font", "");
  81. this._setProperty("font-family", v);
  82. } else {
  83. this._setProperty("font-family", module.exports.parse(v));
  84. }
  85. },
  86. get() {
  87. return this.getPropertyValue("font-family");
  88. },
  89. enumerable: true,
  90. configurable: true
  91. };