@d3plus/text 3.0.3 → 3.0.4

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/README.md CHANGED
@@ -30,7 +30,7 @@ Live examples can be found on [d3plus.org](https://d3plus.org/), which includes
30
30
  * [strip](#strip) - Removes all non ASCII characters from a string.
31
31
  * [textSplit](#textSplit) - Splits a given sentence into an array of words.
32
32
  * [textWrap](#textWrap) - Based on the defined styles and dimensions, breaks a string into an array of strings for each line of text.
33
- * [titleCase](#titleCase) - Capitalizes the first letter of each word in a phrase/sentence.
33
+ * [titleCase](#titleCase) - Capitalizes the first letter of each word in a phrase/sentence, accounting for words in English that should be kept lowercase such as "and" or "of", as well as acronym that should be kept uppercase such as "CEO" or "TVs".
34
34
  * [trim](#trim) - Cross-browser implementation of [trim](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim).
35
35
  * [trimLeft](#trimLeft) - Cross-browser implementation of [trimLeft](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimLeft).
36
36
  * [trimRight](#trimRight) - Cross-browser implementation of [trimRight](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/TrimRight).
@@ -62,7 +62,7 @@ This is a global function
62
62
  ---
63
63
 
64
64
  <a name="textSplit"></a>
65
- #### d3plus.**textSplit**(sentence) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textSplit.js#L51)
65
+ #### d3plus.**textSplit**(sentence) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textSplit.js#L3)
66
66
 
67
67
  Splits a given sentence into an array of words.
68
68
 
@@ -92,7 +92,7 @@ This is a global function
92
92
  * [.width([*value*])](#textWrap.width)
93
93
 
94
94
 
95
- <a name="textWrap.fontFamily" href="#textWrap.fontFamily">#</a> d3plus..**fontFamily**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L90)
95
+ <a name="textWrap.fontFamily" href="#textWrap.fontFamily">#</a> d3plus..**fontFamily**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L92)
96
96
 
97
97
  If *value* is specified, sets the font family accessor to the specified function or string and returns this generator. If *value* is not specified, returns the current font family.
98
98
 
@@ -100,7 +100,7 @@ If *value* is specified, sets the font family accessor to the specified function
100
100
  This is a static method of [<code>textWrap</code>](#textWrap)
101
101
 
102
102
 
103
- <a name="textWrap.fontSize" href="#textWrap.fontSize">#</a> d3plus..**fontSize**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L99)
103
+ <a name="textWrap.fontSize" href="#textWrap.fontSize">#</a> d3plus..**fontSize**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L101)
104
104
 
105
105
  If *value* is specified, sets the font size accessor to the specified function or number and returns this generator. If *value* is not specified, returns the current font size.
106
106
 
@@ -108,7 +108,7 @@ If *value* is specified, sets the font size accessor to the specified function o
108
108
  This is a static method of [<code>textWrap</code>](#textWrap)
109
109
 
110
110
 
111
- <a name="textWrap.fontWeight" href="#textWrap.fontWeight">#</a> d3plus..**fontWeight**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L108)
111
+ <a name="textWrap.fontWeight" href="#textWrap.fontWeight">#</a> d3plus..**fontWeight**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L110)
112
112
 
113
113
  If *value* is specified, sets the font weight accessor to the specified function or number and returns this generator. If *value* is not specified, returns the current font weight.
114
114
 
@@ -116,7 +116,7 @@ If *value* is specified, sets the font weight accessor to the specified function
116
116
  This is a static method of [<code>textWrap</code>](#textWrap)
117
117
 
118
118
 
119
- <a name="textWrap.height" href="#textWrap.height">#</a> d3plus..**height**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L117)
119
+ <a name="textWrap.height" href="#textWrap.height">#</a> d3plus..**height**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L119)
120
120
 
121
121
  If *value* is specified, sets height limit to the specified value and returns this generator. If *value* is not specified, returns the current value.
122
122
 
@@ -124,7 +124,7 @@ If *value* is specified, sets height limit to the specified value and returns th
124
124
  This is a static method of [<code>textWrap</code>](#textWrap)
125
125
 
126
126
 
127
- <a name="textWrap.lineHeight" href="#textWrap.lineHeight">#</a> d3plus..**lineHeight**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L126)
127
+ <a name="textWrap.lineHeight" href="#textWrap.lineHeight">#</a> d3plus..**lineHeight**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L128)
128
128
 
129
129
  If *value* is specified, sets the line height accessor to the specified function or number and returns this generator. If *value* is not specified, returns the current line height accessor, which is 1.1 times the [font size](#textWrap.fontSize) by default.
130
130
 
@@ -132,7 +132,7 @@ If *value* is specified, sets the line height accessor to the specified function
132
132
  This is a static method of [<code>textWrap</code>](#textWrap)
133
133
 
134
134
 
135
- <a name="textWrap.maxLines" href="#textWrap.maxLines">#</a> d3plus..**maxLines**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L135)
135
+ <a name="textWrap.maxLines" href="#textWrap.maxLines">#</a> d3plus..**maxLines**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L137)
136
136
 
137
137
  If *value* is specified, sets the maximum number of lines allowed when wrapping.
138
138
 
@@ -140,7 +140,7 @@ If *value* is specified, sets the maximum number of lines allowed when wrapping.
140
140
  This is a static method of [<code>textWrap</code>](#textWrap)
141
141
 
142
142
 
143
- <a name="textWrap.overflow" href="#textWrap.overflow">#</a> d3plus..**overflow**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L144)
143
+ <a name="textWrap.overflow" href="#textWrap.overflow">#</a> d3plus..**overflow**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L146)
144
144
 
145
145
  If *value* is specified, sets the overflow to the specified boolean and returns this generator. If *value* is not specified, returns the current overflow value.
146
146
 
@@ -148,7 +148,7 @@ If *value* is specified, sets the overflow to the specified boolean and returns
148
148
  This is a static method of [<code>textWrap</code>](#textWrap)
149
149
 
150
150
 
151
- <a name="textWrap.split" href="#textWrap.split">#</a> d3plus..**split**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L153)
151
+ <a name="textWrap.split" href="#textWrap.split">#</a> d3plus..**split**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L155)
152
152
 
153
153
  If *value* is specified, sets the word split function to the specified function and returns this generator. If *value* is not specified, returns the current word split function.
154
154
 
@@ -156,7 +156,7 @@ If *value* is specified, sets the word split function to the specified function
156
156
  This is a static method of [<code>textWrap</code>](#textWrap)
157
157
 
158
158
 
159
- <a name="textWrap.width" href="#textWrap.width">#</a> d3plus..**width**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L162)
159
+ <a name="textWrap.width" href="#textWrap.width">#</a> d3plus..**width**([*value*]) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/textWrap.js#L164)
160
160
 
161
161
  If *value* is specified, sets width limit to the specified value and returns this generator. If *value* is not specified, returns the current value.
162
162
 
@@ -166,9 +166,9 @@ This is a static method of [<code>textWrap</code>](#textWrap)
166
166
  ---
167
167
 
168
168
  <a name="titleCase"></a>
169
- #### d3plus.**titleCase**(str) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/titleCase.js#L6)
169
+ #### d3plus.**titleCase**(str) [<>](https://github.com/d3plus/d3plus/blob/main/packages/text/src/titleCase.js#L7)
170
170
 
171
- Capitalizes the first letter of each word in a phrase/sentence.
171
+ Capitalizes the first letter of each word in a phrase/sentence, accounting for words in English that should be kept lowercase such as "and" or "of", as well as acronym that should be kept uppercase such as "CEO" or "TVs".
172
172
 
173
173
 
174
174
  This is a global function
@@ -1,76 +1,15 @@
1
- import { default as stringify } from "./stringify.js";
2
- import { default as combiningMarks } from "./combiningMarks.js";
3
- import { merge } from "d3-array";
4
- var splitChars = [
5
- "-",
6
- ";",
7
- ":",
8
- "&",
9
- "|",
10
- "u0E2F",
11
- "u0EAF",
12
- "u0EC6",
13
- "u0ECC",
14
- "u104A",
15
- "u104B",
16
- "u104C",
17
- "u104D",
18
- "u104E",
19
- "u104F",
20
- "u2013",
21
- "u2014",
22
- "u2027",
23
- "u3000",
24
- "u3001",
25
- "u3002",
26
- "uFF0C",
27
- "uFF5E" // wave dash
28
- ];
29
- var prefixChars = [
30
- "'",
31
- "<",
32
- "(",
33
- "{",
34
- "[",
35
- "u00AB",
36
- "u300A",
37
- "u3008" // left angle bracket
38
- ];
39
- var suffixChars = [
40
- "'",
41
- ">",
42
- ")",
43
- "}",
44
- "]",
45
- ".",
46
- "!",
47
- "?",
48
- "/",
49
- "u00BB",
50
- "u300B",
51
- "u3009" // right angle bracket
52
- ].concat(splitChars);
53
- var burmeseRange = "\u1000-\u102A\u103F-\u1049\u1050-\u1055";
54
- var japaneseRange = "\u3040-\u309f\u30a0-\u30ff\uff00-\uff0b\uff0d-\uff5d\uff5f-\uff9f\u3400-\u4dbf";
55
- var chineseRange = "\u3400-\u9FBF";
56
- var laoRange = "\u0E81-\u0EAE\u0EB0-\u0EC4\u0EC8-\u0ECB\u0ECD-\u0EDD";
57
- var noSpaceRange = burmeseRange + chineseRange + japaneseRange + laoRange;
58
- var splitWords = new RegExp("(\\".concat(splitChars.join("|\\"), ")*[^\\s|\\").concat(splitChars.join("|\\"), "]*(\\").concat(splitChars.join("|\\"), ")*"), "g");
59
- var noSpaceLanguage = new RegExp("[".concat(noSpaceRange, "]"));
60
- var splitAllChars = new RegExp("(\\".concat(prefixChars.join("|\\"), ")*[").concat(noSpaceRange, "](\\").concat(suffixChars.join("|\\"), "|\\").concat(combiningMarks.join("|\\"), ")*|[a-z0-9]+"), "gi");
1
+ import LineBreaker from "linebreak";
61
2
  /**
62
3
  @function textSplit
63
4
  @desc Splits a given sentence into an array of words.
64
5
  @param {String} sentence
65
6
  */ export default function(sentence) {
66
- if (!noSpaceLanguage.test(sentence)) return stringify(sentence).match(splitWords).filter(function(w) {
67
- return w.length;
68
- });
69
- return merge(stringify(sentence).match(splitWords).map(function(d) {
70
- if (noSpaceLanguage.test(d)) return d.match(splitAllChars);
71
- return [
72
- d
73
- ];
74
- }));
7
+ var breaker = new LineBreaker(sentence);
8
+ var bk, last, words = [];
9
+ while(bk = breaker.nextBreak()){
10
+ var word = sentence.slice(last, bk.position);
11
+ words.push(word);
12
+ last = bk.position;
13
+ }
14
+ return words;
75
15
  }
76
- export { prefixChars, splitChars, splitWords, suffixChars };
@@ -21,11 +21,11 @@ import { trimRight } from "./trim.js";
21
21
  "line-height": lineHeight
22
22
  };
23
23
  var line = 1, textProg = "", truncated = false, widthProg = 0;
24
- var lineData = [], sizes = textWidth(words, style), space = textWidth(" ", style);
24
+ var lineData = [], sizes = textWidth(words, style);
25
25
  for(var i = 0; i < words.length; i++){
26
26
  var word = words[i];
27
27
  var wordWidth = sizes[words.indexOf(word)];
28
- word += sentence.slice(textProg.length + word.length).match("^( |\n)*", "g")[0];
28
+ // newline if breaking character or not enough width
29
29
  if (textProg.slice(-1) === "\n" || widthProg + wordWidth > width) {
30
30
  if (!i && !overflow) {
31
31
  truncated = true;
@@ -43,7 +43,6 @@ import { trimRight } from "./trim.js";
43
43
  else lineData[line - 1] += word;
44
44
  textProg += word;
45
45
  widthProg += wordWidth;
46
- widthProg += word.match(/[\s]*$/g)[0].length * space;
47
46
  }
48
47
  return {
49
48
  lines: lineData,
@@ -1,4 +1,4 @@
1
- import { suffixChars, default as textSplit } from "./textSplit.js";
1
+ import textSplit from "./textSplit.js";
2
2
  var lowercase = [
3
3
  "a",
4
4
  "an",
@@ -27,7 +27,7 @@ var lowercase = [
27
27
  "vs",
28
28
  "vs."
29
29
  ];
30
- var uppercase = [
30
+ var acronyms = [
31
31
  "CEO",
32
32
  "CFO",
33
33
  "CNC",
@@ -41,35 +41,22 @@ var uppercase = [
41
41
  "TV",
42
42
  "UI"
43
43
  ];
44
+ var uppercase = acronyms.reduce(function(arr, d) {
45
+ return arr.push("".concat(d, "s")), arr;
46
+ }, acronyms.map(function(d) {
47
+ return d.toLowerCase();
48
+ }));
44
49
  /**
45
50
  @function titleCase
46
- @desc Capitalizes the first letter of each word in a phrase/sentence.
51
+ @desc Capitalizes the first letter of each word in a phrase/sentence, accounting for words in English that should be kept lowercase such as "and" or "of", as well as acronym that should be kept uppercase such as "CEO" or "TVs".
47
52
  @param {String} str The string to apply the title case logic.
48
53
  */ export default function(str) {
49
- if (str === void 0) return "";
50
- var smalls = lowercase.map(function(s) {
51
- return s.toLowerCase();
52
- });
53
- var bigs = uppercase.slice();
54
- bigs = bigs.concat(bigs.map(function(b) {
55
- return "".concat(b, "s");
56
- }));
57
- var biglow = bigs.map(function(b) {
58
- return b.toLowerCase();
59
- });
60
- var split = textSplit(str);
61
- return split.map(function(s, i) {
62
- if (s) {
63
- var lower = s.toLowerCase();
64
- var stripped = suffixChars.includes(lower.charAt(lower.length - 1)) ? lower.slice(0, -1) : lower;
65
- var bigindex = biglow.indexOf(stripped);
66
- if (bigindex >= 0) return bigs[bigindex];
67
- else if (smalls.includes(stripped) && i !== 0 && i !== split.length - 1) return lower;
68
- else return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase();
69
- } else return "";
70
- }).reduce(function(ret, s, i) {
71
- if (i && str.charAt(ret.length) === " ") ret += " ";
72
- ret += s;
73
- return ret;
54
+ if (str === undefined) return "";
55
+ return textSplit(str).reduce(function(str, word, i) {
56
+ var formattedWord = word;
57
+ var trimmedWord = word.toLowerCase().slice(0, -1);
58
+ var exempt = uppercase.includes(trimmedWord) || lowercase.includes(trimmedWord) && i !== 0 && word.toLowerCase() !== trimmedWord;
59
+ if (!exempt) formattedWord = word.charAt(0).toUpperCase() + word.slice(1);
60
+ return str + formattedWord;
74
61
  }, "");
75
62
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@d3plus/text",
3
- "version": "3.0.3",
3
+ "version": "3.0.4",
4
4
  "description": "A smart SVG text box with line wrapping and automatic font size scaling.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -34,9 +34,9 @@
34
34
  "test": "eslint index.js src/**/*.js && eslint --global=it test && mocha 'test/**/*-test.js'"
35
35
  },
36
36
  "dependencies": {
37
- "@d3plus/dom": "3.0.3",
38
- "d3-array": "^3.2.4",
37
+ "@d3plus/dom": "3.0.4",
39
38
  "d3-selection": "^3.0.0",
40
- "d3-transition": "^3.0.1"
39
+ "d3-transition": "^3.0.1",
40
+ "linebreak": "^1.1.0"
41
41
  }
42
42
  }