dumi 2.3.0-alpha.4 → 2.3.0-alpha.6
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/dist/features/compile/index.js +14 -1
- package/dist/features/derivative.js +39 -15
- package/dist/features/locales.js +12 -2
- package/dist/loaders/markdown/index.js +4 -2
- package/dist/loaders/markdown/transformer/index.js +12 -11
- package/dist/loaders/markdown/transformer/rehypeRaw.js +9 -6
- package/dist/service/cli.js +2 -2
- package/dist/service/forkedDev.js +1 -1
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +6 -0
- package/package.json +6 -5
- package/theme-default/slots/Navbar/index.less +2 -0
|
@@ -33,6 +33,7 @@ __export(compile_exports, {
|
|
|
33
33
|
});
|
|
34
34
|
module.exports = __toCommonJS(compile_exports);
|
|
35
35
|
var import_react = __toESM(require("../../techStacks/react"));
|
|
36
|
+
var import_assets = require("../assets");
|
|
36
37
|
var compile_default = (api) => {
|
|
37
38
|
api.describe({ key: "dumi:compile" });
|
|
38
39
|
api.register({
|
|
@@ -81,7 +82,19 @@ var compile_default = (api) => {
|
|
|
81
82
|
mode: "text"
|
|
82
83
|
}).end().end().oneOf("md").use("babel-loader").loader(babelInUmi.loader).options(babelInUmi.options).end().use("md-loader").loader(loaderPath).options({
|
|
83
84
|
...loaderBaseOpts,
|
|
84
|
-
builtins: api.service.themeData.builtins
|
|
85
|
+
builtins: api.service.themeData.builtins,
|
|
86
|
+
onResolveDemos(demos) {
|
|
87
|
+
const assets = demos.reduce(
|
|
88
|
+
(ret, demo) => {
|
|
89
|
+
if ("asset" in demo)
|
|
90
|
+
ret.push(demo.asset);
|
|
91
|
+
return ret;
|
|
92
|
+
},
|
|
93
|
+
[]
|
|
94
|
+
);
|
|
95
|
+
(0, import_assets.addExampleAssets)(assets);
|
|
96
|
+
},
|
|
97
|
+
onResolveAtomMeta: import_assets.addAtomMeta
|
|
85
98
|
});
|
|
86
99
|
memo.module.rule("dumi-page").type("javascript/auto").test(/\.(j|t)sx?$/).resourceQuery(/(meta|frontmatter)$/).use("page-meta-loader").loader(require.resolve("../../loaders/page"));
|
|
87
100
|
memo.module.rule("dumi-demo").type("javascript/auto").test(/\..+$/).enforce("pre").resourceQuery(/techStack/).use("demo-loader").loader(require.resolve("../../loaders/demo")).options({ techStacks, cwd: api.cwd });
|
|
@@ -65,7 +65,7 @@ function safeExcludeInMFSU(api, excludes) {
|
|
|
65
65
|
var derivative_default = (api) => {
|
|
66
66
|
api.describe({ key: "dumi:derivative" });
|
|
67
67
|
api.onCheck(() => {
|
|
68
|
-
var _a, _b, _c;
|
|
68
|
+
var _a, _b, _c, _d, _e, _f;
|
|
69
69
|
[
|
|
70
70
|
"clientLoader",
|
|
71
71
|
"deadCode",
|
|
@@ -113,23 +113,47 @@ var derivative_default = (api) => {
|
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
try {
|
|
116
|
-
const
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
116
|
+
const tsconfigPath = import_path.default.join(api.cwd, "tsconfig.json");
|
|
117
|
+
const tsconfig = require(tsconfigPath);
|
|
118
|
+
const dotDumiWildcard = `${import_constants.LOCAL_DUMI_DIR}/**/*`;
|
|
119
|
+
if ((_b = tsconfig.include) == null ? void 0 : _b.includes(dotDumiWildcard)) {
|
|
120
|
+
tsconfig.include = tsconfig.include.filter(
|
|
121
|
+
(i) => i !== dotDumiWildcard
|
|
122
|
+
);
|
|
123
|
+
import_fs.default.writeFileSync(
|
|
124
|
+
tsconfigPath,
|
|
125
|
+
JSON.stringify(tsconfig, null, 2),
|
|
126
|
+
"utf-8"
|
|
127
|
+
);
|
|
128
|
+
import_plugin_utils.logger.info(
|
|
129
|
+
`tsconfig.json \`include\` option has been patched automatically, please check and commit it.
|
|
130
|
+
${import_plugin_utils.chalk.grey("see also: https://github.com/umijs/dumi/pull/1902")}`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
const dotDumiPath = import_path.default.join(api.cwd, import_constants.LOCAL_DUMI_DIR);
|
|
134
|
+
const dotDumiTsconfigPath = import_path.default.join(dotDumiPath, "tsconfig.json");
|
|
135
|
+
const hasDotDumiTsFiles = import_fs.default.existsSync(dotDumiPath) && import_fs.default.readdirSync(dotDumiPath).some(
|
|
136
|
+
(f) => import_constants.LOCAL_PAGES_DIR.endsWith(`/${f}`) || import_constants.LOCAL_THEME_DIR.endsWith(`/${f}`) || /\.tsx?$/.test(f)
|
|
137
|
+
);
|
|
138
|
+
if (hasDotDumiTsFiles && !import_fs.default.existsSync(dotDumiTsconfigPath) && !((_c = tsconfig.include) == null ? void 0 : _c.some((i) => /(\.\/)?.dumi\//.test(i)))) {
|
|
139
|
+
import_fs.default.writeFileSync(
|
|
140
|
+
dotDumiTsconfigPath,
|
|
141
|
+
JSON.stringify(
|
|
142
|
+
{ extends: "../tsconfig.json", include: ["**/*"] },
|
|
143
|
+
null,
|
|
144
|
+
2
|
|
145
|
+
),
|
|
146
|
+
"utf-8"
|
|
147
|
+
);
|
|
148
|
+
import_plugin_utils.logger.info(
|
|
149
|
+
"In order to make type prompt works for theme files, .dumi/tsconfig.json has been created automatically, please check and commit it."
|
|
123
150
|
);
|
|
124
151
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
})) {
|
|
152
|
+
const configFileName = ((_d = api.service.configManager) == null ? void 0 : _d.mainConfigFile) && import_path.default.basename((_e = api.service.configManager) == null ? void 0 : _e.mainConfigFile);
|
|
153
|
+
if (configFileName && // only .dumirc.ts need to be included in the root tsconfig.json, because the dot files will be excluded by default
|
|
154
|
+
/^\..+\.ts$/.test(configFileName) && !((_f = tsconfig.include) == null ? void 0 : _f.includes(configFileName))) {
|
|
129
155
|
import_plugin_utils.logger.warn(
|
|
130
|
-
`Please append
|
|
131
|
-
" & "
|
|
132
|
-
)} into \`include\` option of \`tsconfig.json\`, to make sure the types exported by framework works.`
|
|
156
|
+
`Please append \`${configFileName}\` into \`include\` option of tsconfig.json, to make sure the type prompt works for it.`
|
|
133
157
|
);
|
|
134
158
|
}
|
|
135
159
|
} catch {
|
package/dist/features/locales.js
CHANGED
|
@@ -32,6 +32,7 @@ __export(locales_exports, {
|
|
|
32
32
|
default: () => locales_default
|
|
33
33
|
});
|
|
34
34
|
module.exports = __toCommonJS(locales_exports);
|
|
35
|
+
var import_constants = require("../constants");
|
|
35
36
|
var import_path = __toESM(require("path"));
|
|
36
37
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
37
38
|
var locales_default = (api) => {
|
|
@@ -125,15 +126,24 @@ const cache = createIntlCache();
|
|
|
125
126
|
|
|
126
127
|
const LocalesContainer: FC<{ children: ReactNode }> = (props) => {
|
|
127
128
|
const getIntl = useCallback(() => {
|
|
129
|
+
const base = "${api.config.base.replace(/\/$/, "")}"
|
|
128
130
|
const matched = locales.slice().reverse().find((locale) => (
|
|
129
131
|
'suffix' in locale
|
|
130
132
|
// suffix mode
|
|
131
133
|
? history.location.pathname.replace(/([^/])\\/$/, '$1').endsWith(locale.suffix)
|
|
132
134
|
// base mode
|
|
133
135
|
: history.location.pathname.replace(/([^/])\\/$/, '$1')
|
|
134
|
-
.startsWith(
|
|
136
|
+
.startsWith(base + locale.base)
|
|
135
137
|
));
|
|
136
|
-
|
|
138
|
+
let locale = matched ? matched.id : locales[0].id;
|
|
139
|
+
// using query on demos
|
|
140
|
+
if(history.location.pathname.startsWith(base + '/${import_constants.SP_ROUTE_PREFIX}demos')){
|
|
141
|
+
const params = new URLSearchParams(history.location.search);
|
|
142
|
+
// match the locale of the query
|
|
143
|
+
if (params.get('locale')){
|
|
144
|
+
locale = params.get('locale');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
137
147
|
const localeMessages = messages[locale] || {};
|
|
138
148
|
|
|
139
149
|
// append internal message, for use intl as string template util
|
|
@@ -152,7 +152,9 @@ function emit(opts, ret) {
|
|
|
152
152
|
}
|
|
153
153
|
function getDepsCacheKey(deps = []) {
|
|
154
154
|
return JSON.stringify(
|
|
155
|
-
deps.map(
|
|
155
|
+
deps.map(
|
|
156
|
+
(file) => `${file}:${(0, import_utils.getContentHash)(import_fs.default.readFileSync(file, "utf-8"))}`
|
|
157
|
+
)
|
|
156
158
|
);
|
|
157
159
|
}
|
|
158
160
|
var deferrer = {};
|
|
@@ -163,7 +165,7 @@ function mdLoader(content) {
|
|
|
163
165
|
const cache = (0, import_utils.getCache)("md-loader");
|
|
164
166
|
const baseCacheKey = [
|
|
165
167
|
this.resourcePath,
|
|
166
|
-
|
|
168
|
+
(0, import_utils.getContentHash)(content),
|
|
167
169
|
JSON.stringify(import_plugin_utils.lodash.omit(opts, ["mode", "builtins", "onResolveDemos"]))
|
|
168
170
|
].join(":");
|
|
169
171
|
const cacheKey = [
|
|
@@ -58,14 +58,14 @@ function keepSoftBreak(pkg) {
|
|
|
58
58
|
const ver = ((_b = pkg == null ? void 0 : pkg.devDependencies) == null ? void 0 : _b.dumi) ?? ((_c = pkg == null ? void 0 : pkg.dependencies) == null ? void 0 : _c.dumi) ?? "^2.0.0";
|
|
59
59
|
return !import_plugin_utils.semver.subset(ver, import_constants.VERSION_2_DEPRECATE_SOFT_BREAKS);
|
|
60
60
|
}
|
|
61
|
-
function applyUnifiedPlugin(opts) {
|
|
61
|
+
async function applyUnifiedPlugin(opts) {
|
|
62
62
|
const [plugin, options] = Array.isArray(opts.plugin) ? opts.plugin : [opts.plugin];
|
|
63
|
-
|
|
63
|
+
let mod = typeof plugin === "function" ? plugin : await import(plugin);
|
|
64
64
|
const fn = mod.default || mod;
|
|
65
65
|
opts.processor.use(fn, options);
|
|
66
66
|
}
|
|
67
67
|
var transformer_default = async (raw, opts) => {
|
|
68
|
-
var _a
|
|
68
|
+
var _a;
|
|
69
69
|
let fileLocaleLessPath = opts.fileAbsPath;
|
|
70
70
|
const { unified } = await import("unified");
|
|
71
71
|
const { default: remarkParse } = await import("remark-parse");
|
|
@@ -94,13 +94,13 @@ var transformer_default = async (raw, opts) => {
|
|
|
94
94
|
if (keepSoftBreak(opts.pkg)) {
|
|
95
95
|
processor.use(import_remarkBreaks.default, { fileAbsPath: opts.fileAbsPath });
|
|
96
96
|
}
|
|
97
|
-
(
|
|
98
|
-
|
|
97
|
+
for (const plugin of opts.extraRemarkPlugins ?? []) {
|
|
98
|
+
await applyUnifiedPlugin({
|
|
99
99
|
plugin,
|
|
100
100
|
processor,
|
|
101
101
|
cwd: opts.cwd
|
|
102
|
-
})
|
|
103
|
-
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
104
|
processor.use(remarkRehype, { allowDangerousHtml: true }).use(import_rehypeRaw.default, {
|
|
105
105
|
fileAbsPath: opts.fileAbsPath
|
|
106
106
|
}).use(import_rehypeHighlightLine.default).use(rehypeRemoveComments, { removeConditional: true }).use(import_rehypeStrip.default).use(import_rehypeImg.default).use(import_rehypeDemo.default, {
|
|
@@ -115,13 +115,14 @@ var transformer_default = async (raw, opts) => {
|
|
|
115
115
|
fileAbsPath: opts.fileAbsPath,
|
|
116
116
|
routes: opts.routes
|
|
117
117
|
}).use(rehypeAutolinkHeadings).use(import_rehypeIsolation.default).use(import_rehypeEnhancedTag.default).use(import_rehypeDesc.default).use(import_rehypeText.default);
|
|
118
|
-
(
|
|
119
|
-
|
|
118
|
+
for (const plugin of opts.extraRehypePlugins ?? []) {
|
|
119
|
+
await applyUnifiedPlugin({
|
|
120
120
|
plugin,
|
|
121
121
|
processor,
|
|
122
122
|
cwd: opts.cwd
|
|
123
|
-
})
|
|
124
|
-
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
processor.data("fileAbsPath", opts.fileAbsPath);
|
|
125
126
|
const result = await processor.use(import_rehypeJsxify.default).process(raw);
|
|
126
127
|
return {
|
|
127
128
|
content: String(result.value),
|
|
@@ -35,7 +35,7 @@ module.exports = __toCommonJS(rehypeRaw_exports);
|
|
|
35
35
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
36
36
|
var raw;
|
|
37
37
|
var visit;
|
|
38
|
-
var COMPONENT_NAME_REGEX =
|
|
38
|
+
var COMPONENT_NAME_REGEX = /(<)([A-Z][a-zA-Z\d]*)([\s|>])/g;
|
|
39
39
|
var COMPONENT_PROP_REGEX = /\s[a-z][a-z\d]*[A-Z]+[a-zA-Z\d]*(=|\s|>)/g;
|
|
40
40
|
var COMPONENT_STUB_ATTR = "$tag-name";
|
|
41
41
|
var PROP_STUB_ATTR = "-$u";
|
|
@@ -53,10 +53,13 @@ function rehypeRaw(opts) {
|
|
|
53
53
|
visit(tree, (node) => {
|
|
54
54
|
var _a;
|
|
55
55
|
if (node.type === "raw" && COMPONENT_NAME_REGEX.test(node.value)) {
|
|
56
|
-
node.value = node.value.replace(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
node.value = node.value.replace(
|
|
57
|
+
COMPONENT_NAME_REGEX,
|
|
58
|
+
(str, bracket, tagName, next, i, full) => {
|
|
59
|
+
const isWithinQuotes = /="[^"]*$/.test(full.slice(0, i)) && /^[^"]*"/.test(full.slice(i)) || /='[^']*$/.test(full.slice(0, i)) && /^[^']*'/.test(full.slice(i));
|
|
60
|
+
return isWithinQuotes ? str : `${bracket}${tagName} ${COMPONENT_STUB_ATTR}="${tagName}"${next}`;
|
|
61
|
+
}
|
|
62
|
+
);
|
|
60
63
|
node.value = node.value.replace(COMPONENT_PROP_REGEX, (str) => {
|
|
61
64
|
return str.replace(
|
|
62
65
|
/[A-Z]/g,
|
|
@@ -72,7 +75,7 @@ function rehypeRaw(opts) {
|
|
|
72
75
|
File: ${opts.fileAbsPath}`);
|
|
73
76
|
}
|
|
74
77
|
});
|
|
75
|
-
const newTree = raw(tree, vFile);
|
|
78
|
+
const newTree = raw(tree, { file: vFile });
|
|
76
79
|
visit(newTree, "element", (node) => {
|
|
77
80
|
var _a, _b;
|
|
78
81
|
if ((_a = node.properties) == null ? void 0 : _a[COMPONENT_STUB_ATTR]) {
|
package/dist/service/cli.js
CHANGED
|
@@ -22,7 +22,7 @@ __export(cli_exports, {
|
|
|
22
22
|
run: () => run
|
|
23
23
|
});
|
|
24
24
|
module.exports = __toCommonJS(cli_exports);
|
|
25
|
-
var import_node = require("
|
|
25
|
+
var import_node = require("@umijs/utils/dist/node");
|
|
26
26
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
27
27
|
var import_constants = require("./constants");
|
|
28
28
|
var import_dev = require("./dev");
|
|
@@ -30,7 +30,7 @@ var import_printHelp = require("./printHelp");
|
|
|
30
30
|
var import_service = require("./service");
|
|
31
31
|
(0, import_node.catchUnhandledRejection)();
|
|
32
32
|
async function run(opts) {
|
|
33
|
-
(0, import_node.checkVersion)();
|
|
33
|
+
(0, import_node.checkVersion)(import_constants.MIN_NODE_VERSION);
|
|
34
34
|
(0, import_node.setNodeTitle)(import_constants.FRAMEWORK_NAME);
|
|
35
35
|
(0, import_plugin_utils.setNoDeprecation)();
|
|
36
36
|
const args = (0, import_plugin_utils.yParser)(process.argv.slice(2), {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/service/forkedDev.ts
|
|
2
|
-
var import_node = require("
|
|
2
|
+
var import_node = require("@umijs/utils/dist/node");
|
|
3
3
|
var import_plugin_utils = require("umi/plugin-utils");
|
|
4
4
|
var import_constants = require("./constants");
|
|
5
5
|
var import_service = require("./service");
|
package/dist/utils.d.ts
CHANGED
|
@@ -44,4 +44,8 @@ export declare function getProjectRoot(cwd: string): string;
|
|
|
44
44
|
*/
|
|
45
45
|
export declare function componentToChunkName(component: string, cwdPath?: string): string;
|
|
46
46
|
export declare function generateMetaChunkName(path: string, cwd: string, locales?: string[]): string;
|
|
47
|
+
/**
|
|
48
|
+
* generate hash for string
|
|
49
|
+
*/
|
|
50
|
+
export declare function getContentHash(content: string, length?: number): string;
|
|
47
51
|
export {};
|
package/dist/utils.js
CHANGED
|
@@ -32,6 +32,7 @@ __export(utils_exports, {
|
|
|
32
32
|
componentToChunkName: () => componentToChunkName,
|
|
33
33
|
generateMetaChunkName: () => generateMetaChunkName,
|
|
34
34
|
getCache: () => getCache,
|
|
35
|
+
getContentHash: () => getContentHash,
|
|
35
36
|
getFileContentByRegExp: () => getFileContentByRegExp,
|
|
36
37
|
getFileIdFromFsPath: () => getFileIdFromFsPath,
|
|
37
38
|
getFileRangeLines: () => getFileRangeLines,
|
|
@@ -40,6 +41,7 @@ __export(utils_exports, {
|
|
|
40
41
|
tryFatherBuildConfigs: () => tryFatherBuildConfigs
|
|
41
42
|
});
|
|
42
43
|
module.exports = __toCommonJS(utils_exports);
|
|
44
|
+
var import_crypto = require("crypto");
|
|
43
45
|
var import_file_system_cache = __toESM(require("file-system-cache"));
|
|
44
46
|
var import_fs = __toESM(require("fs"));
|
|
45
47
|
var import_js_yaml = __toESM(require("js-yaml"));
|
|
@@ -149,11 +151,15 @@ function generateMetaChunkName(path2, cwd, locales = []) {
|
|
|
149
151
|
const locale = ifLocale ? `__${chunkName.replace(localeRegExp, "$1")}` : "";
|
|
150
152
|
return `meta__${dir}${locale}`;
|
|
151
153
|
}
|
|
154
|
+
function getContentHash(content2, length = 8) {
|
|
155
|
+
return (0, import_crypto.createHash)("md5").update(content2).digest("hex").slice(0, length);
|
|
156
|
+
}
|
|
152
157
|
// Annotate the CommonJS export names for ESM import in node:
|
|
153
158
|
0 && (module.exports = {
|
|
154
159
|
componentToChunkName,
|
|
155
160
|
generateMetaChunkName,
|
|
156
161
|
getCache,
|
|
162
|
+
getContentHash,
|
|
157
163
|
getFileContentByRegExp,
|
|
158
164
|
getFileIdFromFsPath,
|
|
159
165
|
getFileRangeLines,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dumi",
|
|
3
|
-
"version": "2.3.0-alpha.
|
|
3
|
+
"version": "2.3.0-alpha.6",
|
|
4
4
|
"description": "📖 Documentation Generator of React Component",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"generator",
|
|
@@ -82,8 +82,9 @@
|
|
|
82
82
|
"@swc/core": "1.3.72",
|
|
83
83
|
"@types/hast": "^2.3.5",
|
|
84
84
|
"@types/mdast": "^3.0.12",
|
|
85
|
-
"@umijs/bundler-utils": "^4.0.
|
|
86
|
-
"@umijs/core": "^4.0.
|
|
85
|
+
"@umijs/bundler-utils": "^4.0.83",
|
|
86
|
+
"@umijs/core": "^4.0.83",
|
|
87
|
+
"@umijs/utils": "^4.0.83",
|
|
87
88
|
"animated-scroll-to": "^2.3.0",
|
|
88
89
|
"classnames": "2.3.2",
|
|
89
90
|
"codesandbox": "^2.2.3",
|
|
@@ -131,7 +132,7 @@
|
|
|
131
132
|
"remark-rehype": "^10.1.0",
|
|
132
133
|
"sass": "^1.64.1",
|
|
133
134
|
"sitemap": "^7.1.1",
|
|
134
|
-
"umi": "^4.0.
|
|
135
|
+
"umi": "^4.0.83",
|
|
135
136
|
"unified": "^10.1.2",
|
|
136
137
|
"unist-util-visit": "^4.1.2",
|
|
137
138
|
"unist-util-visit-parents": "^5.1.3",
|
|
@@ -151,7 +152,7 @@
|
|
|
151
152
|
"@types/pluralize": "^0.0.30",
|
|
152
153
|
"@types/react": "^18.2.17",
|
|
153
154
|
"@types/react-copy-to-clipboard": "^5.0.4",
|
|
154
|
-
"@umijs/lint": "^4.0.
|
|
155
|
+
"@umijs/lint": "^4.0.83",
|
|
155
156
|
"@umijs/plugins": "4.0.32",
|
|
156
157
|
"dumi-theme-mobile": "workspace:*",
|
|
157
158
|
"eslint": "^8.46.0",
|
|
@@ -113,6 +113,7 @@
|
|
|
113
113
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 10%);
|
|
114
114
|
border-radius: 6px;
|
|
115
115
|
transition: all 0.2s ease-in-out;
|
|
116
|
+
z-index: 1;
|
|
116
117
|
|
|
117
118
|
@{dark-selector} & {
|
|
118
119
|
background-color: lighten(@c-site-bg-dark, 6%);
|
|
@@ -126,6 +127,7 @@
|
|
|
126
127
|
font-size: 15px;
|
|
127
128
|
line-height: 1.6;
|
|
128
129
|
text-align: left;
|
|
130
|
+
white-space: nowrap;
|
|
129
131
|
|
|
130
132
|
@media @mobile {
|
|
131
133
|
display: inline;
|