@liforma/client 0.4.8 → 0.4.9
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/CHANGELOG.md +12 -0
- package/dist/next/index.js +507 -180
- package/dist/next/index.js.map +1 -1
- package/dist/next/next/createLiformaSessionRouteHandler.d.ts +4 -0
- package/dist/next/next/createLiformaSessionRouteHandler.d.ts.map +1 -1
- package/dist/next/v2/api/mintPublicSession.d.ts +1 -0
- package/dist/next/v2/api/mintPublicSession.d.ts.map +1 -1
- package/dist/next/v2/api/sessionEndpointRequest.d.ts +4 -0
- package/dist/next/v2/api/sessionEndpointRequest.d.ts.map +1 -1
- package/dist/next/v2/embed/iframeHost.d.ts +12 -1
- package/dist/next/v2/embed/iframeHost.d.ts.map +1 -1
- package/dist/next/v2/embed/protocol.d.ts +33 -1
- package/dist/next/v2/embed/protocol.d.ts.map +1 -1
- package/dist/next/v2/experience.d.ts +15 -2
- package/dist/next/v2/experience.d.ts.map +1 -1
- package/dist/next/v2/experienceEvents.d.ts +3 -1
- package/dist/next/v2/experienceEvents.d.ts.map +1 -1
- package/dist/next/v2/sdkRelease.d.ts +3 -0
- package/dist/next/v2/sdkRelease.d.ts.map +1 -0
- package/dist/next/v2/types/sessionInteraction.d.ts +17 -0
- package/dist/next/v2/types/sessionInteraction.d.ts.map +1 -1
- package/dist/next/widget/mountExperienceWidget.d.ts.map +1 -1
- package/dist/next/widget/types.d.ts +4 -0
- package/dist/next/widget/types.d.ts.map +1 -1
- package/dist/npm/index.js +533 -220
- package/dist/npm/index.js.map +1 -1
- package/dist/npm/svelte/experienceLoadError.d.ts.map +1 -1
- package/dist/npm/svelte/experienceLoadErrorStyles.d.ts +1 -1
- package/dist/npm/svelte/experienceLoadErrorStyles.d.ts.map +1 -1
- package/dist/npm/v2/api/mintPublicSession.d.ts +1 -0
- package/dist/npm/v2/api/mintPublicSession.d.ts.map +1 -1
- package/dist/npm/v2/api/sessionEndpointRequest.d.ts +4 -0
- package/dist/npm/v2/api/sessionEndpointRequest.d.ts.map +1 -1
- package/dist/npm/v2/embed/iframeHost.d.ts +12 -1
- package/dist/npm/v2/embed/iframeHost.d.ts.map +1 -1
- package/dist/npm/v2/embed/protocol.d.ts +33 -1
- package/dist/npm/v2/embed/protocol.d.ts.map +1 -1
- package/dist/npm/v2/experience.d.ts +15 -2
- package/dist/npm/v2/experience.d.ts.map +1 -1
- package/dist/npm/v2/experienceEvents.d.ts +3 -1
- package/dist/npm/v2/experienceEvents.d.ts.map +1 -1
- package/dist/npm/v2/index.d.ts +1 -1
- package/dist/npm/v2/index.d.ts.map +1 -1
- package/dist/npm/v2/npm.d.ts +1 -1
- package/dist/npm/v2/npm.d.ts.map +1 -1
- package/dist/npm/v2/sdkRelease.d.ts +3 -0
- package/dist/npm/v2/sdkRelease.d.ts.map +1 -0
- package/dist/npm/v2/types/sessionInteraction.d.ts +17 -0
- package/dist/npm/v2/types/sessionInteraction.d.ts.map +1 -1
- package/dist/npm/widget/mountExperienceWidget.d.ts.map +1 -1
- package/dist/npm/widget/types.d.ts +4 -0
- package/dist/npm/widget/types.d.ts.map +1 -1
- package/dist/react/component/experienceComponentLaunch.d.ts.map +1 -1
- package/dist/react/component/experienceComponentTypes.d.ts +5 -0
- package/dist/react/component/experienceComponentTypes.d.ts.map +1 -1
- package/dist/react/index.js +974 -646
- package/dist/react/index.js.map +1 -1
- package/dist/react/svelte/experienceLoadError.d.ts.map +1 -1
- package/dist/react/svelte/experienceLoadErrorStyles.d.ts +1 -1
- package/dist/react/svelte/experienceLoadErrorStyles.d.ts.map +1 -1
- package/dist/react/v2/api/mintPublicSession.d.ts +1 -0
- package/dist/react/v2/api/mintPublicSession.d.ts.map +1 -1
- package/dist/react/v2/api/sessionEndpointRequest.d.ts +4 -0
- package/dist/react/v2/api/sessionEndpointRequest.d.ts.map +1 -1
- package/dist/react/v2/embed/iframeHost.d.ts +12 -1
- package/dist/react/v2/embed/iframeHost.d.ts.map +1 -1
- package/dist/react/v2/embed/protocol.d.ts +33 -1
- package/dist/react/v2/embed/protocol.d.ts.map +1 -1
- package/dist/react/v2/experience.d.ts +15 -2
- package/dist/react/v2/experience.d.ts.map +1 -1
- package/dist/react/v2/experienceEvents.d.ts +3 -1
- package/dist/react/v2/experienceEvents.d.ts.map +1 -1
- package/dist/react/v2/sdkRelease.d.ts +3 -0
- package/dist/react/v2/sdkRelease.d.ts.map +1 -0
- package/dist/react/v2/types/sessionInteraction.d.ts +17 -0
- package/dist/react/v2/types/sessionInteraction.d.ts.map +1 -1
- package/dist/react/widget/mountExperienceWidget.d.ts.map +1 -1
- package/dist/react/widget/types.d.ts +4 -0
- package/dist/react/widget/types.d.ts.map +1 -1
- package/dist/sdk/v2/client.js +2 -2
- package/dist/sdk/v2/client.js.map +1 -1
- package/dist/svelte/Experience.svelte +4 -0
- package/dist/svelte/experienceLoadError.js +37 -15
- package/dist/svelte/experienceLoadError.test.js +8 -0
- package/dist/svelte/experienceLoadErrorOverlay.js +1 -1
- package/dist/svelte/experienceLoadErrorStyles.d.ts +1 -1
- package/dist/svelte/experienceLoadErrorStyles.js +1 -0
- package/package.json +1 -1
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
speechOnly = false,
|
|
65
65
|
fit,
|
|
66
66
|
attribution,
|
|
67
|
+
alreadyConverted,
|
|
67
68
|
avatarId,
|
|
68
69
|
backdropId,
|
|
69
70
|
locationId,
|
|
@@ -114,6 +115,7 @@
|
|
|
114
115
|
conversationProcessor ? identityKey(conversationProcessor) : 0,
|
|
115
116
|
speechOnly,
|
|
116
117
|
attribution,
|
|
118
|
+
alreadyConverted,
|
|
117
119
|
avatarId,
|
|
118
120
|
backdropId,
|
|
119
121
|
locationId,
|
|
@@ -336,6 +338,7 @@
|
|
|
336
338
|
speechInputMode,
|
|
337
339
|
speechOnly,
|
|
338
340
|
attribution,
|
|
341
|
+
alreadyConverted,
|
|
339
342
|
conversationProcessor
|
|
340
343
|
};
|
|
341
344
|
}
|
|
@@ -356,6 +359,7 @@
|
|
|
356
359
|
speechInputMode,
|
|
357
360
|
speechOnly,
|
|
358
361
|
attribution,
|
|
362
|
+
alreadyConverted,
|
|
359
363
|
conversationProcessor
|
|
360
364
|
};
|
|
361
365
|
}
|
|
@@ -5,6 +5,26 @@ function toErrorMessage(error) {
|
|
|
5
5
|
return error.message;
|
|
6
6
|
return String(error);
|
|
7
7
|
}
|
|
8
|
+
function readErrorMeta(error) {
|
|
9
|
+
if (!error || typeof error !== 'object')
|
|
10
|
+
return {};
|
|
11
|
+
const record = error;
|
|
12
|
+
const code = typeof record.code === 'string' && record.code.trim() && record.code.trim() !== 'UNKNOWN'
|
|
13
|
+
? record.code.trim()
|
|
14
|
+
: undefined;
|
|
15
|
+
const requestId = typeof record.requestId === 'string' && record.requestId.trim()
|
|
16
|
+
? record.requestId.trim()
|
|
17
|
+
: undefined;
|
|
18
|
+
return { code, requestId };
|
|
19
|
+
}
|
|
20
|
+
function formatTechnicalDetail(message, meta) {
|
|
21
|
+
const parts = [message];
|
|
22
|
+
if (meta.code)
|
|
23
|
+
parts.push(`Code: ${meta.code}`);
|
|
24
|
+
if (meta.requestId)
|
|
25
|
+
parts.push(`Request id: ${meta.requestId}`);
|
|
26
|
+
return parts.join('\n');
|
|
27
|
+
}
|
|
8
28
|
function currentPageOrigin() {
|
|
9
29
|
try {
|
|
10
30
|
if (typeof globalThis.location?.origin === 'string' && globalThis.location.origin) {
|
|
@@ -23,49 +43,51 @@ export function extractOriginFromMessage(message) {
|
|
|
23
43
|
return ORIGIN_IN_MESSAGE.exec(message)?.[1];
|
|
24
44
|
}
|
|
25
45
|
export function presentExperienceLoadError(error, options) {
|
|
26
|
-
const
|
|
46
|
+
const rawMessage = toErrorMessage(error).trim() || 'Unknown error';
|
|
47
|
+
const meta = readErrorMeta(error);
|
|
48
|
+
const technicalMessage = formatTechnicalDetail(rawMessage, meta);
|
|
27
49
|
const experienceId = options?.experienceId?.trim() ||
|
|
28
|
-
extractExperienceIdFromMessage(
|
|
50
|
+
extractExperienceIdFromMessage(rawMessage) ||
|
|
29
51
|
undefined;
|
|
30
52
|
const origin = options?.origin?.trim() ||
|
|
31
|
-
extractOriginFromMessage(
|
|
53
|
+
extractOriginFromMessage(rawMessage) ||
|
|
32
54
|
currentPageOrigin() ||
|
|
33
55
|
undefined;
|
|
34
|
-
if (/No playable experience found/i.test(
|
|
35
|
-
/^Experience is not available\.?$/i.test(
|
|
36
|
-
/^Unknown experience\.?$/i.test(
|
|
37
|
-
/experience_unavailable/i.test(
|
|
56
|
+
if (/No playable experience found/i.test(rawMessage) ||
|
|
57
|
+
/^Experience is not available\.?$/i.test(rawMessage) ||
|
|
58
|
+
/^Unknown experience\.?$/i.test(rawMessage) ||
|
|
59
|
+
/experience_unavailable/i.test(rawMessage)) {
|
|
38
60
|
const idLabel = experienceId ?? 'the requested experience';
|
|
39
61
|
return {
|
|
40
62
|
kind: 'not_found',
|
|
41
63
|
title: 'The application tried to load an avatar experience that doesn’t exist.',
|
|
42
|
-
detail: `Experience with id ${idLabel} does not exist`,
|
|
64
|
+
detail: formatTechnicalDetail(`Experience with id ${idLabel} does not exist`, meta),
|
|
43
65
|
technicalMessage,
|
|
44
66
|
experienceId,
|
|
45
67
|
origin
|
|
46
68
|
};
|
|
47
69
|
}
|
|
48
|
-
if (/origin_not_allowed/i.test(
|
|
49
|
-
/is not an allowed origin/i.test(
|
|
50
|
-
/^Origin not allowed/i.test(
|
|
70
|
+
if (/origin_not_allowed/i.test(rawMessage) ||
|
|
71
|
+
/is not an allowed origin/i.test(rawMessage) ||
|
|
72
|
+
/^Origin not allowed/i.test(rawMessage)) {
|
|
51
73
|
const originLabel = origin ?? 'this page';
|
|
52
74
|
const idLabel = experienceId ?? 'the requested experience';
|
|
53
75
|
return {
|
|
54
76
|
kind: 'origin_not_allowed',
|
|
55
77
|
title: 'The application tried to load an avatar experience from a website that isn’t allowed.',
|
|
56
|
-
detail: `Origin ${originLabel} is not allowed for experience ${idLabel}`,
|
|
78
|
+
detail: formatTechnicalDetail(`Origin ${originLabel} is not allowed for experience ${idLabel}`, meta),
|
|
57
79
|
technicalMessage,
|
|
58
80
|
experienceId,
|
|
59
81
|
origin
|
|
60
82
|
};
|
|
61
83
|
}
|
|
62
|
-
if (/browser_embeds_disabled/i.test(
|
|
63
|
-
/^Browser embeds are not enabled/i.test(
|
|
84
|
+
if (/browser_embeds_disabled/i.test(rawMessage) ||
|
|
85
|
+
/^Browser embeds are not enabled/i.test(rawMessage)) {
|
|
64
86
|
const idLabel = experienceId ?? 'the requested experience';
|
|
65
87
|
return {
|
|
66
88
|
kind: 'browser_embeds_disabled',
|
|
67
89
|
title: 'The application tried to load an avatar experience that isn’t enabled for browser embeds.',
|
|
68
|
-
detail: `Browser embeds are not enabled for experience ${idLabel}`,
|
|
90
|
+
detail: formatTechnicalDetail(`Browser embeds are not enabled for experience ${idLabel}`, meta),
|
|
69
91
|
technicalMessage,
|
|
70
92
|
experienceId,
|
|
71
93
|
origin
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import { presentExperienceLoadError } from './experienceLoadError';
|
|
3
|
+
import { LiformaError } from '../v2/errors/LiformaError';
|
|
3
4
|
describe('presentExperienceLoadError', () => {
|
|
4
5
|
it('maps unavailable experiences to a friendly not-found presentation', () => {
|
|
5
6
|
const presentation = presentExperienceLoadError(new Error('No playable experience found for “exp_01MISSING”. Check that the experience id is correct.'), { experienceId: 'exp_01MISSING' });
|
|
@@ -15,4 +16,11 @@ describe('presentExperienceLoadError', () => {
|
|
|
15
16
|
expect(presentation.experienceId).toBe('exp_01DEMO');
|
|
16
17
|
expect(presentation.origin).toBe('http://localhost:5173');
|
|
17
18
|
});
|
|
19
|
+
it('includes code and request id in generic mint failure details', () => {
|
|
20
|
+
const presentation = presentExperienceLoadError(new LiformaError('API database schema is out of date (missing column actorLiformaUserId). Apply pending Prisma migrations on api.liforma.ai.', { code: 'SCHEMA_OUT_OF_DATE', requestId: 'req_abc', status: 502 }));
|
|
21
|
+
expect(presentation.kind).toBe('generic');
|
|
22
|
+
expect(presentation.detail).toContain('API database schema is out of date');
|
|
23
|
+
expect(presentation.detail).toContain('Code: SCHEMA_OUT_OF_DATE');
|
|
24
|
+
expect(presentation.detail).toContain('Request id: req_abc');
|
|
25
|
+
});
|
|
18
26
|
});
|
|
@@ -30,7 +30,7 @@ export function createExperienceLoadErrorOverlay(container, initial) {
|
|
|
30
30
|
title.textContent = presentation.title;
|
|
31
31
|
detail.textContent = presentation.detail;
|
|
32
32
|
detail.hidden = !advancedOpen;
|
|
33
|
-
advancedBtn.textContent = advancedOpen ? 'Hide details' : '
|
|
33
|
+
advancedBtn.textContent = advancedOpen ? 'Hide details' : 'Show details';
|
|
34
34
|
advancedBtn.setAttribute('aria-expanded', advancedOpen ? 'true' : 'false');
|
|
35
35
|
}
|
|
36
36
|
render();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** Subset of session loading overlay styles for pre-attach Experience load errors. */
|
|
2
2
|
export declare const EXPERIENCE_LOAD_ERROR_STYLE_ID = "liforma-experience-load-error-styles";
|
|
3
3
|
export declare function injectExperienceLoadErrorStyles(): void;
|
|
4
|
-
export declare const EXPERIENCE_LOAD_ERROR_CSS = "\n\t.liforma-loading-screen {\n\t\tinset: 0;\n\t\tz-index: 20;\n\t\tbox-sizing: border-box;\n\t\toverflow-x: clip;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tmax-width: 100vw;\n\t\tbackground:\n\t\t\tradial-gradient(circle at 50% 60%, rgba(79, 126, 196, 0.18), transparent 38%),\n\t\t\t#030508;\n\t\tfont-family: system-ui, -apple-system, sans-serif;\n\t\tcolor: #e8f0ff;\n\t\ttext-align: center;\n\t}\n\t.liforma-loading-screen-absolute {\n\t\tposition: absolute;\n\t}\n\t.liforma-loading-card {\n\t\tposition: absolute;\n\t\tleft: 50%;\n\t\ttop: 60%;\n\t\ttransform: translate(-50%, -50%);\n\t\twidth: min(22rem, calc(100% - 2.5rem));\n\t\tmax-width: calc(100% - max(1.25rem, env(safe-area-inset-left, 0px)) - max(1.25rem, env(safe-area-inset-right, 0px)));\n\t\tbox-sizing: border-box;\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t\tborder: 0;\n\t\tbackground: transparent;\n\t\tbox-shadow: none;\n\t}\n\t.liforma-loading-card-error {\n\t\tdisplay: block;\n\t\ttext-align: center;\n\t\tpadding: 1rem 1.05rem;\n\t\tborder-radius: 14px;\n\t\tborder: 1px solid rgba(255, 154, 154, 0.28);\n\t\tbackground:\n\t\t\tlinear-gradient(180deg, rgba(21, 29, 42, 0.92), rgba(9, 13, 20, 0.92));\n\t}\n\t.liforma-loading-kicker {\n\t\tmargin: 0 0 0.18rem;\n\t\tcolor: #8ba4c5;\n\t\tfont-size: 0.68rem;\n\t\tfont-weight: 700;\n\t\ttext-transform: uppercase;\n\t\tletter-spacing: 0.08em;\n\t}\n\t.liforma-loading-error {\n\t\tmargin: 0;\n\t\tmax-width: 28rem;\n\t\tcolor: #ffb4b4;\n\t\tfont-size: 0.92rem;\n\t\tline-height: 1.4;\n\t}\n\t.liforma-loading-error-title {\n\t\tmargin: 0;\n\t\tcolor: #f6ebe8;\n\t\tfont-size: 0.98rem;\n\t\tfont-weight: 650;\n\t\tline-height: 1.35;\n\t}\n\t.liforma-loading-error-advanced {\n\t\tmargin: 0.85rem 0 0;\n\t\tpadding: 0;\n\t\tborder: 0;\n\t\tbackground: transparent;\n\t\tcolor: #9eb7d8;\n\t\tfont: inherit;\n\t\tfont-size: 0.78rem;\n\t\tfont-weight: 650;\n\t\tletter-spacing: 0.02em;\n\t\ttext-decoration: underline;\n\t\ttext-underline-offset: 0.18em;\n\t\tcursor: pointer;\n\t}\n\t.liforma-loading-error-advanced:hover,\n\t.liforma-loading-error-advanced:focus-visible {\n\t\tcolor: #d7e6ff;\n\t\toutline: none;\n\t}\n\t.liforma-loading-error-detail {\n\t\tmargin: 0.7rem 0 0;\n\t\tpadding: 0.65rem 0.7rem;\n\t\tborder-radius: 10px;\n\t\tborder: 1px solid rgba(158, 191, 255, 0.16);\n\t\tbackground: rgba(3, 5, 8, 0.45);\n\t\tcolor: #c6d4e8;\n\t\tfont-size: 0.78rem;\n\t\tfont-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n\t\tline-height: 1.4;\n\t\ttext-align: left;\n\t\tword-break: break-word;\n\t}\n\t.liforma-loading-error-detail[hidden] {\n\t\tdisplay: none;\n\t}\n";
|
|
4
|
+
export declare const EXPERIENCE_LOAD_ERROR_CSS = "\n\t.liforma-loading-screen {\n\t\tinset: 0;\n\t\tz-index: 20;\n\t\tbox-sizing: border-box;\n\t\toverflow-x: clip;\n\t\twidth: 100%;\n\t\theight: 100%;\n\t\tmax-width: 100vw;\n\t\tbackground:\n\t\t\tradial-gradient(circle at 50% 60%, rgba(79, 126, 196, 0.18), transparent 38%),\n\t\t\t#030508;\n\t\tfont-family: system-ui, -apple-system, sans-serif;\n\t\tcolor: #e8f0ff;\n\t\ttext-align: center;\n\t}\n\t.liforma-loading-screen-absolute {\n\t\tposition: absolute;\n\t}\n\t.liforma-loading-card {\n\t\tposition: absolute;\n\t\tleft: 50%;\n\t\ttop: 60%;\n\t\ttransform: translate(-50%, -50%);\n\t\twidth: min(22rem, calc(100% - 2.5rem));\n\t\tmax-width: calc(100% - max(1.25rem, env(safe-area-inset-left, 0px)) - max(1.25rem, env(safe-area-inset-right, 0px)));\n\t\tbox-sizing: border-box;\n\t\tmargin: 0;\n\t\tpadding: 0;\n\t\tborder: 0;\n\t\tbackground: transparent;\n\t\tbox-shadow: none;\n\t}\n\t.liforma-loading-card-error {\n\t\tdisplay: block;\n\t\ttext-align: center;\n\t\tpadding: 1rem 1.05rem;\n\t\tborder-radius: 14px;\n\t\tborder: 1px solid rgba(255, 154, 154, 0.28);\n\t\tbackground:\n\t\t\tlinear-gradient(180deg, rgba(21, 29, 42, 0.92), rgba(9, 13, 20, 0.92));\n\t}\n\t.liforma-loading-kicker {\n\t\tmargin: 0 0 0.18rem;\n\t\tcolor: #8ba4c5;\n\t\tfont-size: 0.68rem;\n\t\tfont-weight: 700;\n\t\ttext-transform: uppercase;\n\t\tletter-spacing: 0.08em;\n\t}\n\t.liforma-loading-error {\n\t\tmargin: 0;\n\t\tmax-width: 28rem;\n\t\tcolor: #ffb4b4;\n\t\tfont-size: 0.92rem;\n\t\tline-height: 1.4;\n\t}\n\t.liforma-loading-error-title {\n\t\tmargin: 0;\n\t\tcolor: #f6ebe8;\n\t\tfont-size: 0.98rem;\n\t\tfont-weight: 650;\n\t\tline-height: 1.35;\n\t}\n\t.liforma-loading-error-advanced {\n\t\tmargin: 0.85rem 0 0;\n\t\tpadding: 0;\n\t\tborder: 0;\n\t\tbackground: transparent;\n\t\tcolor: #9eb7d8;\n\t\tfont: inherit;\n\t\tfont-size: 0.78rem;\n\t\tfont-weight: 650;\n\t\tletter-spacing: 0.02em;\n\t\ttext-decoration: underline;\n\t\ttext-underline-offset: 0.18em;\n\t\tcursor: pointer;\n\t}\n\t.liforma-loading-error-advanced:hover,\n\t.liforma-loading-error-advanced:focus-visible {\n\t\tcolor: #d7e6ff;\n\t\toutline: none;\n\t}\n\t.liforma-loading-error-detail {\n\t\tmargin: 0.7rem 0 0;\n\t\tpadding: 0.65rem 0.7rem;\n\t\tborder-radius: 10px;\n\t\tborder: 1px solid rgba(158, 191, 255, 0.16);\n\t\tbackground: rgba(3, 5, 8, 0.45);\n\t\tcolor: #c6d4e8;\n\t\tfont-size: 0.78rem;\n\t\tfont-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;\n\t\tline-height: 1.4;\n\t\ttext-align: left;\n\t\twhite-space: pre-wrap;\n\t\tword-break: break-word;\n\t}\n\t.liforma-loading-error-detail[hidden] {\n\t\tdisplay: none;\n\t}\n";
|
|
@@ -104,6 +104,7 @@ export const EXPERIENCE_LOAD_ERROR_CSS = `
|
|
|
104
104
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
105
105
|
line-height: 1.4;
|
|
106
106
|
text-align: left;
|
|
107
|
+
white-space: pre-wrap;
|
|
107
108
|
word-break: break-word;
|
|
108
109
|
}
|
|
109
110
|
.liforma-loading-error-detail[hidden] {
|