common.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // src/helper/css/common.ts
  2. var PSEUDO_GLOBAL_SELECTOR = ":-hono-global";
  3. var isPseudoGlobalSelectorRe = new RegExp(`^${PSEUDO_GLOBAL_SELECTOR}{(.*)}$`);
  4. var DEFAULT_STYLE_ID = "hono-css";
  5. var SELECTOR = /* @__PURE__ */ Symbol();
  6. var CLASS_NAME = /* @__PURE__ */ Symbol();
  7. var STYLE_STRING = /* @__PURE__ */ Symbol();
  8. var SELECTORS = /* @__PURE__ */ Symbol();
  9. var EXTERNAL_CLASS_NAMES = /* @__PURE__ */ Symbol();
  10. var CSS_ESCAPED = /* @__PURE__ */ Symbol();
  11. var IS_CSS_ESCAPED = /* @__PURE__ */ Symbol();
  12. var rawCssString = (value) => {
  13. return {
  14. [CSS_ESCAPED]: value
  15. };
  16. };
  17. var toHash = (str) => {
  18. let i = 0, out = 11;
  19. while (i < str.length) {
  20. out = 101 * out + str.charCodeAt(i++) >>> 0;
  21. }
  22. return "css-" + out;
  23. };
  24. var normalizeLabel = (label) => {
  25. return label.trim().replace(/\s+/g, "-");
  26. };
  27. var isValidClassName = (name) => /^-?[_a-zA-Z][_a-zA-Z0-9-]*$/.test(name);
  28. var RESERVED_KEYFRAME_NAMES = /* @__PURE__ */ new Set([
  29. "default",
  30. "inherit",
  31. "initial",
  32. "none",
  33. "revert",
  34. "revert-layer",
  35. "unset"
  36. ]);
  37. var isValidKeyframeName = (name) => isValidClassName(name) && !RESERVED_KEYFRAME_NAMES.has(name.toLowerCase());
  38. var defaultOnInvalidSlug = (slug) => {
  39. console.warn(`Invalid slug: ${slug}`);
  40. };
  41. var cssStringReStr = [
  42. '"(?:(?:\\\\[\\s\\S]|[^"\\\\])*)"',
  43. // double quoted string
  44. "'(?:(?:\\\\[\\s\\S]|[^'\\\\])*)'"
  45. // single quoted string
  46. ].join("|");
  47. var minifyCssRe = new RegExp(
  48. [
  49. "(" + cssStringReStr + ")",
  50. // $1: quoted string
  51. "(?:" + [
  52. "^\\s+",
  53. // head whitespace
  54. "\\/\\*.*?\\*\\/\\s*",
  55. // multi-line comment
  56. "\\/\\/.*\\n\\s*",
  57. // single-line comment
  58. "\\s+$"
  59. // tail whitespace
  60. ].join("|") + ")",
  61. "\\s*;\\s*(}|$)\\s*",
  62. // $2: trailing semicolon
  63. "\\s*([{};:,])\\s*",
  64. // $3: whitespace around { } : , ;
  65. "(\\s)\\s+"
  66. // $4: 2+ spaces
  67. ].join("|"),
  68. "g"
  69. );
  70. var minify = (css) => {
  71. return css.replace(minifyCssRe, (_, $1, $2, $3, $4) => $1 || $2 || $3 || $4 || "");
  72. };
  73. var buildStyleString = (strings, values) => {
  74. const selectors = [];
  75. const externalClassNames = [];
  76. const label = strings[0].match(/^\s*\/\*(.*?)\*\//)?.[1] || "";
  77. let styleString = "";
  78. for (let i = 0, len = strings.length; i < len; i++) {
  79. styleString += strings[i];
  80. let vArray = values[i];
  81. if (typeof vArray === "boolean" || vArray === null || vArray === void 0) {
  82. continue;
  83. }
  84. if (!Array.isArray(vArray)) {
  85. vArray = [vArray];
  86. }
  87. for (let j = 0, len2 = vArray.length; j < len2; j++) {
  88. let value = vArray[j];
  89. if (typeof value === "boolean" || value === null || value === void 0) {
  90. continue;
  91. }
  92. if (typeof value === "string") {
  93. if (/([\\"'\/])/.test(value)) {
  94. styleString += value.replace(/([\\"']|(?<=<)\/)/g, "\\$1");
  95. } else {
  96. styleString += value;
  97. }
  98. } else if (typeof value === "number") {
  99. styleString += value;
  100. } else if (value[CSS_ESCAPED]) {
  101. styleString += value[CSS_ESCAPED];
  102. } else if (value[CLASS_NAME].startsWith("@keyframes ")) {
  103. selectors.push(value);
  104. styleString += ` ${value[CLASS_NAME].substring(11)} `;
  105. } else {
  106. if (strings[i + 1]?.match(/^\s*{/)) {
  107. selectors.push(value);
  108. value = `.${value[CLASS_NAME]}`;
  109. } else {
  110. selectors.push(...value[SELECTORS]);
  111. externalClassNames.push(...value[EXTERNAL_CLASS_NAMES]);
  112. value = value[STYLE_STRING];
  113. const valueLen = value.length;
  114. if (valueLen > 0) {
  115. const lastChar = value[valueLen - 1];
  116. if (lastChar !== ";" && lastChar !== "}") {
  117. value += ";";
  118. }
  119. }
  120. }
  121. styleString += `${value || ""}`;
  122. }
  123. }
  124. }
  125. return [label, minify(styleString), selectors, externalClassNames];
  126. };
  127. var cssCommon = (strings, values, classNameSlug, onInvalidSlug) => {
  128. let [label, thisStyleString, selectors, externalClassNames] = buildStyleString(strings, values);
  129. const isPseudoGlobal = isPseudoGlobalSelectorRe.exec(thisStyleString);
  130. if (isPseudoGlobal) {
  131. thisStyleString = isPseudoGlobal[1];
  132. }
  133. const hash = toHash(label + thisStyleString);
  134. let customSlug;
  135. if (classNameSlug) {
  136. const slug = classNameSlug(hash, normalizeLabel(label), thisStyleString);
  137. if (slug) {
  138. if (isValidClassName(slug)) {
  139. customSlug = slug;
  140. } else {
  141. ;
  142. (onInvalidSlug || defaultOnInvalidSlug)(slug);
  143. }
  144. }
  145. }
  146. const selector = (isPseudoGlobal ? PSEUDO_GLOBAL_SELECTOR : "") + (customSlug || hash);
  147. const className = (isPseudoGlobal ? selectors.map((s) => s[CLASS_NAME]) : [selector, ...externalClassNames]).join(" ");
  148. return {
  149. [SELECTOR]: selector,
  150. [CLASS_NAME]: className,
  151. [STYLE_STRING]: thisStyleString,
  152. [SELECTORS]: selectors,
  153. [EXTERNAL_CLASS_NAMES]: externalClassNames
  154. };
  155. };
  156. var cxCommon = (args) => {
  157. for (let i = 0, len = args.length; i < len; i++) {
  158. const arg = args[i];
  159. if (typeof arg === "string") {
  160. args[i] = {
  161. [SELECTOR]: "",
  162. [CLASS_NAME]: "",
  163. [STYLE_STRING]: "",
  164. [SELECTORS]: [],
  165. [EXTERNAL_CLASS_NAMES]: [arg]
  166. };
  167. }
  168. }
  169. return args;
  170. };
  171. var keyframesCommon = (strings, values, classNameSlug, onInvalidSlug) => {
  172. const [label, styleString] = buildStyleString(strings, values);
  173. const hash = toHash(label + styleString);
  174. let customSlug;
  175. if (classNameSlug) {
  176. const slug = classNameSlug(hash, normalizeLabel(label), styleString);
  177. if (slug) {
  178. if (isValidKeyframeName(slug)) {
  179. customSlug = slug;
  180. } else {
  181. ;
  182. (onInvalidSlug || defaultOnInvalidSlug)(slug);
  183. }
  184. }
  185. }
  186. return {
  187. [SELECTOR]: "",
  188. [CLASS_NAME]: `@keyframes ${customSlug || hash}`,
  189. [STYLE_STRING]: styleString,
  190. [SELECTORS]: [],
  191. [EXTERNAL_CLASS_NAMES]: []
  192. };
  193. };
  194. var viewTransitionNameIndex = 0;
  195. var viewTransitionCommon = ((strings, values, classNameSlug, onInvalidSlug) => {
  196. if (!strings) {
  197. strings = [`/* h-v-t ${viewTransitionNameIndex++} */`];
  198. }
  199. const content = Array.isArray(strings) ? cssCommon(strings, values, classNameSlug, onInvalidSlug) : strings;
  200. const transitionName = content[CLASS_NAME];
  201. const res = cssCommon(
  202. ["view-transition-name:", ""],
  203. // eslint-disable-line @typescript-eslint/no-explicit-any
  204. [transitionName],
  205. classNameSlug,
  206. onInvalidSlug
  207. );
  208. content[CLASS_NAME] = PSEUDO_GLOBAL_SELECTOR + content[CLASS_NAME];
  209. content[STYLE_STRING] = content[STYLE_STRING].replace(
  210. /(?<=::view-transition(?:[a-z-]*)\()(?=\))/g,
  211. transitionName
  212. );
  213. res[CLASS_NAME] = res[SELECTOR] = transitionName;
  214. res[SELECTORS] = [...content[SELECTORS], content];
  215. return res;
  216. });
  217. export {
  218. CLASS_NAME,
  219. DEFAULT_STYLE_ID,
  220. EXTERNAL_CLASS_NAMES,
  221. IS_CSS_ESCAPED,
  222. PSEUDO_GLOBAL_SELECTOR,
  223. SELECTOR,
  224. SELECTORS,
  225. STYLE_STRING,
  226. buildStyleString,
  227. cssCommon,
  228. cxCommon,
  229. isPseudoGlobalSelectorRe,
  230. keyframesCommon,
  231. minify,
  232. rawCssString,
  233. viewTransitionCommon
  234. };