jsantell / poet Goto Github PK
View Code? Open in Web Editor NEWA node.js blog engine
Home Page: jsantell.github.io/poet
License: MIT License
A node.js blog engine
Home Page: jsantell.github.io/poet
License: MIT License
I noticed that if I setup watcher it works fine for editing existing files and creating new files.
But when I remove the file from _posts folder I can see that watcher callback is fired but the removed post is still there.
When I install poet via npm install poet --save
, it puts "poet": "~1.0.0rc1"
into package.json
. I think this should actually be "poet": "~1.0.0-rc1"
. Otherwise NPM complains.
But anyway, great module, thanks!
Hi,
I have found some issues with the slug handling.
Short explanation how I am using Poet:
I am working on a small company website where I not only use Poet for the news section (= a blog), but also to power a set of products, a set of services and a set of career opportunities. So I have 4 separate instances in my application and it works great so far. However, because I am also using it to manage a set of products and services, I am very concerned about the URLs and need them to be in a specific way. Before the recent changes I could get away with defining the filenames of the markdown files. But now I have to define the slug myself inside of the markdown file. I like the new handling better, because now the filenames are not so important anymore. However, I found some issues with the slug handling.
I fixed the second issue by changing the regex inside convertStringToSlug to include the parentheses:
.replace(/[^\w- ()]+/g,'')
Alex
TypeError: Cannot call method 'apply' of undefined
at Poet.middleware (/Library/Server/Web/Data/Sites//node_modules/poet/lib/poet/utils.js:136:19)
at Object. (/Library/Server/Web/Data/Sites//app.js:9:14)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:901:3
hi.
as3:/poet/examples# npm install poet -g/poet/examples#
npm http GET https://registry.npmjs.org/poet
npm http 200 https://registry.npmjs.org/poet
npm http GET https://registry.npmjs.org/marked
npm http GET https://registry.npmjs.org/underscore
npm http GET https://registry.npmjs.org/json-front-matter
npm http GET https://registry.npmjs.org/when
npm http GET https://registry.npmjs.org/front-matter
npm http GET https://registry.npmjs.org/fs-then
npm http GET https://registry.npmjs.org/jade
npm http 304 https://registry.npmjs.org/marked
npm http 304 https://registry.npmjs.org/underscore
npm http 304 https://registry.npmjs.org/front-matter
npm http 304 https://registry.npmjs.org/fs-then
npm http 304 https://registry.npmjs.org/json-front-matter
npm http 304 https://registry.npmjs.org/when
npm http 304 https://registry.npmjs.org/jade
npm http GET https://registry.npmjs.org/yaml-js/0.0.7
npm http 304 https://registry.npmjs.org/yaml-js/0.0.7
npm http GET https://registry.npmjs.org/mkdirp
npm http GET https://registry.npmjs.org/transformers/2.1.0
npm http GET https://registry.npmjs.org/character-parser/1.2.0
npm http GET https://registry.npmjs.org/with
npm http GET https://registry.npmjs.org/monocle/1.1.51
npm http GET https://registry.npmjs.org/constantinople
npm http GET https://registry.npmjs.org/commander/2.1.0
npm http 304 https://registry.npmjs.org/monocle/1.1.51
npm http 304 https://registry.npmjs.org/mkdirp
npm http 304 https://registry.npmjs.org/with
npm http 304 https://registry.npmjs.org/character-parser/1.2.0
npm http 304 https://registry.npmjs.org/constantinople
npm http 304 https://registry.npmjs.org/commander/2.1.0
npm http 304 https://registry.npmjs.org/transformers/2.1.0
npm http GET https://registry.npmjs.org/uglify-js
npm http GET https://registry.npmjs.org/readdirp
npm http GET https://registry.npmjs.org/uglify-js/2.4.0
npm http GET https://registry.npmjs.org/uglify-js
npm http GET https://registry.npmjs.org/promise
npm http GET https://registry.npmjs.org/css
npm http 304 https://registry.npmjs.org/readdirp
npm http 304 https://registry.npmjs.org/uglify-js/2.4.0
npm http 304 https://registry.npmjs.org/uglify-js
npm http 304 https://registry.npmjs.org/uglify-js
npm http 304 https://registry.npmjs.org/promise
npm http 304 https://registry.npmjs.org/css
npm http GET https://registry.npmjs.org/is-promise
npm http GET https://registry.npmjs.org/css-stringify/1.0.5
npm http GET https://registry.npmjs.org/css-parse/1.0.4
npm http 304 https://registry.npmjs.org/is-promise
npm http 304 https://registry.npmjs.org/css-stringify/1.0.5
npm http 304 https://registry.npmjs.org/css-parse/1.0.4
npm http GET https://registry.npmjs.org/source-map
npm http GET https://registry.npmjs.org/optimist
npm http GET https://registry.npmjs.org/uglify-to-browserify
npm http GET https://registry.npmjs.org/async
npm http 304 https://registry.npmjs.org/optimist
npm http 304 https://registry.npmjs.org/async
npm http 304 https://registry.npmjs.org/uglify-to-browserify
npm http 304 https://registry.npmjs.org/source-map
npm http GET https://registry.npmjs.org/minimatch
npm http 304 https://registry.npmjs.org/minimatch
npm http GET https://registry.npmjs.org/wordwrap
npm http 304 https://registry.npmjs.org/wordwrap
npm http GET https://registry.npmjs.org/amdefine
npm http 304 https://registry.npmjs.org/amdefine
npm http GET https://registry.npmjs.org/sigmund
npm http GET https://registry.npmjs.org/lru-cache
npm http 304 https://registry.npmjs.org/sigmund
npm http 304 https://registry.npmjs.org/lru-cache
...
[email protected] /usr/local/lib/node_modules/poet
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected] ([email protected])
└── [email protected] ([email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected])
as3:
as3:/poet/examples# poet --help/poet/examples#
-bash: poet: command not found
as3:
Crossposting here from StackOverflow. New to Poet, the post title is not behaving as I'd expect from the example.
I expect that if a post were in the file hello.md
and had the configuration {{{ title: 'hello-world', ...}}}
that this would be available at the route http://hostname/post/hello
and have the display render the title to the reader as <h1>hello-world</h1>
. That's the way it seems to be working in the reference blog, e.g.:
However, in my case it seems to be using the title attribute for both the URL and the display string. In my case, the post is accessible only at http://hostname/posts/hello-world
and the page title is also rendered as <h1>hello-world</h1>
.
What might I be doing wrong?
I can't seem to find any support for paginating categories. Should implement my own route for that? Is there a snippet of code that already implements paginations, like a helper I could use?
thanks!
I want to try running Poet as our blogging engine.
Our site's an existing node app, and I want to put the blog on /blog
.
How can I wrap Poet up into /routes/blog.js
so that it's self-contained and I can import it like anything e;se in app.js
?
Great lib btw.
how is the option postsPerPage accessible from the jade templates?
if I set the value to 3
poet.set({
posts: './_posts/',
postsPerPage: 3,
how do I reference it from the index.jade file?
extends layout
block content
- var posts = getPosts(0,5)
I've tried using postsPerPage
and options.postsPerPage
but neither works. It's problably something simple I am missing. Any advice?
Trying to follow the examples for how to get Poet up and running. Still no success with Poet 2.0 and Express 4.x
poet.createPostRoute().createPageRoute().createTagRoute().createCategoryRout
^
TypeError: Object #<Poet> has no method 'createPostRoute'
So I created a somewhat limited setup like this, since I expect that the poet routes are setup by default?
express = require 'express'
app = express!
Poet = require 'poet'
app.set 'view engine', 'jade'
app.set 'views', __dirname + '/views'
app.use express.static(__dirname + '/public')
poet = Poet app,
posts: './_posts/'
postsPerPage: 5
metaFormat: 'json'
poet.init!.then( ->
console.log 'poet initialized'
)
app.get '/', (req, res) ->
res.render 'index'
app.get '/rss', (req, res) ->
# Only get the latest posts
posts = poet.helpers.getPosts 0, 5
res.setHeader 'Content-Type', 'application/rss+xml'
res.render 'rss', posts: posts
module.exports = app
But when I go to localhost:3000
all I get is "Welcome to" and localhost:3000/posts
gives me Cannot GET /posts
error.
// views/index.jade
extends layout
block content
h1= title
p Welcome to #{title}
// routes/index.js
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.render('index', { title: 'Express' });
});
module.exports = router;
Any ideas? Anyone had success with Poet 2.0 and Express 4.0? Where can I find documentation, examples or a working app with this setup?
Thanks ;)
I don't understand the "JSON frontmatter" option when YAML's already a superset of JSON. Why is there a separate "JSON frontmatter" syntax (with triple-curly-braces) when the existing YAML frontmatter syntax works perfectly well for JSON (with a trailing separator line)?
In your method util,
/**
* Takes `lambda` function and returns a method. When returned method is
* invoked, it calls the wrapped `lambda` and passes `this` as a first argument
* and given arguments as the rest.
*
* @params {Function} lambda
* @returns {Function}
*/
function method (lambda) {
return function () {
return lambda.apply(null, [this].concat(Array.prototype.slice.call(arguments, 0)));
};
}
exports.method = method;
you pass null
as the first argument to apply. Why would you not pass this
as the first argument so that you would have the ability to use this
in the wrapped functions and have it point to the Poet instance. I'm aware you are making sure that the poet instance is always the first argument in the wrapped functions (so this would be redundant) but would it hurt any? Wouldn't having this
point to GLOBAL
be risky?
I am more trying to understand why than anything else.
Poet strikes a very nice balance between control and usability. Coolness. I don't see a wiki. I did see the invite to tweet, but that format is a bit limiting. :)
Do I understand correctly that Poet parses all of the posts and keeps all of the posts in memory? If so, can someone comment on scaling? Would it make sense to add hooks for a backing db? I realize this would come at the cost of the simple files store plus watch() model.
I've noticed that there are several places where there seems to be discrepancies between styles in the codebase. For instance, some places we have a single var
statement while in others we have multiple. I've also noticed that there are inline var
statements inside of for
loops.
Would it be a good idea to have someone clean up the codebase in order to follow some general style? I understand working with in an open source everybody codes based on their preferences, but it would be nice to have some uniformity.
Along these same lines, maybe we could introduce jslint
into the project?
function readMoreLink (post) {
var anchor = '<a href="' + post.url + '"';
anchor += ' title="Read more of ' + post.title + '">read more</a>';
return '<p class="read-more">' + anchor + '</p>';
}
Now I can center it if I like :)
p.read-more {
text-align: center;
}
Possibly I actually am doing something wrong, but I am using the example views and tags of unpublished posts are displayed even with showDrafts: false
.
As an enhancement the ability to produce an RSS or Atom feed based on the posts would be great.
I'm slowly working on an RSS feed builder but I am unsure if it should be part of the core or implemented as an addon (or how to go about making it an addon).
As of now, posts cannot be scheduled, as an explicit modification on a file must happen in order for the watcher to fire.
When a post is loaded with a future date and showFuture
is false
, watch should be scheduled to fire as if the future post was edited at its date so Poet reloads it and adds it as a current post.
This would allow post scheduling, currently only available if done manually or with added code.
Issue affects only current version, works fine in 0.2.9. Latest version breaks previously working app. Seems like it's somewhere in the middleware, I'll take a look later.
11:46:57 web.1 | started with pid 4683
11:46:58 web.1 |
11:46:58 web.1 | /Users/icyfenix/Projects/Websites/lizthedeveloper/node_modules/poet/lib/poet/utils.js:128
11:46:58 web.1 | return lambda.apply(null, [this].concat(Array.prototype.slice.call(argumen
11:46:58 web.1 | ^
11:46:58 web.1 | TypeError: Cannot call method 'apply' of undefined
11:46:58 web.1 | at Poet.middleware (/Users/icyfenix/Projects/Websites/lizthedeveloper/node_modules/poet/lib/poet/utils.js:128:19)
11:46:58 web.1 | at Function.poet.set.posts (/Users/icyfenix/Projects/Websites/lizthedeveloper/app.js:30:15)
11:46:58 web.1 | at Function.app.configure (/Users/icyfenix/Projects/Websites/lizthedeveloper/node_modules/express/lib/application.js:395:61)
11:46:58 web.1 | at Object. (/Users/icyfenix/Projects/Websites/lizthedeveloper/app.js:19:5)
11:46:58 web.1 | at Module._compile (module.js:456:26)
11:46:58 web.1 | at Object.Module._extensions..js (module.js:474:10)
11:46:58 web.1 | at Module.load (module.js:356:32)
11:46:58 web.1 | at Function.Module._load (module.js:312:12)
11:46:58 web.1 | at Function.Module.runMain (module.js:497:10)
11:46:58 web.1 | at startup (node.js:119:16)
11:46:58 web.1 | exited with code 8
11:46:58 system | sending SIGTERM to all processes
feature request - support for github style syntax highlighting:
function foo() {};
I don't have as much time as I used to for maintaining Poet, so if there is anyone who's interested in helping out for responding to PR's, merging in patches, experience in managing open source projects, post here!
The scope of Poet is still a lightweight blogging engine, and should not bloat with features that can be handled by third party modules, but features that allow poet be extensible to allow external capabilities (additional data-stores, templating, static rendering) and a maintainer who will continue this perspective.
Thanks!
I'm not sure I'm understanding how the pagination function works. Do I have to create a separate view to make this work.
poet.init(function ( locals ) {
locals.numPages = locals.getPageCount();
});
poet.addRoute('/pages/:page', function (req, res) {
var page = req.params.page,
lastPost = page * 3;
res.render('blog', {
posts: poet.helpers.getPosts(lastPost - 3, lastPost),
page: page
});
});
But what gets returned it is just the main first blog page with the 20 posts I wish to show per page. The view layout is:
- var posts = getPosts(0,100) - var page = 1 - each post in posts include includes/postSnippet include includes/pagination
there's good possibility i'm not doing this right but, here's the code!
var app = require('express')();
var Poet = require('poet');
var poet = Poet(app, {
postsPerPage: 5,
posts: __dirname + '/../_posts/',
metaFormat: 'json',
routes: { }
});
poet.init().then(function () {
console.log('___________', arguments);
});
i've logged the promise that's returns from the poet init call, so i know it's a promise, but for some reason it's not being resolved :/
any info is much appreciated!
It will be a nice feature if you support hierarchical posts, like
[:parent]/[:post]
Is it possible to create multiple instances of peot?
What I need is to put different posts (.md or .jade) in different folders, and route them with different urls.
e.g.
'/article/:article' direct to articles in my site
'/news/:news' direct to news
'/product/:product' direct to products.
any idea?
thanks.
I'd like to create (or steal) a plugin to extend Poet to generate the pages as a static site.
a) is this something that would fit in with Poet?
2) any advice on where to start?
The docs say:
Built in helper methods are stored on the Poet instance's
helper
property. Used internally, and in the view locals, they can be used outside of Poet as well.
Shouldn't that be helpers
instead?
I've added the following block of code as per the Watcher example:
poet.watch(function() {
console.log("Poet reloaded");
}).init().then(function() {
console.log("Ready to go!");
});
While updating the content of an existing post makes the post get updated when viewed in a browser, creating new posts or deleting existing ones doesn't work unless I close the poet instance and start a new one.
The "Poet reloaded" print appears in all three cases, i.e. update/create/delete.
I have a wordpress blog with hundreds of articles.I can't abandon it.Please write a article about how to import from blogger and wordpress.
I don't know what's causing this, but I have about 60 posts in one blog, and the var parsed = (options.metaFormat === 'yaml' ? yamlFm : jsonFm)(data);
call inside utils.js for one post always returns an object with parsed.attributes
as {}
and parsed.body
containing the whole front-matter. I thought it might be a problem with the post, but here's what's weird:
jsonFm(data)
again returns a valid object as the resultI suspect that this might have something to do with promises, but I don't know enough about that to be certain either way.
It would be helpful to be able to set the "date" in the metadata as sometime in the future, and not have the blog post be displayed unless the date is current or in the past. That would provide the blog author the ability to write posts that are automatically displayed on the specified date. I feel like that would be a handy feature for Poet. I would love to contribute a pull request if you feel like it is something that is worth adding.
This is with regards to the commit 7c4c65e.
It works well enough with one invalid route (aka a route missing a :param
) but if the user specifies multiple invalid routes, the current one in the routes object is replaced by the new one. This is because utils.getRouteType
returns null
for both, and so they match. Hence, utils.getRoute
returns the current invalid route, which is assigned to currentRoute
, and hence replaced by the new invalid route.
Instead of trying to fix this, I believe it would be better to just disallow users from adding invalid routes with an assert. Thoughts?
There should exist some way of stopping watchers in case it's needed.
Watchers are preventing Poet to end gracefully if the Express instance is closed without exitting the whole process. Removing the watchers (via close
) would allow it.
What path can you use when referencing images from within markdown posts
(the images being in the same _posts directory as the markdown posts)?
It'd be great to be able to drop in new files in the _posts directory or make edits and then see your updates immediately on page refresh.
I was looking at Paul Miller's Chokidar for this purpose. He uses it for the application assembler Brunch and it seems to fit the need here.
I played around with watching the _posts directory with Chokidar and it looks very doable: you can react to file addition events, file edit events, and delete events. Some error handling will need to be done if a file is added that doesn't yet have the proper JSON attributes yet.
This suggestion may alter the way the init() call is made- poet would have to respond to Chokidar add events instead of iterating through the directory explicitly. Calling the callback passed into init() would be a little trickier. One way I can think of doing this is knowing how many n
posts exist in the _posts directory before the Chokidar watcher starts. Then when you've processed n
posts through the file add event, you know you have initialized.
If I get a chance later this week I'll send a PR with the ideas I've come up with.
package.json needs either to be locked to express version 3.5.0 or the following should be fixed:
...node_modules/poet/lib/poet/utils.js:74
app.locals(helpers);
^
TypeError: Property 'locals' of object function (req, res, next) {
app.handle(req, res, next);
} is not a function
...
Is it possible to add a function which returns the URL of the page on which the post is located?
For example there are 15 posts, 5 posts per page, and the post "blah" is on page 3.
I want to display on the post "blah" a link back to the page where it is located (page 3). This needs to be dynamically adjusted by Poet, because if new posts are added the post "blah" will move to page 4, etc.
Thanks!
I think one thing that would make this project easy to get started for users is write some "Tutorial" docs so that users can see some examples of deploying on different platforms (ie: Github pages).
Any thoughts?
Hi!
Does poet.init([callback]) have a synchronous version?
The example in the README.md file uses the old createPostListRoute()
instead of createPageRoute()
Sorry for the rather vague title of the bug, but I'm seeing some inconsistent behaviour with promises.
Following the "Watcher" example, I have the following block of code:
poet.watch(function() {
console.log("Poet reloaded");
}).init().then(function() {
console.log("Ready to go!");
});
but the "Ready to go!" print never appears. If I change the code above to look like the following block:
poet.watch(function() {
console.log("Poet reloaded");
}).init(function() {
console.log("Ready to go!");
});
the "Ready to go!" print appears.
First of all, let me say that I love what has been done with Poet. Before I bumped into it, I did some brainstorming on what I'd want from a relatively simple blog engine that I could attach to my homepage (the back-end of which is run in node), and Poet is almost a superset of the features I want. I'm in the process of tinkering with Poet and adding it to my website.
While using the local file system for posts is nice for its simplicity, it can be a bit of a pain for apps using Poet that are a) kept on GitHub, and b) deployed elsewhere (eg Heroku), since the deployment cycle is essentially
create blog post -> commit to GitHub -> deploy to Heroku (or wherever)
and that's a rather annoying process. If posts can instead be added to a database/No SQL key-value store/etc, then no such deployment is necessary.
I propose adding different data models to Poet, allowing the storage of posts in databases, as follows:
poet-model-mongo
, poet-model-mysql
, etc) should be their own node modules.options
which would default to the current choice of using the app's local file system.options
, there is an optional object with a key of modelOptions
that includes, eg, access credentials, the host name of the database to connect to, etc.getPost
, getPosts
, getPostsWithTag
, etc. This would mean that createHelpers
would just call the relevant data helper methods from the given data model.Would this kind of thing be welcome?
It looks like if you instantiate poet before modules that affect express "local" templating scope they fail to initialize properly
An example.
Works:
# Middleware
app.use(assets)
app.use(express.static(__dirname + '/public'))
# Global vars for templates
app.locals.pretty = config.debug
app.locals.helpers = require('./app/helpers') # template helpers etc
app.locals.__env =
hostname: config.hostname
debug: config.debug
ga_id: config.ga_id
version: require('./package').version
poet = Poet(app,
postsPerPage: config.blog.per_page
posts: __dirname + '/posts'
metaFormat: 'json'
routes:
'/blog/read/:post': 'post'
'/blog/:page': 'page'
'/blog/tag/:tag': 'tag'
)
# Init routing
poet.init()
app.use(app.router)
server.initialize(app)
Fails:
poet = Poet(app,
postsPerPage: config.blog.per_page
posts: __dirname + '/posts'
metaFormat: 'json'
routes:
'/blog/read/:post': 'post'
'/blog/:page': 'page'
'/blog/tag/:tag': 'tag'
)
# Middleware
app.use(assets)
app.use(express.static(__dirname + '/public'))
# Global vars for templates
app.locals.pretty = config.debug
app.locals.helpers = require('./app/helpers') # template helpers etc
app.locals.__env =
hostname: config.hostname
debug: config.debug
ga_id: config.ga_id
version: require('./package').version
# Init routing
poet.init()
app.use(app.router)
server.initialize(app)
Currently you can navigate to say page 100500 and poet still tries to render it even if there's only 5 pages. Same with say having /page/:num and then trying to open http://jsantell.com/page/lol e.g. lacks validation. Providing custom 404 callback or specifying a 404 template as an option would be fantastic!
And one star goes to gryffindor, that's a one nice blog engine, thanks!
Hello,
Thanks for the great work, Poet is awesome!
Even if not directly a problem due to Poet, I noticed that most of the exemple files contain app.use(app.router);
. The thing is, with Express 3, registering a new route will automatically add the router middleware to the stack if not already present. So, doing it explicitly after the Poet instantiation will result in adding a second router middleware to the stack (a simple console.log(app.stack);
will show this).
Another issue is that, if one would like to add some middlewares (as order matters) before/after the router one, one would actually instantiate Poet at the bottom right before any additional Express routes if any.
What do you think about that?
Need an api that allows to getPageCount which excludes drafts.
Useful for paging
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.