Compare commits
4 commits
7964405502
...
de55f4a4de
Author | SHA1 | Date | |
---|---|---|---|
de55f4a4de | |||
1bed02b456 | |||
f065860edb | |||
67896b2380 |
12 changed files with 78 additions and 24 deletions
|
@ -11,8 +11,7 @@ browser and detect feed URLs in web pages.
|
||||||
```
|
```
|
||||||
git clone https://git.platypush.tech/blacklight/rss-viewer-browser-extension
|
git clone https://git.platypush.tech/blacklight/rss-viewer-browser-extension
|
||||||
cd rss-viewer-browser-extension
|
cd rss-viewer-browser-extension
|
||||||
npm install
|
./build.sh
|
||||||
npm run build
|
|
||||||
```
|
```
|
||||||
|
|
||||||
A file named `dist.crx` will be generated - just drop it into your browser's extensions.
|
A file named `dist.crx` will be generated - just drop it into your browser's extensions.
|
||||||
|
|
6
build.sh
Executable file
6
build.sh
Executable file
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
zip -r dist dist
|
||||||
|
mv dist.zip dist.crx
|
8
package-lock.json
generated
8
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "sample-project",
|
"name": "rss-viewer-browser-ext",
|
||||||
"version": "1.0.0",
|
"version": "0.1.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "sample-project",
|
"name": "rss-viewer-browser-ext",
|
||||||
"version": "1.0.0",
|
"version": "0.1.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dotenv": "^16.0.0",
|
"dotenv": "^16.0.0",
|
||||||
"node-sass": "^8.0.0",
|
"node-sass": "^8.0.0",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "rss-viewer-browser-ext",
|
"name": "rss-viewer-browser-ext",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import browser from 'webextension-polyfill';
|
import browser from 'webextension-polyfill';
|
||||||
|
|
||||||
browser.webNavigation.onCompleted.addListener(
|
browser.webNavigation.onCompleted.addListener(
|
||||||
async (event: {tabId: string;}) => {
|
async (event: {tabId: string;}) => {
|
||||||
const { tabId } = event
|
const { tabId } = event
|
||||||
await browser.tabs.sendMessage(tabId, {type: 'renderFeed'})
|
await browser.tabs.sendMessage(tabId, {type: 'renderFeed'})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
34
src/main.ts
34
src/main.ts
|
@ -136,10 +136,7 @@ const getFeedRoot = () => {
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
|
|
||||||
browser.runtime.onMessage.addListener(async (message: {type: Object}) => {
|
const renderFeed = () => {
|
||||||
if (message.type !== 'renderFeed')
|
|
||||||
return
|
|
||||||
|
|
||||||
const xmlDoc = getFeedRoot()
|
const xmlDoc = getFeedRoot()
|
||||||
if (!xmlDoc)
|
if (!xmlDoc)
|
||||||
// Not an RSS feed
|
// Not an RSS feed
|
||||||
|
@ -151,4 +148,33 @@ browser.runtime.onMessage.addListener(async (message: {type: Object}) => {
|
||||||
|
|
||||||
browser.storage.local.set(parseFeed(channel))
|
browser.storage.local.set(parseFeed(channel))
|
||||||
window.location.href = browser.runtime.getURL('viewer/index.html')
|
window.location.href = browser.runtime.getURL('viewer/index.html')
|
||||||
|
}
|
||||||
|
|
||||||
|
const extractFeedUrl = () => {
|
||||||
|
const links = Array.from(document.getElementsByTagName('link'))
|
||||||
|
.filter((link) =>
|
||||||
|
link.getAttribute('rel') === 'alternate' &&
|
||||||
|
link.getAttribute('type') === 'application/rss+xml'
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!links.length)
|
||||||
|
return
|
||||||
|
|
||||||
|
let link = links[0].getAttribute('href') || ''
|
||||||
|
if (link.length && !link.match(/^https?:\/\//)) {
|
||||||
|
let port = window.location.port
|
||||||
|
if (port.length)
|
||||||
|
port = `:${port}`
|
||||||
|
link = `${window.location.protocol}//${window.location.hostname}${port}${link}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return link.length ? link : null
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.runtime.onMessage.addListener(async (message: {type: Object}) => {
|
||||||
|
if (message.type === 'renderFeed')
|
||||||
|
return renderFeed()
|
||||||
|
if (message.type === 'extractFeedUrl')
|
||||||
|
return extractFeedUrl()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "RSS Viewer",
|
"name": "RSS Viewer",
|
||||||
"description": "An easy way to render RSS feeds directly in your browser",
|
"description": "An easy way to render RSS feeds directly in your browser",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"action": {
|
"action": {
|
||||||
"default_icon": {
|
"default_icon": {
|
||||||
|
|
|
@ -1,14 +1,34 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="popup">
|
<div class="popup">
|
||||||
Nothing interesting here
|
<div v-if="feedUrl">
|
||||||
|
<a :href="feedUrl" target="_blank">Found a feed URL</a>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
No feed URLs found on this page
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script>
|
||||||
|
import browser from 'webextension-polyfill';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Popup',
|
name: 'Popup',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
feedUrl: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async mounted() {
|
||||||
|
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true })
|
||||||
|
this.feedUrl = await browser.tabs.sendMessage(tab.id, {type: 'extractFeedUrl'})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.popup {
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Popup</title>
|
<title>RSS Viewer Popup</title>
|
||||||
</head>
|
</head>
|
||||||
<body style="min-width: 200px;">
|
<body style="min-width: 200px;">
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
//import { createPinia } from "pinia";
|
|
||||||
import App from "./Popup.vue";
|
import App from "./Popup.vue";
|
||||||
|
|
||||||
const app = createApp(App) //.use(createPinia());
|
const app = createApp(App)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
|
@ -18,7 +18,8 @@
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="item" v-for="item, i in (feed.items || [])" :key="i">
|
<div class="item" v-for="item, i in (feed.items || [])" :key="i">
|
||||||
<div class="header" @click="expandedItems[i] = !expandedItems[i]">
|
<div class="header" :class="{expanded: expandedItems[i]}"
|
||||||
|
@click="expandedItems[i] = !expandedItems[i]">
|
||||||
<h2 v-if="item.title?.length">
|
<h2 v-if="item.title?.length">
|
||||||
<a :href="item.url" target="_blank" v-text="item.title" />
|
<a :href="item.url" target="_blank" v-text="item.title" />
|
||||||
</h2>
|
</h2>
|
||||||
|
@ -124,6 +125,10 @@ main {
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
border-radius: 1em;
|
border-radius: 1em;
|
||||||
|
|
||||||
|
&.expanded {
|
||||||
|
border-radius: 1em 1em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #cff7cf;
|
background: #cff7cf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
//import { createPinia } from "pinia";
|
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
|
|
||||||
const app = createApp(App) // .use(createPinia());
|
const app = createApp(App)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
Loading…
Reference in a new issue