diff --git a/src/components/article.tsx b/src/components/article.tsx index 03a3032..34bd2bf 100644 --- a/src/components/article.tsx +++ b/src/components/article.tsx @@ -5,7 +5,7 @@ import { RSSItem } from "../scripts/models/item" import { Stack, CommandBarButton, IContextualMenuProps, FocusZone, ContextualMenuItemType, Spinner, Icon, Link } from "@fluentui/react" import { RSSSource, SourceOpenTarget } from "../scripts/models/source" 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] @@ -214,7 +214,9 @@ class Article extends React.Component { loadFull = async () => { this.setState({ fullContent: "", loaded: false, error: false }) 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 }) } catch { this.setState({ loaded: true, error: true, errorDescription: "MERCURY_PARSER_FAILURE" }) diff --git a/src/scripts/utils.ts b/src/scripts/utils.ts index 82a12f5..42b2c0c 100644 --- a/src/scripts/utils.ts +++ b/src/scripts/utils.ts @@ -29,6 +29,14 @@ const rssParser = new Parser({ }) 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) { let result: Response try { @@ -38,11 +46,7 @@ export async function parseRSS(url: string) { } if (result && result.ok) { try { - const buffer = await result.arrayBuffer() - 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)) + return await rssParser.parseString(await decodeFetchResponse(result)) } catch { throw new Error(intl.get("log.parseError")) }