text-slicer 0.1.1 → 0.2.1

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,26 @@
1
+ {
2
+ "env": {
3
+ "browser": true,
4
+ "es2022": true
5
+ },
6
+ "extends": [
7
+ "airbnb-base",
8
+ "plugin:@typescript-eslint/recommended"
9
+ ],
10
+ "parser": "@typescript-eslint/parser",
11
+ "parserOptions": {
12
+ "ecmaVersion": "latest",
13
+ "sourceType": "module",
14
+ "project": "./tsconfig.json"
15
+ },
16
+ "plugins": ["@typescript-eslint"],
17
+ "rules": {
18
+ "max-len": [
19
+ "off",
20
+ {
21
+ "code": 100,
22
+ "ignoreUrls": true
23
+ }
24
+ ]
25
+ }
26
+ }
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>750B gzipped</sup></p>
13
+ <p align="center"><sup>850B 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
 
@@ -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;gBAaK,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;IAqBC,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\n private originalText: string;\n\n private readonly splitMode: 'words' | 'chars' | 'both';\n\n private readonly cssVariables: boolean;\n\n private readonly dataAttributes: boolean;\n\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 = 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,101 @@ 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
+ textElement;
15
+ originalText;
16
+ splitMode;
17
+ cssVariables;
18
+ dataAttributes;
19
+ charIndexCounter;
20
+ constructor(options = {}){
21
+ this.textElement = options.container instanceof HTMLElement ? options.container : document.querySelector(options.container || ".text-slicer");
22
+ if (!this.textElement) {
23
+ this.originalText = "";
24
+ this.splitMode = "both";
25
+ this.cssVariables = false;
26
+ this.dataAttributes = false;
27
+ this.charIndexCounter = 0;
28
+ return;
29
+ }
30
+ this.originalText = this.textElement.textContent?.trim() || "";
31
+ this.splitMode = options.splitMode || "both";
32
+ this.cssVariables = options.cssVariables || false;
33
+ this.dataAttributes = options.dataAttributes || false;
34
+ this.charIndexCounter = 0;
34
35
  }
35
36
  split() {
36
- if (!this.#textElement) return;
37
- this.#clear();
38
- this.#charIndexCounter = 0;
37
+ if (!this.textElement) return;
38
+ this.clear();
39
+ this.charIndexCounter = 0;
39
40
  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);
41
+ const words = this.originalText.split(" ");
42
+ const charCount = this.originalText.length;
43
+ if (this.splitMode === "words" || this.splitMode === "both") this.splitWords(fragment, words);
44
+ else if (this.splitMode === "chars") this.splitChars(fragment);
45
+ this.textElement.appendChild(fragment);
46
+ if (this.cssVariables) {
47
+ this.textElement.style.setProperty("--word-total", words.length.toString());
48
+ this.textElement.style.setProperty("--char-total", charCount.toString());
48
49
  }
49
50
  }
