@power-seo/sitemap 1.0.6 → 1.0.7
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 +91 -91
- package/package.json +13 -13
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -18,16 +18,16 @@ XML sitemap generation for TypeScript — streaming output, automatic index spli
|
|
|
18
18
|
|
|
19
19
|
## Why @power-seo/sitemap?
|
|
20
20
|
|
|
21
|
-
|
|
|
22
|
-
|
|
23
|
-
| Spec compliance
|
|
24
|
-
| Large sites
|
|
25
|
-
| Memory usage
|
|
26
|
-
| Image indexing
|
|
27
|
-
| Video SEO
|
|
28
|
-
| News sitemaps
|
|
29
|
-
| Hostname handling | ❌ Hardcode absolute URLs everywhere
|
|
30
|
-
| Validation
|
|
21
|
+
| | Without | With |
|
|
22
|
+
| ----------------- | ----------------------------------------- | --------------------------------------------------- |
|
|
23
|
+
| Spec compliance | ❌ Hand-built XML, wrong namespaces | ✅ Correct `<urlset>` + namespace declarations |
|
|
24
|
+
| Large sites | ❌ Single file breaks at 50,000 URLs | ✅ Auto-split + sitemap index generation |
|
|
25
|
+
| Memory usage | ❌ String concat spikes on large catalogs | ✅ Synchronous generator yields chunks |
|
|
26
|
+
| Image indexing | ❌ Product images undiscoverable | ✅ `<image:image>` extension per URL |
|
|
27
|
+
| Video SEO | ❌ No structured video metadata | ✅ `<video:video>` extension with title, duration |
|
|
28
|
+
| News sitemaps | ❌ Missing publication + date tags | ✅ `<news:news>` extension for Google News |
|
|
29
|
+
| Hostname handling | ❌ Hardcode absolute URLs everywhere | ✅ Pass `hostname` once; use relative `loc` paths |
|
|
30
|
+
| Validation | ❌ Silent bad data reaches Google | ✅ `validateSitemapUrl()` returns errors + warnings |
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
@@ -53,20 +53,20 @@ XML sitemap generation for TypeScript — streaming output, automatic index spli
|
|
|
53
53
|
|
|
54
54
|
## Comparison
|
|
55
55
|
|
|
56
|
-
| Feature
|
|
57
|
-
|
|
|
58
|
-
| Image sitemap extension
|
|
59
|
-
| Video sitemap extension
|
|
60
|
-
| News sitemap extension
|
|
61
|
-
| Streaming generation
|
|
62
|
-
| Auto index splitting
|
|
63
|
-
| URL validation
|
|
64
|
-
| Hostname + relative loc paths
|
|
65
|
-
| Zero runtime dependencies
|
|
66
|
-
| Edge runtime compatible
|
|
67
|
-
| TypeScript-first
|
|
68
|
-
| Tree-shakeable
|
|
69
|
-
| Next.js `app/sitemap.ts` adapter |
|
|
56
|
+
| Feature | @power-seo/sitemap | next-sitemap | sitemap (npm) | xmlbuilder2 |
|
|
57
|
+
| -------------------------------- | :----------------: | :----------: | :-----------: | :---------: |
|
|
58
|
+
| Image sitemap extension | ✅ | ✅ | ✅ | ❌ |
|
|
59
|
+
| Video sitemap extension | ✅ | ❌ | ✅ | ❌ |
|
|
60
|
+
| News sitemap extension | ✅ | ❌ | ✅ | ❌ |
|
|
61
|
+
| Streaming generation | ✅ | ❌ | ❌ | ❌ |
|
|
62
|
+
| Auto index splitting | ✅ | ✅ | ❌ | ❌ |
|
|
63
|
+
| URL validation | ✅ | ❌ | ❌ | ❌ |
|
|
64
|
+
| Hostname + relative loc paths | ✅ | ❌ | ❌ | ❌ |
|
|
65
|
+
| Zero runtime dependencies | ✅ | ❌ | ❌ | ❌ |
|
|
66
|
+
| Edge runtime compatible | ✅ | ❌ | ❌ | ❌ |
|
|
67
|
+
| TypeScript-first | ✅ | Partial | ❌ | ❌ |
|
|
68
|
+
| Tree-shakeable | ✅ | ❌ | ❌ | ❌ |
|
|
69
|
+
| Next.js `app/sitemap.ts` adapter | ✅ | ✅ | ❌ | ❌ |
|
|
70
70
|
|
|
71
71
|
---
|
|
72
72
|
|
|
@@ -317,12 +317,12 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
|
|
317
317
|
function generateSitemap(config: SitemapConfig): string;
|
|
318
318
|
```
|
|
319
319
|
|
|
320
|
-
| Prop
|
|
321
|
-
|
|
|
322
|
-
| `hostname`
|
|
323
|
-
| `urls`
|
|
324
|
-
| `maxUrlsPerSitemap` | `number`
|
|
325
|
-
| `outputDir`
|
|
320
|
+
| Prop | Type | Required | Description |
|
|
321
|
+
| ------------------- | -------------- | -------- | ------------------------------------------------------------------------- |
|
|
322
|
+
| `hostname` | `string` | ✅ | Base URL prepended to relative `loc` paths (e.g. `'https://example.com'`) |
|
|
323
|
+
| `urls` | `SitemapURL[]` | ✅ | Array of URL entries |
|
|
324
|
+
| `maxUrlsPerSitemap` | `number` | — | Override the 50,000-URL chunk size (used by `splitSitemap`) |
|
|
325
|
+
| `outputDir` | `string` | — | Optional output directory hint (informational; does not write files) |
|
|
326
326
|
|
|
327
327
|
### `streamSitemap(hostname, urls)`
|
|
328
328
|
|
|
@@ -335,10 +335,10 @@ function streamSitemap(
|
|
|
335
335
|
|
|
336
336
|
Synchronous generator. Yields XML string chunks — one for the XML declaration and opening tag, one per `<url>` block, and one for the closing tag. Does not buffer the full XML in memory.
|
|
337
337
|
|
|
338
|
-
| Param
|
|
339
|
-
|
|
|
340
|
-
| `hostname` | `string`
|
|
341
|
-
| `urls`
|
|
338
|
+
| Param | Type | Description |
|
|
339
|
+
| ---------- | ---------------------- | ------------------------------------------------------------------ |
|
|
340
|
+
| `hostname` | `string` | Base URL prepended to relative `loc` paths |
|
|
341
|
+
| `urls` | `Iterable<SitemapURL>` | Any iterable of URL entries — arrays, generators, database cursors |
|
|
342
342
|
|
|
343
343
|
### `splitSitemap(config, sitemapUrlPattern?)`
|
|
344
344
|
|
|
@@ -351,17 +351,17 @@ function splitSitemap(
|
|
|
351
351
|
|
|
352
352
|
Splits a large URL set into multiple sitemap files and returns the index XML and all sitemap XMLs. The `sitemapUrlPattern` parameter controls generated filenames using `{index}` as a placeholder.
|
|
353
353
|
|
|
354
|
-
| Param
|
|
355
|
-
|
|
|
356
|
-
| `config`
|
|
357
|
-
| `sitemapUrlPattern` | `string`
|
|
354
|
+
| Param | Type | Default | Description |
|
|
355
|
+
| ------------------- | --------------- | ------------------------ | --------------------------------------- |
|
|
356
|
+
| `config` | `SitemapConfig` | — | Same config as `generateSitemap()` |
|
|
357
|
+
| `sitemapUrlPattern` | `string` | `'/sitemap-{index}.xml'` | Filename pattern for each split sitemap |
|
|
358
358
|
|
|
359
359
|
**Return value:**
|
|
360
360
|
|
|
361
|
-
| Field
|
|
362
|
-
|
|
|
363
|
-
| `index`
|
|
364
|
-
| `sitemaps` | `Array<{ filename: string; xml: string }>` | Each split sitemap with its filename and XML string
|
|
361
|
+
| Field | Type | Description |
|
|
362
|
+
| ---------- | ------------------------------------------ | ---------------------------------------------------------------- |
|
|
363
|
+
| `index` | `string` | Sitemap index XML (`<sitemapindex>`) referencing all split files |
|
|
364
|
+
| `sitemaps` | `Array<{ filename: string; xml: string }>` | Each split sitemap with its filename and XML string |
|
|
365
365
|
|
|
366
366
|
### `generateSitemapIndex(config)`
|
|
367
367
|
|
|
@@ -369,8 +369,8 @@ Splits a large URL set into multiple sitemap files and returns the index XML and
|
|
|
369
369
|
function generateSitemapIndex(config: SitemapIndexConfig): string;
|
|
370
370
|
```
|
|
371
371
|
|
|
372
|
-
| Prop
|
|
373
|
-
|
|
|
372
|
+
| Prop | Type | Description |
|
|
373
|
+
| ---------- | --------------------- | ---------------------------------------------------- |
|
|
374
374
|
| `sitemaps` | `SitemapIndexEntry[]` | Array of `{ loc: string; lastmod?: string }` entries |
|
|
375
375
|
|
|
376
376
|
### `validateSitemapUrl(url)`
|
|
@@ -391,45 +391,45 @@ function toNextSitemap(urls: SitemapURL[]): NextSitemapEntry[];
|
|
|
391
391
|
|
|
392
392
|
Converts a `SitemapURL[]` to the array format expected by Next.js App Router's `app/sitemap.ts` file convention. Invalid URLs (per `validateSitemapUrl`) are filtered out automatically. `lastmod` strings are converted to `Date` objects; `changefreq` is mapped to `changeFrequency`.
|
|
393
393
|
|
|
394
|
-
| Field | Type
|
|
395
|
-
| ----------------- |
|
|
396
|
-
| `url` | `string`
|
|
397
|
-
| `lastModified` | `Date \| string`
|
|
398
|
-
| `changeFrequency` | `string`
|
|
399
|
-
| `priority` | `number`
|
|
394
|
+
| Field | Type | Description |
|
|
395
|
+
| ----------------- | ---------------- | ------------------------------------ |
|
|
396
|
+
| `url` | `string` | Absolute URL (`loc`) |
|
|
397
|
+
| `lastModified` | `Date \| string` | From `lastmod` (converted to `Date`) |
|
|
398
|
+
| `changeFrequency` | `string` | From `changefreq` |
|
|
399
|
+
| `priority` | `number` | From `priority` |
|
|
400
400
|
|
|
401
401
|
---
|
|
402
402
|
|
|
403
403
|
## Types
|
|
404
404
|
|
|
405
|
-
| Type
|
|
406
|
-
|
|
|
407
|
-
| `SitemapConfig`
|
|
408
|
-
| `SitemapURL`
|
|
409
|
-
| `SitemapImage`
|
|
410
|
-
| `SitemapVideo`
|
|
411
|
-
| `SitemapNews`
|
|
412
|
-
| `SitemapIndexConfig`
|
|
413
|
-
| `SitemapIndexEntry`
|
|
414
|
-
| `SitemapValidationResult` | `{ valid: boolean; errors: string[]; warnings: string[] }`
|
|
405
|
+
| Type | Description |
|
|
406
|
+
| ------------------------- | --------------------------------------------------------------------------------------------- |
|
|
407
|
+
| `SitemapConfig` | `{ hostname: string; urls: SitemapURL[]; maxUrlsPerSitemap?: number; outputDir?: string }` |
|
|
408
|
+
| `SitemapURL` | Single URL entry — see field table below |
|
|
409
|
+
| `SitemapImage` | `{ loc: string; caption?: string; geoLocation?: string; title?: string; license?: string }` |
|
|
410
|
+
| `SitemapVideo` | Video extension entry with `thumbnailLoc`, `title`, `description`, and optional fields |
|
|
411
|
+
| `SitemapNews` | `{ publication: { name: string; language: string }; publicationDate: string; title: string }` |
|
|
412
|
+
| `SitemapIndexConfig` | `{ sitemaps: SitemapIndexEntry[] }` |
|
|
413
|
+
| `SitemapIndexEntry` | `{ loc: string; lastmod?: string }` |
|
|
414
|
+
| `SitemapValidationResult` | `{ valid: boolean; errors: string[]; warnings: string[] }` |
|
|
415
415
|
|
|
416
416
|
### `SitemapURL` Fields
|
|
417
417
|
|
|
418
|
-
| Prop
|
|
419
|
-
|
|
|
420
|
-
| `loc`
|
|
421
|
-
| `lastmod`
|
|
422
|
-
| `changefreq` | `'always' \| 'hourly' \| 'daily' \| 'weekly' \| 'monthly' \| 'yearly' \| 'never'` | —
|
|
423
|
-
| `priority`
|
|
424
|
-
| `images`
|
|
425
|
-
| `videos`
|
|
426
|
-
| `news`
|
|
418
|
+
| Prop | Type | Default | Description |
|
|
419
|
+
| ------------ | --------------------------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------ |
|
|
420
|
+
| `loc` | `string` | — | **Required.** URL path (e.g. `/about`) or absolute URL. Hostname is prepended to relative paths. |
|
|
421
|
+
| `lastmod` | `string` | — | Last modified date — ISO 8601 or `YYYY-MM-DD` |
|
|
422
|
+
| `changefreq` | `'always' \| 'hourly' \| 'daily' \| 'weekly' \| 'monthly' \| 'yearly' \| 'never'` | — | Suggested crawl frequency |
|
|
423
|
+
| `priority` | `number` | (no tag emitted) | Priority 0.0–1.0. When omitted, no `<priority>` tag is written. |
|
|
424
|
+
| `images` | `SitemapImage[]` | — | Image extension entries — emits `<image:image>` blocks |
|
|
425
|
+
| `videos` | `SitemapVideo[]` | — | Video extension entries — emits `<video:video>` blocks |
|
|
426
|
+
| `news` | `SitemapNews` | — | News extension entry — emits `<news:news>` block |
|
|
427
427
|
|
|
428
428
|
### Constants
|
|
429
429
|
|
|
430
|
-
| Constant
|
|
431
|
-
|
|
|
432
|
-
| `MAX_URLS_PER_SITEMAP`
|
|
430
|
+
| Constant | Value | Description |
|
|
431
|
+
| ------------------------ | ------------ | ------------------------------------------------------------- |
|
|
432
|
+
| `MAX_URLS_PER_SITEMAP` | `50_000` | Maximum URLs allowed per sitemap file (spec limit) |
|
|
433
433
|
| `MAX_SITEMAP_SIZE_BYTES` | `52_428_800` | Maximum sitemap file size in bytes (50 MB = 50 × 1024 × 1024) |
|
|
434
434
|
|
|
435
435
|
---
|
|
@@ -476,25 +476,25 @@ Converts a `SitemapURL[]` to the array format expected by Next.js App Router's `
|
|
|
476
476
|
|
|
477
477
|
All 17 packages are independently installable — use only what you need.
|
|
478
478
|
|
|
479
|
-
| Package
|
|
480
|
-
|
|
|
481
|
-
| [`@power-seo/core`](https://www.npmjs.com/package/@power-seo/core)
|
|
482
|
-
| [`@power-seo/react`](https://www.npmjs.com/package/@power-seo/react)
|
|
483
|
-
| [`@power-seo/meta`](https://www.npmjs.com/package/@power-seo/meta)
|
|
484
|
-
| [`@power-seo/schema`](https://www.npmjs.com/package/@power-seo/schema)
|
|
485
|
-
| [`@power-seo/content-analysis`](https://www.npmjs.com/package/@power-seo/content-analysis) | `npm i @power-seo/content-analysis` | Yoast-style SEO content scoring engine with React components
|
|
486
|
-
| [`@power-seo/readability`](https://www.npmjs.com/package/@power-seo/readability)
|
|
487
|
-
| [`@power-seo/preview`](https://www.npmjs.com/package/@power-seo/preview)
|
|
488
|
-
| [`@power-seo/sitemap`](https://www.npmjs.com/package/@power-seo/sitemap)
|
|
489
|
-
| [`@power-seo/redirects`](https://www.npmjs.com/package/@power-seo/redirects)
|
|
490
|
-
| [`@power-seo/links`](https://www.npmjs.com/package/@power-seo/links)
|
|
491
|
-
| [`@power-seo/audit`](https://www.npmjs.com/package/@power-seo/audit)
|
|
492
|
-
| [`@power-seo/images`](https://www.npmjs.com/package/@power-seo/images)
|
|
493
|
-
| [`@power-seo/ai`](https://www.npmjs.com/package/@power-seo/ai)
|
|
494
|
-
| [`@power-seo/analytics`](https://www.npmjs.com/package/@power-seo/analytics)
|
|
495
|
-
| [`@power-seo/search-console`](https://www.npmjs.com/package/@power-seo/search-console)
|
|
496
|
-
| [`@power-seo/integrations`](https://www.npmjs.com/package/@power-seo/integrations)
|
|
497
|
-
| [`@power-seo/tracking`](https://www.npmjs.com/package/@power-seo/tracking)
|
|
479
|
+
| Package | Install | Description |
|
|
480
|
+
| ------------------------------------------------------------------------------------------ | ----------------------------------- | ----------------------------------------------------------------------- |
|
|
481
|
+
| [`@power-seo/core`](https://www.npmjs.com/package/@power-seo/core) | `npm i @power-seo/core` | Framework-agnostic utilities, types, validators, and constants |
|
|
482
|
+
| [`@power-seo/react`](https://www.npmjs.com/package/@power-seo/react) | `npm i @power-seo/react` | React SEO components — meta, Open Graph, Twitter Card, breadcrumbs |
|
|
483
|
+
| [`@power-seo/meta`](https://www.npmjs.com/package/@power-seo/meta) | `npm i @power-seo/meta` | SSR meta helpers for Next.js App Router, Remix v2, and generic SSR |
|
|
484
|
+
| [`@power-seo/schema`](https://www.npmjs.com/package/@power-seo/schema) | `npm i @power-seo/schema` | Type-safe JSON-LD structured data — 20 builders + 18 React components |
|
|
485
|
+
| [`@power-seo/content-analysis`](https://www.npmjs.com/package/@power-seo/content-analysis) | `npm i @power-seo/content-analysis` | Yoast-style SEO content scoring engine with React components |
|
|
486
|
+
| [`@power-seo/readability`](https://www.npmjs.com/package/@power-seo/readability) | `npm i @power-seo/readability` | Readability scoring — Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI |
|
|
487
|
+
| [`@power-seo/preview`](https://www.npmjs.com/package/@power-seo/preview) | `npm i @power-seo/preview` | SERP, Open Graph, and Twitter/X Card preview generators |
|
|
488
|
+
| [`@power-seo/sitemap`](https://www.npmjs.com/package/@power-seo/sitemap) | `npm i @power-seo/sitemap` | XML sitemap generation, streaming, index splitting, and validation |
|
|
489
|
+
| [`@power-seo/redirects`](https://www.npmjs.com/package/@power-seo/redirects) | `npm i @power-seo/redirects` | Redirect engine with Next.js, Remix, and Express adapters |
|
|
490
|
+
| [`@power-seo/links`](https://www.npmjs.com/package/@power-seo/links) | `npm i @power-seo/links` | Link graph analysis — orphan detection, suggestions, equity scoring |
|
|
491
|
+
| [`@power-seo/audit`](https://www.npmjs.com/package/@power-seo/audit) | `npm i @power-seo/audit` | Full SEO audit engine — meta, content, structure, performance rules |
|
|
492
|
+
| [`@power-seo/images`](https://www.npmjs.com/package/@power-seo/images) | `npm i @power-seo/images` | Image SEO — alt text, lazy loading, format analysis, image sitemaps |
|
|
493
|
+
| [`@power-seo/ai`](https://www.npmjs.com/package/@power-seo/ai) | `npm i @power-seo/ai` | LLM-agnostic AI prompt templates and parsers for SEO tasks |
|
|
494
|
+
| [`@power-seo/analytics`](https://www.npmjs.com/package/@power-seo/analytics) | `npm i @power-seo/analytics` | Merge GSC + audit data, trend analysis, ranking insights, dashboard |
|
|
495
|
+
| [`@power-seo/search-console`](https://www.npmjs.com/package/@power-seo/search-console) | `npm i @power-seo/search-console` | Google Search Console API — OAuth2, service account, URL inspection |
|
|
496
|
+
| [`@power-seo/integrations`](https://www.npmjs.com/package/@power-seo/integrations) | `npm i @power-seo/integrations` | Semrush and Ahrefs API clients with rate limiting and pagination |
|
|
497
|
+
| [`@power-seo/tracking`](https://www.npmjs.com/package/@power-seo/tracking) | `npm i @power-seo/tracking` | GA4, Clarity, PostHog, Plausible, Fathom — scripts + consent management |
|
|
498
498
|
|
|
499
499
|
---
|
|
500
500
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@power-seo/sitemap",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "XML sitemap generation, streaming, and validation with image, video, and news support",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -17,8 +17,18 @@
|
|
|
17
17
|
"files": [
|
|
18
18
|
"dist"
|
|
19
19
|
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsup",
|
|
22
|
+
"dev": "tsup --watch",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"lint": "eslint src/",
|
|
27
|
+
"lint:fix": "eslint src/ --fix",
|
|
28
|
+
"clean": "rimraf dist"
|
|
29
|
+
},
|
|
20
30
|
"dependencies": {
|
|
21
|
-
"@power-seo/core": "
|
|
31
|
+
"@power-seo/core": "workspace:*"
|
|
22
32
|
},
|
|
23
33
|
"devDependencies": {
|
|
24
34
|
"rimraf": "^6.1.3",
|
|
@@ -50,15 +60,5 @@
|
|
|
50
60
|
"funding": {
|
|
51
61
|
"type": "github",
|
|
52
62
|
"url": "https://github.com/sponsors/cybercraftbd"
|
|
53
|
-
},
|
|
54
|
-
"scripts": {
|
|
55
|
-
"build": "tsup",
|
|
56
|
-
"dev": "tsup --watch",
|
|
57
|
-
"test": "vitest run",
|
|
58
|
-
"test:watch": "vitest",
|
|
59
|
-
"typecheck": "tsc --noEmit",
|
|
60
|
-
"lint": "eslint src/",
|
|
61
|
-
"lint:fix": "eslint src/ --fix",
|
|
62
|
-
"clean": "rimraf dist"
|
|
63
63
|
}
|
|
64
|
-
}
|
|
64
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 CCBD SEO Contributors
|
|
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.
|