text-slicer 0.1.1 → 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 +3 -0
- package/.eslintrc.json +22 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +48 -53
- package/dist/index.js.map +1 -1
- package/dist/index.module.js +48 -53
- package/dist/index.module.js.map +1 -1
- package/package.json +12 -20
- package/src/index.ts +147 -0
- package/src/TextSlicer.js +0 -153
package/.eslintignore
ADDED
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/dist/index.d.ts
ADDED
|
@@ -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 $
|
|
13
|
-
class $
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
this
|
|
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;
|
|
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
|
|
37
|
-
this
|
|
38
|
-
this
|
|
31
|
+
if (!this.textElement) return;
|
|
32
|
+
this.clear();
|
|
33
|
+
this.charIndexCounter = 0;
|
|
39
34
|
const fragment = document.createDocumentFragment();
|
|
40
|
-
const words = this
|
|
41
|
-
const charCount = this
|
|
42
|
-
if (this
|
|
43
|
-
else if (this
|
|
44
|
-
this
|
|
45
|
-
if (this
|
|
46
|
-
this
|
|
47
|
-
this
|
|
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
|
-
|
|
45
|
+
splitWords(fragment, words) {
|
|
51
46
|
words.forEach((word, wordIndex)=>{
|
|
52
|
-
if (this
|
|
53
|
-
const wordSpan = this
|
|
47
|
+
if (this.splitMode === "both") {
|
|
48
|
+
const wordSpan = this.createWordSpan(wordIndex, word);
|
|
54
49
|
word.split("").forEach((char)=>{
|
|
55
|
-
const charSpan = this
|
|
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
|
|
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($
|
|
59
|
+
if (wordIndex < words.length - 1) fragment.append($a196c1ed25598f0e$var$TextSlicer.createSpaceSpan());
|
|
65
60
|
});
|
|
66
61
|
}
|
|
67
|
-
|
|
68
|
-
this
|
|
69
|
-
const charSpan = this
|
|
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
|
-
|
|
68
|
+
createWordSpan(index, word = "") {
|
|
74
69
|
const wordSpan = document.createElement("span");
|
|
75
70
|
wordSpan.classList.add("word");
|
|
76
|
-
if (this
|
|
77
|
-
if (this
|
|
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
|
-
|
|
75
|
+
createCharSpan(char) {
|
|
81
76
|
const charSpan = document.createElement("span");
|
|
82
77
|
charSpan.textContent = char;
|
|
83
|
-
if (this
|
|
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
|
|
88
|
-
this
|
|
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
|
|
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
|
-
|
|
99
|
-
this
|
|
93
|
+
clear() {
|
|
94
|
+
if (this.textElement) this.textElement.innerHTML = "";
|
|
100
95
|
}
|
|
101
96
|
init() {
|
|
102
97
|
this.split();
|
|
103
98
|
}
|
|
104
99
|
}
|
|
105
|
-
var $
|
|
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":";;;;;;;;;;;;AAAA,MAAM;
|
|
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"}
|
package/dist/index.module.js
CHANGED
|
@@ -1,97 +1,92 @@
|
|
|
1
|
-
class $
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this
|
|
16
|
-
|
|
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
|
|
25
|
-
this
|
|
26
|
-
this
|
|
19
|
+
if (!this.textElement) return;
|
|
20
|
+
this.clear();
|
|
21
|
+
this.charIndexCounter = 0;
|
|
27
22
|
const fragment = document.createDocumentFragment();
|
|
28
|
-
const words = this
|
|
29
|
-
const charCount = this
|
|
30
|
-
if (this
|
|
31
|
-
else if (this
|
|
32
|
-
this
|
|
33
|
-
if (this
|
|
34
|
-
this
|
|
35
|
-
this
|
|
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
|
-
|
|
33
|
+
splitWords(fragment, words) {
|
|
39
34
|
words.forEach((word, wordIndex)=>{
|
|
40
|
-
if (this
|
|
41
|
-
const wordSpan = this
|
|
35
|
+
if (this.splitMode === "both") {
|
|
36
|
+
const wordSpan = this.createWordSpan(wordIndex, word);
|
|
42
37
|
word.split("").forEach((char)=>{
|
|
43
|
-
const charSpan = this
|
|
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
|
|
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($
|
|
47
|
+
if (wordIndex < words.length - 1) fragment.append($643fcf18b2d2e76f$var$TextSlicer.createSpaceSpan());
|
|
53
48
|
});
|
|
54
49
|
}
|
|
55
|
-
|
|
56
|
-
this
|
|
57
|
-
const charSpan = this
|
|
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
|
-
|
|
56
|
+
createWordSpan(index, word = "") {
|
|
62
57
|
const wordSpan = document.createElement("span");
|
|
63
58
|
wordSpan.classList.add("word");
|
|
64
|
-
if (this
|
|
65
|
-
if (this
|
|
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
|
-
|
|
63
|
+
createCharSpan(char) {
|
|
69
64
|
const charSpan = document.createElement("span");
|
|
70
65
|
charSpan.textContent = char;
|
|
71
|
-
if (this
|
|
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
|
|
76
|
-
this
|
|
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
|
|
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
|
-
|
|
87
|
-
this
|
|
81
|
+
clear() {
|
|
82
|
+
if (this.textElement) this.textElement.innerHTML = "";
|
|
88
83
|
}
|
|
89
84
|
init() {
|
|
90
85
|
this.split();
|
|
91
86
|
}
|
|
92
87
|
}
|
|
93
|
-
var $
|
|
88
|
+
var $643fcf18b2d2e76f$export$2e2bcd8739ae039 = $643fcf18b2d2e76f$var$TextSlicer;
|
|
94
89
|
|
|
95
90
|
|
|
96
|
-
export {$
|
|
91
|
+
export {$643fcf18b2d2e76f$export$2e2bcd8739ae039 as default};
|
|
97
92
|
//# sourceMappingURL=index.module.js.map
|
package/dist/index.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"mappings":"AAAA,MAAM;
|
|
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.
|
|
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;
|