Mercurial > addons > firefox-addons > feed-preview
comparison js/feed-preview.js @ 6:5d7c13e998e9
Create feed previews using a stream filter
Instead of replacing the feed document with an XHTML preview from a content
script after it has already been rendered, create an XHTML preview using a
stream filter before it is passed into the rendering engine and use an XSL
style sheet to convert it to HTML. This has two advantages, firstly it
results in an HTMLDocument with the full HTML DOM available and secondly it
avoids rendering the document twice.
Refactor the feed preview creation and split parsing and rendering into
seperate modules.
author | Guido Berhoerster <guido+feed-preview@berhoerster.name> |
---|---|
date | Thu, 08 Nov 2018 16:30:34 +0100 |
parents | |
children | fcd65cf3f634 |
comparison
equal
deleted
inserted
replaced
5:341a0f4b7ce0 | 6:5d7c13e998e9 |
---|---|
1 /* | |
2 * Copyright (C) 2018 Guido Berhoerster <guido+feed-preview@berhoerster.name> | |
3 * | |
4 * This Source Code Form is subject to the terms of the Mozilla Public | |
5 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. | |
7 */ | |
8 | |
9 'use strict'; | |
10 | |
11 export function renderFeedPreview(feedPreviewDocument, feed) { | |
12 // inject XSL stylesheet which transforms XHTML to HTML allowing the use of | |
13 // the HTML DOM | |
14 let xslFilename = browser.runtime.getURL('web_resources/xhtml-to-html.xsl'); | |
15 let xmlStylesheetNode = | |
16 feedPreviewDocument.createProcessingInstruction('xml-stylesheet', | |
17 `type="application/xslt+xml" href="${xslFilename}"`); | |
18 feedPreviewDocument.firstChild.after(xmlStylesheetNode); | |
19 | |
20 feedPreviewDocument.querySelector('link[rel=stylesheet]').href = | |
21 browser.runtime.getURL('web_resources/style/feed-preview.css'); | |
22 | |
23 feedPreviewDocument.querySelector('title').textContent = feed.title; | |
24 feedPreviewDocument.querySelector('#feed-title').textContent = feed.title; | |
25 feedPreviewDocument.querySelector('#feed-subtitle').textContent = | |
26 feed.subtitle; | |
27 | |
28 if (typeof feed.logo !== 'undefined') { | |
29 let feedLogoTemplate = | |
30 feedPreviewDocument.querySelector('#feed-logo-template'); | |
31 let logoNode = feedPreviewDocument.importNode(feedLogoTemplate.content, | |
32 true); | |
33 let imgElement = logoNode.querySelector('#feed-logo'); | |
34 imgElement.setAttribute('src', feed.logo.url); | |
35 imgElement.setAttribute('alt', feed.logo.title); | |
36 feedPreviewDocument.querySelector('#feed-header').prepend(logoNode); | |
37 } | |
38 | |
39 let entryTemplateElement = | |
40 feedPreviewDocument.querySelector('#entry-template'); | |
41 let entryTitleTemplateElement = | |
42 feedPreviewDocument.querySelector('#entry-title-template'); | |
43 let entryTitleLinkedTemplateElement = | |
44 feedPreviewDocument.querySelector('#entry-title-linked-template'); | |
45 let entryFileListTemplateElement = | |
46 feedPreviewDocument.querySelector('#entry-files-list-template'); | |
47 let entryFileTemplateElement = | |
48 feedPreviewDocument.querySelector('#entry-file-template'); | |
49 if (feed.entries.length === 0) { | |
50 let hintTemplateElement = | |
51 previewDocument.querySelector('#no-entries-hint-template'); | |
52 let hintNode = previewDocument.importNode(hintTemplateElement.content, | |
53 true); | |
54 hintNode.querySelector("#no-entries-hint").textContent = | |
55 browser.i18n.getMessage('noEntriesHint'); | |
56 | |
57 previewDocument.body.append(hintNode); | |
58 } | |
59 for (let entry of feed.entries) { | |
60 let entryNode = | |
61 feedPreviewDocument.importNode(entryTemplateElement.content, | |
62 true); | |
63 let titleElement; | |
64 let titleNode; | |
65 | |
66 if (typeof entry.link !== 'undefined') { | |
67 titleNode = feedPreviewDocument | |
68 .importNode(entryTitleLinkedTemplateElement.content, true); | |
69 titleElement = titleNode.querySelector('.entry-link'); | |
70 titleElement.href = entry.link; | |
71 titleElement.title = entry.title; | |
72 } else { | |
73 titleNode = feedPreviewDocument | |
74 .importNode(entryTitleTemplateElement.content, true); | |
75 titleElement = titleNode.querySelector('.entry-title'); | |
76 } | |
77 titleElement.textContent = entry.title; | |
78 entryNode.querySelector('.entry-header').prepend(titleNode); | |
79 | |
80 let timeElement = entryNode.querySelector('.entry-date > time'); | |
81 timeElement.textContent = entry.date.toLocaleString(); | |
82 | |
83 let contentElement = entryNode.querySelector('.entry-content'); | |
84 let contentDocument = new DOMParser().parseFromString(entry.content, | |
85 'text/html'); | |
86 let stylesheetElement = contentDocument.createElement('link'); | |
87 stylesheetElement.rel = 'stylesheet'; | |
88 stylesheetElement.href = | |
89 browser.runtime.getURL('web_resources/style/entry-content.css'); | |
90 contentDocument.head.appendChild(stylesheetElement); | |
91 contentElement.srcdoc = new XMLSerializer() | |
92 .serializeToString(contentDocument); | |
93 contentElement.title = entry.title; | |
94 | |
95 if (entry.files.length > 0) { | |
96 let fileListNode = feedPreviewDocument | |
97 .importNode(entryFileListTemplateElement.content, true); | |
98 fileListNode.querySelector('.entry-files-title').textContent = | |
99 browser.i18n.getMessage('filesTitle'); | |
100 let fileListElement = | |
101 fileListNode.querySelector('.entry-files-list'); | |
102 | |
103 for (let file of entry.files) { | |
104 let fileNode = feedPreviewDocument | |
105 .importNode(entryFileTemplateElement.content, true); | |
106 | |
107 let fileLinkElement = | |
108 fileNode.querySelector('.entry-file-link'); | |
109 fileLinkElement.href = file.url; | |
110 fileLinkElement.title = file.filename; | |
111 fileLinkElement.textContent = file.filename; | |
112 | |
113 fileNode.querySelector('.entry-file-info').textContent = | |
114 `(${file.type}, ${file.size} bytes)`; | |
115 | |
116 fileListElement.appendChild(fileNode); | |
117 } | |
118 | |
119 entryNode.querySelector('.entry').append(fileListNode); | |
120 } | |
121 | |
122 feedPreviewDocument.body.append(entryNode); | |
123 } | |
124 } |