vanilla-lazyload
4 months ago
jquery.lazy.av.min.js
4 years ago
jquery.lazy.iframe.min.js
4 years ago
jquery.lazy.js
3 years ago
jquery.lazy.min.js
3 years ago
lazyload.min.js
4 years ago
loader.js
1 week ago
two_delay.js
1 week ago
two_elementor_video_to_iframe.js
4 years ago
two_lazyload.js
3 years ago
two_merge_google_font_faces.js
3 years ago
two_worker.js
2 years ago
two_yt_vi_lazyload.js
3 years ago
two_yt_vi_lazyload.min.js
3 years ago
two_merge_google_font_faces.js
255 lines
| 1 | function two_merge_google_fonts(css_code) { |
| 2 | /* https://raw.githubusercontent.com/jotform/css.js/master/css.js */ |
| 3 | /* jshint unused:false */ |
| 4 | |
| 5 | var two_cssjs = function () { |
| 6 | this.cssImportStatements = []; |
| 7 | |
| 8 | this.cssRegex = new RegExp("([\\s\\S]*?){([\\s\\S]*?)}", "gi"); |
| 9 | this.cssKeyframeRegex = "((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})"; |
| 10 | this.combinedCSSRegex = |
| 11 | // eslint-disable-next-line max-len |
| 12 | "((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})"; |
| 13 | //to match css & media queries together |
| 14 | this.cssCommentsRegex = "(\\/\\*[\\s\\S]*?\\*\\/)"; |
| 15 | this.cssImportStatementRegex = new RegExp("@import .*?;", "gi"); |
| 16 | }; |
| 17 | |
| 18 | |
| 19 | /* |
| 20 | Parses given css string, and returns css object |
| 21 | keys as selectors and values are css rules |
| 22 | eliminates all css comments before parsing |
| 23 | |
| 24 | @param source css string to be parsed |
| 25 | |
| 26 | @return object css |
| 27 | */ |
| 28 | two_cssjs.prototype.parseCSS = function (source) { |
| 29 | if (source === undefined) { |
| 30 | return []; |
| 31 | } |
| 32 | |
| 33 | var css = []; |
| 34 | //strip out comments |
| 35 | |
| 36 | //get import statements |
| 37 | |
| 38 | while (true) { |
| 39 | var imports = this.cssImportStatementRegex.exec(source); |
| 40 | if (imports !== null) { |
| 41 | this.cssImportStatements.push(imports[0]); |
| 42 | css.push({ |
| 43 | selector: "@imports", |
| 44 | type: "imports", |
| 45 | styles: imports[0], |
| 46 | }); |
| 47 | } else { |
| 48 | break; |
| 49 | } |
| 50 | } |
| 51 | source = source.replace(this.cssImportStatementRegex, ""); |
| 52 | //get keyframe statements |
| 53 | var keyframesRegex = new RegExp(this.cssKeyframeRegex, "gi"); |
| 54 | var arr; |
| 55 | while (true) { |
| 56 | arr = keyframesRegex.exec(source); |
| 57 | if (arr === null) { |
| 58 | break; |
| 59 | } |
| 60 | css.push({ |
| 61 | selector: "@keyframes", |
| 62 | type: "keyframes", |
| 63 | styles: arr[0], |
| 64 | }); |
| 65 | } |
| 66 | source = source.replace(keyframesRegex, ""); |
| 67 | |
| 68 | //unified regex |
| 69 | var unified = new RegExp(this.combinedCSSRegex, "gi"); |
| 70 | |
| 71 | while (true) { |
| 72 | arr = unified.exec(source); |
| 73 | if (arr === null) { |
| 74 | break; |
| 75 | } |
| 76 | var selector = ""; |
| 77 | if (arr[2] === undefined) { |
| 78 | selector = arr[5].split("\r\n").join("\n").trim(); |
| 79 | } else { |
| 80 | selector = arr[2].split("\r\n").join("\n").trim(); |
| 81 | } |
| 82 | |
| 83 | /* |
| 84 | fetch comments and associate it with current selector |
| 85 | */ |
| 86 | var commentsRegex = new RegExp(this.cssCommentsRegex, "gi"); |
| 87 | var comments = commentsRegex.exec(selector); |
| 88 | if (comments !== null) { |
| 89 | selector = selector.replace(commentsRegex, "").trim(); |
| 90 | } |
| 91 | |
| 92 | // Never have more than a single line break in a row |
| 93 | selector = selector.replace(/\n+/, "\n"); |
| 94 | |
| 95 | //determine the type |
| 96 | if (selector.indexOf("@media") !== -1) { |
| 97 | //we have a media query |
| 98 | var cssObject = { |
| 99 | selector: selector, |
| 100 | type: "media", |
| 101 | subStyles: this.parseCSS(arr[3] + "\n}"), //recursively parse media query inner css |
| 102 | }; |
| 103 | if (comments !== null) { |
| 104 | cssObject.comments = comments[0]; |
| 105 | } |
| 106 | css.push(cssObject); |
| 107 | } else { |
| 108 | //we have standard css |
| 109 | var rules = this.parseRules(arr[6]); |
| 110 | var style = { |
| 111 | selector: selector, |
| 112 | rules: rules, |
| 113 | }; |
| 114 | if (selector === "@font-face") { |
| 115 | style.type = "font-face"; |
| 116 | } |
| 117 | if (comments !== null) { |
| 118 | style.comments = comments[0]; |
| 119 | } |
| 120 | css.push(style); |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | return css; |
| 125 | }; |
| 126 | |
| 127 | /* |
| 128 | parses given string containing css directives |
| 129 | and returns an array of objects containing ruleName:ruleValue pairs |
| 130 | |
| 131 | @param rules, css directive string example |
| 132 | \n\ncolor:white;\n font-size:18px;\n |
| 133 | */ |
| 134 | two_cssjs.prototype.parseRules = function (rules) { |
| 135 | //convert all windows style line endings to unix style line endings |
| 136 | rules = rules.split("\r\n").join("\n"); |
| 137 | var ret = []; |
| 138 | |
| 139 | rules = rules.split(";"); |
| 140 | |
| 141 | //proccess rules line by line |
| 142 | for (var i = 0; i < rules.length; i++) { |
| 143 | var line = rules[i]; |
| 144 | |
| 145 | //determine if line is a valid css directive, ie color:white; |
| 146 | line = line.trim(); |
| 147 | if (line.indexOf(":") !== -1) { |
| 148 | //line contains : |
| 149 | line = line.split(":"); |
| 150 | var cssDirective = line[0].trim(); |
| 151 | var cssValue = line.slice(1).join(":").trim(); |
| 152 | |
| 153 | //more checks |
| 154 | if (cssDirective.length < 1 || cssValue.length < 1) { |
| 155 | continue; //there is no css directive or value that is of length 1 or 0 |
| 156 | // PLAIN WRONG WHAT ABOUT margin:0; ? |
| 157 | } |
| 158 | |
| 159 | //push rule |
| 160 | ret.push({ |
| 161 | directive: cssDirective, |
| 162 | value: cssValue, |
| 163 | }); |
| 164 | } else { |
| 165 | //if there is no ':', but what if it was mis splitted value which starts with base64 |
| 166 | if (line.trim().substr(0, 7) === "base64,") { |
| 167 | //hack :) |
| 168 | ret[ret.length - 1].value += line.trim(); |
| 169 | } else { |
| 170 | //add rule, even if it is defective |
| 171 | if (line.length > 0) { |
| 172 | ret.push({ |
| 173 | directive: "", |
| 174 | value: line, |
| 175 | defective: true, |
| 176 | }); |
| 177 | } |
| 178 | } |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | return ret; //we are done! |
| 183 | }; |
| 184 | |
| 185 | |
| 186 | let face_values = [ |
| 187 | "ascent-override", |
| 188 | "descent-override", |
| 189 | "font-display", |
| 190 | "font-family", |
| 191 | "font-stretch", |
| 192 | "font-style", |
| 193 | "font-weight", |
| 194 | "font-feature-settings", |
| 195 | "font-variation-settings", |
| 196 | "line-gap-override", |
| 197 | "size-adjust", |
| 198 | "src", |
| 199 | "unicode-range" |
| 200 | ]; |
| 201 | |
| 202 | let css = new two_cssjs(); |
| 203 | let font_faces = {}; |
| 204 | |
| 205 | for (let code of css.parseCSS(css_code)) { |
| 206 | if (code['type'] !== 'font-face') { |
| 207 | continue; |
| 208 | } |
| 209 | |
| 210 | let ff = {}; |
| 211 | for (let rule of code['rules']) { |
| 212 | ff[rule['directive']] = rule['value']; |
| 213 | } |
| 214 | |
| 215 | let key_ = ""; |
| 216 | for (let d of face_values) { |
| 217 | if (d !== 'font-weight') { |
| 218 | key_ += (ff[d]) ? ff[d] : "-"; |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | if (!font_faces[key_]) { |
| 223 | font_faces[key_] = []; |
| 224 | } |
| 225 | |
| 226 | font_faces[key_].push(ff); |
| 227 | } |
| 228 | |
| 229 | let new_css = ""; |
| 230 | for (let key_ in font_faces) { |
| 231 | |
| 232 | let font_weights = []; |
| 233 | let face_css = ""; |
| 234 | for (let face of font_faces[key_]) { |
| 235 | font_weights.push(parseInt(face['font-weight'])); |
| 236 | if (face_css === "") { |
| 237 | for (let d in face) { |
| 238 | if (d !== 'font-weight') { |
| 239 | face_css += d + ":" + face[d] + ";"; |
| 240 | } |
| 241 | } |
| 242 | } |
| 243 | } |
| 244 | |
| 245 | if (font_weights.length === 1) { |
| 246 | face_css += 'font-weight:' + font_weights[0] + ";"; |
| 247 | } else { |
| 248 | face_css += 'font-weight:' + Math.min(...font_weights) + " " + Math.max(...font_weights) + ";"; |
| 249 | } |
| 250 | |
| 251 | new_css += "@font-face {" + face_css + "}"; |
| 252 | } |
| 253 | |
| 254 | return new_css; |
| 255 | } |