Coder Social home page Coder Social logo

cabinjs / cabin Goto Github PK

View Code? Open in Web Editor NEW
873.0 7.0 44.0 4.92 MB

:evergreen_tree: Cabin is the best self-hosted JavaScript and Node.js logging service. Made for @forwardemail.

Home Page: https://forwardemail.net/docs/node-js-logging-service

License: MIT License

JavaScript 87.40% HTML 11.70% Shell 0.90%
bunyan winston koa express logging logs service cabin sentry raven

cabin's Introduction

cabin

build status code style styled with prettier made with lass license npm downloads

Cabin is the best self-hosted JavaScript and Node.js logging service.
Supports Node v14+, Browser Environments, Express, Koa, and Lad

Cabin is compatible with Sentry, Airbrake, Papertrail, Loggly, and Bugsnag.

Table of Contents

Foreword

Please defer to Axe's Foreword for more insight.

Cabin is a layer on top of Axe that provides automatic logging for route middleware requests and errors.

Quick Start

npm install express axe cabin signale
const express = require('express');
const Axe = require('axe');
const Cabin = require('cabin');
const app = express();
const { Signale } = require('signale');

// initialize a new instance of Axe (see below TODO's that appeal to you)
const logger = new Axe({
  logger: new Signale()
});

// TODO: if you want to send logs to an HTTP endpoint then follow this guide:
// https://github.com/cabinjs/axe/#send-logs-to-http-endpoint

// TODO: if you want to send logs to Slack then follow this guide:
// https://github.com/cabinjs/axe/#send-logs-to-slack

// TODO: if you want to send logs to Sentry then follow this guide:
// https://github.com/cabinjs/axe/#send-logs-to-sentry

// TODO: if you want to send logs to Datadog then follow this guide:
// https://github.com/cabinjs/axe/#send-logs-to-datadog

// TODO: if you want to send logs to Papertrail then follow this guide:
// https://github.com/cabinjs/axe/#send-logs-to-papertrail

// TODO: if you want to suppress specific log metadata then follow this guide:
// https://github.com/cabinjs/axe/#suppress-logger-data

// initialize a new instance of Cabin with an Axe logger instance
const cabin = new Cabin({ logger });

//
// initialize route logging middleware
//
// NOTE: this will automatically log route middleware requests and errors
//
app.use(cabin.middleware);

app.get('/', (req, res, next) => res.send('OK'));

// start the server
app.listen(3000);
curl http://localhost:3000

Features

Security, Privacy, and Business Focused

Cabin will automatically detect and mask the following list of extremely sensitive types of data in your logs:

*Credit card numbers from the following providers are automatically detected and masked: Visa, Mastercard, American Express, Diners Club, Discover, JCB, UnionPay, Maestro, Mir, Elo, Hiper, Hipercard

Reduce Disk Storage Costs

Reduce your disk storage costs through Cabin's automatic conversion of Streams, Buffers, and ArrayBuffers to simplified, descriptive-only objects that otherwise would be unreadable (and obviously pollute your log files and disk storage).

Before:

{
  "request": {
    "body": {
      "file": {
        "type": "Buffer",
        "data": [
          76,
          111,
          114,
          101,
          109,
          32,
          105,
          112,
          115,
          117,
          109,
          32,
          100,
          111,
          108,
          111,
          114,
          32,
          115,
          105,
          116,
          '...'
        ]
      }
    }
  }
}

After

{
  "request": {
    "body": {
      "file": {
        "type": "Buffer",
        "byteLength": 2787
      }
    }
  }
}

Cross-Platform and Cross-Browser Compatible

Cabin works with the most popular Node.js HTTP frameworks (e.g. Express and Koa), request body handling packages (e.g. multer and body-parser), and the passport authentication framework.

It supports Node v14+ and modern browsers out of the box (its browser-ready bundle is only 20 KB).

npx browserslist
and_chr 107
and_ff 106
and_qq 13.1
and_uc 13.4
android 107
chrome 107
chrome 106
chrome 105
edge 107
edge 106
edge 105
firefox 106
firefox 105
firefox 102
ios_saf 16.1
ios_saf 16.0
ios_saf 15.6
ios_saf 15.5
ios_saf 14.5-14.8
kaios 2.5
op_mini all
op_mob 64
opera 91
opera 90
safari 16.1
safari 16.0
safari 15.6
samsung 18.0
samsung 17.0

Send Logs to an HTTP endpoint

See the Quick Start section above and our guide at https://github.com/cabinjs/axe/#send-logs-to-http-endpoint.

Send Logs to Slack

See the Quick Start section above and our guide at https://github.com/cabinjs/axe/#send-logs-to-slack.

Send Logs to Sentry

