仲裁视频会议H5

index.js 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. 'use strict';
  2. const parser = require('postcss-selector-parser');
  3. const canUnquote = require('./lib/canUnquote.js');
  4. const pseudoElements = new Set([
  5. '::before',
  6. '::after',
  7. '::first-letter',
  8. '::first-line',
  9. ]);
  10. /**
  11. * @param {parser.Attribute} selector
  12. * @return {void}
  13. */
  14. function attribute(selector) {
  15. if (selector.value) {
  16. if (selector.raws.value) {
  17. // Join selectors that are split over new lines
  18. selector.raws.value = selector.raws.value.replace(/\\\n/g, '').trim();
  19. }
  20. if (canUnquote(selector.value)) {
  21. selector.quoteMark = null;
  22. }
  23. if (selector.operator) {
  24. selector.operator = /** @type {parser.AttributeOperator} */ (
  25. selector.operator.trim()
  26. );
  27. }
  28. }
  29. selector.rawSpaceBefore = '';
  30. selector.rawSpaceAfter = '';
  31. selector.spaces.attribute = { before: '', after: '' };
  32. selector.spaces.operator = { before: '', after: '' };
  33. selector.spaces.value = {
  34. before: '',
  35. after: selector.insensitive ? ' ' : '',
  36. };
  37. if (selector.raws.spaces) {
  38. selector.raws.spaces.attribute = {
  39. before: '',
  40. after: '',
  41. };
  42. selector.raws.spaces.operator = {
  43. before: '',
  44. after: '',
  45. };
  46. selector.raws.spaces.value = {
  47. before: '',
  48. after: selector.insensitive ? ' ' : '',
  49. };
  50. if (selector.insensitive) {
  51. selector.raws.spaces.insensitive = {
  52. before: '',
  53. after: '',
  54. };
  55. }
  56. }
  57. selector.attribute = selector.attribute.trim();
  58. }
  59. /**
  60. * @param {parser.Combinator} selector
  61. * @return {void}
  62. */
  63. function combinator(selector) {
  64. const value = selector.value.trim();
  65. selector.spaces.before = '';
  66. selector.spaces.after = '';
  67. selector.rawSpaceBefore = '';
  68. selector.rawSpaceAfter = '';
  69. selector.value = value.length ? value : ' ';
  70. }
  71. const pseudoReplacements = new Map([
  72. [':nth-child', ':first-child'],
  73. [':nth-of-type', ':first-of-type'],
  74. [':nth-last-child', ':last-child'],
  75. [':nth-last-of-type', ':last-of-type'],
  76. ]);
  77. /**
  78. * @param {parser.Pseudo} selector
  79. * @return {void}
  80. */
  81. function pseudo(selector) {
  82. const value = selector.value.toLowerCase();
  83. if (selector.nodes.length === 1 && pseudoReplacements.has(value)) {
  84. const first = selector.at(0);
  85. const one = first.at(0);
  86. if (first.length === 1) {
  87. if (one.value === '1') {
  88. selector.replaceWith(
  89. parser.pseudo({
  90. value: /** @type {string} */ (pseudoReplacements.get(value)),
  91. })
  92. );
  93. }
  94. if (one.value && one.value.toLowerCase() === 'even') {
  95. one.value = '2n';
  96. }
  97. }
  98. if (first.length === 3) {
  99. const two = first.at(1);
  100. const three = first.at(2);
  101. if (
  102. one.value &&
  103. one.value.toLowerCase() === '2n' &&
  104. two.value === '+' &&
  105. three.value === '1'
  106. ) {
  107. one.value = 'odd';
  108. two.remove();
  109. three.remove();
  110. }
  111. }
  112. return;
  113. }
  114. selector.walk((child) => {
  115. if (child.type === 'selector' && child.parent) {
  116. const uniques = new Set();
  117. child.parent.each((sibling) => {
  118. const siblingStr = String(sibling);
  119. if (!uniques.has(siblingStr)) {
  120. uniques.add(siblingStr);
  121. } else {
  122. sibling.remove();
  123. }
  124. });
  125. }
  126. });
  127. if (pseudoElements.has(value)) {
  128. selector.value = selector.value.slice(1);
  129. }
  130. }
  131. const tagReplacements = new Map([
  132. ['from', '0%'],
  133. ['100%', 'to'],
  134. ]);
  135. /**
  136. * @param {parser.Tag} selector
  137. * @return {void}
  138. */
  139. function tag(selector) {
  140. const value = selector.value.toLowerCase();
  141. if (tagReplacements.has(value)) {
  142. selector.value = /** @type {string} */ (tagReplacements.get(value));
  143. }
  144. }
  145. /**
  146. * @param {parser.Universal} selector
  147. * @return {void}
  148. */
  149. function universal(selector) {
  150. const next = selector.next();
  151. if (next && next.type !== 'combinator') {
  152. selector.remove();
  153. }
  154. }
  155. const reducers = new Map(
  156. /** @type {[string, ((selector: parser.Node) => void)][]}*/ ([
  157. ['attribute', attribute],
  158. ['combinator', combinator],
  159. ['pseudo', pseudo],
  160. ['tag', tag],
  161. ['universal', universal],
  162. ])
  163. );
  164. /**
  165. * @type {import('postcss').PluginCreator<void>}
  166. * @return {import('postcss').Plugin}
  167. */
  168. function pluginCreator() {
  169. return {
  170. postcssPlugin: 'postcss-minify-selectors',
  171. OnceExit(css) {
  172. const cache = new Map();
  173. const processor = parser((selectors) => {
  174. const uniqueSelectors = new Set();
  175. selectors.walk((sel) => {
  176. // Trim whitespace around the value
  177. sel.spaces.before = sel.spaces.after = '';
  178. const reducer = reducers.get(sel.type);
  179. if (reducer !== undefined) {
  180. reducer(sel);
  181. return;
  182. }
  183. const toString = String(sel);
  184. if (
  185. sel.type === 'selector' &&
  186. sel.parent &&
  187. sel.parent.type !== 'pseudo'
  188. ) {
  189. if (!uniqueSelectors.has(toString)) {
  190. uniqueSelectors.add(toString);
  191. } else {
  192. sel.remove();
  193. }
  194. }
  195. });
  196. selectors.nodes.sort();
  197. });
  198. css.walkRules((rule) => {
  199. const selector =
  200. rule.raws.selector && rule.raws.selector.value === rule.selector
  201. ? rule.raws.selector.raw
  202. : rule.selector;
  203. // If the selector ends with a ':' it is likely a part of a custom mixin,
  204. // so just pass through.
  205. if (selector[selector.length - 1] === ':') {
  206. return;
  207. }
  208. if (cache.has(selector)) {
  209. rule.selector = cache.get(selector);
  210. return;
  211. }
  212. const optimizedSelector = processor.processSync(selector);
  213. rule.selector = optimizedSelector;
  214. cache.set(selector, optimizedSelector);
  215. });
  216. },
  217. };
  218. }
  219. pluginCreator.postcss = true;
  220. module.exports = pluginCreator;