wensity 0.1.7 → 0.1.8
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 +3 -3
- package/dist/index.js +166 -65
- package/package.json +10 -10
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -7,8 +7,8 @@ Install open-code components and UI primitives from the Wensity registry into yo
|
|
|
7
7
|
npx wensity@latest init
|
|
8
8
|
|
|
9
9
|
# Or apply a shareable preset from https://ui.wensity.com/docs/primitives/setup
|
|
10
|
-
# Preset support requires wensity 0.1.
|
|
11
|
-
npx wensity@
|
|
10
|
+
# Preset support requires wensity 0.1.8 or later
|
|
11
|
+
npx wensity@latest init --preset <wsty1-code>
|
|
12
12
|
|
|
13
13
|
# Install a primitive or component
|
|
14
14
|
npx wensity@latest add button
|
|
@@ -38,7 +38,7 @@ Plain `init` (no `--preset`) refuses to overwrite an existing `wensity.json` unl
|
|
|
38
38
|
| `wensity list` | List registry entries |
|
|
39
39
|
| `wensity add <slug>` | Install source (skips existing files) |
|
|
40
40
|
| `wensity update <slug>` | Re-download and overwrite local source |
|
|
41
|
-
| `wensity version` | Print `0.1.
|
|
41
|
+
| `wensity version` | Print `0.1.8` |
|
|
42
42
|
|
|
43
43
|
Premium components and blocks require an API token from the Wensity dashboard. Tokens are stored at `~/.config/wensity/credentials.json` with `0600` permissions.
|
|
44
44
|
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { dirname as dirname6, join as join6 } from "path";
|
|
|
6
6
|
|
|
7
7
|
// src/constants.ts
|
|
8
8
|
var CLI_NAME = "wensity";
|
|
9
|
-
var CLI_VERSION = "0.1.
|
|
9
|
+
var CLI_VERSION = "0.1.8";
|
|
10
10
|
var CONFIG_FILE_NAME = "wensity.json";
|
|
11
11
|
var DEFAULT_API_ORIGIN = "https://ui.wensity.com";
|
|
12
12
|
var DEFAULT_REGISTRY_PATH = "/api/registry";
|
|
@@ -769,6 +769,9 @@ function utf8ByteLength(text) {
|
|
|
769
769
|
return new TextEncoder().encode(text).byteLength;
|
|
770
770
|
}
|
|
771
771
|
var BASE64URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
772
|
+
var COMPACT_CANONICAL_PREFIX = "c";
|
|
773
|
+
var COMPACT_CANONICAL_BODY_LENGTH = 3;
|
|
774
|
+
var COMPACT_CANONICAL_ENCODED_LENGTH = COMPACT_CANONICAL_PREFIX.length + COMPACT_CANONICAL_BODY_LENGTH;
|
|
772
775
|
function toBase64Url(bytes) {
|
|
773
776
|
let out = "";
|
|
774
777
|
for (let i = 0; i < bytes.length; i += 3) {
|
|
@@ -808,6 +811,66 @@ function fromBase64Url(code) {
|
|
|
808
811
|
}
|
|
809
812
|
return outIndex === out.length ? out : out.subarray(0, outIndex);
|
|
810
813
|
}
|
|
814
|
+
function indexOfPresetValue(values, value, path) {
|
|
815
|
+
const index = values.indexOf(value);
|
|
816
|
+
if (index < 0) {
|
|
817
|
+
throw new PresetValidationError(`Invalid compact preset value at ${path}.`, path);
|
|
818
|
+
}
|
|
819
|
+
return index;
|
|
820
|
+
}
|
|
821
|
+
function readCompactChar(char) {
|
|
822
|
+
if (!char) return -1;
|
|
823
|
+
return BASE64URL_ALPHABET.indexOf(char);
|
|
824
|
+
}
|
|
825
|
+
function encodeCompactCanonicalPayload(payload) {
|
|
826
|
+
let value = indexOfPresetValue(BASE_COLOR_IDS, payload.baseColor, "preset.baseColor");
|
|
827
|
+
value = value << 3 | indexOfPresetValue(THEME_COLOR_IDS, payload.themeColor, "preset.themeColor");
|
|
828
|
+
value = value << 2 | indexOfPresetValue(CHART_PALETTE_IDS, payload.chartPalette, "preset.chartPalette");
|
|
829
|
+
value = value << 1 | indexOfPresetValue(HEADING_FONT_IDS, payload.headingFont, "preset.headingFont");
|
|
830
|
+
value = value << 1 | indexOfPresetValue(BODY_FONT_IDS, payload.bodyFont, "preset.bodyFont");
|
|
831
|
+
value = value << 1 | indexOfPresetValue(ICON_LIBRARIES, payload.iconLibrary, "preset.iconLibrary");
|
|
832
|
+
value = value << 2 | indexOfPresetValue(RADIUS_PRESETS, payload.radius, "preset.radius");
|
|
833
|
+
return `${COMPACT_CANONICAL_PREFIX}${BASE64URL_ALPHABET[value >> 12 & 63]}${BASE64URL_ALPHABET[value >> 6 & 63]}${BASE64URL_ALPHABET[value & 63]}`;
|
|
834
|
+
}
|
|
835
|
+
function decodeCompactCanonicalPayload(encoded) {
|
|
836
|
+
if (encoded.length !== COMPACT_CANONICAL_ENCODED_LENGTH || !encoded.startsWith(COMPACT_CANONICAL_PREFIX)) {
|
|
837
|
+
throw new PresetValidationError("Compact preset code has an invalid length.", "preset");
|
|
838
|
+
}
|
|
839
|
+
const a = readCompactChar(encoded[1]);
|
|
840
|
+
const b = readCompactChar(encoded[2]);
|
|
841
|
+
const c = readCompactChar(encoded[3]);
|
|
842
|
+
if (a < 0 || b < 0 || c < 0) {
|
|
843
|
+
throw new PresetValidationError("Compact preset code is not valid base64url.", "preset");
|
|
844
|
+
}
|
|
845
|
+
let value = a << 12 | b << 6 | c;
|
|
846
|
+
const radius = RADIUS_PRESETS[value & 3];
|
|
847
|
+
value >>= 2;
|
|
848
|
+
const iconLibrary = ICON_LIBRARIES[value & 1];
|
|
849
|
+
value >>= 1;
|
|
850
|
+
const bodyFont = BODY_FONT_IDS[value & 1];
|
|
851
|
+
value >>= 1;
|
|
852
|
+
const headingFont = HEADING_FONT_IDS[value & 1];
|
|
853
|
+
value >>= 1;
|
|
854
|
+
const chartPalette = CHART_PALETTE_IDS[value & 3];
|
|
855
|
+
value >>= 2;
|
|
856
|
+
const themeColor = THEME_COLOR_IDS[value & 7];
|
|
857
|
+
value >>= 3;
|
|
858
|
+
const baseColor = BASE_COLOR_IDS[value & 7];
|
|
859
|
+
value >>= 3;
|
|
860
|
+
if (value !== 0 || !baseColor || !themeColor || !chartPalette || !headingFont || !bodyFont || !iconLibrary || !radius) {
|
|
861
|
+
throw new PresetValidationError("Compact preset code contains an out-of-range value.", "preset");
|
|
862
|
+
}
|
|
863
|
+
return {
|
|
864
|
+
v: 2,
|
|
865
|
+
baseColor,
|
|
866
|
+
themeColor,
|
|
867
|
+
chartPalette,
|
|
868
|
+
headingFont,
|
|
869
|
+
bodyFont,
|
|
870
|
+
iconLibrary,
|
|
871
|
+
radius
|
|
872
|
+
};
|
|
873
|
+
}
|
|
811
874
|
function stableStringifyCodecPayload(payload) {
|
|
812
875
|
const parts = [
|
|
813
876
|
`"v":${payload.v}`,
|
|
@@ -1039,18 +1102,6 @@ function validateCodecPayloadCanonical(value) {
|
|
|
1039
1102
|
radius: value.radius
|
|
1040
1103
|
};
|
|
1041
1104
|
}
|
|
1042
|
-
function stableStringifyCodecPayloadCanonical(payload) {
|
|
1043
|
-
return `{${[
|
|
1044
|
-
`"v":${payload.v}`,
|
|
1045
|
-
`"baseColor":${JSON.stringify(payload.baseColor)}`,
|
|
1046
|
-
`"themeColor":${JSON.stringify(payload.themeColor)}`,
|
|
1047
|
-
`"chartPalette":${JSON.stringify(payload.chartPalette)}`,
|
|
1048
|
-
`"headingFont":${JSON.stringify(payload.headingFont)}`,
|
|
1049
|
-
`"bodyFont":${JSON.stringify(payload.bodyFont)}`,
|
|
1050
|
-
`"iconLibrary":${JSON.stringify(payload.iconLibrary)}`,
|
|
1051
|
-
`"radius":${JSON.stringify(payload.radius)}`
|
|
1052
|
-
].join(",")}}`;
|
|
1053
|
-
}
|
|
1054
1105
|
function encodePresetCanonical(style) {
|
|
1055
1106
|
const normalized = normalizeStyleConfigCanonical(style);
|
|
1056
1107
|
const payload = {
|
|
@@ -1063,15 +1114,7 @@ function encodePresetCanonical(style) {
|
|
|
1063
1114
|
iconLibrary: normalized.iconLibrary,
|
|
1064
1115
|
radius: normalized.radius
|
|
1065
1116
|
};
|
|
1066
|
-
const
|
|
1067
|
-
const bytes = new TextEncoder().encode(json);
|
|
1068
|
-
if (bytes.byteLength > PRESET_CODEC_MAX_DECODED_JSON_BYTES) {
|
|
1069
|
-
throw new PresetValidationError(
|
|
1070
|
-
`Preset JSON exceeds ${PRESET_CODEC_MAX_DECODED_JSON_BYTES} bytes.`,
|
|
1071
|
-
"preset"
|
|
1072
|
-
);
|
|
1073
|
-
}
|
|
1074
|
-
const code = `${PRESET_CODEC_PREFIX}.${toBase64Url(bytes)}`;
|
|
1117
|
+
const code = `${PRESET_CODEC_PREFIX}.${encodeCompactCanonicalPayload(payload)}`;
|
|
1075
1118
|
if (code.length > PRESET_CODEC_MAX_CODE_LENGTH) {
|
|
1076
1119
|
throw new PresetValidationError(
|
|
1077
1120
|
`Preset code exceeds ${PRESET_CODEC_MAX_CODE_LENGTH} characters.`,
|
|
@@ -1101,6 +1144,9 @@ function decodePresetEnvelope(code) {
|
|
|
1101
1144
|
if (!encoded) {
|
|
1102
1145
|
throw new PresetValidationError("Preset code payload is empty.", "preset");
|
|
1103
1146
|
}
|
|
1147
|
+
if (encoded.length === COMPACT_CANONICAL_ENCODED_LENGTH && encoded.startsWith(COMPACT_CANONICAL_PREFIX)) {
|
|
1148
|
+
return decodeCompactCanonicalPayload(encoded);
|
|
1149
|
+
}
|
|
1104
1150
|
if (encoded.includes("=") || /[^A-Za-z0-9_-]/.test(encoded)) {
|
|
1105
1151
|
throw new PresetValidationError("Preset code payload is not valid unpadded base64url.", "preset");
|
|
1106
1152
|
}
|
|
@@ -1313,74 +1359,122 @@ var THEME_COLOR_PALETTE = {
|
|
|
1313
1359
|
light: { ...DEFAULT_CONTROL_SOLID_LIGHT },
|
|
1314
1360
|
dark: { ...DEFAULT_CONTROL_SOLID_DARK }
|
|
1315
1361
|
},
|
|
1362
|
+
//
|
|
1363
|
+
// Named hues stay the same true, saturated color family in both modes —
|
|
1364
|
+
// dark mode gets one step deeper (never a washed-out pastel tint of the
|
|
1365
|
+
// light-mode color). This mirrors how shadcn's own theme presets work:
|
|
1366
|
+
// e.g. its "red" theme ships `oklch(0.505 … 27.518)` (~Tailwind red-700)
|
|
1367
|
+
// for light and `oklch(0.444 … 26.899)` (~red-800, darker not lighter)
|
|
1368
|
+
// for dark, with a near-white foreground in both. Hex stops below are
|
|
1369
|
+
// Tailwind v4's red/blue/violet/green/orange 600/700/800/900/50 values.
|
|
1316
1370
|
red: {
|
|
1317
1371
|
light: {
|
|
1318
|
-
controlSolid: "#
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1372
|
+
controlSolid: "#c10007",
|
|
1373
|
+
// red-700
|
|
1374
|
+
controlSolidHover: "#e7000b",
|
|
1375
|
+
// red-600 — brighter on hover
|
|
1376
|
+
controlSolidActive: "#9f0712",
|
|
1377
|
+
// red-800 — darker on press
|
|
1378
|
+
controlSolidForeground: "#fef2f2"
|
|
1379
|
+
// red-50
|
|
1322
1380
|
},
|
|
1323
1381
|
dark: {
|
|
1324
|
-
controlSolid: "#
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1382
|
+
controlSolid: "#9f0712",
|
|
1383
|
+
// red-800
|
|
1384
|
+
controlSolidHover: "#c10007",
|
|
1385
|
+
// red-700 — brighter on hover
|
|
1386
|
+
controlSolidActive: "#82181a",
|
|
1387
|
+
// red-900 — darker on press
|
|
1388
|
+
controlSolidForeground: "#fef2f2"
|
|
1389
|
+
// red-50
|
|
1328
1390
|
}
|
|
1329
1391
|
},
|
|
1330
1392
|
blue: {
|
|
1331
1393
|
light: {
|
|
1332
|
-
controlSolid: "#
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1394
|
+
controlSolid: "#1447e6",
|
|
1395
|
+
// blue-700
|
|
1396
|
+
controlSolidHover: "#155dfc",
|
|
1397
|
+
// blue-600
|
|
1398
|
+
controlSolidActive: "#193cb8",
|
|
1399
|
+
// blue-800
|
|
1400
|
+
controlSolidForeground: "#eff6ff"
|
|
1401
|
+
// blue-50
|
|
1336
1402
|
},
|
|
1337
1403
|
dark: {
|
|
1338
|
-
controlSolid: "#
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1404
|
+
controlSolid: "#193cb8",
|
|
1405
|
+
// blue-800
|
|
1406
|
+
controlSolidHover: "#1447e6",
|
|
1407
|
+
// blue-700
|
|
1408
|
+
controlSolidActive: "#1c398e",
|
|
1409
|
+
// blue-900
|
|
1410
|
+
controlSolidForeground: "#eff6ff"
|
|
1411
|
+
// blue-50
|
|
1342
1412
|
}
|
|
1343
1413
|
},
|
|
1344
1414
|
violet: {
|
|
1345
1415
|
light: {
|
|
1346
|
-
controlSolid: "#
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1416
|
+
controlSolid: "#7008e7",
|
|
1417
|
+
// violet-700
|
|
1418
|
+
controlSolidHover: "#7f22fe",
|
|
1419
|
+
// violet-600
|
|
1420
|
+
controlSolidActive: "#5d0ec0",
|
|
1421
|
+
// violet-800
|
|
1422
|
+
controlSolidForeground: "#f5f3ff"
|
|
1423
|
+
// violet-50
|
|
1350
1424
|
},
|
|
1351
1425
|
dark: {
|
|
1352
|
-
controlSolid: "#
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1426
|
+
controlSolid: "#5d0ec0",
|
|
1427
|
+
// violet-800
|
|
1428
|
+
controlSolidHover: "#7008e7",
|
|
1429
|
+
// violet-700
|
|
1430
|
+
controlSolidActive: "#4d179a",
|
|
1431
|
+
// violet-900
|
|
1432
|
+
controlSolidForeground: "#f5f3ff"
|
|
1433
|
+
// violet-50
|
|
1356
1434
|
}
|
|
1357
1435
|
},
|
|
1358
1436
|
green: {
|
|
1359
1437
|
light: {
|
|
1360
|
-
controlSolid: "#
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1438
|
+
controlSolid: "#008236",
|
|
1439
|
+
// green-700
|
|
1440
|
+
controlSolidHover: "#00a63e",
|
|
1441
|
+
// green-600
|
|
1442
|
+
controlSolidActive: "#016630",
|
|
1443
|
+
// green-800
|
|
1444
|
+
controlSolidForeground: "#f0fdf4"
|
|
1445
|
+
// green-50
|
|
1364
1446
|
},
|
|
1365
1447
|
dark: {
|
|
1366
|
-
controlSolid: "#
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1448
|
+
controlSolid: "#016630",
|
|
1449
|
+
// green-800
|
|
1450
|
+
controlSolidHover: "#008236",
|
|
1451
|
+
// green-700
|
|
1452
|
+
controlSolidActive: "#0d542b",
|
|
1453
|
+
// green-900
|
|
1454
|
+
controlSolidForeground: "#f0fdf4"
|
|
1455
|
+
// green-50
|
|
1370
1456
|
}
|
|
1371
1457
|
},
|
|
1372
1458
|
orange: {
|
|
1373
1459
|
light: {
|
|
1374
|
-
controlSolid: "#
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1460
|
+
controlSolid: "#ca3500",
|
|
1461
|
+
// orange-700
|
|
1462
|
+
controlSolidHover: "#f54900",
|
|
1463
|
+
// orange-600
|
|
1464
|
+
controlSolidActive: "#9f2d00",
|
|
1465
|
+
// orange-800
|
|
1466
|
+
controlSolidForeground: "#fff7ed"
|
|
1467
|
+
// orange-50
|
|
1378
1468
|
},
|
|
1379
1469
|
dark: {
|
|
1380
|
-
controlSolid: "#
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1470
|
+
controlSolid: "#9f2d00",
|
|
1471
|
+
// orange-800
|
|
1472
|
+
controlSolidHover: "#ca3500",
|
|
1473
|
+
// orange-700
|
|
1474
|
+
controlSolidActive: "#7e2a0c",
|
|
1475
|
+
// orange-900
|
|
1476
|
+
controlSolidForeground: "#fff7ed"
|
|
1477
|
+
// orange-50
|
|
1384
1478
|
}
|
|
1385
1479
|
}
|
|
1386
1480
|
};
|
|
@@ -2709,8 +2803,15 @@ function encodePresetFileJson(parsed) {
|
|
|
2709
2803
|
}
|
|
2710
2804
|
if (v === 2) {
|
|
2711
2805
|
const payload = validateCodecPayloadCanonical(parsed);
|
|
2712
|
-
|
|
2713
|
-
|
|
2806
|
+
return encodePresetCanonical({
|
|
2807
|
+
baseColor: payload.baseColor,
|
|
2808
|
+
themeColor: payload.themeColor,
|
|
2809
|
+
chartPalette: payload.chartPalette,
|
|
2810
|
+
headingFont: payload.headingFont,
|
|
2811
|
+
bodyFont: payload.bodyFont,
|
|
2812
|
+
iconLibrary: payload.iconLibrary,
|
|
2813
|
+
radius: payload.radius
|
|
2814
|
+
});
|
|
2714
2815
|
}
|
|
2715
2816
|
throw new PresetValidationError(
|
|
2716
2817
|
`Unsupported preset payload version ${String(v)}. This preset may require a newer version of the Wensity CLI.`,
|
|
@@ -2744,7 +2845,7 @@ function toCliPresetError(error) {
|
|
|
2744
2845
|
const message = error.message;
|
|
2745
2846
|
if (/Unsupported preset payload version/i.test(message)) {
|
|
2746
2847
|
return new CliError(
|
|
2747
|
-
`Invalid preset: ${message} Upgrade the Wensity CLI (wensity@
|
|
2848
|
+
`Invalid preset: ${message} Upgrade the Wensity CLI (wensity@latest) and try again.`
|
|
2748
2849
|
);
|
|
2749
2850
|
}
|
|
2750
2851
|
return new CliError(`Invalid preset: ${message}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wensity",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Wensity component registry CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,16 +13,22 @@
|
|
|
13
13
|
"dist",
|
|
14
14
|
"README.md"
|
|
15
15
|
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup --config tsup.config.ts",
|
|
18
|
+
"typecheck": "tsc --noEmit",
|
|
19
|
+
"test": "vitest run --config vitest.config.ts",
|
|
20
|
+
"lint": "echo 'no lint'"
|
|
21
|
+
},
|
|
16
22
|
"engines": {
|
|
17
23
|
"node": ">=20.0.0"
|
|
18
24
|
},
|
|
19
25
|
"devDependencies": {
|
|
20
26
|
"@types/node": "^22.10.2",
|
|
27
|
+
"@wensity/preset": "workspace:*",
|
|
21
28
|
"lucide-react": "^1.24.0",
|
|
22
29
|
"tsup": "^8.3.5",
|
|
23
30
|
"typescript": "^5.7.2",
|
|
24
|
-
"vitest": "^4.1.5"
|
|
25
|
-
"@wensity/preset": "0.1.0"
|
|
31
|
+
"vitest": "^4.1.5"
|
|
26
32
|
},
|
|
27
33
|
"publishConfig": {
|
|
28
34
|
"access": "public"
|
|
@@ -32,11 +38,5 @@
|
|
|
32
38
|
"cli-table3": "^0.6.5",
|
|
33
39
|
"ora": "^9.4.0",
|
|
34
40
|
"picocolors": "^1.1.1"
|
|
35
|
-
},
|
|
36
|
-
"scripts": {
|
|
37
|
-
"build": "tsup --config tsup.config.ts",
|
|
38
|
-
"typecheck": "tsc --noEmit",
|
|
39
|
-
"test": "vitest run --config vitest.config.ts",
|
|
40
|
-
"lint": "echo 'no lint'"
|
|
41
41
|
}
|
|
42
|
-
}
|
|
42
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Ksparth12
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|