See the Quick Start section above and our guide at https://github.com/cabinjs/axe/#send-logs-to-sentry.

Send Logs to Datadog

See the Quick Start section above and our guide at https://github.com/cabinjs/axe/#send-logs-to-datadog.

Send Logs to Papertrail

See the Quick Start section above and our guide at https://github.com/cabinjs/axe/#send-logs-to-papertrail.

Suppress Logger Data

See the Quick Start section above and our guide at https://github.com/cabinjs/axe/#suppress-logger-data.

Install

Note that as of v11.0.0 Cabin requires a peer dependency of Axe to be installed.

npm:

npm install cabin axe

Usage

Logging

const Cabin = require('cabin');
const cabin = new Cabin({
  // ... see the Quick Start and Options sections
});

cabin.info('hello world');
cabin.error(new Error('oops!'));

Route Logging Middleware

app.use(cabin.middleware);

See either the Node or Browser instructions below for further route middleware usage and proper setup.

Node

The examples below show how to use Cabin in combination with Axe, Signale (instead of console), and how to add an accurate X-Response-Time response time metric to your logs and response headers automatically.

Koa

  1. Install required and recommended dependencies:

    npm install koa cabin signale request-received koa-better-response-time koa-better-request-id
  2. Implement the example code below (also found here):

    const Koa = require('koa');
    const Cabin = require('cabin');
    const Router = require('koa-router');
    const requestReceived = require('request-received');
    const responseTime = require('koa-better-response-time');
    const requestId = require('koa-better-request-id');
    const { Signale } = require('signale');
    
    const app = new Koa();
    const router = new Router();
    const cabin = new Cabin({
      logger: new Signale()
    });
    
    // adds request received hrtime and date symbols to request object
    // (which is used by Cabin internally to add `request.timestamp` to logs
    app.use(requestReceived);
    
    // adds `X-Response-Time` header to responses
    app.use(responseTime());
    
    // adds or re-uses `X-Request-Id` header
    app.use(requestId());
    
    // use the cabin middleware (adds request-based logging and helpers)
    app.use(cabin.middleware);
    
    // add your user/session management middleware here (e.g. passport)
    // ...
    
    // an example home page route
    router.get('/', ctx => {
      ctx.logger.info('visited home page');
      ctx.body = 'hello world';
    });
    
    // this assumes that you are using passport which
    // exposes `ctx.logout` to log out the logged in user
    router.get('/logout', ctx => {
      ctx.logger.warn('Logged out');
      ctx.logout();
      ctx.redirect('/');
    });
    
    app.use(router.routes());
    app.use(router.allowedMethods());
    
    app.listen(3000, () => {
      cabin.info('app started');
    });
  3. See Koa convenience methods below for helper utilities you can use while writing code.

Express

  1. Install required and recommended dependencies:

    npm install express cabin signale request-received response-time express-request-id
  2. Implement the example code below (also found here):

    const express = require('express');
    const Cabin = require('cabin');
    const requestReceived = require('request-received');
    const responseTime = require('response-time');
    const requestId = require('express-request-id');
    const { Signale } = require('signale');
    
    const app = express();
    const cabin = new Cabin({
      logger: new Signale()
    });
    
    // adds request received hrtime and date symbols to request object
    // (which is used by Cabin internally to add `request.timestamp` to logs
    app.use(requestReceived);
    
    // adds `X-Response-Time` header to responses
    app.use(responseTime());
    
    // adds or re-uses `X-Request-Id` header
    app.use(requestId());
    
    // use the cabin middleware (adds request-based logging and helpers)
    app.use(cabin.middleware);
    
    // add your user/session management middleware here (e.g. passport)
    // ...
    
    // an example home page route
    app.get('/', (req, res) => {
      req.logger.info('visited home page');
      res.send('hello world');
    });
    
    // this assumes that you are using passport which
    // exposes `req.logout` to log out the logged in user
    app.get('/logout', (req, res) => {
      req.logger.warn('logged out');
      req.logout();
      res.redirect('/');
    });
    
    app.listen(3000, () => {
      cabin.info('app started');
    });
  3. See Express convenience methods below for helper utilities you can use while writing code.

Convenience Methods

In order to easily interact and use the logger utility function exposed by app.use(cabin.middleware), we expose convenient helper methods in Express and Koa:

Express
  • req.log
  • req.logger
  • res.log
  • res.logger
Koa
  • ctx.log
  • ctx.logger
  • ctx.request.log
  • ctx.request.logger
  • ctx.response.log
  • ctx.response.logger

Browser

This package requires Promise support, therefore you will need to polyfill if you are using an unsupported browser (namely Opera mini).

We no longer support IE as of Cabin v10.0.0+.

VanillaJS

