@ecency/render-helper 2.3.16 → 2.4.1
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/LICENSE +1 -1
- package/README.md +171 -17
- package/dist/browser/index.d.ts +32 -0
- package/dist/browser/index.js +1556 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/node/index.cjs +1575 -0
- package/dist/node/index.cjs.map +1 -0
- package/dist/node/index.mjs +1559 -0
- package/dist/node/index.mjs.map +1 -0
- package/package.json +49 -47
- package/lib/cache.d.ts +0 -3
- package/lib/cache.js +0 -21
- package/lib/cache.js.map +0 -1
- package/lib/catch-post-image.d.ts +0 -2
- package/lib/catch-post-image.js +0 -76
- package/lib/catch-post-image.js.map +0 -1
- package/lib/consts/allowed-attributes.const.d.ts +0 -2
- package/lib/consts/allowed-attributes.const.js +0 -71
- package/lib/consts/allowed-attributes.const.js.map +0 -1
- package/lib/consts/dom-parser.const.d.ts +0 -2
- package/lib/consts/dom-parser.const.js +0 -12
- package/lib/consts/dom-parser.const.js.map +0 -1
- package/lib/consts/index.d.ts +0 -5
- package/lib/consts/index.js +0 -22
- package/lib/consts/index.js.map +0 -1
- package/lib/consts/regexes.const.d.ts +0 -44
- package/lib/consts/regexes.const.js +0 -49
- package/lib/consts/regexes.const.js.map +0 -1
- package/lib/consts/section-list.const.d.ts +0 -1
- package/lib/consts/section-list.const.js +0 -24
- package/lib/consts/section-list.const.js.map +0 -1
- package/lib/consts/white-list.const.d.ts +0 -2
- package/lib/consts/white-list.const.js +0 -37
- package/lib/consts/white-list.const.js.map +0 -1
- package/lib/helper.d.ts +0 -5
- package/lib/helper.js +0 -60
- package/lib/helper.js.map +0 -1
- package/lib/index.d.ts +0 -8
- package/lib/index.js +0 -19
- package/lib/index.js.map +0 -1
- package/lib/markdown-2-html.d.ts +0 -2
- package/lib/markdown-2-html.js +0 -25
- package/lib/markdown-2-html.js.map +0 -1
- package/lib/methods/a.method.d.ts +0 -1
- package/lib/methods/a.method.js +0 -647
- package/lib/methods/a.method.js.map +0 -1
- package/lib/methods/clean-reply.method.d.ts +0 -1
- package/lib/methods/clean-reply.method.js +0 -37
- package/lib/methods/clean-reply.method.js.map +0 -1
- package/lib/methods/get-inner-html.method.d.ts +0 -1
- package/lib/methods/get-inner-html.method.js +0 -16
- package/lib/methods/get-inner-html.method.js.map +0 -1
- package/lib/methods/iframe.method.d.ts +0 -1
- package/lib/methods/iframe.method.js +0 -159
- package/lib/methods/iframe.method.js.map +0 -1
- package/lib/methods/img.method.d.ts +0 -4
- package/lib/methods/img.method.js +0 -50
- package/lib/methods/img.method.js.map +0 -1
- package/lib/methods/index.d.ts +0 -7
- package/lib/methods/index.js +0 -24
- package/lib/methods/index.js.map +0 -1
- package/lib/methods/linkify.method.d.ts +0 -1
- package/lib/methods/linkify.method.js +0 -56
- package/lib/methods/linkify.method.js.map +0 -1
- package/lib/methods/markdown-to-html.method.d.ts +0 -1
- package/lib/methods/markdown-to-html.method.js +0 -98
- package/lib/methods/markdown-to-html.method.js.map +0 -1
- package/lib/methods/noop.method.d.ts +0 -1
- package/lib/methods/noop.method.js +0 -6
- package/lib/methods/noop.method.js.map +0 -1
- package/lib/methods/p.method.d.ts +0 -1
- package/lib/methods/p.method.js +0 -11
- package/lib/methods/p.method.js.map +0 -1
- package/lib/methods/remove-child-nodes.method.d.ts +0 -1
- package/lib/methods/remove-child-nodes.method.js +0 -10
- package/lib/methods/remove-child-nodes.method.js.map +0 -1
- package/lib/methods/sanitize-html.method.d.ts +0 -1
- package/lib/methods/sanitize-html.method.js +0 -42
- package/lib/methods/sanitize-html.method.js.map +0 -1
- package/lib/methods/text.method.d.ts +0 -1
- package/lib/methods/text.method.js +0 -69
- package/lib/methods/text.method.js.map +0 -1
- package/lib/methods/traverse.method.d.ts +0 -3
- package/lib/methods/traverse.method.js +0 -38
- package/lib/methods/traverse.method.js.map +0 -1
- package/lib/post-body-summary.d.ts +0 -2
- package/lib/post-body-summary.js +0 -123
- package/lib/post-body-summary.js.map +0 -1
- package/lib/proxify-image-src.d.ts +0 -5
- package/lib/proxify-image-src.js +0 -86
- package/lib/proxify-image-src.js.map +0 -1
- package/lib/render-helper.js +0 -1
- package/lib/types/entry.interface.d.ts +0 -7
- package/lib/types/entry.interface.js +0 -3
- package/lib/types/entry.interface.js.map +0 -1
- package/lib/types/index.d.ts +0 -2
- package/lib/types/index.js +0 -19
- package/lib/types/index.js.map +0 -1
- package/lib/types/xss-white-list.interface.d.ts +0 -6
- package/lib/types/xss-white-list.interface.js +0 -3
- package/lib/types/xss-white-list.interface.js.map +0 -1
- package/src/cache.ts +0 -15
- package/src/catch-post-image.spec.ts +0 -144
- package/src/catch-post-image.ts +0 -78
- package/src/consts/allowed-attributes.const.ts +0 -69
- package/src/consts/dom-parser.const.ts +0 -6
- package/src/consts/index.ts +0 -5
- package/src/consts/regexes.const.ts +0 -46
- package/src/consts/section-list.const.ts +0 -20
- package/src/consts/white-list.const.ts +0 -33
- package/src/external-types/multihashes.d.ts +0 -3
- package/src/helper.spec.ts +0 -16
- package/src/helper.ts +0 -61
- package/src/index.ts +0 -18
- package/src/markdown-2-html.spec.ts +0 -1239
- package/src/markdown-2-html.ts +0 -25
- package/src/methods/a.method.ts +0 -791
- package/src/methods/clean-reply.method.ts +0 -32
- package/src/methods/get-inner-html.method.ts +0 -11
- package/src/methods/iframe.method.ts +0 -176
- package/src/methods/img.method.ts +0 -62
- package/src/methods/index.ts +0 -7
- package/src/methods/linkify.method.ts +0 -61
- package/src/methods/markdown-to-html.method.ts +0 -104
- package/src/methods/noop.method.ts +0 -1
- package/src/methods/p.method.ts +0 -6
- package/src/methods/remove-child-nodes.method.ts +0 -5
- package/src/methods/sanitize-html.method.ts +0 -32
- package/src/methods/text.method.ts +0 -77
- package/src/methods/traverse.method.ts +0 -33
- package/src/post-body-summary.spec.ts +0 -150
- package/src/post-body-summary.ts +0 -130
- package/src/proxify-image-src.spec.ts +0 -76
- package/src/proxify-image-src.ts +0 -77
- package/src/sanitize-html.spec.ts +0 -15
- package/src/test/data/index.ts +0 -12
- package/src/test/data/json/muratkbesiroglu____sci-fi-novel-underground-city-part-13.json +0 -2120
- package/src/test/data/json/steemitboard____steemitboard-notify-dunsky-20181210t153450000z.json +0 -47
- package/src/test/data/legacy/10.json +0 -5
- package/src/test/data/legacy/20.json +0 -5
- package/src/test/data/legacy/21.json +0 -5
- package/src/test/data/legacy/2112524.json +0 -5
- package/src/test/data/legacy/22.json +0 -5
- package/src/test/data/legacy/23.json +0 -5
- package/src/test/data/legacy/24.json +0 -5
- package/src/test/data/legacy/25.json +0 -5
- package/src/test/data/legacy/26.json +0 -5
- package/src/test/data/legacy/27.JSON +0 -5
- package/src/test/data/legacy/28.json +0 -5
- package/src/test/data/legacy/29.json +0 -5
- package/src/test/data/legacy/31.json +0 -5
- package/src/test/snaps.json +0 -8
- package/src/types/entry.interface.ts +0 -7
- package/src/types/index.ts +0 -2
- package/src/types/xss-white-list.interface.ts +0 -7
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,22 +1,176 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ecency render helper
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Project Overview
|
|
4
4
|
|
|
5
|
-
-
|
|
6
|
-
- custom markdown to amp
|
|
7
|
-
- content summary extract
|
|
8
|
-
- customize proxy endpoint
|
|
9
|
-
- image links proxify
|
|
10
|
-
- catch content image/thumbnail
|
|
11
|
-
- embedded media filters
|
|
12
|
-
- internalized links
|
|
13
|
-
- cached responses
|
|
14
|
-
- xss protection
|
|
5
|
+
`@ecency/render-helper` is a TypeScript library for rendering and sanitizing markdown+HTML content for the Ecency social platform (built on Hive blockchain). It provides security-focused content rendering with XSS protection, image proxification, and embedded media filtering.
|
|
15
6
|
|
|
7
|
+
## Key Commands
|
|
16
8
|
|
|
17
|
-
|
|
9
|
+
### Development (from package directory)
|
|
10
|
+
- `pnpm build` - Build with tsup (creates browser ESM + Node CJS/ESM bundles)
|
|
11
|
+
- `pnpm test` - Run vitest tests
|
|
12
|
+
- `pnpm lint` - Run ESLint on TypeScript source files
|
|
18
13
|
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
14
|
+
### From Monorepo Root
|
|
15
|
+
- `pnpm render-helper` - Build render-helper package
|
|
16
|
+
- `pnpm build:packages` - Build all packages (sdk, wallets, renderer, render-helper)
|
|
17
|
+
- `pnpm publish:render-helper` - Manually publish to npm
|
|
18
|
+
|
|
19
|
+
### CI/CD
|
|
20
|
+
- Part of vision-next monorepo with centralized GitHub Actions (`.github/workflows/packages.yml`)
|
|
21
|
+
- Automatically detects changes to `packages/render-helper/**` using git diff
|
|
22
|
+
- On push to `develop` branch, builds and publishes to npm
|
|
23
|
+
- Uses OIDC (OpenID Connect) for secure npm authentication
|
|
24
|
+
- Version must be incremented in package.json for successful publish
|
|
25
|
+
|
|
26
|
+
## Architecture
|
|
27
|
+
|
|
28
|
+
### Core Modules
|
|
29
|
+
|
|
30
|
+
**Main Entry Point** (`src/index.ts`):
|
|
31
|
+
- `renderPostBody` - Convert markdown+HTML to sanitized HTML
|
|
32
|
+
- `catchPostImage` - Extract first image from post content or metadata
|
|
33
|
+
- `postBodySummary` - Generate text summary from post body
|
|
34
|
+
- `proxifyImageSrc` - Proxify image URLs through Ecency's image server
|
|
35
|
+
- `setProxyBase` - Configure image proxy endpoint (default: `https://images.ecency.com`)
|
|
36
|
+
- `setCacheSize` - Configure LRU cache size (default: 60 entries)
|
|
37
|
+
|
|
38
|
+
### Processing Pipeline
|
|
39
|
+
|
|
40
|
+
1. **markdown-2-html.ts**: Main rendering pipeline
|
|
41
|
+
- Converts Entry objects (Hive posts) or raw strings
|
|
42
|
+
- Uses LRU cache with keys based on `author-permlink-last_update-updated`
|
|
43
|
+
- Calls `cleanReply()` to normalize input, then `markdownToHTML()` to render
|
|
44
|
+
|
|
45
|
+
2. **traverse.method.ts**: DOM tree walker
|
|
46
|
+
- Recursively processes parsed HTML nodes
|
|
47
|
+
- Applies specialized handlers for `<a>`, `<iframe>`, `<img>`, `<p>`, and text nodes
|
|
48
|
+
- Passes `forApp` flag to differentiate app vs web rendering
|
|
49
|
+
- Tracks `firstImageFound` state for image processing
|
|
50
|
+
|
|
51
|
+
3. **sanitize-html.method.ts**: XSS protection
|
|
52
|
+
- Uses `xss` library with strict whitelist (ALLOWED_ATTRIBUTES)
|
|
53
|
+
- Blocks event handlers (`on*` attributes)
|
|
54
|
+
- Validates URLs (must be `https?://`, blocks `javascript:`)
|
|
55
|
+
- Strips `<style>` tags and CSS
|
|
56
|
+
- Whitelists specific `id` attributes via `ID_WHITELIST` regex
|
|
57
|
+
|
|
58
|
+
4. **Node-specific processors** (`src/methods/`):
|
|
59
|
+
- `a.method.ts` - Link handling, internalization for whitelisted domains
|
|
60
|
+
- `iframe.method.ts` - Embedded content filtering (YouTube, 3speak, etc.)
|
|
61
|
+
- `img.method.ts` - Image proxification and lazy loading
|
|
62
|
+
- `p.method.ts` - Paragraph processing for inline data attributes
|
|
63
|
+
- `text.method.ts` - Link detection and linkification
|
|
64
|
+
|
|
65
|
+
### Image Processing
|
|
66
|
+
|
|
67
|
+
**proxify-image-src.ts**:
|
|
68
|
+
- Converts external image URLs to Ecency's CDN using multihash encoding
|
|
69
|
+
- Reuses existing proxy hashes to avoid re-encoding
|
|
70
|
+
- Supports format conversion (webp/png) and resizing (width/height)
|
|
71
|
+
- Handles legacy domains (images.hive.blog, steemitimages.com)
|
|
72
|
+
|
|
73
|
+
**catch-post-image.ts**:
|
|
74
|
+
- Extracts featured image from `json_metadata.image` field
|
|
75
|
+
- Falls back to first `<img>` in rendered HTML body
|
|
76
|
+
- Preserves GIF format (doesn't resize animated images)
|
|
77
|
+
|
|
78
|
+
### Security Considerations
|
|
79
|
+
|
|
80
|
+
**Whitelist Management** (`src/consts/white-list.const.ts`):
|
|
81
|
+
- `WHITE_LIST` - Trusted Hive frontend domains (ecency.com, peakd.com, etc.)
|
|
82
|
+
- `OLD_LIST` - Deprecated Steem-era domains
|
|
83
|
+
- Links to whitelisted domains are converted to internal app routes
|
|
84
|
+
|
|
85
|
+
**XSS Protection**:
|
|
86
|
+
- All HTML goes through `sanitizeHtml()` with strict attribute whitelist
|
|
87
|
+
- No inline styles allowed (CSS disabled)
|
|
88
|
+
- Event handlers stripped
|
|
89
|
+
- URL schemes validated
|
|
90
|
+
|
|
91
|
+
### Caching Strategy
|
|
92
|
+
|
|
93
|
+
- LRU cache v11 (`src/cache.ts`) stores rendered HTML and extracted images
|
|
94
|
+
- Cache keys include content hash (last_update, updated) to auto-invalidate
|
|
95
|
+
- Separate cache entries for different image sizes and formats
|
|
96
|
+
- Default size: 60 entries
|
|
97
|
+
- Uses modern `LRUCache` named import from lru-cache v11
|
|
98
|
+
|
|
99
|
+
## File Structure
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
src/
|
|
103
|
+
├── index.ts # Main exports
|
|
104
|
+
├── markdown-2-html.ts # Primary rendering entry point
|
|
105
|
+
├── catch-post-image.ts # Image extraction
|
|
106
|
+
├── post-body-summary.ts # Summary generation
|
|
107
|
+
├── proxify-image-src.ts # Image URL proxification
|
|
108
|
+
├── helper.ts # Utilities (doc creation, cache keys, validators)
|
|
109
|
+
├── cache.ts # LRU cache wrapper
|
|
110
|
+
├── consts/ # Configuration constants
|
|
111
|
+
│ ├── white-list.const.ts # Trusted domains
|
|
112
|
+
│ ├── allowed-attributes.const.ts # XSS whitelist
|
|
113
|
+
│ ├── section-list.const.ts # App route sections
|
|
114
|
+
│ └── regexes.const.ts # Pattern matching
|
|
115
|
+
├── methods/ # DOM node processors
|
|
116
|
+
│ ├── traverse.method.ts # Main tree walker
|
|
117
|
+
│ ├── sanitize-html.method.ts # XSS protection
|
|
118
|
+
│ ├── markdown-to-html.method.ts # Remarkable wrapper
|
|
119
|
+
│ ├── a.method.ts # Link processing
|
|
120
|
+
│ ├── iframe.method.ts # Embed handling
|
|
121
|
+
│ ├── img.method.ts # Image processing
|
|
122
|
+
│ └── ...
|
|
123
|
+
└── types/ # TypeScript interfaces
|
|
124
|
+
└── entry.interface.ts # Hive post structure
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Build System
|
|
128
|
+
|
|
129
|
+
- Uses **tsup** for bundling (shared with other vision-next packages)
|
|
130
|
+
- TypeScript 5.6+ with strict mode enabled
|
|
131
|
+
- Outputs three bundles:
|
|
132
|
+
- `dist/browser/index.js` - Browser ESM with TypeScript declarations
|
|
133
|
+
- `dist/node/index.mjs` - Node ESM
|
|
134
|
+
- `dist/node/index.cjs` - Node CommonJS
|
|
135
|
+
- Configuration: `tsup.config.ts` (dual browser/node builds)
|
|
136
|
+
- All dependencies are externalized (not bundled)
|
|
137
|
+
|
|
138
|
+
## Platform Support
|
|
139
|
+
|
|
140
|
+
### React Native (iOS/Android)
|
|
141
|
+
|
|
142
|
+
This package fully supports React Native applications:
|
|
143
|
+
|
|
144
|
+
- **Package Resolution**: The `react-native` field in `package.json` exports ensures React Native bundlers (Metro) automatically resolve to the browser build (`dist/browser/index.js`)
|
|
145
|
+
- **Crypto Support**: When `platform !== 'web'` (i.e., React Native environment), the package uses `react-native-crypto-js` for cryptographic operations
|
|
146
|
+
- **Usage**: Simply import the package normally in your React Native project - no special configuration needed
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
import { renderPostBody, postBodySummary } from '@ecency/render-helper'
|
|
150
|
+
|
|
151
|
+
// The platform parameter determines the build target
|
|
152
|
+
// 'web' = browser/web, any other value = React Native
|
|
153
|
+
const html = renderPostBody(entry, false, 'react-native')
|
|
154
|
+
const summary = postBodySummary(entry, 200, 'react-native')
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Platform Parameter**:
|
|
158
|
+
- `'web'` - Uses browser APIs and standard crypto
|
|
159
|
+
- Any other value (e.g., `'react-native'`, `'mobile'`) - Uses React Native-compatible implementations including `react-native-crypto-js`
|
|
160
|
+
- The platform parameter is required in `renderPostBody()` and `postBodySummary()` functions
|
|
161
|
+
|
|
162
|
+
## Testing
|
|
163
|
+
|
|
164
|
+
- Vitest for unit tests (to be migrated from Jest)
|
|
165
|
+
- Test files: `*.spec.ts` adjacent to source
|
|
166
|
+
- Tests should verify XSS protection for new features
|
|
167
|
+
- Do not load external JS/libraries in embed support (security requirement)
|
|
168
|
+
|
|
169
|
+
## Important Notes
|
|
170
|
+
|
|
171
|
+
- When adding embed support for new platforms, implement server-side rendering only
|
|
172
|
+
- All external content must go through sanitization
|
|
173
|
+
- Version bumps required for auto-publish via CI
|
|
174
|
+
- Part of vision-next monorepo - changes require updating across dependent packages
|
|
175
|
+
- The `@ecency/renderer` package uses this as a workspace dependency
|
|
176
|
+
- Exports are optimized for tree-shaking with proper ESM structure
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
interface Entry {
|
|
2
|
+
author?: string;
|
|
3
|
+
permlink?: string;
|
|
4
|
+
last_update?: string;
|
|
5
|
+
body: any;
|
|
6
|
+
json_metadata?: any;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
declare function markdown2Html(obj: Entry | string, forApp?: boolean, webp?: boolean, parentDomain?: string): string;
|
|
10
|
+
|
|
11
|
+
declare function catchPostImage(obj: Entry | string, width?: number, height?: number, format?: string): string | null;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generate a text summary from an Entry object or raw string
|
|
15
|
+
* @param obj - Entry object or raw post body string
|
|
16
|
+
* @param length - Maximum length of the summary (default: 200, use 0 for no truncation)
|
|
17
|
+
* @param platform - Target platform: 'web' for browser/Node.js, 'ios'/'android' for React Native (default: 'web')
|
|
18
|
+
* Controls entity/placeholder handling - 'web' skips placeholder substitution, other values enable it
|
|
19
|
+
* @returns Text summary of the post body
|
|
20
|
+
*/
|
|
21
|
+
declare function getPostBodySummary(obj: Entry | string, length?: number, platform?: 'ios' | 'android' | 'web'): string;
|
|
22
|
+
|
|
23
|
+
declare function setProxyBase(p: string): void;
|
|
24
|
+
declare function proxifyImageSrc(url?: string, width?: number, height?: number, format?: string): string;
|
|
25
|
+
|
|
26
|
+
declare function setCacheSize(size: number): void;
|
|
27
|
+
|
|
28
|
+
declare const SECTION_LIST: string[];
|
|
29
|
+
|
|
30
|
+
declare function isValidPermlink(permlink: string): boolean;
|
|
31
|
+
|
|
32
|
+
export { SECTION_LIST, catchPostImage, isValidPermlink, getPostBodySummary as postBodySummary, proxifyImageSrc, markdown2Html as renderPostBody, setCacheSize, setProxyBase };
|