Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

creamcrop

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

creamcrop - npm Package Compare versions

Comparing version 0.3.0 to 0.4.0

.github/workflows/codeql-analysis.yml

10

CHANGELOG.md

@@ -0,1 +1,11 @@

# v0.4.0
Adds:
- Improved Web Design
- Auto-update RSS feeds
- Custom port and host values for `cream serve`
- Add RSS sorting by date, independent of feed
- Add `%pubdate%` option for format options
- Add `%update%` option for website templates which get's replaced with an auto-update script
# v0.3.0

@@ -2,0 +12,0 @@

2

docs/_coverpage.md

@@ -5,3 +5,3 @@ ![header](./assets/Favicon.png)

# Creamcrop <small>v0.3.0</small>
# Creamcrop <small>v0.4.0</small>

@@ -8,0 +8,0 @@ > A cream-of-the-crop, top-of-the-top, slice-and-chop, absolutely minimalist news getter

> Configuration for the package
Configuration for the package is located at the `.creamcroprc` file,
which is auto-generated, and currently only contains the feeds to use
when generating the webiste. However, there are plans to extend this
to allow for more configuration in the package, including custom formats,
website templates, and more.
which is auto-generated, and contains easy ways to add custom HTML templates
and format's for the website when served.
## Configuration Syntax

@@ -32,3 +29,3 @@

| `feeds` | Array of feeds to parse | No default. **Required**. | An array of URLs to feeds |
| `format` | The format of the output. Each value should be surrounded by `%`. | `<a href="%link%">%item%</a> from <a href="%feedlink%">%feed%</a>` | `%feed%`- The name of the RSS feed the item is in. <br> `%feedlink%` - The RSS feed's link that the item is in. <br> `%item%` - The name of the RSS feed Item. <br> `%itemlink%` Link to the item. |
| `custom` | A custom HTML template. Inside the HTML, use `%feed%`, which will be replaced by the content of the feed. | A basic HTML page. | The relative path to the HTML template file |
| `format` | The format of the output. Each value should be surrounded by `%`. | `<a href="%link%">%title%</a> from <a href="%feedlink%">%feed%</a>` | `%feed%`- The name of the RSS feed the item is in. <br> `%feedlink%` - The RSS feed's link that the item is in. <br> `%title%` - The name of the RSS feed Item. <br> `%link%` Link to the item. <br> `%pubdate%` - The publication date. |
| `custom` | A custom HTML template. Inside the HTML, use `%feed%`, which will be replaced by the content of the feed. Use `%update%` in the HTML, which will be replaced by a script that auto-updates the RSS feed. | A basic HTML page. | The relative path to the HTML template file |

@@ -79,3 +79,3 @@ > Learn the fundamentals of creamcrop

Qlabs (@Quantalabs)
0.3.0
0.4.0
```

@@ -121,3 +121,3 @@

$ cream --version
0.3.0
0.4.0
```
{
"name": "creamcrop",
"version": "0.3.0",
"version": "0.4.0",
"description": "A cream-of-the-crop, top-of-the-top, slice-and-chop, absolutely minimalist news getter.",

@@ -5,0 +5,0 @@ "main": "src/index.js",

@@ -23,3 +23,3 @@ <div align='center'>

(creamcrop|cream) fetch [url] Fetch a feed.
(creamcrop|cream) serve [url] Serves website from RSS feed
(creamcrop|cream) serve [dir] Serves website from config file in [dir].
(creamcrop|cream) about Displays package info and exits.

@@ -26,0 +26,0 @@

@@ -76,2 +76,20 @@ #!/usr/bin/env node

description: 'The directory of the config file.'
}),
yargs.option('port', {
alias: 'p',
type: 'number',
default: 8080,
description: 'The port to run the server on.'
}),
yargs.option('host', {
alias: 'h',
type: 'string',
default: 'localhost',
description: 'The host to run the server on.'
}),
yargs.option('interval', {
alias: 'i',
type: 'number',
default: 300000,
description: 'The interval to check for new posts. Defaults to 5 minutes.'
})

@@ -81,3 +99,3 @@ },

(async () => {
await web.serve(argv.dir)
await web.serve(argv.dir, argv.port, argv.host, argv.interval)
})();

@@ -126,4 +144,8 @@ }

process.on('SIGINT', function() {
console.log('\nExiting...')
process.exit(0)
});
exports.about = about
exports.version = version
const http = require('http');
const fs = require('fs');
const rss = require('./rss');
const metadata = require('./metadata');