This is the solution for you if you're just using <script> tags everywhere!

<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=Promise"></script>
<script src="https://unpkg.com/cabin"></script>
<script type="text/javascript">
  (function() {
    var cabin = new Cabin();
    cabin.setUser({
      id: '1',
      email: '[email protected]',
      full_name: 'Test'
    });
    cabin.info('viewed docs');
  })();
</script>

Required Browser Features

We recommend using https://cdnjs.cloudflare.com/polyfill (specifically with the bundle mentioned in VanillaJS above):

<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=Promise"></script>
  • Promise is not supported in op_mini all

Bundler

This assumes you are using browserify, webpack, rollup, or another bundler.

const Cabin = require('cabin');

const cabin = new Cabin();

cabin.setUser({
  id: '1',
  email: '[email protected]',
  full_name: 'Test'
});

cabin.info('viewed docs');

Automatic Request Logging

Server

For server-side logging of requests, the Cabin middleware cabin.middleware will automatically log requests for you upon completion. Just make sure you are using express-request-id middleware like in the examples above in order for the X-Request-Id header to be set (and re-used if already exists, e.g. generated from client side as in below). If you're using Koa make sure to use koa-better-request-id as shown in the examples above.

Browser

We strongly recommend that you implement one of the following code snippets with xhook (for either VanillaJS or Bundler approaches) so that all your XHR requests have a X-Request-Id automatically added (which in turn ensures both client and server have matching request ID's). Imagine how awesome your logs will be when you can see the full trace starting with the client!

HTML
<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=Promise"></script>
<script src="https://unpkg.com/xhook"></script>
<script src="https://unpkg.com/cabin"></script>
<script src="https://unpkg.com/parse-request"></script>
<script src="https://unpkg.com/cuid"></script>
<script>
  (function() {
    var cabin = new Cabin();
    cabin.setUser({
      id: '1',
      email: '[email protected]',
      full_name: 'Test'
    });
    xhook.before(function(req) {
      if (typeof req.headers !== 'object') req.headers = {};

      if (!req.headers['X-Request-Id'])
        req.headers['X-Request-Id'] = cuid();

      if (!req.headers['User-Agent'])
        req.headers['User-Agent'] = window.navigator.userAgent;

      if (!req.headers['Referer'])
        req.headers['Referer'] = window.document.referrer;

      if (!req.headers['Cookie'])
        req.headers['Cookie'] = window.document.cookie;

      cabin.info('xhr', parseRequest({ req: req }));
    });
  })();
</script>
Pug

You can do a similar approach with React, EJS, or another templating language.

script(src='https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=Promise')
script(src='https://unpkg.com/xhook')
script(src='https://unpkg.com/cabin')
script(src='https://unpkg.com/parse-request')
script(src='https://unpkg.com/cuid')
script.
  (function() {
    var cabin = new Cabin();
    cabin.setUser({
      id: '1',
      email: '[email protected]',
      full_name: 'Test'
    });
    xhook.before(function(req) {
      if (typeof req.headers !== 'object') req.headers = {};

      if (!req.headers['X-Request-Id'])
        req.headers['X-Request-Id'] = cuid();

      if (!req.headers['X-Request-Id'])
        req.headers['X-Request-Id'] = cuid();

      if (!req.headers['User-Agent'])
        req.headers['User-Agent'] = window.navigator.userAgent;

      if (!req.headers['Referer'])
        req.headers['Referer'] = window.document.referrer;

      if (!req.headers['Cookie'])
        req.headers['Cookie'] = window.document.cookie;

      cabin.info('xhr', parseRequest({ req: req }));
    });
  })();
Bundler

npm:

npm install cabin xhook cuid
const Cabin = require('cabin');
const xhook = require('xhook');
const parseRequest = require('parse-request');
const cuid = require('cuid');

const cabin = new Cabin();

cabin.setUser({
  id: '1',
  email: '[email protected]',
  full_name: 'Test'
});

xhook.before(req => {
  if (typeof req.headers !== 'object') req.headers = {};

  if (!req.headers['X-Request-Id'])
    req.headers['X-Request-Id'] = cuid();

  //
  // NOTE: you may want to add User-Agent, Referer, and Cookie (see above)
  //
  cabin.info('xhr', parseRequest({ req: req }));
});

Stack Traces and Error Handling

We leave it up to you to decide how you wish to handle stack traces and errors, but we've documented our approaches for Node and Browser environments below.

Node

If you're using Lad, then you don't need to worry about error handling, as it's built-in (complete with graceful reloading, even for database connections).

However you can otherwise use a tool such as uncaught to listen for errors, or bind purely to process events emitted as shown below:

const Cabin = require('cabin');

const cabin = new Cabin();

process.on('uncaughtException', err => {
  cabin.error(err);
  process.exit(1);
});

process.on('unhandledRejection', err => {
  cabin.error(err);
});

Browser

Since cross-browser support is very limited and non-standardized for errors and stack traces, we highly recommend to use StackTrace.

StackTrace

We recommend to use StackTrace instead of TraceKit as it is a more modern alternative and provides much similarity between your Browser and your Node errors (stackframes are basically similar to representations in Gecko and V8, aka the ones you get with Node).

It does require you to have a polyfill if you're using it in the browser (only if you're supporting browsers that don't support standardized Promises/JSON). You'll basically need es6-promise and json3 polyfills for browsers you wish to support that don't have them. The example below shows you how to polyfill, don't worry! You can reference Caniuse data on Promises and JSON respectively if you need.

The example below demonstrates using StackTrace with uncaught to catch global errors below.

<script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=Promise"></script>
<script src="https://unpkg.com/stackframe"></script>
<script src="https://unpkg.com/stacktrace-js"></script>
<script src="https://unpkg.com/uncaught"></script>
<script src="https://unpkg.com/cabin"></script>
<script src="https://unpkg.com/prepare-stack-trace"></script>

<script type="text/javascript">
  (function() {
    //
    // Sourced from the StackTrace example from CabinJS docs
    // <https://github.com/cabinjs/cabin#stacktrace>
    //
    var cabin = new Cabin();

    // Use cabin globally in your app (instead of `console`)
    window.cabin = cabin;

    // Bind event listeners
    uncaught.start();
    uncaught.addListener(function(err, event) {
      if (!err) {
        if (typeof ErrorEvent === 'function' && event instanceof ErrorEvent)
          return cabin.error(event.message, { event: event });
        cabin.error({ event: event });
        return;
      }
      // this will transform the error's `stack` property
      // to be consistently similar to Gecko and V8 stackframes
      StackTrace.fromError(err)
        .then(function(stackframes) {
          err.stack = prepareStackTrace(err, stackframes);
          cabin.error(err);
        })
        .catch(function(err2) {
          cabin.error(err);
          cabin.error(err2);
        });
    });
  })();
</script>

Options

  • logger (Object or Axe instance) - if you have a custom logger you wish to use or an existing Axe instance – defaults to an instance of Axe which uses console as the logger – if you do not pass an instance of Axe, then an instance will be created and the logger option will be passed down
  • meta (Object) - defaults to an empty object - this will get passed as metadata (e.g. you could set a custom meta.user object here for every request)
  • parseRequest (Object) - defaults to an empty object, which means it will use the defaults from parse-request (see Metadata below)
  • errorProps (Array) - a list of properties to cherry-pick from the error object parsed out of err thanks to parse-err (by default all properties are returned; even non-enumerable ones and ones on the prototype object) (see Metadata below)
  • message (Function) - inspired by morgan, and defaults to a dev-friendly format (or if in production mode, then it uses a standard Apache common log format)). – when requests finish, it will utilize logger to output an error, warn, or info level log based off the status code, and this function is used to determine the string sent to the logger. It accepts one argument options, which is comprised of options.level, options.req, options.res, and optionally (if and only if Koa) options.ctx. It is required that this function return a String. See src/message.js for the default message function. Note that both dev-friendly and Apache common log formats are stripped of basic auth lines for obvious security reasons. Note that if a null or undefined value is returned from the message function, then the logger will not be invoked unless there is an error.

Display Metadata and Stack Traces

Under the hood, Cabin uses Axe which provides us with several options, including one to show metadata (e.g. request headers, body, and user) and another to show stack traces for errors.

To show/hide application metadata and/or stack traces, see the Axe options documentation.

Cabin uses the package parse-request to parse the request metadata for you automatically in your Express and Koa applications.

Here's an example of a parsed metadata object:

{
  request: {
    method: 'POST',
    query: {
      foo: 'bar',
      beep: 'boop'
    },
    headers: {
      host: '127.0.0.1:63955',
      'accept-encoding': 'gzip, deflate',
      'user-agent': 'node-superagent/3.8.3',
      authorization: 'Basic ********************',
      accept: 'application/json',
      cookie: 'foo=bar;beep=boop',
      'content-type': 'multipart/form-data; boundary=--------------------------930511303948232291410214',
      'content-length': '1599',
      connection: 'close'
    },
    cookies: {
      foo: 'bar',
      beep: 'boop'
    },
    body: '{"product_id":"5d0350ef2ca74d11ee6e4f00","name":"nifty","surname":"lettuce","bank_account_number":"1234567890","card":{"number":"****-****-****-****"},"stripe_token":"***************","favorite_color":"green"}',
    url: '/?foo=bar&beep=boop',
    timestamp: '2019-06-14T07:46:55.568Z',
    id: 'fd6225ed-8db0-4862-8566-0c0ad6f4c7c9',
    http_version: '1.1',
    files: '{"avatar":[{"fieldname":"avatar","originalname":"avatar.png","encoding":"7bit","mimetype":"image/png","buffer":{"type":"Buffer","byteLength":216},"size":216}],"boop":[{"fieldname":"boop","originalname":"boop-1.txt","encoding":"7bit","mimetype":"text/plain","buffer":{"type":"Buffer","byteLength":7},"size":7},{"fieldname":"boop","originalname":"boop-2.txt","encoding":"7bit","mimetype":"text/plain","buffer":{"type":"Buffer","byteLength":7},"size":7}]}'
  },
  user: {
    ip_address: '::ffff:127.0.0.1'
  },
  id: '5d0350ef2ca74d11ee6e4f01',
  timestamp: '2019-06-14T07:46:55.000Z',
  duration: 6.651317
}

