text-slicer 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintignore ADDED
@@ -0,0 +1,3 @@
1
+ node_modules
2
+ .parcel
3
+ dist
package/.eslintrc.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "env": {
3
+ "browser": true,
4
+ "es2021": true
5
+ },
6
+ "extends": [
7
+ "airbnb-base"
8
+ ],
9
+ "parserOptions": {
10
+ "ecmaVersion": "latest",
11
+ "sourceType": "module"
12
+ },
13
+ "rules": {
14
+ "max-len": [
15
+ "off",
16
+ {
17
+ "code": 100,
18
+ "ignoreUrls": true
19
+ }
20
+ ]
21
+ }
22
+ }
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  </div>
11
11
 
12
12
  <p align="center">TextSlicer is designed to split text within an HTML element into separate words and/or characters, wrapping each word and/or character in separate span elements.</p>
13
- <p align="center"><sup>850B gzipped</sup></p>
13
+ <p align="center"><sup>750B gzipped</sup></p>
14
14
  <p align="center"><a href="https://codepen.io/ux-ui/full/vYMoGoG">Demo</a></p>
15
15
  <br>
16
16
 
@@ -41,8 +41,9 @@ textSlicer.init();
41
41
  document.addEventListener('DOMContentLoaded', () => {
42
42
  const textSlicer = new TextSlicer({
43
43
  container: '.text-slicer',
44
- mode: 'both',
44
+ splitMode: 'both',
45
45
  cssVariables: true,
46
+ dataAttributes: true,
46
47
  });
47
48
 
48
49
  textSlicer.init();
@@ -0,0 +1,13 @@
1
+ export default class TextSlicer {
2
+ constructor(options?: {
3
+ container?: HTMLElement | string;
4
+ splitMode?: 'words' | 'chars' | 'both';
5
+ cssVariables?: boolean;
6
+ dataAttributes?: boolean;
7
+ });
8
+ split(): void;
9
+ init(): void;
10
+ }
11
+ export default TextSlicer;
12
+
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"mappings":"AAAA,qBAAM,UAAU;gBAQK,OAAO,GAAE;QAC1B,SAAS,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;QACjC,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;QACvC,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,cAAc,CAAC,EAAE,OAAO,CAAC;KACrB;IAsBC,KAAK,IAAI,IAAI;IA0Gb,IAAI,IAAI,IAAI;CAGpB;AAED,eAAe,UAAU,CAAC","sources":["src/src/index.ts","src/index.ts"],"sourcesContent":[null,"class TextSlicer {\n private readonly textElement: HTMLElement | null;\n private originalText: string;\n private readonly splitMode: 'words' | 'chars' | 'both';\n private readonly cssVariables: boolean;\n private readonly dataAttributes: boolean;\n private charIndexCounter: number;\n\n public constructor(options: {\n container?: HTMLElement | string;\n splitMode?: 'words' | 'chars' | 'both';\n cssVariables?: boolean;\n dataAttributes?: boolean;\n } = {}) {\n this.textElement =\n options.container instanceof HTMLElement\n ? options.container\n : document.querySelector(options.container || '.text-slicer');\n\n if (!this.textElement) {\n this.originalText = '';\n this.splitMode = 'both';\n this.cssVariables = false;\n this.dataAttributes = false;\n this.charIndexCounter = 0;\n return;\n }\n\n this.originalText = this.textElement.textContent?.trim() || '';\n this.splitMode = options.splitMode || 'both';\n this.cssVariables = options.cssVariables || false;\n this.dataAttributes = options.dataAttributes || false;\n this.charIndexCounter = 0;\n }\n\n public split(): void {\n if (!this.textElement) return;\n\n this.clear();\n this.charIndexCounter = 0;\n\n const fragment = document.createDocumentFragment();\n const words = this.originalText.split(' ');\n const charCount = this.originalText.length;\n\n if (this.splitMode === 'words' || this.splitMode === 'both') {\n this.splitWords(fragment, words);\n } else if (this.splitMode === 'chars') {\n this.splitChars(fragment);\n }\n\n this.textElement.appendChild(fragment);\n\n if (this.cssVariables) {\n this.textElement.style.setProperty('--word-total', words.length.toString());\n this.textElement.style.setProperty('--char-total', charCount.toString());\n }\n }\n\n private splitWords(fragment: DocumentFragment, words: string[]): void {\n words.forEach((word, wordIndex) => {\n if (this.splitMode === 'both') {\n const wordSpan = this.createWordSpan(wordIndex, word);\n\n word.split('').forEach((char) => {\n const charSpan = this.createCharSpan(char);\n wordSpan.append(charSpan);\n });\n\n fragment.append(wordSpan);\n } else {\n const wordSpan = this.createWordSpan(wordIndex);\n wordSpan.append(document.createTextNode(word));\n fragment.append(wordSpan);\n }\n\n if (wordIndex < words.length - 1) {\n fragment.append(TextSlicer.createSpaceSpan());\n }\n });\n }\n\n private splitChars(fragment: DocumentFragment): void {\n this.originalText.split('').forEach((char) => {\n const charSpan = this.createCharSpan(char);\n fragment.append(charSpan);\n });\n }\n\n private createWordSpan(index: number, word: string = ''): HTMLElement {\n const wordSpan = document.createElement('span');\n wordSpan.classList.add('word');\n\n if (this.dataAttributes) {\n wordSpan.setAttribute('data-word', word);\n }\n\n if (this.cssVariables) {\n wordSpan.style.setProperty('--word-index', index.toString());\n }\n\n return wordSpan;\n }\n\n private createCharSpan(char: string): HTMLElement {\n const charSpan = document.createElement('span');\n charSpan.textContent = char;\n\n if (this.dataAttributes) {\n charSpan.setAttribute('data-char', char);\n }\n\n if (char === ' ') {\n charSpan.classList.add('whitespace');\n } else {\n charSpan.classList.add('char');\n\n if (this.cssVariables) {\n charSpan.style.setProperty('--char-index', this.charIndexCounter.toString());\n }\n\n this.charIndexCounter += 1;\n }\n\n return charSpan;\n }\n\n private static createSpaceSpan(): HTMLElement {\n const spaceSpan = document.createElement('span');\n spaceSpan.classList.add('whitespace');\n spaceSpan.textContent = ' ';\n\n return spaceSpan;\n }\n\n private clear(): void {\n if (this.textElement) {\n this.textElement.innerHTML = '';\n }\n }\n\n public init(): void {\n this.split();\n }\n}\n\nexport default TextSlicer;\n"],"names":[],"version":3,"file":"index.d.ts.map"}
package/dist/index.js CHANGED
@@ -9,100 +9,95 @@ function $parcel$export(e, n, v, s) {
9
9
 
10
10
  $parcel$defineInteropFlag(module.exports);
11
11
 
12
- $parcel$export(module.exports, "default", function () { return $70cf2c47938f006f$export$2e2bcd8739ae039; });
13
- class $70cf2c47938f006f$var$TextSlicer {
14
- #textElement;
15
- #originalText;
16
- #splitMode;
17
- #cssVariables;
18
- #dataAttributes;
19
- #charIndexCounter;
20
- /**
21
- * @param {Object} options - Configuration options for the TextSlicer.
22
- * @param {HTMLElement|string} [options.container] - The container element or a selector for the text to split.
23
- * @param {string} [options.splitMode='both'] - The splitMode, can be 'words', 'chars', or 'both'.
24
- * @param {boolean} [options.cssVariables=false] - Whether to use CSS variables for indices.
25
- * @param {boolean} [options.dataAttributes=false] - Whether to add data attributes for words and chars.
26
- */ constructor(options = {}){
27
- this.#textElement = options.container instanceof HTMLElement ? options.container : document.querySelector(options.container || ".text-slicer");
28
- if (!this.#textElement) return;
29
- this.#originalText = this.#textElement.textContent.trim();
30
- this.#splitMode = options.splitMode || "both";
31
- this.#cssVariables = options.cssVariables || false;
32
- this.#dataAttributes = options.dataAttributes || false;
33
- this.#charIndexCounter = 0;
12
+ $parcel$export(module.exports, "default", function () { return $a196c1ed25598f0e$export$2e2bcd8739ae039; });
13
+ class $a196c1ed25598f0e$var$TextSlicer {
14
+ constructor(options = {}){
15
+ this.textElement = options.container instanceof HTMLElement ? options.container : document.querySelector(options.container || ".text-slicer");
16
+ if (!this.textElement) {
17
+ this.originalText = "";
18
+ this.splitMode = "both";
19
+ this.cssVariables = false;
20
+ this.dataAttributes = false;
21
+ this.charIndexCounter = 0;
22
+ return;
23
+ }
24
+ this.originalText = this.textElement.textContent?.trim() || "";
25
+ this.splitMode = options.splitMode || "both";
26
+ this.cssVariables = options.cssVariables || false;
27
+ this.dataAttributes = options.dataAttributes || false;
28
+ this.charIndexCounter = 0;
34
29
  }
35
30
  split() {
36
- if (!this.#textElement) return;
37
- this.#clear();
38
- this.#charIndexCounter = 0;
31
+ if (!this.textElement) return;
32
+ this.clear();
33
+ this.charIndexCounter = 0;
39
34
  const fragment = document.createDocumentFragment();
40
- const words = this.#originalText.split(" ");
41
- const charCount = this.#originalText.length;
42
- if (this.#splitMode === "words" || this.#splitMode === "both") this.#splitWords(fragment, words);
43
- else if (this.#splitMode === "chars") this.#splitChars(fragment);
44
- this.#textElement.appendChild(fragment);
45
- if (this.#cssVariables) {
46
- this.#textElement.style.setProperty("--word-total", words.length);
47
- this.#textElement.style.setProperty("--char-total", charCount);
35
+ const words = this.originalText.split(" ");
36
+ const charCount = this.originalText.length;
37
+ if (this.splitMode === "words" || this.splitMode === "both") this.splitWords(fragment, words);
38
+ else if (this.splitMode === "chars") this.splitChars(fragment);
39
+ this.textElement.appendChild(fragment);
40
+ if (this.cssVariables) {
41
+ this.textElement.style.setProperty("--word-total", words.length.toString());
42
+ this.textElement.style.setProperty("--char-total", charCount.toString());
48
43
  }
49
44
  }
50
- #splitWords(fragment, words) {
45
+ splitWords(fragment, words) {
51
46
  words.forEach((word, wordIndex)=>{
52
- if (this.#splitMode === "both") {
53
- const wordSpan = this.#createWordSpan(wordIndex, word);
47
+ if (this.splitMode === "both") {
48
+ const wordSpan = this.createWordSpan(wordIndex, word);
54
49
  word.split("").forEach((char)=>{
55
- const charSpan = this.#createCharSpan(char);
50
+ const charSpan = this.createCharSpan(char);
56
51
  wordSpan.append(charSpan);
57
52
  });
58
53
  fragment.append(wordSpan);
59
54
  } else {
60
- const wordSpan = this.#createWordSpan(wordIndex);
55
+ const wordSpan = this.createWordSpan(wordIndex);
61
56
  wordSpan.append(document.createTextNode(word));
62
57
  fragment.append(wordSpan);
63
58
  }
64
- if (wordIndex < words.length - 1) fragment.append($70cf2c47938f006f$var$TextSlicer.#createSpaceSpan());
59
+ if (wordIndex < words.length - 1) fragment.append($a196c1ed25598f0e$var$TextSlicer.createSpaceSpan());
65
60
  });
66
61
  }
67
- #splitChars(fragment) {
68
- this.#originalText.split("").forEach((char)=>{
69
- const charSpan = this.#createCharSpan(char);
62
+ splitChars(fragment) {
63
+ this.originalText.split("").forEach((char)=>{
64
+ const charSpan = this.createCharSpan(char);
70
65
  fragment.append(charSpan);
71
66
  });
72
67
  }
73
- #createWordSpan(index, word = "") {
68
+ createWordSpan(index, word = "") {
74
69
  const wordSpan = document.createElement("span");
75
70
  wordSpan.classList.add("word");
76
- if (this.#dataAttributes) wordSpan.setAttribute("data-word", word);
77
- if (this.#cssVariables) wordSpan.style.setProperty("--word-index", index);
71
+ if (this.dataAttributes) wordSpan.setAttribute("data-word", word);
72
+ if (this.cssVariables) wordSpan.style.setProperty("--word-index", index.toString());
78
73
  return wordSpan;
79
74
  }
80
- #createCharSpan(char) {
75
+ createCharSpan(char) {
81
76
  const charSpan = document.createElement("span");
82
77
  charSpan.textContent = char;
83
- if (this.#dataAttributes) charSpan.setAttribute("data-char", char);
78
+ if (this.dataAttributes) charSpan.setAttribute("data-char", char);
84
79
  if (char === " ") charSpan.classList.add("whitespace");
85
80
  else {
86
81
  charSpan.classList.add("char");
87
- if (this.#cssVariables) charSpan.style.setProperty("--char-index", this.#charIndexCounter);
88
- this.#charIndexCounter += 1;
82
+ if (this.cssVariables) charSpan.style.setProperty("--char-index", this.charIndexCounter.toString());
83
+ this.charIndexCounter += 1;
89
84
  }
90
85
  return charSpan;
91
86
  }
92
- static #createSpaceSpan() {
87
+ static createSpaceSpan() {
93
88
  const spaceSpan = document.createElement("span");
94
89
  spaceSpan.classList.add("whitespace");
95
90
  spaceSpan.textContent = " ";
96
91
  return spaceSpan;
97
92
  }
98
- #clear() {
99
- this.#textElement.innerHTML = "";
93
+ clear() {
94
+ if (this.textElement) this.textElement.innerHTML = "";
100
95
  }
101
96
  init() {
102
97
  this.split();
103
98
  }
104
99
  }
105
- var $70cf2c47938f006f$export$2e2bcd8739ae039 = $70cf2c47938f006f$var$TextSlicer;
100
+ var $a196c1ed25598f0e$export$2e2bcd8739ae039 = $a196c1ed25598f0e$var$TextSlicer;
106
101
 
107
102
 
108
103
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"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","sources":["src/TextSlicer.js"],"sourcesContent":["class TextSlicer {\n #textElement;\n\n #originalText;\n\n #splitMode;\n\n #cssVariables;\n\n #dataAttributes;\n\n #charIndexCounter;\n\n /**\n * @param {Object} options - Configuration options for the TextSlicer.\n * @param {HTMLElement|string} [options.container] - The container element or a selector for the text to split.\n * @param {string} [options.splitMode='both'] - The splitMode, can be 'words', 'chars', or 'both'.\n * @param {boolean} [options.cssVariables=false] - Whether to use CSS variables for indices.\n * @param {boolean} [options.dataAttributes=false] - Whether to add data attributes for words and chars.\n */\n\n constructor(options = {}) {\n this.#textElement = options.container instanceof HTMLElement\n ? options.container\n : document.querySelector(options.container || '.text-slicer');\n\n if (!this.#textElement) {\n return;\n }\n\n this.#originalText = this.#textElement.textContent.trim();\n this.#splitMode = options.splitMode || 'both';\n this.#cssVariables = options.cssVariables || false;\n this.#dataAttributes = options.dataAttributes || false;\n this.#charIndexCounter = 0;\n }\n\n split() {\n if (!this.#textElement) return;\n\n this.#clear();\n this.#charIndexCounter = 0;\n\n const fragment = document.createDocumentFragment();\n const words = this.#originalText.split(' ');\n const charCount = this.#originalText.length;\n\n if (this.#splitMode === 'words' || this.#splitMode === 'both') {\n this.#splitWords(fragment, words);\n } else if (this.#splitMode === 'chars') {\n this.#splitChars(fragment);\n }\n\n this.#textElement.appendChild(fragment);\n\n if (this.#cssVariables) {\n this.#textElement.style.setProperty('--word-total', words.length);\n this.#textElement.style.setProperty('--char-total', charCount);\n }\n }\n\n #splitWords(fragment, words) {\n words.forEach((word, wordIndex) => {\n if (this.#splitMode === 'both') {\n const wordSpan = this.#createWordSpan(wordIndex, word);\n\n word.split('').forEach((char) => {\n const charSpan = this.#createCharSpan(char);\n\n wordSpan.append(charSpan);\n });\n\n fragment.append(wordSpan);\n } else {\n const wordSpan = this.#createWordSpan(wordIndex);\n\n wordSpan.append(document.createTextNode(word));\n fragment.append(wordSpan);\n }\n\n if (wordIndex < words.length - 1) {\n fragment.append(TextSlicer.#createSpaceSpan());\n }\n });\n }\n\n #splitChars(fragment) {\n this.#originalText.split('').forEach((char) => {\n const charSpan = this.#createCharSpan(char);\n\n fragment.append(charSpan);\n });\n }\n\n #createWordSpan(index, word = '') {\n const wordSpan = document.createElement('span');\n\n wordSpan.classList.add('word');\n\n if (this.#dataAttributes) {\n wordSpan.setAttribute('data-word', word);\n }\n\n if (this.#cssVariables) {\n wordSpan.style.setProperty('--word-index', index);\n }\n\n return wordSpan;\n }\n\n #createCharSpan(char) {\n const charSpan = document.createElement('span');\n\n charSpan.textContent = char;\n\n if (this.#dataAttributes) {\n charSpan.setAttribute('data-char', char);\n }\n\n if (char === ' ') {\n charSpan.classList.add('whitespace');\n } else {\n charSpan.classList.add('char');\n\n if (this.#cssVariables) {\n charSpan.style.setProperty('--char-index', this.#charIndexCounter);\n }\n\n this.#charIndexCounter += 1;\n }\n\n return charSpan;\n }\n\n static #createSpaceSpan() {\n const spaceSpan = document.createElement('span');\n\n spaceSpan.classList.add('whitespace');\n spaceSpan.textContent = ' ';\n\n return spaceSpan;\n }\n\n #clear() {\n this.#textElement.innerHTML = '';\n }\n\n init() {\n this.split();\n }\n}\n\nexport default TextSlicer;\n"],"names":[],"version":3,"file":"index.js.map"}
1
+ {"mappings":"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","sources":["src/index.ts"],"sourcesContent":["class TextSlicer {\n private readonly textElement: HTMLElement | null;\n private originalText: string;\n private readonly splitMode: 'words' | 'chars' | 'both';\n private readonly cssVariables: boolean;\n private readonly dataAttributes: boolean;\n private charIndexCounter: number;\n\n public constructor(options: {\n container?: HTMLElement | string;\n splitMode?: 'words' | 'chars' | 'both';\n cssVariables?: boolean;\n dataAttributes?: boolean;\n } = {}) {\n this.textElement =\n options.container instanceof HTMLElement\n ? options.container\n : document.querySelector(options.container || '.text-slicer');\n\n if (!this.textElement) {\n this.originalText = '';\n this.splitMode = 'both';\n this.cssVariables = false;\n this.dataAttributes = false;\n this.charIndexCounter = 0;\n return;\n }\n\n this.originalText = this.textElement.textContent?.trim() || '';\n this.splitMode = options.splitMode || 'both';\n this.cssVariables = options.cssVariables || false;\n this.dataAttributes = options.dataAttributes || false;\n this.charIndexCounter = 0;\n }\n\n public split(): void {\n if (!this.textElement) return;\n\n this.clear();\n this.charIndexCounter = 0;\n\n const fragment = document.createDocumentFragment();\n const words = this.originalText.split(' ');\n const charCount = this.originalText.length;\n\n if (this.splitMode === 'words' || this.splitMode === 'both') {\n this.splitWords(fragment, words);\n } else if (this.splitMode === 'chars') {\n this.splitChars(fragment);\n }\n\n this.textElement.appendChild(fragment);\n\n if (this.cssVariables) {\n this.textElement.style.setProperty('--word-total', words.length.toString());\n this.textElement.style.setProperty('--char-total', charCount.toString());\n }\n }\n\n private splitWords(fragment: DocumentFragment, words: string[]): void {\n words.forEach((word, wordIndex) => {\n if (this.splitMode === 'both') {\n const wordSpan = this.createWordSpan(wordIndex, word);\n\n word.split('').forEach((char) => {\n const charSpan = this.createCharSpan(char);\n wordSpan.append(charSpan);\n });\n\n fragment.append(wordSpan);\n } else {\n const wordSpan = this.createWordSpan(wordIndex);\n wordSpan.append(document.createTextNode(word));\n fragment.append(wordSpan);\n }\n\n if (wordIndex < words.length - 1) {\n fragment.append(TextSlicer.createSpaceSpan());\n }\n });\n }\n\n private splitChars(fragment: DocumentFragment): void {\n this.originalText.split('').forEach((char) => {\n const charSpan = this.createCharSpan(char);\n fragment.append(charSpan);\n });\n }\n\n private createWordSpan(index: number, word: string = ''): HTMLElement {\n const wordSpan = document.createElement('span');\n wordSpan.classList.add('word');\n\n if (this.dataAttributes) {\n wordSpan.setAttribute('data-word', word);\n }\n\n if (this.cssVariables) {\n wordSpan.style.setProperty('--word-index', index.toString());\n }\n\n return wordSpan;\n }\n\n private createCharSpan(char: string): HTMLElement {\n const charSpan = document.createElement('span');\n charSpan.textContent = char;\n\n if (this.dataAttributes) {\n charSpan.setAttribute('data-char', char);\n }\n\n if (char === ' ') {\n charSpan.classList.add('whitespace');\n } else {\n charSpan.classList.add('char');\n\n if (this.cssVariables) {\n charSpan.style.setProperty('--char-index', this.charIndexCounter.toString());\n }\n\n this.charIndexCounter += 1;\n }\n\n return charSpan;\n }\n\n private static createSpaceSpan(): HTMLElement {\n const spaceSpan = document.createElement('span');\n spaceSpan.classList.add('whitespace');\n spaceSpan.textContent = ' ';\n\n return spaceSpan;\n }\n\n private clear(): void {\n if (this.textElement) {\n this.textElement.innerHTML = '';\n }\n }\n\n public init(): void {\n this.split();\n }\n}\n\nexport default TextSlicer;\n"],"names":[],"version":3,"file":"index.js.map"}
@@ -1,97 +1,92 @@
1
- class $fe8af0fdf983f603$var$TextSlicer {
2
- #textElement;
3
- #originalText;
4
- #splitMode;
5
- #cssVariables;
6
- #dataAttributes;
7
- #charIndexCounter;
8
- /**
9
- * @param {Object} options - Configuration options for the TextSlicer.
10
- * @param {HTMLElement|string} [options.container] - The container element or a selector for the text to split.
11
- * @param {string} [options.splitMode='both'] - The splitMode, can be 'words', 'chars', or 'both'.
12
- * @param {boolean} [options.cssVariables=false] - Whether to use CSS variables for indices.
13
- * @param {boolean} [options.dataAttributes=false] - Whether to add data attributes for words and chars.
14
- */ constructor(options = {}){
15
- this.#textElement = options.container instanceof HTMLElement ? options.container : document.querySelector(options.container || ".text-slicer");
16
- if (!this.#textElement) return;
17
- this.#originalText = this.#textElement.textContent.trim();
18
- this.#splitMode = options.splitMode || "both";
19
- this.#cssVariables = options.cssVariables || false;
20
- this.#dataAttributes = options.dataAttributes || false;
21
- this.#charIndexCounter = 0;
1
+ class $643fcf18b2d2e76f$var$TextSlicer {
2
+ constructor(options = {}){
3
+ this.textElement = options.container instanceof HTMLElement ? options.container : document.querySelector(options.container || ".text-slicer");
4
+ if (!this.textElement) {
5
+ this.originalText = "";
6
+ this.splitMode = "both";
7
+ this.cssVariables = false;
8
+ this.dataAttributes = false;
9
+ this.charIndexCounter = 0;
10
+ return;
11
+ }
12
+ this.originalText = this.textElement.textContent?.trim() || "";
13
+ this.splitMode = options.splitMode || "both";
14
+ this.cssVariables = options.cssVariables || false;
15
+ this.dataAttributes = options.dataAttributes || false;
16
+ this.charIndexCounter = 0;
22
17
  }
23
18
  split() {
24
- if (!this.#textElement) return;
25
- this.#clear();
26
- this.#charIndexCounter = 0;
19
+ if (!this.textElement) return;
20
+ this.clear();
21
+ this.charIndexCounter = 0;
27
22
  const fragment = document.createDocumentFragment();
28
- const words = this.#originalText.split(" ");
29
- const charCount = this.#originalText.length;
30
- if (this.#splitMode === "words" || this.#splitMode === "both") this.#splitWords(fragment, words);
31
- else if (this.#splitMode === "chars") this.#splitChars(fragment);
32
- this.#textElement.appendChild(fragment);
33
- if (this.#cssVariables) {
34
- this.#textElement.style.setProperty("--word-total", words.length);
35
- this.#textElement.style.setProperty("--char-total", charCount);
23
+ const words = this.originalText.split(" ");
24
+ const charCount = this.originalText.length;
25
+ if (this.splitMode === "words" || this.splitMode === "both") this.splitWords(fragment, words);
26
+ else if (this.splitMode === "chars") this.splitChars(fragment);
27
+ this.textElement.appendChild(fragment);
28
+ if (this.cssVariables) {
29
+ this.textElement.style.setProperty("--word-total", words.length.toString());
30
+ this.textElement.style.setProperty("--char-total", charCount.toString());
36
31
  }
37
32
  }
38
- #splitWords(fragment, words) {
33
+ splitWords(fragment, words) {
39
34
  words.forEach((word, wordIndex)=>{
40
- if (this.#splitMode === "both") {
41
- const wordSpan = this.#createWordSpan(wordIndex, word);
35
+ if (this.splitMode === "both") {
36
+ const wordSpan = this.createWordSpan(wordIndex, word);
42
37
  word.split("").forEach((char)=>{
43
- const charSpan = this.#createCharSpan(char);
38
+ const charSpan = this.createCharSpan(char);
44
39
  wordSpan.append(charSpan);
45
40
  });
46
41
  fragment.append(wordSpan);
47
42
  } else {
48
- const wordSpan = this.#createWordSpan(wordIndex);
43
+ const wordSpan = this.createWordSpan(wordIndex);
49
44
  wordSpan.append(document.createTextNode(word));
50
45
  fragment.append(wordSpan);
51
46
  }
52
- if (wordIndex < words.length - 1) fragment.append($fe8af0fdf983f603$var$TextSlicer.#createSpaceSpan());
47
+ if (wordIndex < words.length - 1) fragment.append($643fcf18b2d2e76f$var$TextSlicer.createSpaceSpan());
53
48
  });
54
49
  }
55
- #splitChars(fragment) {
56
- this.#originalText.split("").forEach((char)=>{
57
- const charSpan = this.#createCharSpan(char);
50
+ splitChars(fragment) {
51
+ this.originalText.split("").forEach((char)=>{
52
+ const charSpan = this.createCharSpan(char);
58
53
  fragment.append(charSpan);
59
54
  });
60
55
  }
61
- #createWordSpan(index, word = "") {
56
+ createWordSpan(index, word = "") {
62
57
  const wordSpan = document.createElement("span");
63
58
  wordSpan.classList.add("word");
64
- if (this.#dataAttributes) wordSpan.setAttribute("data-word", word);
65
- if (this.#cssVariables) wordSpan.style.setProperty("--word-index", index);
59
+ if (this.dataAttributes) wordSpan.setAttribute("data-word", word);
60
+ if (this.cssVariables) wordSpan.style.setProperty("--word-index", index.toString());
66
61
  return wordSpan;
67
62
  }
68
- #createCharSpan(char) {
63
+ createCharSpan(char) {
69
64
  const charSpan = document.createElement("span");
70
65
  charSpan.textContent = char;
71
- if (this.#dataAttributes) charSpan.setAttribute("data-char", char);
66
+ if (this.dataAttributes) charSpan.setAttribute("data-char", char);
72
67
  if (char === " ") charSpan.classList.add("whitespace");
73
68
  else {
74
69
  charSpan.classList.add("char");
75
- if (this.#cssVariables) charSpan.style.setProperty("--char-index", this.#charIndexCounter);
76
- this.#charIndexCounter += 1;
70
+ if (this.cssVariables) charSpan.style.setProperty("--char-index", this.charIndexCounter.toString());
71
+ this.charIndexCounter += 1;
77
72
  }
78
73
  return charSpan;
79
74
  }
80
- static #createSpaceSpan() {
75
+ static createSpaceSpan() {
81
76
  const spaceSpan = document.createElement("span");
82
77
  spaceSpan.classList.add("whitespace");
83
78
  spaceSpan.textContent = " ";
84
79
  return spaceSpan;
85
80
  }
86
- #clear() {
87
- this.#textElement.innerHTML = "";
81
+ clear() {
82
+ if (this.textElement) this.textElement.innerHTML = "";
88
83
  }
89
84
  init() {
90
85
  this.split();
91
86
  }
92
87
  }
93
- var $fe8af0fdf983f603$export$2e2bcd8739ae039 = $fe8af0fdf983f603$var$TextSlicer;
88
+ var $643fcf18b2d2e76f$export$2e2bcd8739ae039 = $643fcf18b2d2e76f$var$TextSlicer;
94
89
 
95
90
 
96
- export {$fe8af0fdf983f603$export$2e2bcd8739ae039 as default};
91
+ export {$643fcf18b2d2e76f$export$2e2bcd8739ae039 as default};
97
92
  //# sourceMappingURL=index.module.js.map
@@ -1 +1 @@
1
- {"mappings":"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","sources":["src/TextSlicer.js"],"sourcesContent":["class TextSlicer {\n #textElement;\n\n #originalText;\n\n #splitMode;\n\n #cssVariables;\n\n #dataAttributes;\n\n #charIndexCounter;\n\n /**\n * @param {Object} options - Configuration options for the TextSlicer.\n * @param {HTMLElement|string} [options.container] - The container element or a selector for the text to split.\n * @param {string} [options.splitMode='both'] - The splitMode, can be 'words', 'chars', or 'both'.\n * @param {boolean} [options.cssVariables=false] - Whether to use CSS variables for indices.\n * @param {boolean} [options.dataAttributes=false] - Whether to add data attributes for words and chars.\n */\n\n constructor(options = {}) {\n this.#textElement = options.container instanceof HTMLElement\n ? options.container\n : document.querySelector(options.container || '.text-slicer');\n\n if (!this.#textElement) {\n return;\n }\n\n this.#originalText = this.#textElement.textContent.trim();\n this.#splitMode = options.splitMode || 'both';\n this.#cssVariables = options.cssVariables || false;\n this.#dataAttributes = options.dataAttributes || false;\n this.#charIndexCounter = 0;\n }\n\n split() {\n if (!this.#textElement) return;\n\n this.#clear();\n this.#charIndexCounter = 0;\n\n const fragment = document.createDocumentFragment();\n const words = this.#originalText.split(' ');\n const charCount = this.#originalText.length;\n\n if (this.#splitMode === 'words' || this.#splitMode === 'both') {\n this.#splitWords(fragment, words);\n } else if (this.#splitMode === 'chars') {\n this.#splitChars(fragment);\n }\n\n this.#textElement.appendChild(fragment);\n\n if (this.#cssVariables) {\n this.#textElement.style.setProperty('--word-total', words.length);\n this.#textElement.style.setProperty('--char-total', charCount);\n }\n }\n\n #splitWords(fragment, words) {\n words.forEach((word, wordIndex) => {\n if (this.#splitMode === 'both') {\n const wordSpan = this.#createWordSpan(wordIndex, word);\n\n word.split('').forEach((char) => {\n const charSpan = this.#createCharSpan(char);\n\n wordSpan.append(charSpan);\n });\n\n fragment.append(wordSpan);\n } else {\n const wordSpan = this.#createWordSpan(wordIndex);\n\n wordSpan.append(document.createTextNode(word));\n fragment.append(wordSpan);\n }\n\n if (wordIndex < words.length - 1) {\n fragment.append(TextSlicer.#createSpaceSpan());\n }\n });\n }\n\n #splitChars(fragment) {\n this.#originalText.split('').forEach((char) => {\n const charSpan = this.#createCharSpan(char);\n\n fragment.append(charSpan);\n });\n }\n\n #createWordSpan(index, word = '') {\n const wordSpan = document.createElement('span');\n\n wordSpan.classList.add('word');\n\n if (this.#dataAttributes) {\n wordSpan.setAttribute('data-word', word);\n }\n\n if (this.#cssVariables) {\n wordSpan.style.setProperty('--word-index', index);\n }\n\n return wordSpan;\n }\n\n #createCharSpan(char) {\n const charSpan = document.createElement('span');\n\n charSpan.textContent = char;\n\n if (this.#dataAttributes) {\n charSpan.setAttribute('data-char', char);\n }\n\n if (char === ' ') {\n charSpan.classList.add('whitespace');\n } else {\n charSpan.classList.add('char');\n\n if (this.#cssVariables) {\n charSpan.style.setProperty('--char-index', this.#charIndexCounter);\n }\n\n this.#charIndexCounter += 1;\n }\n\n return charSpan;\n }\n\n static #createSpaceSpan() {\n const spaceSpan = document.createElement('span');\n\n spaceSpan.classList.add('whitespace');\n spaceSpan.textContent = ' ';\n\n return spaceSpan;\n }\n\n #clear() {\n this.#textElement.innerHTML = '';\n }\n\n init() {\n this.split();\n }\n}\n\nexport default TextSlicer;\n"],"names":[],"version":3,"file":"index.module.js.map"}
1
+ {"mappings":"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","sources":["src/index.ts"],"sourcesContent":["class TextSlicer {\n private readonly textElement: HTMLElement | null;\n private originalText: string;\n private readonly splitMode: 'words' | 'chars' | 'both';\n private readonly cssVariables: boolean;\n private readonly dataAttributes: boolean;\n private charIndexCounter: number;\n\n public constructor(options: {\n container?: HTMLElement | string;\n splitMode?: 'words' | 'chars' | 'both';\n cssVariables?: boolean;\n dataAttributes?: boolean;\n } = {}) {\n this.textElement =\n options.container instanceof HTMLElement\n ? options.container\n : document.querySelector(options.container || '.text-slicer');\n\n if (!this.textElement) {\n this.originalText = '';\n this.splitMode = 'both';\n this.cssVariables = false;\n this.dataAttributes = false;\n this.charIndexCounter = 0;\n return;\n }\n\n this.originalText = this.textElement.textContent?.trim() || '';\n this.splitMode = options.splitMode || 'both';\n this.cssVariables = options.cssVariables || false;\n this.dataAttributes = options.dataAttributes || false;\n this.charIndexCounter = 0;\n }\n\n public split(): void {\n if (!this.textElement) return;\n\n this.clear();\n this.charIndexCounter = 0;\n\n const fragment = document.createDocumentFragment();\n const words = this.originalText.split(' ');\n const charCount = this.originalText.length;\n\n if (this.splitMode === 'words' || this.splitMode === 'both') {\n this.splitWords(fragment, words);\n } else if (this.splitMode === 'chars') {\n this.splitChars(fragment);\n }\n\n this.textElement.appendChild(fragment);\n\n if (this.cssVariables) {\n this.textElement.style.setProperty('--word-total', words.length.toString());\n this.textElement.style.setProperty('--char-total', charCount.toString());\n }\n }\n\n private splitWords(fragment: DocumentFragment, words: string[]): void {\n words.forEach((word, wordIndex) => {\n if (this.splitMode === 'both') {\n const wordSpan = this.createWordSpan(wordIndex, word);\n\n word.split('').forEach((char) => {\n const charSpan = this.createCharSpan(char);\n wordSpan.append(charSpan);\n });\n\n fragment.append(wordSpan);\n } else {\n const wordSpan = this.createWordSpan(wordIndex);\n wordSpan.append(document.createTextNode(word));\n fragment.append(wordSpan);\n }\n\n if (wordIndex < words.length - 1) {\n fragment.append(TextSlicer.createSpaceSpan());\n }\n });\n }\n\n private splitChars(fragment: DocumentFragment): void {\n this.originalText.split('').forEach((char) => {\n const charSpan = this.createCharSpan(char);\n fragment.append(charSpan);\n });\n }\n\n private createWordSpan(index: number, word: string = ''): HTMLElement {\n const wordSpan = document.createElement('span');\n wordSpan.classList.add('word');\n\n if (this.dataAttributes) {\n wordSpan.setAttribute('data-word', word);\n }\n\n if (this.cssVariables) {\n wordSpan.style.setProperty('--word-index', index.toString());\n }\n\n return wordSpan;\n }\n\n private createCharSpan(char: string): HTMLElement {\n const charSpan = document.createElement('span');\n charSpan.textContent = char;\n\n if (this.dataAttributes) {\n charSpan.setAttribute('data-char', char);\n }\n\n if (char === ' ') {\n charSpan.classList.add('whitespace');\n } else {\n charSpan.classList.add('char');\n\n if (this.cssVariables) {\n charSpan.style.setProperty('--char-index', this.charIndexCounter.toString());\n }\n\n this.charIndexCounter += 1;\n }\n\n return charSpan;\n }\n\n private static createSpaceSpan(): HTMLElement {\n const spaceSpan = document.createElement('span');\n spaceSpan.classList.add('whitespace');\n spaceSpan.textContent = ' ';\n\n return spaceSpan;\n }\n\n private clear(): void {\n if (this.textElement) {\n this.textElement.innerHTML = '';\n }\n }\n\n public init(): void {\n this.split();\n }\n}\n\nexport default TextSlicer;\n"],"names":[],"version":3,"file":"index.module.js.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "text-slicer",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "TextSlicer is designed to split text within an HTML element into separate words and/or characters, wrapping each word and/or character in separate span elements.",
5
5
  "author": "ux-ui.pro",
6
6
  "license": "MIT",
@@ -13,35 +13,31 @@
13
13
  },
14
14
  "homepage": "https://github.com/ux-ui-pro/text-slicer",
15
15
  "sideEffects": false,
16
- "main": "dist/index.js",
17
- "module": "dist/index.module.js",
18
- "targets": {
19
- "main": {
20
- "source": "src/TextSlicer.js"
21
- },
22
- "module": {
23
- "source": "src/TextSlicer.js"
24
- }
25
- },
26
- "browserslist": "> 0.5%, last 2 versions, not dead",
27
16
  "scripts": {
28
17
  "clean": "rm -rf dist .parcel-cache",
29
18
  "build": "yarn clean && parcel build",
30
- "lint:js": "eslint --ext .js",
19
+ "lint:js": "eslint --ext .ts,.js",
31
20
  "lintfix": "yarn lint:js --fix"
32
21
  },
22
+ "browserslist": "> 0.5%, last 2 versions, not dead",
23
+ "source": "src/index.ts",
24
+ "main": "dist/index.js",
25
+ "module": "dist/index.module.js",
26
+ "types": "dist/index.d.ts",
33
27
  "devDependencies": {
28
+ "@parcel/packager-ts": "2.12.0",
29
+ "@parcel/transformer-sass": "2.12.0",
30
+ "@parcel/transformer-typescript-types": "2.12.0",
34
31
  "eslint": "^7.32.0 || ^8.57.0",
35
- "eslint-plugin-import": "^2.29.1",
36
32
  "eslint-config-airbnb-base": "^15.0.0",
37
- "parcel": "^2.12.0"
33
+ "parcel": "^2.12.0",
34
+ "typescript": "^5.4.5"
38
35
  },
39
36
  "keywords": [
40
37
  "text",
41
38
  "splitter",
42
39
  "splitting",
43
40
  "DOM",
44
- "manipulation",
45
41
  "animation",
46
42
  "JavaScript",
47
43
  "effects",
@@ -54,16 +50,12 @@
54
50
  "variables",
55
51
  "web",
56
52
  "development",
57
- "transformation",
58
- "customization",
59
53
  "frontend",
60
- "element",
61
54
  "library",
62
55
  "content",
63
56
  "custom",
64
57
  "effects",
65
58
  "textslicer",
66
- "textmanipulation",
67
59
  "js",
68
60
  "webdev",
69
61
  "textprocessing"
package/src/index.ts ADDED
@@ -0,0 +1,147 @@
1
+ class TextSlicer {
2
+ private readonly textElement: HTMLElement | null;
3
+ private originalText: string;
4
+ private readonly splitMode: 'words' | 'chars' | 'both';
5
+ private readonly cssVariables: boolean;
6
+ private readonly dataAttributes: boolean;
7
+ private charIndexCounter: number;
8
+
9
+ public constructor(options: {
10
+ container?: HTMLElement | string;
11
+ splitMode?: 'words' | 'chars' | 'both';
12
+ cssVariables?: boolean;
13
+ dataAttributes?: boolean;
14
+ } = {}) {
15
+ this.textElement =
16
+ options.container instanceof HTMLElement
17
+ ? options.container
18
+ : document.querySelector(options.container || '.text-slicer');
19
+
20
+ if (!this.textElement) {
21
+ this.originalText = '';
22
+ this.splitMode = 'both';
23
+ this.cssVariables = false;
24
+ this.dataAttributes = false;
25
+ this.charIndexCounter = 0;
26
+ return;
27
+ }
28
+
29
+ this.originalText = this.textElement.textContent?.trim() || '';
30
+ this.splitMode = options.splitMode || 'both';
31
+ this.cssVariables = options.cssVariables || false;
32
+ this.dataAttributes = options.dataAttributes || false;
33
+ this.charIndexCounter = 0;
34
+ }
35
+
36
+ public split(): void {
37
+ if (!this.textElement) return;
38
+
39
+ this.clear();
40
+ this.charIndexCounter = 0;
41
+
42
+ const fragment = document.createDocumentFragment();
43
+ const words = this.originalText.split(' ');
44
+ const charCount = this.originalText.length;
45
+
46
+ if (this.splitMode === 'words' || this.splitMode === 'both') {
47
+ this.splitWords(fragment, words);
48
+ } else if (this.splitMode === 'chars') {
49
+ this.splitChars(fragment);
50
+ }
51
+
52
+ this.textElement.appendChild(fragment);
53
+
54
+ if (this.cssVariables) {
55
+ this.textElement.style.setProperty('--word-total', words.length.toString());
56
+ this.textElement.style.setProperty('--char-total', charCount.toString());
57
+ }
58
+ }
59
+
60
+ private splitWords(fragment: DocumentFragment, words: string[]): void {
61
+ words.forEach((word, wordIndex) => {
62
+ if (this.splitMode === 'both') {
63
+ const wordSpan = this.createWordSpan(wordIndex, word);
64
+
65
+ word.split('').forEach((char) => {
66
+ const charSpan = this.createCharSpan(char);
67
+ wordSpan.append(charSpan);
68
+ });
69
+
70
+ fragment.append(wordSpan);
71
+ } else {
72
+ const wordSpan = this.createWordSpan(wordIndex);
73
+ wordSpan.append(document.createTextNode(word));
74
+ fragment.append(wordSpan);
75
+ }
76
+
77
+ if (wordIndex < words.length - 1) {
78
+ fragment.append(TextSlicer.createSpaceSpan());
79
+ }
80
+ });
81
+ }
82
+
83
+ private splitChars(fragment: DocumentFragment): void {
84
+ this.originalText.split('').forEach((char) => {
85
+ const charSpan = this.createCharSpan(char);
86
+ fragment.append(charSpan);
87
+ });
88
+ }
89
+
90
+ private createWordSpan(index: number, word: string = ''): HTMLElement {
91
+ const wordSpan = document.createElement('span');
92
+ wordSpan.classList.add('word');
93
+
94
+ if (this.dataAttributes) {
95
+ wordSpan.setAttribute('data-word', word);
96
+ }
97
+
98
+ if (this.cssVariables) {
99
+ wordSpan.style.setProperty('--word-index', index.toString());
100
+ }
101
+
102
+ return wordSpan;
103
+ }
104
+
105
+ private createCharSpan(char: string): HTMLElement {
106
+ const charSpan = document.createElement('span');
107
+ charSpan.textContent = char;
108
+
109
+ if (this.dataAttributes) {
110
+ charSpan.setAttribute('data-char', char);
111
+ }
112
+
113
+ if (char === ' ') {
114
+ charSpan.classList.add('whitespace');
115
+ } else {
116
+ charSpan.classList.add('char');
117
+
118
+ if (this.cssVariables) {
119
+ charSpan.style.setProperty('--char-index', this.charIndexCounter.toString());
120
+ }
121
+
122
+ this.charIndexCounter += 1;
123
+ }
124
+
125
+ return charSpan;
126
+ }
127
+
128
+ private static createSpaceSpan(): HTMLElement {
129
+ const spaceSpan = document.createElement('span');
130
+ spaceSpan.classList.add('whitespace');
131
+ spaceSpan.textContent = ' ';
132
+
133
+ return spaceSpan;
134
+ }
135
+
136
+ private clear(): void {
137
+ if (this.textElement) {
138
+ this.textElement.innerHTML = '';
139
+ }
140
+ }
141
+
142
+ public init(): void {
143
+ this.split();
144
+ }
145
+ }
146
+
147
+ export default TextSlicer;
package/src/TextSlicer.js DELETED
@@ -1,153 +0,0 @@
1
- class TextSlicer {
2
- #textElement;
3
-
4
- #originalText;
5
-
6
- #splitMode;
7
-
8
- #cssVariables;
9
-
10
- #dataAttributes;
11
-
12
- #charIndexCounter;
13
-
14
- /**
15
- * @param {Object} options - Configuration options for the TextSlicer.
16
- * @param {HTMLElement|string} [options.container] - The container element or a selector for the text to split.
17
- * @param {string} [options.splitMode='both'] - The splitMode, can be 'words', 'chars', or 'both'.
18
- * @param {boolean} [options.cssVariables=false] - Whether to use CSS variables for indices.
19
- * @param {boolean} [options.dataAttributes=false] - Whether to add data attributes for words and chars.
20
- */
21
-
22
- constructor(options = {}) {
23
- this.#textElement = options.container instanceof HTMLElement
24
- ? options.container
25
- : document.querySelector(options.container || '.text-slicer');
26
-
27
- if (!this.#textElement) {
28
- return;
29
- }
30
-
31
- this.#originalText = this.#textElement.textContent.trim();
32
- this.#splitMode = options.splitMode || 'both';
33
- this.#cssVariables = options.cssVariables || false;
34
- this.#dataAttributes = options.dataAttributes || false;
35
- this.#charIndexCounter = 0;
36
- }
37
-
38
- split() {
39
- if (!this.#textElement) return;
40
-
41
- this.#clear();
42
- this.#charIndexCounter = 0;
43
-
44
- const fragment = document.createDocumentFragment();
45
- const words = this.#originalText.split(' ');
46
- const charCount = this.#originalText.length;
47
-
48
- if (this.#splitMode === 'words' || this.#splitMode === 'both') {
49
- this.#splitWords(fragment, words);
50
- } else if (this.#splitMode === 'chars') {
51
- this.#splitChars(fragment);
52
- }
53
-
54
- this.#textElement.appendChild(fragment);
55
-
56
- if (this.#cssVariables) {
57
- this.#textElement.style.setProperty('--word-total', words.length);
58
- this.#textElement.style.setProperty('--char-total', charCount);
59
- }
60
- }
61
-
62
- #splitWords(fragment, words) {
63
- words.forEach((word, wordIndex) => {
64
- if (this.#splitMode === 'both') {
65
- const wordSpan = this.#createWordSpan(wordIndex, word);
66
-
67
- word.split('').forEach((char) => {
68
- const charSpan = this.#createCharSpan(char);
69
-
70
- wordSpan.append(charSpan);
71
- });
72
-
73
- fragment.append(wordSpan);
74
- } else {
75
- const wordSpan = this.#createWordSpan(wordIndex);
76
-
77
- wordSpan.append(document.createTextNode(word));
78
- fragment.append(wordSpan);
79
- }
80
-
81
- if (wordIndex < words.length - 1) {
82
- fragment.append(TextSlicer.#createSpaceSpan());
83
- }
84
- });
85
- }
86
-
87
- #splitChars(fragment) {
88
- this.#originalText.split('').forEach((char) => {
89
- const charSpan = this.#createCharSpan(char);
90
-
91
- fragment.append(charSpan);
92
- });
93
- }
94
-
95
- #createWordSpan(index, word = '') {
96
- const wordSpan = document.createElement('span');
97
-
98
- wordSpan.classList.add('word');
99
-
100
- if (this.#dataAttributes) {
101
- wordSpan.setAttribute('data-word', word);
102
- }
103
-
104
- if (this.#cssVariables) {
105
- wordSpan.style.setProperty('--word-index', index);
106
- }
107
-
108
- return wordSpan;
109
- }
110
-
111
- #createCharSpan(char) {
112
- const charSpan = document.createElement('span');
113
-
114
- charSpan.textContent = char;
115
-
116
- if (this.#dataAttributes) {
117
- charSpan.setAttribute('data-char', char);
118
- }
119
-
120
- if (char === ' ') {
121
- charSpan.classList.add('whitespace');
122
- } else {
123
- charSpan.classList.add('char');
124
-
125
- if (this.#cssVariables) {
126
- charSpan.style.setProperty('--char-index', this.#charIndexCounter);
127
- }
128
-
129
- this.#charIndexCounter += 1;
130
- }
131
-
132
- return charSpan;
133
- }
134
-
135
- static #createSpaceSpan() {
136
- const spaceSpan = document.createElement('span');
137
-
138
- spaceSpan.classList.add('whitespace');
139
- spaceSpan.textContent = ' ';
140
-
141
- return spaceSpan;
142
- }
143
-
144
- #clear() {
145
- this.#textElement.innerHTML = '';
146
- }
147
-
148
- init() {
149
- this.split();
150
- }
151
- }
152
-
153
- export default TextSlicer;