fix mercury parser encoding detection

This commit is contained in:
刘浩远 2020-08-09 18:22:01 +08:00
parent 7deb250bcc
commit 42e819834b
2 changed files with 13 additions and 7 deletions

View File

@ -5,7 +5,7 @@ import { RSSItem } from "../scripts/models/item"
import { Stack, CommandBarButton, IContextualMenuProps, FocusZone, ContextualMenuItemType, Spinner, Icon, Link } from "@fluentui/react" import { Stack, CommandBarButton, IContextualMenuProps, FocusZone, ContextualMenuItemType, Spinner, Icon, Link } from "@fluentui/react"
import { RSSSource, SourceOpenTarget } from "../scripts/models/source" import { RSSSource, SourceOpenTarget } from "../scripts/models/source"
import { shareSubmenu } from "./context-menu" import { shareSubmenu } from "./context-menu"
import { platformCtrl } from "../scripts/utils" import { platformCtrl, decodeFetchResponse } from "../scripts/utils"
const FONT_SIZE_OPTIONS = [12, 13, 14, 15, 16, 17, 18, 19, 20] const FONT_SIZE_OPTIONS = [12, 13, 14, 15, 16, 17, 18, 19, 20]
@ -214,7 +214,9 @@ class Article extends React.Component<ArticleProps, ArticleState> {
loadFull = async () => { loadFull = async () => {
this.setState({ fullContent: "", loaded: false, error: false }) this.setState({ fullContent: "", loaded: false, error: false })
try { try {
const html = await (await fetch(this.props.item.link)).text() const result = await fetch(this.props.item.link)
if (!result || !result.ok) throw new Error()
const html = await decodeFetchResponse(result)
this.setState({ fullContent: html }) this.setState({ fullContent: html })
} catch { } catch {
this.setState({ loaded: true, error: true, errorDescription: "MERCURY_PARSER_FAILURE" }) this.setState({ loaded: true, error: true, errorDescription: "MERCURY_PARSER_FAILURE" })

View File

@ -29,6 +29,14 @@ const rssParser = new Parser({
}) })
const CHARSET_RE = /charset=([^()<>@,;:\"/[\]?.=\s]*)/i const CHARSET_RE = /charset=([^()<>@,;:\"/[\]?.=\s]*)/i
export async function decodeFetchResponse(response: Response) {
const buffer = await response.arrayBuffer()
const ctype = response.headers.has("content-type") && response.headers.get("content-type")
const charset = (ctype && CHARSET_RE.test(ctype)) ? CHARSET_RE.exec(ctype)[1] : "utf-8"
const decoder = new TextDecoder(charset)
return decoder.decode(buffer)
}
export async function parseRSS(url: string) { export async function parseRSS(url: string) {
let result: Response let result: Response
try { try {
@ -38,11 +46,7 @@ export async function parseRSS(url: string) {
} }
if (result && result.ok) { if (result && result.ok) {
try { try {
const buffer = await result.arrayBuffer() return await rssParser.parseString(await decodeFetchResponse(result))
const ctype = result.headers.has("content-type") && result.headers.get("content-type")
const charset = (ctype && CHARSET_RE.test(ctype)) ? CHARSET_RE.exec(ctype)[1] : "utf-8"
const decoder = new TextDecoder(charset)
return await rssParser.parseString(decoder.decode(buffer))
} catch { } catch {
throw new Error(intl.get("log.parseError")) throw new Error(intl.get("log.parseError"))
} }