@sj-distributor/react-iconfont-cli 2.4.2 → 2.5.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/README.md +26 -0
- package/libs/generateComponent.js +10 -1
- package/libs/replace.d.ts +1 -0
- package/libs/replace.js +5 -1
- package/package.json +1 -1
- package/templates/SingleIcon.js.template +9 -1
- package/templates/SingleIcon.tsx.template +9 -1
package/README.md
CHANGED
|
@@ -155,6 +155,32 @@ export const App = () => {
|
|
|
155
155
|
</div>
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
+
## 无障碍支持(WCAG)
|
|
159
|
+
|
|
160
|
+
无障碍属性添加在最终生成的单图标 SVG 上。重新运行生成命令后,现有调用无需修改即可获得默认的可访问名称。
|
|
161
|
+
|
|
162
|
+
将生成类似下面的 SVG:
|
|
163
|
+
|
|
164
|
+
```html
|
|
165
|
+
<svg role="img" aria-label="alipay" focusable="false">...</svg>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
默认的 `aria-label` 是本包提供的兜底值:它根据去除前缀后的图标名生成,并将连字符、下划线和驼峰命名转换为空格。例如 `arrow-left` 会生成 `aria-label="arrow left"`。
|
|
169
|
+
|
|
170
|
+
本包无法判断图标在具体页面中的含义和语言。调用方应根据实际语境覆盖默认标签:
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
<IconFont name="alipay" aria-label="支付宝" />
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
如果图标只是装饰,或者所在按钮、链接已经有可访问名称,可以显式隐藏图标,避免读屏软件重复朗读:
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
<button type="button" aria-label="关闭">
|
|
180
|
+
<IconFont name="close" aria-hidden="true" />
|
|
181
|
+
</button>
|
|
182
|
+
```
|
|
183
|
+
|
|
158
184
|
## 更新图标
|
|
159
185
|
|
|
160
186
|
当 iconfont 项目图标有变更时,更新 `iconfont.json` 中的 `symbol_url` 后重新生成:
|
|
@@ -39,6 +39,7 @@ var generateComponent = function (data, config) {
|
|
|
39
39
|
cases += "".concat((0, whitespace_1.whitespace)(6), "return <").concat(componentName, " {...rest} />;\n");
|
|
40
40
|
singleFile = (0, getTemplate_1.getTemplate)("SingleIcon" + jsxExtension);
|
|
41
41
|
singleFile = (0, replace_1.replaceSize)(singleFile, config.default_icon_size);
|
|
42
|
+
singleFile = (0, replace_1.replaceAriaLabel)(singleFile, getAccessibleLabel(iconIdAfterTrim));
|
|
42
43
|
if (jsxExtension === ".tsx") {
|
|
43
44
|
singleFile = (0, replace_1.replaceReactName)(singleFile, config.can_import_react);
|
|
44
45
|
}
|
|
@@ -74,7 +75,7 @@ var generateComponent = function (data, config) {
|
|
|
74
75
|
exports.generateComponent = generateComponent;
|
|
75
76
|
var generateCase = function (data, baseIdent) {
|
|
76
77
|
var e_1, _a;
|
|
77
|
-
var template = "\n".concat((0, whitespace_1.whitespace)(baseIdent), "<svg viewBox=\"").concat(data.$.viewBox, "\" width={size} height={size} style={style} {...rest}>\n");
|
|
78
|
+
var template = "\n".concat((0, whitespace_1.whitespace)(baseIdent), "<svg viewBox=\"").concat(data.$.viewBox, "\" width={size} height={size} style={style} role={role} aria-label={accessibilityLabel} focusable=\"false\" {...rest}>\n");
|
|
78
79
|
// Determine the primary fill color (first path's fill)
|
|
79
80
|
// to distinguish primary paths from detail paths at runtime.
|
|
80
81
|
var primaryFill = getPrimaryFill(data);
|
|
@@ -115,6 +116,14 @@ var generateCase = function (data, baseIdent) {
|
|
|
115
116
|
template += "".concat((0, whitespace_1.whitespace)(baseIdent), "</svg>\n");
|
|
116
117
|
return template;
|
|
117
118
|
};
|
|
119
|
+
var getAccessibleLabel = function (iconName) {
|
|
120
|
+
var label = iconName
|
|
121
|
+
.replace(/([a-z\d])([A-Z])/g, "$1 $2")
|
|
122
|
+
.replace(/[-_.=+#@!~*]+/g, " ")
|
|
123
|
+
.replace(/\s+/g, " ")
|
|
124
|
+
.trim();
|
|
125
|
+
return label || iconName;
|
|
126
|
+
};
|
|
118
127
|
var getPrimaryFill = function (data) {
|
|
119
128
|
var e_2, _a;
|
|
120
129
|
var _b;
|
package/libs/replace.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const replaceSize: (content: string, size: number) => string;
|
|
2
|
+
export declare const replaceAriaLabel: (content: string, label: string) => string;
|
|
2
3
|
export declare const replaceCases: (content: string, cases: string) => string;
|
|
3
4
|
export declare const replaceNames: (content: string, names: string[]) => string;
|
|
4
5
|
export declare const replaceNamesArray: (content: string, names: string[]) => string;
|
package/libs/replace.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.replaceExports = exports.replaceSizeUnit = exports.replaceImports = exports.replaceSingleIconContent = exports.replaceReactName = exports.replaceComponentName = exports.replaceNamesArray = exports.replaceNames = exports.replaceCases = exports.replaceSize = void 0;
|
|
3
|
+
exports.replaceExports = exports.replaceSizeUnit = exports.replaceImports = exports.replaceSingleIconContent = exports.replaceReactName = exports.replaceComponentName = exports.replaceNamesArray = exports.replaceNames = exports.replaceCases = exports.replaceAriaLabel = exports.replaceSize = void 0;
|
|
4
4
|
var replaceSize = function (content, size) {
|
|
5
5
|
return content.replace(/#size#/g, String(size));
|
|
6
6
|
};
|
|
7
7
|
exports.replaceSize = replaceSize;
|
|
8
|
+
var replaceAriaLabel = function (content, label) {
|
|
9
|
+
return content.replace(/#ariaLabel#/g, JSON.stringify(label));
|
|
10
|
+
};
|
|
11
|
+
exports.replaceAriaLabel = replaceAriaLabel;
|
|
8
12
|
var replaceCases = function (content, cases) {
|
|
9
13
|
return content.replace(/#cases#/g, cases);
|
|
10
14
|
};
|
package/package.json
CHANGED
|
@@ -7,8 +7,16 @@ const DEFAULT_STYLE = {
|
|
|
7
7
|
display: 'block',
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
const #componentName# = ({
|
|
10
|
+
const #componentName# = ({
|
|
11
|
+
size = #size#,
|
|
12
|
+
color,
|
|
13
|
+
style: _style,
|
|
14
|
+
role = 'img',
|
|
15
|
+
'aria-label': ariaLabel,
|
|
16
|
+
...rest
|
|
17
|
+
}) => {
|
|
11
18
|
const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE;
|
|
19
|
+
const accessibilityLabel = typeof ariaLabel === 'string' && ariaLabel.trim() ? ariaLabel.trim() : #ariaLabel#;
|
|
12
20
|
|
|
13
21
|
return (#iconContent# );
|
|
14
22
|
};
|
|
@@ -13,8 +13,16 @@ const DEFAULT_STYLE: CSSProperties = {
|
|
|
13
13
|
display: 'block',
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
const #componentName#: FunctionComponent<Props> = ({
|
|
16
|
+
const #componentName#: FunctionComponent<Props> = ({
|
|
17
|
+
size = #size#,
|
|
18
|
+
color,
|
|
19
|
+
style: _style,
|
|
20
|
+
role = 'img',
|
|
21
|
+
'aria-label': ariaLabel,
|
|
22
|
+
...rest
|
|
23
|
+
}) => {
|
|
17
24
|
const style = _style ? { ...DEFAULT_STYLE, ..._style } : DEFAULT_STYLE;
|
|
25
|
+
const accessibilityLabel = ariaLabel && ariaLabel.trim() ? ariaLabel.trim() : #ariaLabel#;
|
|
18
26
|
|
|
19
27
|
return (#iconContent# );
|
|
20
28
|
};
|