@@ -10,3 +11,3 @@ /**

*/
async function serve(dir) {
async function serve(dir, port, host, interval) {
if (fs.existsSync(dir+'/.creamcroprc') || fs.existsSync(dir+'.creamcroprc')) {

@@ -19,84 +20,123 @@ console.log('Found config file, generating website...')

}
let feed = {
items: []
};
let config = JSON.parse(fs.readFileSync(dir+'/.creamcroprc'));
for (var x in config.feeds) {
let data = await rss.parse(config.feeds[x]);
for (var fitem in data.items) {
feed.items.push({
title: data.items[fitem].title,
link: data.items[fitem].link,
feed: data.title,
feedlink: data.link,
});
async function generate(dir) {
let feed = {
items: []
};
let config = JSON.parse(fs.readFileSync(dir+'/.creamcroprc'));
for (var x in config.feeds) {
let data = await rss.parse(config.feeds[x]);
for (var fitem in data.items) {
feed.items.push({
title: data.items[fitem].title,
link: data.items[fitem].link,
feed: data.title,
feedlink: data.link,
pubdate: data.items[fitem].isoDate
});
}
}
}
function format(title, link, feedlink, feed) {
if (config.format !== undefined) {
var format = config.format
format = format.replace(/%title%/g, title);
format = format.replace(/%link%/g, link);
format = format.replace(/%feed%/g, feed);
format = format.replace(/%feedlink%/g, feedlink);
return format;
// Sort all the items in feed.items by date
feed.items = feed.items.sort(function(a, b) {
return new Date(b.pubdate) - new Date(a.pubdate);
});
function format(title, link, feedlink, feed, pubdate, add="", end="") {
if (config.format !== undefined) {
var format = config.format
format = format.replace(/%title%/g, title);
format = format.replace(/%link%/g, link);
format = format.replace(/%feed%/g, feed);
format = format.replace(/%feedlink%/g, feedlink);
format = format.replace(/%pubdate%/g, new Date(pubdate).toLocaleDateString());
return format;
}
else {
return `${add}<a href="${link}">${title}</a> from <a href="${feedlink}">${feed}</a>${end}`;
}
}
else {
return `<a href="${link}">${title}</a> from <a href="${feedlink}">${feed}</a>`;
}
}
let html = ''
let html = ''
if (config.custom !== undefined) {
console.log('\nParsing custom HTML...');
if (config.custom !== undefined) {
console.log('\nParsing custom HTML...');
let customconf = ''
if (fs.existsSync(dir+config.custom)) {
customconf = fs.readFileSync(dir+config.custom, {encoding:'utf8', flag:'r'});
}
else if (fs.existsSync(dir+'/'+config.custom)) {
customconf = fs.readFileSync(dir+'/'+config.custom, {encoding:'utf8', flag:'r'});
}
else {
console.log('Custom file not found: ' + dir+config.custom);
process.exit(1);
}
let customconf = ''
if (fs.existsSync(dir+config.custom)) {
customconf = fs.readFileSync(dir+config.custom, {encoding:'utf8', flag:'r'});
}
else if (fs.existsSync(dir+'/'+config.custom)) {
customconf = fs.readFileSync(dir+'/'+config.custom, {encoding:'utf8', flag:'r'});
}
else {
console.log('Custom file not found: ' + dir+config.custom);
process.exit(1);
}
console.log('\nParsing RSS feed(s)...');
customconf = customconf.replace(/%feed%/g, feed.items.map(item => `
<li>
${format(item.title, item.link, item.feedlink, item.feed)}
</li>
`).join('\n'));
console.log('\nParsing RSS feed(s)...');
customconf = customconf.replace(/%feed%/g, feed.items.map(item => `
${format(item.title, item.link, item.feedlink, item.feed, item.pubdate)}
`).join('\n'));
// Replace %update% with automatic reloading script with interval in customconf
customconf = customconf.replace(/%update%/g, `
<script>
setTimeout(function(){
window.location.reload(1);
}, ${Number(interval)});
</script>
`);
html = customconf
}
html = customconf
}
else {
console.log('\nParsing RSS feed(s)...\n');
html = `
<!DOCTYPE html>
<html>
<head>
<title>Creamcrop | A cream-of-the-crop, top-of-the-top, slice-and-chop, absolutely minimalist news getter</title>
</head>
<body>
<h1>Your News Feed</h1>
<sub>Your news feed from creamcrop, the cream-of-the-crop, top-of-the-top, slice-and-chop, absolutely minimalist news getter.</sub>
<ul>
${feed.items.map(item => `
<li>
${format(item.title, item.link, item.feedlink, item.feed)}
</li>
`).join('\n')}
</ul>
</body>
</html>
`;
else {
console.log('\nParsing RSS feed(s)...\n');
html = `
<!DOCTYPE html>
<html>
<head>
<title>Creamcrop | A cream-of-the-crop, top-of-the-top, slice-and-chop, absolutely minimalist news getter</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Georama&display=swap" rel="stylesheet">
<meta charset="utf-8">
<meta name="generator" content="Creamcrop ${metadata.version}" />
</head>
<body style="font-family: 'Georama', sans-serif; margin: 0; border: none; padding: 0; overflow-x: hidden;">
<section id="main-content">
<h1 style="width: 100vw; text-align: center;">Your News Feed</h1>
<p style="margin: auto; text-align: center;">Your news feed from creamcrop, the cream-of-the-crop, top-of-the-top, slice-and-chop, absolutely minimalist news getter.</p>
<br>
<hr style="width: 50vw; margin: auto;">
<br>
<ol style="width: 100vw; text-align: center; list-style-position: inside;">
${feed.items.map(item => `
${format(item.title, item.link, item.feedlink, item.feed, item.pubdate, '<li>', '</li>')}
`).join('\n')}
</ol style="width: 100vw; text-align: center;">
</section>
<br><br>
<!-- Add footer -->
<footer style="width: 100vw; text-align: center; bottom: 0; position: fixed; background-color: white;">
<p>Creamcrop | A cream-of-the-crop, top-of-the-top, slice-and-chop, absolutely minimalist news getter</p>
</footer>
<script>
setTimeout(function(){
window.location.reload(1);
}, ${Number(interval)});
</script>
</body>
</html>
`;
}
return html;
}
const requestListener = function (req, res) {
let html = await generate(dir);
const requestListener = async function (req, res) {
res.writeHead(200, {

@@ -106,9 +146,15 @@ 'Content-Type': 'text/html'

res.end(html);
if (req.url === '/') {
html = await generate(dir);
res.end(html);
}
}
const server = http.createServer(requestListener);
server.listen(8080);
console.log('\n\nServer running at http://localhost:8080')
const server = await http.createServer(requestListener);
server.listen(port, host, () => {
console.log(`Server is running on http://${host}:${port}`);
});
}
exports.serve = serve
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc