vendor: 4,186 bytes, lines 1-180
1(function (global, factory) { 2 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 3 typeof define === 'function' && define.amd ? define(factory) : 4 (global.Splitting = factory()); 5}(this, (function () { 'use strict'; 6 7var root = document; 8var createText = root.createTextNode.bind(root); 9 10/** 11 * # setProperty 12 * Apply a CSS var 13 * @param el{HTMLElement} 14 * @param varName {string} 15 * @param value {string|number} 16 */ 17function setProperty(el, varName, value) { 18 el.style.setProperty(varName, value); 19} 20 21/** 22 * 23 * @param {Node} el 24 * @param {Node} child 25 */ 26function appendChild(el, child) { 27 return el.appendChild(child); 28} 29 30function createElement(parent, key, text, whitespace) { 31 var el = root.createElement('span'); 32 key && (el.className = key); 33 if (text) { 34 !whitespace && el.setAttribute("data-" + key, text); 35 el.textContent = text; 36 } 37 return (parent && appendChild(parent, el)) || el; 38} 39 40function getData(el, key) { 41 return el.getAttribute("data-" + key) 42} 43 44/** 45 * 46 * @param e {import('../types').Target} 47 * @param parent {HTMLElement} 48 * @returns {HTMLElement[]} 49 */ 50function $(e, parent) { 51 52 return !e || e.length == 0 53 ? // null or empty string returns empty array 54 [] 55 : e.nodeName 56 ? // a single element is wrapped in an array 57 [e] 58 : // selector and NodeList are converted to Element[] 59 [].slice.call(e[0].nodeName ? e : (parent || root).querySelectorAll(e)); 60} 61 62/** 63 * Creates and fills an array with the value provided 64 * @template {T} 65 * @param {number} len 66 * @param {() => T} valueProvider 67 * @return {T} 68 */ 69function Array2D(len) { 70 var a = []; 71 for (; len--; ) { 72 a[len] = []; 73 } 74 return a; 75} 76 77function each(items, fn) { 78 items && items.some(fn); 79} 80 81function selectFrom(obj) { 82 return function (key) { 83 return obj[key]; 84 } 85} 86 87/** 88 * # Splitting.index 89 * Index split elements and add them to a Splitting instance. 90 * 91 * @param element {HTMLElement} 92 * @param key {string} 93 * @param items {HTMLElement[] | HTMLElement[][]} 94 */ 95function index(element, key, items) { 96 var prefix = '--' + key; 97 var cssVar = prefix + "-index"; 98 99 each(items, function (items, i) { 100 if (Array.isArray(items)) { 101 each(items, function(item) { 102 setProperty(item, cssVar, i); 103 }); 104 } else { 105 setProperty(items, cssVar, i); 106 } 107 }); 108 109 setProperty(element, prefix + "-total", items.length); 110} 111 112/** 113 * @type {Record<string, import('./types').ISplittingPlugin>} 114 */ 115var plugins = {}; 116 117/** 118 * @param by {string} 119 * @param parent {string} 120 * @param deps {string[]} 121 * @return {string[]} 122 */ 123function resolvePlugins(by, parent, deps) { 124 // skip if already visited this dependency 125 var index = deps.indexOf(by); 126 if (index == -1) { 127 // if new to dependency array, add to the beginning 128 deps.unshift(by); 129 130 // recursively call this function for all dependencies 131 each(plugins[by].depends, function(p) { 132 resolvePlugins(p, by, deps); 133 }); 134 } else { 135 // if this dependency was added already move to the left of 136 // the parent dependency so it gets loaded in order 137 var indexOfParent = deps.indexOf(parent); 138 deps.splice(index, 1); 139 deps.splice(indexOfParent, 0, by); 140 } 141 return deps; 142} 143 144/** 145 * Internal utility for creating plugins... essentially to reduce 146 * the size of the library 147 * @param {string} by 148 * @param {string} key 149 * @param {string[]} depends 150 * @param {Function} split 151 * @returns {import('./types').ISplittingPlugin} 152 */ 153function createPlugin(by, depends, key, split) { 154 return { 155 by: by, 156 depends: depends, 157 key: key, 158 split: split 159 } 160} 161 162/** 163 * 164 * @param by {string} 165 * @returns {import('./types').ISplittingPlugin[]} 166 */ 167function resolve(by) { 168 return resolvePlugins(by, 0, []).map(selectFrom(plugins)); 169} 170 171/** 172 * Adds a new plugin to splitting 173 * @param opts {import('./types').ISplittingPlugin} 174 */ 175function add(opts) { 176 plugins[opts.by] = opts; 177} 178 179/** 180 * # Splitting.split
181 * Split an element's textContent into individual elements 182 * @param el {Node} Element to split 183 * @param key {string} 184 * @param splitOn {string} 185 * @param includeSpace {boolean} 186 * @returns {HTMLElement[]} 187 */ 188function splitText(el, key, splitOn, includePrevious, preserveWhitespace) { 189 // Combine any strange text nodes or empty whitespace. 190 el.normalize(); 191 192 // Use fragment to prevent unnecessary DOM thrashing. 193 var elements = []; 194 var F = document.createDocumentFragment(); 195 196 if (includePrevious) { 197 elements.push(el.previousSibling); 198 } 199 200 var allElements = []; 201 $(el.childNodes).some(function(next) { 202 if (next.tagName && !next.hasChildNodes()) { 203 // keep elements without child nodes (no text and no children) 204 allElements.push(next); 205 return; 206 } 207 // Recursively run through child nodes 208 if (next.childNodes && next.childNodes.length) { 209 allElements.push(next); 210 elements.push.apply(elements, splitText(next, key, splitOn, includePrevious, preserveWhitespace)); 211 return; 212 } 213 214 // Get the text to split, trimming out the whitespace 215 /** @type {string} */ 216 var wholeText = next.wholeText || ''; 217 var contents = wholeText.trim(); 218 219 // If there's no text left after trimming whitespace, continue the loop 220 if (contents.length) { 221 // insert leading space if there was one 222 if (wholeText[0] === ' ') { 223 allElements.push(createText(' ')); 224 } 225 // Concatenate the split text children back into the full array 226 each(contents.split(splitOn), function(splitText, i) { 227 if (i && preserveWhitespace) { 228 allElements.push(createElement(F, "whitespace", " ", preserveWhitespace)); 229 } 230 var splitEl = createElement(F, key, splitText); 231 elements.push(splitEl); 232 allElements.push(splitEl); 233 }); 234 // insert trailing space if there was one 235 if (wholeText[wholeText.length - 1] === ' ') { 236 allElements.push(createText(' ')); 237 } 238 } 239 }); 240 241 each(allElements, function(el) { 242 appendChild(F, el); 243 }); 244 245 // Clear out the existing element 246 el.innerHTML = ""; 247 appendChild(el, F); 248 return elements; 249} 250 251/** an empty value */ 252var _ = 0; 253 254function copy(dest, src) { 255 for (var k in src) { 256 dest[k] = src[k]; 257 } 258 return dest; 259} 260 261var WORDS = 'words'; 262 263var wordPlugin = createPlugin( 264 /*by: */ WORDS, 265 /*depends: */ _, 266 /*key: */ 'word', 267 /*split: */ function(el) { 268 return splitText(el, 'word', /\s+/, 0, 1) 269 } 270); 271 272var CHARS = "chars"; 273 274var charPlugin = createPlugin( 275 /*by: */ CHARS, 276 /*depends: */ [WORDS], 277 /*key: */ "char", 278 /*split: */ function(el, options, ctx) { 279 var results = []; 280 281 each(ctx[WORDS], function(word, i) { 282 results.push.apply(results, splitText(word, "char", "", options.whitespace && i)); 283 }); 284 285 return results; 286 } 287); 288 289/** 290 * # Splitting 291 * 292 * @param opts {import('./types').ISplittingOptions} 293 */ 294function Splitting (opts) { 295 opts = opts || {}; 296 var key = opts.key; 297 298 return $(opts.target || '[data-splitting]').map(function(el) { 299 300 var ctx = el['ð']; 301 if (!opts.force && ctx) { 302 return ctx; 303 } 304 305 ctx = el['ð'] = { el: el }; 306 var items = resolve(opts.by || getData(el, 'splitting') || CHARS); 307 var opts2 = copy({}, opts); 308 each(items, function(plugin) { 309 if (plugin.split) { 310 var pluginBy = plugin.by; 311 var key2 = (key ? '-' + key : '') + plugin.key; 312 var results = plugin.split(el, opts2, ctx); 313 key2 && index(el, key2, results); 314 ctx[pluginBy] = results; 315 el.classList.add(pluginBy); 316 } 317 }); 318 319 el.classList.add('splitting'); 320 return ctx; 321 }) 322} 323 324/** 325 * # Splitting.html 326 * 327 * @param opts {import('./types').ISplittingOptions} 328 */ 329function html(opts) { 330 opts = opts || {}; 331 var parent = opts.target = createElement();
vendor: 3,960 bytes, lines 332-498
332 parent.innerHTML = opts.content; 333 Splitting(opts); 334 return parent.outerHTML 335} 336 337Splitting.html = html; 338Splitting.add = add; 339 340function detectGrid(el, options, side) { 341 var items = $(options.matching || el.children, el); 342 var c = {}; 343 344 each(items, function(w) { 345 var val = Math.round(w[side]); 346 (c[val] || (c[val] = [])).push(w); 347 }); 348 349 return Object.keys(c).map(Number).sort(byNumber).map(selectFrom(c)); 350} 351 352function byNumber(a, b) { 353 return a - b; 354} 355 356var linePlugin = createPlugin( 357 /*by: */ 'lines', 358 /*depends: */ [WORDS], 359 /*key: */ 'line', 360 /*split: */ function(el, options, ctx) { 361 return detectGrid(el, { matching: ctx[WORDS] }, 'offsetTop') 362 } 363); 364 365var itemPlugin = createPlugin( 366 /*by: */ 'items', 367 /*depends: */ _, 368 /*key: */ 'item', 369 /*split: */ function(el, options) { 370 return $(options.matching || el.children, el) 371 } 372); 373 374var rowPlugin = createPlugin( 375 /*by: */ 'rows', 376 /*depends: */ _, 377 /*key: */ 'row', 378 /*split: */ function(el, options) { 379 return detectGrid(el, options, "offsetTop"); 380 } 381); 382 383var columnPlugin = createPlugin( 384 /*by: */ 'cols', 385 /*depends: */ _, 386 /*key: */ "col", 387 /*split: */ function(el, options) { 388 return detectGrid(el, options, "offsetLeft"); 389 } 390); 391 392var gridPlugin = createPlugin( 393 /*by: */ 'grid', 394 /*depends: */ ['rows', 'cols'] 395); 396 397var LAYOUT = "layout"; 398 399var layoutPlugin = createPlugin( 400 /*by: */ LAYOUT, 401 /*depends: */ _, 402 /*key: */ _, 403 /*split: */ function(el, opts) { 404 // detect and set options 405 var rows = opts.rows = +(opts.rows || getData(el, 'rows') || 1); 406 var columns = opts.columns = +(opts.columns || getData(el, 'columns') || 1); 407 408 // Seek out the first <img> if the value is true 409 opts.image = opts.image || getData(el, 'image') || el.currentSrc || el.src; 410 if (opts.image) { 411 var img = $("img", el)[0]; 412 opts.image = img && (img.currentSrc || img.src); 413 } 414 415 // add optional image to background 416 if (opts.image) { 417 setProperty(el, "background-image", "url(" + opts.image + ")"); 418 } 419 420 var totalCells = rows * columns; 421 var elements = []; 422 423 var container = createElement(_, "cell-grid"); 424 while (totalCells--) { 425 // Create a span 426 var cell = createElement(container, "cell"); 427 createElement(cell, "cell-inner"); 428 elements.push(cell); 429 } 430 431 // Append elements back into the parent 432 appendChild(el, container); 433 434 return elements; 435 } 436); 437 438var cellRowPlugin = createPlugin( 439 /*by: */ "cellRows", 440 /*depends: */ [LAYOUT], 441 /*key: */ "row", 442 /*split: */ function(el, opts, ctx) { 443 var rowCount = opts.rows; 444 var result = Array2D(rowCount); 445 446 each(ctx[LAYOUT], function(cell, i, src) { 447 result[Math.floor(i / (src.length / rowCount))].push(cell); 448 }); 449 450 return result; 451 } 452); 453 454var cellColumnPlugin = createPlugin( 455 /*by: */ "cellColumns", 456 /*depends: */ [LAYOUT], 457 /*key: */ "col", 458 /*split: */ function(el, opts, ctx) { 459 var columnCount = opts.columns; 460 var result = Array2D(columnCount); 461 462 each(ctx[LAYOUT], function(cell, i) { 463 result[i % columnCount].push(cell); 464 }); 465 466 return result; 467 } 468); 469 470var cellPlugin = createPlugin( 471 /*by: */ "cells", 472 /*depends: */ ['cellRows', 'cellColumns'], 473 /*key: */ "cell", 474 /*split: */ function(el, opt, ctx) { 475 // re-index the layout as the cells 476 return ctx[LAYOUT]; 477 } 478); 479 480// install plugins 481// word/char plugins 482add(wordPlugin); 483add(charPlugin); 484add(linePlugin); 485// grid plugins 486add(itemPlugin); 487add(rowPlugin); 488add(columnPlugin); 489add(gridPlugin); 490// cell-layout plugins 491add(layoutPlugin); 492add(cellRowPlugin); 493add(cellColumnPlugin); 494add(cellPlugin); 495 496return Splitting; 497 498})));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.