As you can see, sensitive data is masked and contextual user information metadata is automatically populated.

Related

  • Forward Email - Free, encrypted, and open-source email forwarding service for custom domains
  • Axe - Logging utility for Node and Browser environments. Chop up your logs!
  • Bree - The best job scheduler for Node.js
  • Lad - Scaffold a Koa webapp and API framework for Node.js
  • Lass - Scaffold a modern boilerplate for Node.js
  • koa-better-error-handler - A better error-handler for Lad and Koa. Makes ctx.throw awesome!

License

MIT © Titanism

#

cabin's People

Contributors

3imed-jaberi avatar dkayzee avatar niftylettuce avatar pkuczynski avatar titanism avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

cabin's Issues

Ability to set listPage URL as well as template.

Sorry, this may be a philosophical request or I may have missed some documentation. Figured you'd be interested since this is a newer project and the intended audience is likely designery folks (with limited designer JS abilities). Great project though, hope I can submit a theme.

What I tried to do

I wanted to put the about page at /index.html and the paginated blog at /blog.html. So I edited the Gruntfile.

    pages: {
      posts: {
        src: 'posts',
        dest: 'dist',
        layout: 'src/layouts/post.ejs',
        url: 'posts/:title/',
        options: {
          pageSrc: 'src/pages',
          data: {
            baseUrl: '/'
          },
          pagination: {
            postsPerPage: 1,
            listPage: 'src/pages/blog.ejs'
          }
        }
      }
    },

I moved index.ejs to blog.ejs and created a new index.ejs with normal, static content. Unfortunately, after running grunt it still builds the blog (correctly using blog.ejs) at index.html. I expected it to do this at /blog.html (which doesn't render) and for index.ejs to build index.html. Can replicate this using https://github.com/snide/Canvas (note, only set up for EJS).

Playing around I was able to get kind of what I wanted, but only when i specifically set listPage: about.ejs (moving the post forloop there as well) which rendered the blog at about.html and let me render index.html from index.ejs. Unfortunately, then my blog would be labeled /about :)

This could be intended. It's blog software, so you may assume index.html MUST show pagination. From looking at the grunt file output though, I just assumed it was easy to change.

Unfortunately I'm a designer, otherwise I'd look deeper into your JS, but I'm guessing there's some sort of reserved naming that needs to be used?

RSS Feed is too large

Hi,

I'm generating an RSS feed (you can see my set-up here: https://github.com/Integralist/Website and the distributed version here: https://github.com/Integralist/integralist.github.com) but I'm using Feedburner and it refuses to now update my feed (partly) because the size of the feed is too large...

Your feed filesize is larger than 512K. 
You need to reduce its size in order for FeedBurner to process it.

...this is because the feed.xml being generated includes the entire contents of my articles rather than a short description.

Is there any way to use a short description (I have one defined as meta data in each of my posts).

Add a "theme doesn't exists" error.

Found this script a while ago, seems like a nice alternative to Jekyll (node.js + grunt <3).

Anyway I just tried to create a blog and spelled wrong on the theme name. The script just hang and even ctrl+c didn't work. Had been great if I instead had got an error message like "Theme doesn't exists".

For example:

$_ cabin new blog theme-path-that-doest/exists

>> Error: the theme "theme-path-that-doest/exists" doesn't exists.

Improve invalid theme prompting

Currently, if a theme cabin.json/package.json is invalid "This theme has an invalid cabin.json" is always printed. A more specific error message would be more helpful.

Issue with rendering all the content on a long post

I've noticed that my content (5000+ words including code examples) fails to render (no errors in the terminal output). The page just stops rendering the content.

It looks like the content is being truncated because there is a set limit maybe?

Not sure what other information I can provide to be honest.

On a Mac with latest OS release and updates.