50
- #splitWords(fragment, words) {
51
+ splitWords(fragment, words) {
51
52
  words.forEach((word, wordIndex)=>{
52
- if (this.#splitMode === "both") {
53
- const wordSpan = this.#createWordSpan(wordIndex, word);
53
+ if (this.splitMode === "both") {
54
+ const wordSpan = this.createWordSpan(wordIndex, word);
54
55
  word.split("").forEach((char)=>{
55
- const charSpan = this.#createCharSpan(char);
56
+ const charSpan = this.createCharSpan(char);
56
57
  wordSpan.append(charSpan);
57
58
  });
58
59
  fragment.append(wordSpan);
59
60
  } else {
60
- const wordSpan = this.#createWordSpan(wordIndex);
61
+ const wordSpan = this.createWordSpan(wordIndex);
61
62
  wordSpan.append(document.createTextNode(word));
62
63
  fragment.append(wordSpan);
63
64
  }
64
- if (wordIndex < words.length - 1) fragment.append($70cf2c47938f006f$var$TextSlicer.#createSpaceSpan());
65
+ if (wordIndex < words.length - 1) fragment.append($a196c1ed25598f0e$var$TextSlicer.createSpaceSpan());
65
66
  });
66
67
  }
67
- #splitChars(fragment) {
68
- this.#originalText.split("").forEach((char)=>{
69
- const charSpan = this.#createCharSpan(char);
68
+ splitChars(fragment) {
69
+ this.originalText.split("").forEach((char)=>{
70
+ const charSpan = this.createCharSpan(char);
70
71
  fragment.append(charSpan);
71
72
  });
72
73
  }
73
- #createWordSpan(index, word = "") {
74
+ createWordSpan(index, word = "") {
74
75
  const wordSpan = document.createElement("span");
75
76
  wordSpan.classList.add("word");
76
- if (this.#dataAttributes) wordSpan.setAttribute("data-word", word);
77
- if (this.#cssVariables) wordSpan.style.setProperty("--word-index", index);
77
+ if (this.dataAttributes) wordSpan.setAttribute("data-word", word);
78
+ if (this.cssVariables) wordSpan.style.setProperty("--word-index", index.toString());
78
79
  return wordSpan;
79
80
  }
80
- #createCharSpan(char) {
81
+ createCharSpan(char) {
81
82
  const charSpan = document.createElement("span");
82
83
  charSpan.textContent = char;
83
- if (this.#dataAttributes) charSpan.setAttribute("data-char", char);
84
+ if (this.dataAttributes) charSpan.setAttribute("data-char", char);
84
85
  if (char === " ") charSpan.classList.add("whitespace");
85
86
  else {
86
87
  charSpan.classList.add("char");
87
- if (this.#cssVariables) charSpan.style.setProperty("--char-index", this.#charIndexCounter);
88
- this.#charIndexCounter += 1;
88
+ if (this.cssVariables) charSpan.style.setProperty("--char-index", this.charIndexCounter.toString());
89
+ this.charIndexCounter += 1;
89
90
  }
90
91
  return charSpan;
91
92
  }
92
- static #createSpaceSpan() {
93
+ static createSpaceSpan() {
93
94
  const spaceSpan = document.createElement("span");
94
95
  spaceSpan.classList.add("whitespace");
95
96
  spaceSpan.textContent = " ";
96
97
  return spaceSpan;
97
98
  }
98
- #clear() {
99
- this.#textElement.innerHTML = "";
99
+ clear() {
100
+ if (this.textElement) this.textElement.innerHTML = "";
100
101
  }
101
102
  init() {
102
103
  this.split();
103
104
  }
104
105
  }
105
- var $70cf2c47938f006f$export$2e2bcd8739ae039 = $70cf2c47938f006f$var$TextSlicer;
106
+ var $a196c1ed25598f0e$export$2e2bcd8739ae039 = $a196c1ed25598f0e$var$TextSlicer;
106
107
 
107
108
 
108
109
  //# 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\n private originalText: string;\n\n private readonly splitMode: 'words' | 'chars' | 'both';\n\n private readonly cssVariables: boolean;\n\n private readonly dataAttributes: boolean;\n\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 = 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,98 @@
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
+ textElement;
3
+ originalText;
4
+ splitMode;
5
+ cssVariables;
6
+ dataAttributes;
7
+ charIndexCounter;
8
+ constructor(options = {}){
9
+ this.textElement = options.container instanceof HTMLElement ? options.container : document.querySelector(options.container || ".text-slicer");
10
+ if (!this.textElement) {
11
+ this.originalText = "";
12
+ this.splitMode = "both";
13
+ this.cssVariables = false;
14
+ this.dataAttributes = false;
15
+ this.charIndexCounter = 0;
16
+ return;
17
+ }
18
+ this.originalText = this.textElement.textContent?.trim() || "";
19
+ this.splitMode = options.splitMode || "both";
20
+ this.cssVariables = options.cssVariables || false;
21
+ this.dataAttributes = options.dataAttributes || false;
22
+ this.charIndexCounter = 0;
22
23
  }
23
24
  split() {
24
- if (!this.#textElement) return;
25
- this.#clear();
26
- this.#charIndexCounter = 0;
25
+ if (!this.textElement) return;
26
+ this.clear();
27
+ this.charIndexCounter = 0;
27
28
  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);
29
+ const words = this.originalText.split(" ");
30
+ const charCount = this.originalText.length;
31
+ if (this.splitMode === "words" || this.splitMode === "both") this.splitWords(fragment, words);
32
+ else if (this.splitMode === "chars") this.splitChars(fragment);
33
+ this.textElement.appendChild(fragment);
34
+ if (this.cssVariables) {
35
+ this.textElement.style.setProperty("--word-total", words.length.toString());
36
+ this.textElement.style.setProperty("--char-total", charCount.toString());
36
37
  }
37
38
  }
38
- #splitWords(fragment, words) {
39
+ splitWords(fragment, words) {
39
40
  words.forEach((word, wordIndex)=>{
40
- if (this.#splitMode === "both") {
41
- const wordSpan = this.#createWordSpan(wordIndex, word);
41
+ if (this.splitMode === "both") {
42
+ const wordSpan = this.createWordSpan(wordIndex, word);
42
43
  word.split("").forEach((char)=>{
43
- const charSpan = this.#createCharSpan(char);
44
+ const charSpan = this.createCharSpan(char);
44
45
  wordSpan.append(charSpan);
45
46
  });
46
47
  fragment.append(wordSpan);
47
48
  } else {
48
- const wordSpan = this.#createWordSpan(wordIndex);
49
+ const wordSpan = this.createWordSpan(wordIndex);
49
50
  wordSpan.append(document.createTextNode(word));
50
51
  fragment.append(wordSpan);
51
52
  }
52
- if (wordIndex < words.length - 1) fragment.append($fe8af0fdf983f603$var$TextSlicer.#createSpaceSpan());
53
+ if (wordIndex < words.length - 1) fragment.append($643fcf18b2d2e76f$var$TextSlicer.createSpaceSpan());
53
54
  });
54
55
  }
55
- #splitChars(fragment) {
56
- this.#originalText.split("").forEach((char)=>{
57
- const charSpan = this.#createCharSpan(char);
56
+ splitChars(fragment) {
57
+ this.originalText.split("").forEach((char)=>{
58
+ const charSpan = this.createCharSpan(char);
58
59
  fragment.append(charSpan);
59
60
  });
60
61
  }
61
- #createWordSpan(index, word = "") {
62
+ createWordSpan(index, word = "") {
62
63
  const wordSpan = document.createElement("span");
63
64
  wordSpan.classList.add("word");
64
- if (this.#dataAttributes) wordSpan.setAttribute("data-word", word);
65
- if (this.#cssVariables) wordSpan.style.setProperty("--word-index", index);
65
+ if (this.dataAttributes) wordSpan.setAttribute("data-word", word);
66
+ if (this.cssVariables) wordSpan.style.setProperty("--word-index", index.toString());
66
67
  return wordSpan;
67
68
  }
68
- #createCharSpan(char) {
69
+ createCharSpan(char) {
69
70
  const charSpan = document.createElement("span");
70
71
  charSpan.textContent = char;
71
- if (this.#dataAttributes) charSpan.setAttribute("data-char", char);
72
+ if (this.dataAttributes) charSpan.setAttribute("data-char", char);
72
73
  if (char === " ") charSpan.classList.add("whitespace");
73
74
  else {
74
75
  charSpan.classList.add("char");
75
- if (this.#cssVariables) charSpan.style.setProperty("--char-index", this.#charIndexCounter);
76
- this.#charIndexCounter += 1;
76
+ if (this.cssVariables) charSpan.style.setProperty("--char-index", this.charIndexCounter.toString());
77
+ this.charIndexCounter += 1;
77
78
  }
78
79
  return charSpan;
79
80
  }
80
- static #createSpaceSpan() {
81
+ static createSpaceSpan() {
81
82
  const spaceSpan = document.createElement("span");
82
83
  spaceSpan.classList.add("whitespace");
83
84
  spaceSpan.textContent = " ";
84
85
  return spaceSpan;
85
86
  }
86
- #clear() {
87
- this.#textElement.innerHTML = "";
87
+ clear() {
88
+ if (this.textElement) this.textElement.innerHTML = "";
88
89
  }
89
90
  init() {
90
91
  this.split();
91
92
  }
92
93
  }
93
- var $fe8af0fdf983f603$export$2e2bcd8739ae039 = $fe8af0fdf983f603$var$TextSlicer;
94
+ var $643fcf18b2d2e76f$export$2e2bcd8739ae039 = $643fcf18b2d2e76f$var$TextSlicer;
94
95
 
95
96
 
96
- export {$fe8af0fdf983f603$export$2e2bcd8739ae039 as default};
97
+ export {$643fcf18b2d2e76f$export$2e2bcd8739ae039 as default};
97
98
  //# 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\n private originalText: string;\n\n private readonly splitMode: 'words' | 'chars' | 'both';\n\n private readonly cssVariables: boolean;\n\n private readonly dataAttributes: boolean;\n\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 = 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.1",
3
+ "version": "0.2.1",
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,33 @@
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 **/*.{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-typescript-types": "2.12.0",
30
+ "@typescript-eslint/eslint-plugin": "^7.11.0",
31
+ "@typescript-eslint/parser": "^7.11.0",
34
32
  "eslint": "^7.32.0 || ^8.57.0",
35
- "eslint-plugin-import": "^2.29.1",
36
33
  "eslint-config-airbnb-base": "^15.0.0",
37
- "parcel": "^2.12.0"
34
+ "eslint-plugin-import": "^2.29.1",
35
+ "parcel": "^2.12.0",
36
+ "typescript": "^5.4.5"
38
37
  },
39
38
  "keywords": [
40
39
  "text",
41
40
  "splitter",
42
41
  "splitting",
43
42
  "DOM",
44
- "manipulation",
45
43
  "animation",
46
44
  "JavaScript",
47
45
  "effects",
@@ -54,16 +52,12 @@
54
52
  "variables",
55
53
  "web",
56
54
  "development",
57
- "transformation",
58
- "customization",
59
55
  "frontend",
60
- "element",
61
56
  "library",
62
57
  "content",
63
58
  "custom",
64
59
  "effects",
65
60
  "textslicer",
66
- "textmanipulation",
67
61
  "js",
68
62
  "webdev",
69
63
  "textprocessing"
package/src/index.ts ADDED
@@ -0,0 +1,151 @@
1
+ class TextSlicer {
2
+ private readonly textElement: HTMLElement | null;
3
+
4
+ private originalText: string;
5
+
6
+ private readonly splitMode: 'words' | 'chars' | 'both';
7
+
8
+ private readonly cssVariables: boolean;
9
+
10
+ private readonly dataAttributes: boolean;
11
+
12
+ private charIndexCounter: number;
13
+
14
+ public constructor(options: {
15
+ container?: HTMLElement | string;
16
+ splitMode?: 'words' | 'chars' | 'both';
17
+ cssVariables?: boolean;
18
+ dataAttributes?: boolean;
19
+ } = {}) {
20
+ this.textElement = options.container instanceof HTMLElement
21
+ ? options.container
22
+ : document.querySelector(options.container || '.text-slicer');
23
+
24
+ if (!this.textElement) {
25
+ this.originalText = '';
26
+ this.splitMode = 'both';
27
+ this.cssVariables = false;
28
+ this.dataAttributes = false;
29
+ this.charIndexCounter = 0;
30
+ return;
31
+ }
32
+
33
+ this.originalText = this.textElement.textContent?.trim() || '';
34
+ this.splitMode = options.splitMode || 'both';
35
+ this.cssVariables = options.cssVariables || false;
36
+ this.dataAttributes = options.dataAttributes || false;
37
+ this.charIndexCounter = 0;
38
+ }
39
+
40
+ public split(): void {
41
+ if (!this.textElement) return;
42
+
43
+ this.clear();
44
+ this.charIndexCounter = 0;
45
+
46
+ const fragment = document.createDocumentFragment();
47
+ const words = this.originalText.split(' ');
48
+ const charCount = this.originalText.length;
49
+
50
+ if (this.splitMode === 'words' || this.splitMode === 'both') {
51
+ this.splitWords(fragment, words);
52
+ } else if (this.splitMode === 'chars') {
53
+ this.splitChars(fragment);
54
+ }
55
+
56
+ this.textElement.appendChild(fragment);
57
+
58
+ if (this.cssVariables) {
59
+ this.textElement.style.setProperty('--word-total', words.length.toString());
60
+ this.textElement.style.setProperty('--char-total', charCount.toString());
61
+ }
62
+ }
63
+
64
+ private splitWords(fragment: DocumentFragment, words: string[]): void {
65
+ words.forEach((word, wordIndex) => {
66
+ if (this.splitMode === 'both') {
67
+ const wordSpan = this.createWordSpan(wordIndex, word);
68
+
69
+ word.split('').forEach((char) => {
70
+ const charSpan = this.createCharSpan(char);
71
+ wordSpan.append(charSpan);
72
+ });
73
+
74
+ fragment.append(wordSpan);
75
+ } else {
76
+ const wordSpan = this.createWordSpan(wordIndex);
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
+ private splitChars(fragment: DocumentFragment): void {
88
+ this.originalText.split('').forEach((char) => {
89
+ const charSpan = this.createCharSpan(char);
90
+ fragment.append(charSpan);
91
+ });
92
+ }
93
+
94
+ private createWordSpan(index: number, word: string = ''): HTMLElement {
95
+ const wordSpan = document.createElement('span');
96
+ wordSpan.classList.add('word');
97
+
98
+ if (this.dataAttributes) {
99
+ wordSpan.setAttribute('data-word', word);
100
+ }
101
+
102
+ if (this.cssVariables) {
103
+ wordSpan.style.setProperty('--word-index', index.toString());
104
+ }
105
+
106
+ return wordSpan;
107
+ }
108
+
109
+ private createCharSpan(char: string): HTMLElement {
110
+ const charSpan = document.createElement('span');
111
+ charSpan.textContent = char;
112
+
113
+ if (this.dataAttributes) {
114
+ charSpan.setAttribute('data-char', char);
115
+ }
116
+
117
+ if (char === ' ') {
118
+ charSpan.classList.add('whitespace');
119
+ } else {
120
+ charSpan.classList.add('char');
121
+
122
+ if (this.cssVariables) {
123
+ charSpan.style.setProperty('--char-index', this.charIndexCounter.toString());
124
+ }
125
+
126
+ this.charIndexCounter += 1;
127
+ }
128
+
129
+ return charSpan;
130
+ }
131
+
132
+ private static createSpaceSpan(): HTMLElement {
133
+ const spaceSpan = document.createElement('span');
134
+ spaceSpan.classList.add('whitespace');
135
+ spaceSpan.textContent = ' ';
136
+
137
+ return spaceSpan;
138
+ }
139
+
140
+ private clear(): void {
141
+ if (this.textElement) {
142
+ this.textElement.innerHTML = '';
143
+ }
144
+ }
145
+
146
+ public init(): void {
147
+ this.split();
148
+ }
149
+ }
150
+
151
+ export default TextSlicer;
package/tsconfig.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "compilerOptions": {
3
+ "isolatedModules": true,
4
+ "target": "es2022"
5
+ }
6
+ }
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;