htmlspanner-ohos
This project is based on HmlSpanner Development.
Introduction
htmlspanner-ohos is an OpenHarmony equivalent migration of Android HtmlSpanner, providing HTML and CSS parsing capabilities for OpenHarmony Text and StyledString. This library supports converting HTML content to StyledString for rich text rendering.
Demo

Installation
ohpm install @ohos/htmlspanner
For more information about OpenHarmony ohpm environment configuration, please refer to How to install OpenHarmony ohpm packages.
Constraints and Limitations
Compatibility
- DevEco Studio: 6.0.1 Beta1(6.0.1.245SP4), SDK: API12 Release(5.0.0.71), ROM: 5.1.0.120;
Permissions
- To load network images, add the network permission in
module.json5:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
Usage Examples
Basic Usage
import { HtmlSpannerText } from '@ohos/htmlspanner'
@Entry
@Component
struct Index {
@State html: string = '<p>Hello <b>World</b>!</p>'
@State css: string = ''
build() {
Column() {
HtmlSpannerText({
html: this.html,
css: this.css
})
}
.width('100%')
.height('100%')
}
}
Link Click Handling
import { HtmlSpannerText } from '@ohos/htmlspanner'
@Entry
@Component
struct Index {
@State html: string = '<a href="https://example.com">Click Link</a>'
build() {
Column() {
HtmlSpannerText({
html: this.html,
css: '',
onLinkClick: (href: string) => {
console.info('Link clicked:', href)
// Handle link click
}
})
}
.width('100%')
.height('100%')
}
}
Custom Tag Handling
import { HtmlSpanner, HtmlSpannerText, TableHandlerCompat } from '@ohos/htmlspanner'
@Entry
@Component
struct Index {
@State html: string = '<table><tr><td>Cell</td></tr></table>'
build() {
Column() {
HtmlSpannerText({
html: this.html,
css: '',
onSpannerReady: (spanner: HtmlSpanner) => {
spanner.registerHandler('table', new TableHandlerCompat(spanner))
}
})
}
.width('100%')
.height('100%')
}
}
Using Compilation Options
import { HtmlSpannerText } from '@ohos/htmlspanner'
@Entry
@Component
struct Index {
@State html: string = '<p> Multiple spaces </p>'
build() {
Column() {
HtmlSpannerText({
html: this.html,
css: '',
spannerOptions: {
stripExtraWhiteSpace: true
}
})
}
.width('100%')
.height('100%')
}
}
Usage Guide
HtmlSpannerText Component
HtmlSpannerText is the most commonly used component for directly rendering HTML content.
Basic Properties:
html: string- HTML contentcss: string- CSS styles (optional)spannerOptions: Partial<HtmlSpannerOptions>- Compilation options (optional)cancellationCallback: CancellationCallback- Cancellation callback (optional)onLinkClick: (href: string) => void- Link click callback (optional)imageLoader: HtmlSpannerImageLoader- Custom image loader (optional)onSpannerReady: (spanner: HtmlSpanner) => void- Spanner ready callback (optional)
HtmlSpanner Class
HtmlSpanner provides lower-level APIs suitable for scenarios requiring manual control over the rendering process.
Main Methods:
// Create instance
const spanner = new HtmlSpanner(options?, rendererOptions?)
// Parse HTML to node tree
const node = spanner.parse(html, callback?)
// Compile to text model
const model = spanner.toModel(html, css?, callback?)
// Render to StyledString
const styledString = spanner.fromHtml(html, css?, callback?)
// Async rendering (supports async image loading)
const styledString = await spanner.fromHtmlAsync(html, css?, callback?)
// Register custom tag handler
spanner.registerHandler(tagName, handler)
// Unregister tag handler
spanner.unregisterHandler(tagName)
CSS Support
The library supports partial CSS properties, including:
- Text styles:
color,font-size,font-weight,font-style,font-family - Text decoration:
text-decoration,text-align,text-indent - Layout:
display,margin-*,padding-* - Background:
background-color - Border:
border-style,border-color,border-width
Image Loading
Default support for the following image sources:
- HTTP/HTTPS URL:
<img src="https://example.com/image.png"> - Application resources:
<img src="$media:icon">or<img src="app.media.icon"> - Local file paths
Custom image loading:
HtmlSpannerText({
html: this.html,
css: '',
imageLoader: (source: string, run: AttachmentRun) => {
// Custom image loading logic
return createDefaultImageAttachment(run)
}
})
Table Support
Table processing requires manual registration of TableHandlerCompat:
import { HtmlSpanner, HtmlSpannerText, TableHandlerCompat } from '@ohos/htmlspanner'
HtmlSpannerText({
html: '<table><tr><td>Cell 1</td><td>Cell 2</td></tr></table>',
css: '',
onSpannerReady: (spanner: HtmlSpanner) => {
spanner.registerHandler('table', new TableHandlerCompat(spanner))
}
})
Cancellation
Supports cancelling long-running parsing tasks via CancellationCallback:
interface CancelGate {
cancelled: boolean
}
class GateCallback implements CancellationCallback {
private readonly gate: CancelGate
constructor(gate: CancelGate) {
this.gate = gate
}
isCancelled(): boolean {
return this.gate.cancelled
}
}
const gate: CancelGate = { cancelled: false }
const callback = new GateCallback(gate)
HtmlSpannerText({
html: largeHtml,
css: '',
cancellationCallback: callback
})
// Cancel parsing
gate.cancelled = true
API Reference
Components
| Name | Description | Main Parameters | Required | HarmonyOS Platform Support |
|---|---|---|---|---|
| HtmlSpannerText | HTML rendering component that directly renders HTML content to StyledString | html: string // HTML content css?: string // CSS styles spannerOptions?: Partial<HtmlSpannerOptions> // compilation options cancellationCallback?: CancellationCallback // cancellation callback imageLoader?: HtmlSpannerImageLoader // image loader onLinkClick?: (href: string) => void // link click callback onSpannerReady?: (spanner: HtmlSpanner) => void // spanner ready callback |
Yes | Yes |
HtmlSpanner Methods
| Method Name | Description | Parameters | Return Value | HarmonyOS Platform Support |
|---|---|---|---|---|
| parse | Parse HTML to node tree | html: string // HTML content callback?: CancellationCallback // cancellation callback |
HtmlSpannerNode | Yes |
| parseUtf8 | Parse UTF-8 bytes | bytes: Uint8Array // UTF-8 byte array callback?: CancellationCallback // cancellation callback |
HtmlSpannerNode | Yes |
| toModel | Compile to text model | html: string // HTML content css?: string // CSS styles callback?: CancellationCallback // cancellation callback |
SpannerTextModel | Yes |
| toModelUtf8 | Compile model from UTF-8 bytes | bytes: Uint8Array // UTF-8 byte array css?: string // CSS styles callback?: CancellationCallback // cancellation callback |
SpannerTextModel | Yes |
| fromHtml | Render to StyledString | html: string // HTML content css?: string // CSS styles callback?: CancellationCallback // cancellation callback |
StyledString | Yes |
| fromHtmlAsync | Async render to StyledString | html: string // HTML content css?: string // CSS styles callback?: CancellationCallback // cancellation callback |
Promise<StyledString> | Yes |
| fromHtmlUtf8 | Render from UTF-8 bytes | bytes: Uint8Array // UTF-8 byte array css?: string // CSS styles callback?: CancellationCallback // cancellation callback |
StyledString | Yes |
| fromTagNode | Render from node tree | root: HtmlSpannerNode // node tree css?: string // CSS styles callback?: CancellationCallback // cancellation callback |
StyledString | Yes |
| toStyledString | Render to StyledString | html: string // HTML content css?: string // CSS styles callback?: CancellationCallback // cancellation callback |
StyledString | Yes |
| toStyledStringAsync | Async render to StyledString | html: string // HTML content css?: string // CSS styles callback?: CancellationCallback // cancellation callback |
Promise<StyledString> | Yes |
| toMutableStyledString | Render to MutableStyledString | html: string // HTML content css?: string // CSS styles callback?: CancellationCallback // cancellation callback |
MutableStyledString | Yes |
| registerHandler | Register tag handler | tagName: string // tag name handler: TagNodeHandlerCompat // handler |
void | Yes |
| unregisterHandler | Unregister tag handler | tagName: string // tag name | void | Yes |
| getHandlerFor | Get tag handler | tagName: string // tag name | TagNodeHandlerCompat | undefined | Yes |
| getFont | Get font | name: string | undefined // font name | FontFamily | Yes |
| setFontResolver | Set font resolver | resolver: FontResolver // font resolver | void | Yes |
| setStripExtraWhiteSpace | Set whitespace folding | value: boolean // whether to fold whitespace | void | Yes |
| setAllowStyling | Set whether to allow styling | value: boolean // whether to allow styling | void | Yes |
| setUseColoursFromStyle | Set whether to use style colors | value: boolean // whether to use style colors | void | Yes |
| setUseFontSizeFromStyle | Set whether to use style font sizes | value: boolean // whether to use style font sizes | void | Yes |
Types
| Name | Description | Fields | HarmonyOS Platform Support |
|---|---|---|---|
| HtmlSpannerOptions | HtmlSpanner constructor options | stripExtraWhiteSpace?: boolean // fold whitespace allowStyling?: boolean // allow styling useColoursFromStyle?: boolean // use style colors useFontSizeFromStyle?: boolean // use style font sizes pruneTags?: string[] // tags to prune fontResolver?: FontResolver // font resolver contrastPatcher?: ContrastPatcher // contrast patcher htmlCleaner?: HtmlSpannerHtmlCleaner // HTML cleaner |
Yes |
| StyledStringRendererOptions | StyledStringRenderer rendering options | - | Yes |
| CancellationCallback | Cancellation callback interface | isCancelled: () => boolean // returns whether cancelled | Yes |
| HtmlSpannerImageLoader | Image loader type | source: string // image source run: AttachmentRun // attachment run info |
Yes |
| HtmlSpannerImageLoaderResult | Image loader return type | ImageAttachment | Promise<ImageAttachment | undefined> | undefined | Yes |
| AttachmentRun | Attachment run information | Contains image position, size, etc. | Yes |
| LinkRun | Link run information | - | Yes |
| CustomRun | Custom run information | - | Yes |
| CustomRunData | Custom run data | - | Yes |
| SerializableStyleRun | Serializable style run | - | Yes |
| TableRowAttachmentPayload | Table row attachment payload | - | Yes |
| StyleProperties | Style properties interface | - | Yes |
| StyleValueUnit | Style value unit | 'px' | 'em' | 'percentage' | 'pt' | 'rem' | 'vw' | 'vh' | 'auto' | Yes |
| TableRasterLayoutSpec | Table raster layout specification | - | Yes |
| TableCellRect | Table cell rectangle | - | Yes |
| TableComplianceLayoutOptions | Table compliance layout options | - | Yes |
| HtmlSpannerTextCustomTagRule | Custom tag rule | tagName: string // tag name style?: HtmlSpannerTextCustomTagStyle // style display?: HtmlSpannerTextCustomTagDisplay // display type |
Yes |
| HtmlSpannerTextCustomTagStyle | Custom tag style | fontFamily?: string // font family fontSize?: number // font size fontWeight?: HtmlSpannerTextCustomTagFontWeight // font weight fontStyle?: HtmlSpannerTextCustomTagFontStyle // font style color?: string // color backgroundColor?: string // background color textDecoration?: HtmlSpannerTextCustomTagTextDecoration // text decoration textAlign?: HtmlSpannerTextCustomTagTextAlign // text align |
Yes |
| HtmlSpannerTextCustomTagDisplay | Custom tag display type | 'inline' | 'block' | Yes |
| HtmlSpannerTextCustomTagFontWeight | Custom tag font weight | number | 'normal' | 'bold' | Yes |
| HtmlSpannerTextCustomTagFontStyle | Custom tag font style | 'normal' | 'italic' | Yes |
| HtmlSpannerTextCustomTagTextAlign | Custom tag text align | 'left' | 'center' | 'right' | 'justify' | Yes |
| HtmlSpannerTextCustomTagTextDecoration | Custom tag text decoration | 'none' | 'underline' | 'line-through' | 'overline' | Yes |
| FontTypeface | Font typeface | fontFamily: string // font family name fontWeight?: number // font weight |
Yes |
| HttpImageLayoutSnapshotVp | HTTP image layout snapshot | - | Yes |
| ScaledHttpImageDecodeDebugInfo | Scaled image decode debug info | - | Yes |
| HttpImageCenterDebugLogger | HTTP image center debug logger | - | Yes |
| HtmlSpannerFileSource | File source | - | Yes |
| HtmlSpannerHtmlSource | HTML source | - | Yes |
| HtmlSpannerLoaderSource | Loader source | - | Yes |
| HtmlSpannerRawFileSource | Raw file source | - | Yes |
| HtmlSpannerTextSource | Text source | - | Yes |
| HtmlSpannerUtf8Source | UTF-8 source | - | Yes |
| SpannerTextModelJson | Text model JSON | - | Yes |
| CssDeclarationCompat | CSS declaration | - | Yes |
| CssRuleCompat | CSS rule | - | Yes |
| CompiledCssRuleCompat | Compiled CSS rule | - | Yes |
| StyleUpdater | Style updater | - | Yes |
| StyleUpdaterHost | Style updater host | - | Yes |
| TagNodeMatcher | Tag node matcher | - | Yes |
Functions
| Name | Description | Parameters | Return Value | HarmonyOS Platform Support |
|---|---|---|---|---|
| createDefaultImageAttachment | Create default image attachment | run: AttachmentRun // attachment run info | ImageAttachment | undefined | Yes |
| createImageCacheKey | Create image cache key | run: AttachmentRun // attachment run info | string | Yes |
| createImagePlaceholder | Create image placeholder | run: AttachmentRun // attachment run info failed: boolean // whether load failed |
StyledString | Yes |
| createScaledHttpImageLoader | Create HTTP image loader | - | HtmlSpannerImageLoader | Yes |
| createScaledHttpImageAttachment | Create scaled HTTP image attachment | run: AttachmentRun // attachment run info displayDensity: number // display density |
ImageAttachment | undefined | Yes |
| createScaledHttpImageAttachmentResolver | Create scaled HTTP image attachment resolver | displayDensity: number // display density | (run: AttachmentRun) => ImageAttachment | undefined | Yes |
| clearHttpImageLayoutCache | Clear HTTP image layout cache | - | void | Yes |
| computeParagraphCenterLineBoxWidthVp | Compute paragraph center line box width | - | number | Yes |
| expandHttpImageForParagraphCenterFromCache | Expand HTTP image from cache | run: AttachmentRun // attachment run info | ImageAttachment | undefined | Yes |
| getHttpImageLayoutSnapshotDimensions | Get HTTP image layout snapshot dimensions | run: AttachmentRun // attachment run info | HttpImageLayoutSnapshotVp | undefined | Yes |
| parseStyleValue | Parse style value | input: string | undefined | null // style string | StyleValue | undefined | Yes |
| translateLegacyFontSize | Translate legacy font size (1-7) | fontSize: number // legacy font size (1-7) | StyleValue | Yes |
| decodeUtf8BytesToString | Decode UTF-8 bytes to string | bytes: Uint8Array // UTF-8 byte array | string | Yes |
| replaceHtmlEntities | Replace HTML entities | text: string // text content inAttribute: boolean // whether in attribute |
string | Yes |
| createDefaultContrastPatcher | Create default contrast patcher | - | ContrastPatcher | Yes |
| defaultHtmlSpannerOptions | Get default options | - | HtmlSpannerOptions | Yes |
| mergeHtmlSpannerOptions | Merge options | options?: Partial<HtmlSpannerOptions> // partial options | HtmlSpannerOptions | Yes |
| defaultStyledStringRendererOptions | Get default renderer options | - | StyledStringRendererOptions | Yes |
| readHtmlSource | Read HTML source | source: HtmlSpannerHtmlSource // HTML source | string | Promise<string> | Yes |
| getDisplayDensity | Get display density | - | number | Yes |
| buildTableRasterLayoutSpecFromAttachmentRun | Build table raster layout spec | run: AttachmentRun // attachment run info | TableRasterLayoutSpec | undefined | Yes |
| createTableComplianceAttachmentResolver | Create table compliance attachment resolver | options?: TableComplianceLayoutOptions // layout options | (run: AttachmentRun) => ImageAttachment | undefined | Yes |
| rasterTableLayoutSpecWithOffscreenCanvas | Raster table layout with offscreen canvas | spec: TableRasterLayoutSpec // layout spec | ImageAttachment | Yes |
| compileCssRulesSkippingFailures | Compile CSS rules skipping failures | rules: string[] // CSS rules array | CompiledCssRuleCompat[] | Yes |
| createMatchersFromSelector | Create matchers from selector | selector: string // CSS selector | TagNodeMatcher[] | Yes |
| matchesSelectorChain | Match selector chain | node: HtmlSpannerNode // HTML node matchers: TagNodeMatcher[] // matcher array |
boolean | Yes |
Obfuscation
Add the following rules in obfuscation-rules.txt to avoid obfuscation:
-keep class @ohos/htmlspanner.** { *; }
-keep class * implements @ohos/htmlspanner.HtmlSpannerImageLoader { *; }
-keep class * implements @ohos/htmlspanner.FontResolver { *; }
-keep class * implements @ohos/htmlspanner.CancellationCallback { *; }
Directory Structure
htmlspanner-ohos/
├── library/ # Core library code
│ ├── src/main/ets/
│ │ ├── components/ # Components (HtmlSpannerText)
│ │ ├── font/ # Font handling
│ │ ├── handler/ # Tag handlers
│ │ ├── htmlspanner/ # Core classes
│ │ ├── model/ # Data models
│ │ ├── parser/ # Parsers
│ │ ├── renderer/ # Renderers
│ │ ├── style/ # Style handling
│ │ ├── table/ # Table handling
│ │ └── util/ # Utility functions
│ └── oh-package.json5 # Library configuration
├── entry/ # Demo application
├── docs/ # Documentation
├── tests/ # Test cases
├── scripts/ # Build scripts
├── LICENSE # License
├── NOTICE # Copyright notice
└── README.OpenSource # Open source notice
License
This project is licensed under the Apache License 2.0.
Third-Party Dependencies
- @ohos/htmlparser2 - HTML parser
- @ohos/postcss - CSS processor