Issue when destination folder is nested

Ran the following command, forgetting to specify the destination folder:

cabin new cabinjs/canvas

The command failed as it tried to mkdir canvas inside of the cabinjs folder that didn't exist.

Do we consider this an error and warn the user that they mistyped the command or actually generate the nested folder?

XML comments not highlighting correctly

If I have some XML in a code block and put a comment after the tag, the comment isn't correctly syntax highlighted. Example:

<element attribute="value" /> <!-- attribute = value -->

It seems to correctly color it (light and italics) if I put a // inside the comment:

<element attribute="value" /> <!-- // attribute = value -->

Result:
39

Update to new major version of commander

I think it is important to stay up to date with our dependencies, so that we can utilize new features and allow contributors to use the latest APIs.

Solving this issue will require refactoring affected code to match the new commander API.

Support Windows

Cabin fails on windows while trying to delete the .git folder after cloning the theme repo.

Fail to compile Compass on first install

I install all the dependencies and run grunt which gets up past the generation of posts but then fails on "compass:dist" with a cannot load such file -- sass/script/node (LoadError) error...

/Users/markmcdonnell/.rbfu/rubies/1.9.3-p385/lib/ruby/1.9.1/rubygems/custom_require.rb:60:in `require': cannot load such file -- sass/script/node (LoadError)

...so I can't get any further with this at the moment :-(

My Ruby dependencies are...

Using chunky_png (1.2.8) 
Using fssm (0.2.10) 
Using sass (3.2.12) 
Using compass (0.12.2) 
Using bundler (1.3.5) 

Change of Ruby version means I'm unable to run Grunt task (missing compass gem)

Hey,

This isn't a direct issue with CabinJS but I'm putting this issue here in case any one can help clarify how to resolve it.

I recently downgraded my Ruby version: https://github.com/Integralist/Website/commit/016ac98319ed41da86299dfb0321ae12a4225e2c and it seems that one of the required gems (specifically compass) is unable to be located...

Running "compass:dist" (compass) task
Verifying property compass.dist exists in config...OK
File: [no files]
Options: sassDir="src/styles", cssDir="dist/styles"
/Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:118:in `require': cannot load such file -- sass/script/node (LoadError)
    from /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:118:in `rescue in require'
    from /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:124:in `require'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/gems/compass-0.12.2/lib/compass/sass_extensions/monkey_patches/browser_support.rb:1:in `<top (required)>'
    from /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:66:in `require'
    from /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:66:in `require'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/gems/compass-0.12.2/lib/compass/sass_extensions/monkey_patches.rb:2:in `block in <top (required)>'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/gems/compass-0.12.2/lib/compass/sass_extensions/monkey_patches.rb:1:in `each'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/gems/compass-0.12.2/lib/compass/sass_extensions/monkey_patches.rb:1:in `<top (required)>'
    from /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:66:in `require'
    from /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:66:in `require'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/gems/compass-0.12.2/lib/compass/sass_extensions.rb:9:in `<top (required)>'
    from /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:66:in `require'
    from /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:66:in `require'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/gems/compass-0.12.2/lib/compass.rb:5:in `block in <top (required)>'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/gems/compass-0.12.2/lib/compass.rb:4:in `each'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/gems/compass-0.12.2/lib/compass.rb:4:in `<top (required)>'
    from /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:66:in `require'
    from /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:66:in `require'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/gems/compass-0.12.2/bin/compass:20:in `block in <top (required)>'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/gems/compass-0.12.2/bin/compass:8:in `fallback_load_path'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/gems/compass-0.12.2/bin/compass:19:in `<top (required)>'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/bin/compass:23:in `load'
    from /Users/markmcdonnell/.gem/ruby/2.0.0/bin/compass:23:in `<main>'
Warning: Task "compass:dist" failed. Use --force to continue.
Error: Task "compass:dist" failed.
    at Task.<anonymous> (/Users/markmcdonnell/Google Drive/Dropbox/Library/Github/integralist (CabinJS)/Website/node_modules/grunt/lib/util/task.js:197:15)
    at null._onTimeout (/Users/markmcdonnell/Google Drive/Dropbox/Library/Github/integralist (CabinJS)/Website/node_modules/grunt/lib/util/task.js:225:33)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

Aborted due to warnings.

I've checked the paths to where the gems are installed...

❯ gem env                                                                 
RubyGems Environment:
  - RUBYGEMS VERSION: 2.0.14
  - RUBY VERSION: 2.0.0 (2013-11-22 patchlevel 353) [x86_64-darwin13.0.0]
  - INSTALLATION DIRECTORY: /Users/markmcdonnell/.gem/ruby/2.0.0
  - RUBY EXECUTABLE: /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/bin/ruby
  - EXECUTABLE DIRECTORY: /Users/markmcdonnell/.gem/ruby/2.0.0/bin
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-darwin-13
  - GEM PATHS:
     - /Users/markmcdonnell/.gem/ruby/2.0.0
     - /Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/gems/2.0.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000
  - REMOTE SOURCES:
     - https://rubygems.org/

...and it seems that they are being installed to the first path and not the second (e.g. when I ls the files I can find them in the first path and not the second).

But, the stack trace seems to suggest that it has correctly found compass when trying the first path so I'm not sure why it then tries the fallback gem path.

I've also tried installing directly to that secondary path: bundle install --path=/Users/markmcdonnell/.rubies/ruby-2.0.0-p353/lib/ruby/gems/2.0.0/gems but when I check the gems directory it doesn't show any gems installed?

Not sure what else to try

Error running Grunt (connect task is failing to be found)

Hi,

I've just discovered that running grunt I get the following error...

Running "default" task

Running "server" task
Warning: Task "connect" not found. Use --force to continue.
Error: Task "connect" not found.
    at Task.run (/Users/markmcdonnell/Box Sync/Library/Github/integralist/Website/node_modules/grunt/lib/util/task.js:171:28)
    at Object.thisTask.fn (/Users/markmcdonnell/Box Sync/Library/Github/integralist/Website/node_modules/grunt/lib/grunt/task.js:78:16)
    at Object.<anonymous> (/Users/markmcdonnell/Box Sync/Library/Github/integralist/Website/node_modules/grunt/lib/util/task.js:282:30)
    at Task.runTaskFn (/Users/markmcdonnell/Box Sync/Library/Github/integralist/Website/node_modules/grunt/lib/util/task.js:235:24)
    at Task.<anonymous> (/Users/markmcdonnell/Box Sync/Library/Github/integralist/Website/node_modules/grunt/lib/util/task.js:281:12)
    at Task.<anonymous> (/Users/markmcdonnell/Box Sync/Library/Github/integralist/Website/node_modules/grunt/lib/util/task.js:215:7)
    at Task.runTaskFn (/Users/markmcdonnell/Box Sync/Library/Github/integralist/Website/node_modules/grunt/lib/util/task.js:238:9)
    at Task.<anonymous> (/Users/markmcdonnell/Box Sync/Library/Github/integralist/Website/node_modules/grunt/lib/util/task.js:281:12)
    at Task.start (/Users/markmcdonnell/Box Sync/Library/Github/integralist/Website/node_modules/grunt/lib/util/task.js:290:5)
    at Object.grunt.tasks (/Users/markmcdonnell/Box Sync/Library/Github/integralist/Website/node_modules/grunt/lib/grunt.js:155:8)

Aborted due to warnings.

You can see my code here: https://github.com/Integralist/Website

I've already run npm install.

Modules...

❯ npm list | grep connect
├─┬ [email protected]
│ └─┬ [email protected]

Gems...

❯ gem list

*** LOCAL GEMS ***

bigdecimal (1.2.0)
bundler (1.5.2)
chunky_png (1.2.9)
compass (0.12.2)
fssm (0.2.10)
io-console (0.4.2)
json (1.7.7)
minitest (4.3.2)
psych (2.0.0)
rake (0.9.6)
rdoc (4.0.0)
sass (3.2.12)
test-unit (2.0.0.0)

Add grunt-pages to package.json

On every new setup cabin new . I'm getting

>> Local Npm module "grunt-pages" not found. Is it installed?
Warning: Task "pages" not found. Use --force to continue.

Adding grunt-pages to the devDependencies fix the issue.

Cabin 'theme' command

I think we should have a command to scaffold out a new theme. We could prompt the theme author about what template languages and CSS preprocessors they want to support and then give them everything they need to immediately start working on their templates, styles, and grunt-pages config.

grunt-usemin

Have you consider to integrate grunt-usemin into the build flow?

Add command to convert blog posts from other platforms

I have seen multiple tweets from people wanting to convert a Wordpress or Octopress site to Cabin, and I think it would be valuable to have a conversion tool to help users escape from inferior blogging platforms 👅

Complete 'generate' command

I think generate is valuable for timestamping and pre-filling the required metadata properties for a post.

Make theme repo input more flexible

Right now the cabin new command accetps user/repo as an optional parameter like so:

cabin new colinwren/Blok

It is often really convenient to just copy the enitre github url like this:

cabin new https://github.com/colinwren/Blok

Cabin should accept both formats

Validate Themes

We need to validate that the cabin.json files have a valid grunt-pages configuration(required properties and folder structure) since it needs to work with our Gruntfile template. I think if the validation fails, we should have a link to report an issue to GitHub.

Make themes node modules to use gemnasium and possibly version

I think it might be valuable to make themes node modules so that they can keep track of the Cabin and grunt-pages version they are currently supporting using gemnasium so that they can keep up to date with the evolution of the project. Additionally, I think it might be valuable to version themes rather than simply pulling the current master branch from the GitHub repo. Npm would provide a way to version the theme.

Create theme feature table

It might be cool to have a table that shows what kinds of things a particular theme supports on its gh-page or repo readme. This would give users a quick overview of what they can expect from the theme.

The Cabin repo could have a standard one that would be used across all the themes. It would look something like this:

Feature Support
Template Langs Jade, EJS
Preprocessors Sass, Less
Responsive yes
Comments yes
Post Tags no

Update Screencast on cabinjs.com

The screencast on cabinjs.com is outdated and needs to be improved. The video quality is spotty at some parts, and is using an older version of cabin. I plan on making a new one which walks the user through customizing the Candy theme and deploying it.

Improve theme discovery

The gh-pages should help users find themes by allowing them to filter themes by template lang/preprocessor support(jade/less) and theme purpose (blogging/docs).

Users should be able to see screenshots of the filtered themes as mentioned in #3 and copy a shell command that they can then run to scaffold out their project.

Example: If the user filtered by Sass and EJS there is no need to prompt them about preprocessor or template language and we can just use --Sass and --EJS options.

cabin new blog colinwren/Blok --Sass --EJS

Incorrect date

It seems that dates aren't being processed correctly. See the attached screenshot of my markdown file vs the rendered output.

incorrect-date

Normalize naming conventions

The goal of this issue is to normalize naming conventions throughout the codebase. This means changing the cabin.json spec and cli inputs to have a consistent name for a piece of information throughout the site creation process.

cabin.json property renaming

template -> templateEngine
style - > preprocessor

config.js added property naming

preprocessorGruntTask -> used when rendering the _package.json and _Gruntfile.js
templateFileExtension -> used when rendering the cabin.json

Improve Cabin logo

The Cabin logo is pretty bland with that black Cabin. @colinwren and I discussed making a cooler logo which would perhaps use the node hexagon and/or more color/imagery surrounding the cabin.

Re-write integration tests

The integration tests are not in good shape right now 😦 We need to have discrete integration tests for different types of user input and situations.

Right now we are simply checking for the existence of files instead of validating the file content so we have no idea if someone breaks the templates or not when contributing.

I am planning on tackling this in the next few days, I hope to have a PR ready sometime this weekend.

Failed to build posts.

So I did cabin new newblog and ran grunt.
It failed with this:
Running "pages:posts" (pages) task Fatal error: Cannot call method 'toString' of undefined

It builds ok if there is no code tags like javascript in the .md files.
I downloaded just grunt-page on its own to build the same file, failed again.
Maybe I am doing something wrong here. Can anyone have a look at this please?

Thanks .

Unzip doesn't work on node 0.8

After getting node 0.8 on my system, I can verify that unzip doesn't work properly. After reading some issues, I discovered that a previous patch version works with node 0.8, but the latest patch only works in newer node versions.

I am considering using a different module, but haven't found one that can plug in as a stream.

Consider adding more prompted options for cabin gruntfile generation

It might be nice to have some additional prompts when the user runs cabin new to allow for a better initial gruntfile.

Some end users might want a dev and a dist build for their site. This is annoying to do by hand each time but really easy to make a gruntfile template for.

Other things that users might want:

Coffeescript compilation, image optimization

Ignoring .svn files.

Hi, guys!
I have a problem with building Cabin JS project on my Jenkins. It runs grunt, bet gives out an fatal error:

Running "pages:posts" (pages) task
Fatal error: The metadata for the following post is formatted incorrectly: posts/.svn/all-wcprops

Is there a way to ignore .svn files from Cabin JS?

app stops working when google icon logo is clicked

Expected behavior

I should be able to add cluster from my google account

Actual behavior

I was unable to add cluster from my gmail account each time I try to ,the app stops working it force closes

How to reproduce

*Download

*Install

*Launch

*Click on add cluster

*Finally ,if you have a google account on your phone it will automatically want to use any of the google accounts you have ,so just click on the gmail app Logo
and wait for the error..

*Cabin 0.5.0
*Android 7.0 nougat

Recording of the bug

https://youtu.be/joZ2NcztWE4



Posted on Utopian.io - Rewarding Open Source Contributors

Best way to push to GitHub pages?

I'm looking to use Cabin to render my GitHub pages, but I don't know the best way to do this. I tried initing dist/ as a git repo, and push that, but ever time I run grunt it seems to blow that directory away and thus killing my repo. Do you have a recommendation on a better way to do this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.