Code Monkey home page Code Monkey logo

grip's Introduction

Grip -- GitHub Readme Instant Preview

Current version on PyPI Say Thanks!

Render local readme files before sending off to GitHub.

Grip is a command-line server application written in Python that uses the GitHub markdown API to render a local readme file. The styles and rendering come directly from GitHub, so you'll know exactly how it will appear. Changes you make to the Readme will be instantly reflected in the browser without requiring a page refresh.

Motivation

Sometimes you just want to see the exact readme result before committing and pushing to GitHub.

Especially when doing Readme-driven development.

Installation

To install grip, simply:

$ pip install grip

On OS X, you can also install with Homebrew:

$ brew install grip

Usage

To render the readme of a repository:

$ cd myrepo
$ grip
 * Running on http://localhost:6419/

Now open a browser and visit http://localhost:6419. Or run with -b and Grip will open a new browser tab for you.

You can also specify a port:

$ grip 80
 * Running on http://localhost:80/

Or an explicit file:

$ grip AUTHORS.md
 * Running on http://localhost:6419/

Alternatively, you could just run grip and visit localhost:6419/AUTHORS.md since grip supports relative URLs.

You can combine the previous examples. Or specify a hostname instead of a port. Or provide both.

$ grip AUTHORS.md 80
 * Running on http://localhost:80/
$ grip CHANGES.md 0.0.0.0
 * Running on http://0.0.0.0:6419/
$ grip . 0.0.0.0:80
 * Running on http://0.0.0.0:80/

You can even bypass the server and export to a single HTML file, with all the styles and assets inlined:

$ grip --export
Exporting to README.html

Control the output name with the second argument:

$ grip README.md --export index.html
Exporting to index.html

If you're exporting a bunch of files, you can prevent styles from being inlining to save space with --no-inline:

$ grip README.md --export --no-inline introduction.html
Exporting to introduction.html

Reading and writing from stdin and stdout is also supported, allowing you to use Grip with other programs:

$ cat README.md | grip -
 * Running on http://localhost:6419/
$ grip AUTHORS.md --export - | bcat
$ cat README.md | grip --export - | less

This allows you to quickly test how things look by entering Markdown directly in your terminal:

$ grip -
Hello **world**!
^D
 * Running on http://localhost:6419/

Note: ^D means Ctrl+D, which works on Linux and OS X. On Windows you'll have to use Ctrl+Z.

Rendering as user-content like comments and issues is also supported, with an optional repository context for linking to issues:

$ grip --user-content --context=joeyespo/grip
 * Running on http://localhost:6419/

For more details and additional options, see the help:

$ grip -h

Access

Grip strives to be as close to GitHub as possible. To accomplish this, grip uses GitHub's Markdown API so that changes to their rendering engine are reflected immediately without requiring you to upgrade grip. However, because of this you may hit the API's hourly rate limit. If this happens, grip offers a way to access the API using your credentials to unlock a much higher rate limit.

$ grip --user <your-username> --pass <your-password>

Or use a personal access token with an empty scope (note that a token is required if your GitHub account is set up with two-factor authentication):

$ grip --pass <token>

You can persist these options in your local configuration. For security purposes, it's highly recommended that you use an access token over a password. (You could also keep your password safe by configuring Grip to grab your password from a password manager.)

There's also a work-in-progress branch to provide offline rendering. Once this resembles GitHub more precisely, it'll be exposed in the CLI, and will ultimately be used as a seamless fallback engine for when the API can't be accessed.

Grip always accesses GitHub over HTTPS, so your README and credentials are protected.

Tips

Here's how others from the community are using Grip.

Want to share your own? Say hello @joeyespo or submit a pull request.

Create a local mirror of a Github Wiki

$ git clone https://github.com/YOUR_USERNAME/YOUR_REPOSITORY.wiki.git
$ cd YOUR_REPOSITORY.wiki
$ grip

By Joshua Gourneau.

Generate HTML documentation from a collection of linked README files

  1. Enter the directory:

    $ cd YOUR_DIR
    $ export GRIPURL=$(pwd)
  2. Include all assets by setting the CACHE_DIRECTORY config variable:

    $ echo "CACHE_DIRECTORY = '$(pwd)/assets'" >> ~/.grip/settings.py
  3. Export all your Markdown files with Grip and replace absolute asset paths with relative paths:

    $ for f in *.md; do grip --export $f --no-inline; done
    $ for f in *.html; do sed -i '' "s?$GRIPURL/??g" $f; done

You can optionally compress the set of HTML files to docs.tgz with:

$ tar -czvf docs.tgz `ls | grep [\.]html$` assets

Looking for a cross platform solution? Here's an equivalent Python script.

By Matthew R. Tanudjaja.

Configuration

To customize Grip, create ~/.grip/settings.py, then add one or more of the following variables:

  • HOST: The host to use when not provided as a CLI argument, localhost by default
  • PORT: The port to use when not provided as a CLI argument, 6419 by default
  • DEBUG: Whether to use Flask's debugger when an error happens, False by default
  • DEBUG_GRIP: Prints extended information when an error happens, False by default
  • API_URL: Base URL for the github API, for example that of a Github Enterprise instance. https://api.github.com by default
  • CACHE_DIRECTORY: The directory, relative to ~/.grip, to place cached assets (this gets run through the following filter: CACHE_DIRECTORY.format(version=__version__)), 'cache-{version}' by default
  • AUTOREFRESH: Whether to automatically refresh the Readme content when the file changes, True by default
  • QUIET: Do not print extended information, False by default
  • STYLE_URLS: Additional URLs that will be added to the rendered page, [] by default
  • USERNAME: The username to use when not provided as a CLI argument, None by default
  • PASSWORD: The password or personal access token to use when not provided as a CLI argument (Please don't save your passwords here. Instead, use an access token or drop in this code grab your password from a password manager), None by default

Note that this is a Python file. If you see 'X' is not defined errors, you may have overlooked some quotes. For example:

USERNAME = 'your-username'
PASSWORD = 'your-personal-access-token'

Environment variables

  • GRIPHOME: Specify an alternative settings.py location, ~/.grip by default
  • GRIPURL: The URL of the Grip server, /__/grip by default

Advanced

This file is a normal Python script, so you can add more advanced configuration.

For example, to read a setting from the environment and provide a default value when it's not set:

PORT = os.environ.get('GRIP_PORT', 8080)

API

You can access the API directly with Python, using it in your own projects:

from grip import serve

serve(port=8080)
 * Running on http://localhost:8080/

Run main directly:

from grip import main

main(argv=['-b', '8080'])
 * Running on http://localhost:8080/

Or access the underlying Flask application for even more flexibility:

from grip import create_app

grip_app = create_app(user_content=True)
# Use in your own app

Documentation

serve

Runs a local server and renders the Readme file located at path when visited in the browser.

serve(path=None, host=None, port=None, user_content=False, context=None, username=None, password=None, render_offline=False, render_wide=False, render_inline=False, api_url=None, title=None, autorefresh=True, browser=False, grip_class=None)
  • path: The filename to render, or the directory containing your Readme file, defaulting to the current working directory
  • host: The host to listen on, defaulting to the HOST configuration variable
  • port: The port to listen on, defaulting to the PORT configuration variable
  • user_content: Whether to render a document as user-content like user comments or issues
  • context: The project context to use when user_content is true, which takes the form of username/project
  • username: The user to authenticate with GitHub to extend the API limit
  • password: The password to authenticate with GitHub to extend the API limit
  • render_offline: Whether to render locally using Python-Markdown (Note: this is a work in progress)
  • render_wide: Whether to render a wide page, False by default (this has no effect when used with user_content)
  • render_inline: Whether to inline the styles within the HTML file
  • api_url: A different base URL for the github API, for example that of a Github Enterprise instance. The default is the public API https://api.github.com.
  • title: The page title, derived from path by default
  • autorefresh: Automatically update the rendered content when the Readme file changes, True by default
  • browser: Open a tab in the browser after the server starts., False by default
  • grip_class: Use a custom Grip class

export

Writes the specified Readme file to an HTML file with styles and assets inlined.

export(path=None, user_content=False, context=None, username=None, password=None, render_offline=False, render_wide=False, render_inline=True, out_filename=None, api_url=None, title=None, quiet=None, theme='light', grip_class=None)
  • path: The filename to render, or the directory containing your Readme file, defaulting to the current working directory
  • user_content: Whether to render a document as user-content like user comments or issues
  • context: The project context to use when user_content is true, which takes the form of username/project
  • username: The user to authenticate with GitHub to extend the API limit
  • password: The password to authenticate with GitHub to extend the API limit
  • render_offline: Whether to render locally using Python-Markdown (Note: this is a work in progress)
  • render_wide: Whether to render a wide page, False by default (this has no effect when used with user_content)
  • render_inline: Whether to inline the styles within the HTML file (Note: unlike the other API functions, this defaults to True)
  • out_filename: The filename to write to, <in_filename>.html by default
  • api_url: A different base URL for the github API, for example that of a Github Enterprise instance. The default is the public API https://api.github.com.
  • title: The page title, derived from path by default
  • quiet: Do not print to the terminal
  • theme: Theme to view markdown file (light mode or dark mode). Valid options ("light", "dark"). Default: "light".
  • grip_class: Use a custom Grip class

create_app

Creates a Flask application you can use to render and serve the Readme files. This is the same app used by serve and export and initializes the cache, using the cached styles when available.

create_app(path=None, user_content=False, context=None, username=None, password=None, render_offline=False, render_wide=False, render_inline=False, api_url=None, title=None, text=None, grip_class=None)
  • path: The filename to render, or the directory containing your Readme file, defaulting to the current working directory
  • user_content: Whether to render a document as user-content like user comments or issues
  • context: The project context to use when user_content is true, which takes the form of username/project
  • username: The user to authenticate with GitHub to extend the API limit
  • password: The password to authenticate with GitHub to extend the API limit
  • render_offline: Whether to render locally using Python-Markdown (Note: this is a work in progress)
  • render_wide: Whether to render a wide page, False by default (this has no effect when used with user_content)
  • render_inline: Whether to inline the styles within the HTML file
  • api_url: A different base URL for the github API, for example that of a Github Enterprise instance. The default is the public API https://api.github.com.
  • title: The page title, derived from path by default
  • text: A string or stream of Markdown text to render instead of being loaded from path (Note: path can be used to set the page title)
  • grip_class: Use a custom Grip class

render_app

Renders the application created by create_app and returns the HTML that would normally appear when visiting that route.

render_app(app, route='/')
  • app: The Flask application to render
  • route: The route to render, '/' by default

render_content

Renders the specified markdown text without caching.

render_content(text, user_content=False, context=None, username=None, password=None, render_offline=False, api_url=None, title=None)
  • text: The Markdown text to render
  • user_content: Whether to render a document as user-content like user comments or issues
  • context: The project context to use when user_content is true, which takes the form of username/project
  • username: The user to authenticate with GitHub to extend the API limit
  • password: The password to authenticate with GitHub to extend the API limit
  • render_offline: Whether to render locally using Python-Markdown (Note: this is a work in progress)
  • api_url: A different base URL for the github API, for example that of a Github Enterprise instance. This is required when not using the offline renderer.
  • title: The page title, derived from path by default

render_page

Renders the markdown from the specified path or text, without caching, and returns an HTML page that resembles the GitHub Readme view.

render_page(path=None, user_content=False, context=None, username=None, password=None, render_offline=False, render_wide=False, render_inline=False, api_url=None, title=None, text=None, quiet=None, theme='light', grip_class=None)
  • path: The path to use for the page title, rendering 'README.md' if None
  • user_content: Whether to render a document as user-content like user comments or issues
  • context: The project context to use when user_content is true, which takes the form of username/project
  • username: The user to authenticate with GitHub to extend the API limit
  • password: The password to authenticate with GitHub to extend the API limit
  • render_offline: Whether to render offline using Python-Markdown (Note: this is a work in progress)
  • render_wide: Whether to render a wide page, False by default (this has no effect when used with user_content)
  • render_inline: Whether to inline the styles within the HTML file
  • api_url: A different base URL for the github API, for example that of a Github Enterprise instance. The default is the public API https://api.github.com.
  • title: The page title, derived from path by default
  • text: A string or stream of Markdown text to render instead of being loaded from path (Note: path can be used to set the page title)
  • quiet: Do not print to the terminal
  • theme: Theme to view markdown file (light mode or dark mode). Valid options ("light", "dark"). Default: "light".
  • grip_class: Use a custom Grip class

clear_cache

Clears the cached styles and assets.

clear_cache(grip_class=None)

main

Runs Grip with the specified arguments.

main(argv=None, force_utf8=True)
  • argv: The arguments to run with, sys.argv[1:] by default
  • force_utf8: Sets the default encoding to utf-8 in the current Python instance. This has no effect on Python 3 since Unicode is handled by default

Classes

class Grip(Flask)

A Flask application that can serve a file or directory containing a README.

Grip(source=None, auth=None, renderer=None, assets=None, render_wide=None, render_inline=None, title=None, autorefresh=None, quiet=None, theme='light', grip_url=None, static_url_path=None, instance_path=None, **kwargs)
default_renderer

Returns the default renderer using the current config. This is only used if renderer is set to None in the constructor.

Grip.default_renderer()
default_asset_manager

Returns the default asset manager using the current config. This is only used if asset_manager is set to None in the constructor.

Grip.default_asset_manager()
add_content_types

Adds the application/x-font-woff and application/octet-stream content types if they are missing. Override to add additional content types on initialization.

Grip.add_content_types()
clear_cache

Clears the downloaded assets.

Grip.clear_cache()
render

Renders the application and returns the HTML unicode that would normally appear when visiting in the browser.

Grip.render(route=None)
  • route: The route to render, / by default
run

Starts a server to render the README. This calls Flask.run internally.

Grip.run(host=None, port=None, debug=None, use_reloader=None, open_browser=False)
  • host: The hostname to listen on. Set this to '0.0.0.0' to have the server available externally as well, 'localhost' by default
  • port: The port of the webserver. Defaults to 6419
  • debug: If given, enable or disable debug mode. See Flask.debug.
  • use_reloader: Should the server automatically restart the python process if modules were changed? False by default unless the DEBUG_GRIP setting is specified.
  • open_browser: Opens the browser to the address when the server starts

class AlreadyRunningError(RuntimeError)

Raised when Grip.run is called while the server is already running.

AlreadyRunningError()

class ReadmeNotFoundError(NotFoundError or IOError)

Raised when the specified Readme could not be found.

ReadmeNotFoundError(path=None, message=None)

class ReadmeAssetManager(object)

Manages the style and font assets rendered with Readme pages. This is an abstract base class.

ReadmeAssetManager(cache_path, style_urls=None)

class GitHubAssetManager(ReadmeAssetManager)

Manages the style and font assets rendered with Readme pages. Set cache_path to None to disable caching.

class ReadmeReader(object)

Reads Readme content from a URL subpath. This is an abstract base class.

ReadmeReader()

class DirectoryReader(ReadmeReader)

Reads Readme files from URL subpaths.

DirectoryReader(path=None, silent=False)

class TextReader(ReadmeReader)

Reads Readme content from the provided unicode string.

TextReader(text, display_filename=None)

class StdinReader(TextReader)

Reads Readme text from STDIN.

StdinReader(display_filename=None)

class ReadmeRenderer(object)

Renders the Readme. This is an abstract base class.

ReadmeRenderer(user_content=None, context=None)

class GitHubRenderer(ReadmeRenderer)

Renders the specified Readme using the GitHub Markdown API.

GitHubRenderer(user_content=None, context=None, api_url=None, raw=None)

class OfflineRenderer(ReadmeRenderer)

Renders the specified Readme locally using pure Python. Note: This is currently an incomplete feature.

OfflineRenderer(user_content=None, context=None)

Constants

SUPPORTED_TITLES

The common Markdown file titles on GitHub.

SUPPORTED_TITLES = ['README', 'Home']
  • filename: The UTF-8 file to read.

SUPPORTED_EXTENSIONS

The supported extensions, as defined by GitHub.

SUPPORTED_EXTENSIONS = ['.md', '.markdown']

DEFAULT_FILENAMES

This constant contains the names Grip looks for when no file is provided.

DEFAULT_FILENAMES = [title + ext
                     for title in SUPPORTED_TITLES
                     for ext in SUPPORTED_EXTENSIONS]

DEFAULT_FILENAME

This constant contains the default Readme filename, namely:

DEFAULT_FILENAME = DEFAULT_FILENAMES[0]  # README.md

DEFAULT_GRIPHOME

This constant points to the default value if the GRIPHOME environment variable is not specified.

DEFAULT_GRIPHOME = '~/.grip'

DEFAULT_GRIPURL

The default URL of the Grip server and all its assets:

DEFAULT_GRIPURL = '/__/grip'

DEFAULT_API_URL

The default app_url value:

DEFAULT_API_URL = 'https://api.github.com'

Testing

Install the package and test requirements:

$ pip install -e .[tests]

Run tests with pytest:

$ pytest

Or to re-run tests as you make changes, use pytest-watch:

$ ptw

External assumption tests

If you're experiencing a problem with Grip, it's likely that an assumption made about the GitHub API has been broken. To verify this, run:

$ pytest -m assumption

Since the external assumptions rely on an internet connection, you may want to skip them when developing locally. Tighten the cycle even further by stopping on the first failure with -x:

$ pytest -xm "not assumption"

Or with pytest-watch:

$ ptw -- -xm "not assumption"

Contributing

  1. Check the open issues or open a new issue to start a discussion around your feature idea or the bug you found
  2. Fork the repository and make your changes
  3. Open a new pull request

If your PR has been waiting a while, feel free to ping me on Twitter.

Use this software often? Say Thanks! 😃

grip's People

Contributors

4ndrej avatar alexandre-mbm avatar anhtumai avatar briancappello avatar bsdlp avatar courajs avatar d13r avatar davisjam avatar erikmhummel avatar godron629 avatar hydhknn avatar init-js avatar isbadawi avatar joelittlejohn avatar joeyespo avatar jwilk avatar kagof avatar kba avatar kindrowboat avatar markbt avatar mekod4 avatar mrexmelle avatar phyllisstein avatar ssundarraj avatar svisser avatar swsnider avatar synapticarbors avatar tomdlt avatar vladwing avatar xx7y7xx 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  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

grip's Issues

Add static directory with help

In regards to #25, the explanation about how to add custom styles is kind of long. Instead, let's create a /static directory to save a step, and add a README to it, explaining how to add custom styles.

[ ] is not supported

I just found that "[ ]" and "[x]" aren't supported.
e.g.

 - [ ] To-do
 - [x] Done

preview:

  • To-do
  • Done

GFM Link problems

It seems the inline links do not work as on github. Example:

### Defined Type: patterndb::update
[update](#defined-type-patterndbupdate)

Exporting rendered HTML to a specific folder using Command Line

Hello,

First of all thanks for such a great repo, very useful!

I am trying to export rendered HTML files to another location but I can't get it working with Command Line. I've readed carefully the readme and I understand that this is possible by specifying out_filename argument.

If I do a Python Script, it works:

#!/usr/bin/env python
from grip import export
export(path='/Foo/Bar/Home.md',out_filename='/Bar/Foo/Home.html')

But If I try with Command Line (in Mac), does not works:

grip --export '/Foo/Bar/Home.md' --out_filename '/Bar/Foo/Home.html'

Thanks!

requirements.txt should have >= versions

It's annoying to fill my virtual environment with exactly some random version, setup.py and requirements.txt should specify dependencies either with no version at all or with >= version number.

Add option to clear the cached styles

Every now and then, GitHub will release a new version of their styles. Currently the only way to clear the cache is to delete or empty the instance directory. There should be a CLI option and API call to do this.

Export to a specific file

The --export option allows exporting Readme files to a single HTML page. Currently, it uses the filename of the input file, but with an .html extension. This should be extended to specify an output file.

Some thoughts

  1. When --export is used, the server isn't run, so the optional <address> argument will be unused. We could have the second argument specify a directory or file to write to in this case.
  2. We could also just have an optional --export=<filename> variation if docopt supports it.

shutdown grip server

Is it possible to shutdown the grip server in the CLI? If not, would it be hard to add this feature?

https issue behind proxy

I've found out that with my works proxy I have issues talking to the https sites grip uses to download from github.

This has been fixed in more recent versions of requests (kennethreitz/requests#1571). I've upgraded to requests==2.1.0 and everything seems to work now so requirements.txt may want to be updated (I'm not sure if there are any potential side effects).

Display images

Hi,

Fantastic little thing ! 👍

It would be nice if it could display images too :)

Grip 2.0 returns 404 when fetching assets

Hey, thanks for Grip, it's great.
I've just moved to Grip 2.0 and got a low priority issue: looks like Grip can't access some of the assets (the 404 errors appear when I hover any title, while trying to render the left "link" icon I suppose).

anto@/doc$ pip freeze -l | grep grip
grip==2.0.0
anto@
/doc$ grip .

127.0.0.1 - - [06/Mar/2014 15:34:36] "GET /SOMEDOC.md HTTP/1.1" 200 -
127.0.0.1 - - [06/Mar/2014 15:34:38] "GET /assets/octicons-deafceee79ffdf46d4a0a2f8a14e1d51ceb507f4.woff HTTP/1.1" 404 -
127.0.0.1 - - [06/Mar/2014 15:34:38] "GET /assets/octicons-f95c8eef34c8eff1cb8667dde633facbbeeeb54c.ttf HTTP/1.1" 404 -
127.0.0.1 - - [06/Mar/2014 15:34:38] "GET /assets/octicons-66ee11e13c4fa39c6db51f395309f82a03355a66.svg HTTP/1.1" 404 -

Thanks again, keep up the great work !

Fix the location of local_config.py

Initially, local_config.py was useful for using the package locally pip install -e . and excluding the file from setup.py.

This makes it hard to override the default config when installed normally. Instead, the app should look in the same directory for this file and setup.py should merely ignore it.

![ScreenShot](screenshot.png?raw=true)

alexandre$ grip --gfm
 * Running on http://localhost:5000/
127.0.0.1 - - [02/Apr/2014 22:19:18] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [02/Apr/2014 22:19:19] "GET /screenshot.png?raw=true HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1701, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1689, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1687, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1360, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1358, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1344, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/lib/python2.7/dist-packages/grip/server.py", line 59, in render
    return render_page(text, filename, gfm, context, app.config['STYLE_URLS'])
  File "/usr/local/lib/python2.7/dist-packages/grip/renderer.py", line 37, in render_page
    return index_template.render(content=render_content(text, gfm, context), filename=filename, style_urls=style_urls)
  File "/usr/local/lib/python2.7/dist-packages/grip/renderer.py", line 26, in render_content
    data = json.dumps(data)
  File "/usr/share/pyshared/simplejson/__init__.py", line 286, in dumps
    return _default_encoder.encode(obj)
  File "/usr/share/pyshared/simplejson/encoder.py", line 226, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/share/pyshared/simplejson/encoder.py", line 296, in iterencode
    return _iterencode(o, 0)
UnicodeDecodeError: 'utf8' codec can't decode byte 0x89 in position 0: invalid start byte
127.0.0.1 - - [02/Apr/2014 22:19:19] "GET /screenshot.png?raw=true HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1701, in __call__

See /alexandre-mbm/osm/blob/ubuntu+i18n/README.md.

Generate files in a directory & create a table of contents

Recently, I want to generate a book written in md. It contains several files saved in one directroy.

So I wonder whether it's possible to add a feature to generate files in a directory and generate a table of contents as well?

Is there a feature like this? Developing or not , I hope I could contribute to that.

Python 3 support

Currently, Grip has SyntaxErrors on Python 3 and also depends on Flask which fails to install on Python 3. It would be nice if Grip installed and ran on Python 3.

Convert files to html

Hi,

I was wondering if it is possible to use this as a converter? Add some option to output the generated html files to a specified folder.

Is this supported?

Cheers!

Store GitHub credentials in a configuration file

I'm running grip --export from the command line, and the result is an HTML file composed of 403 Forbidden. Could a ~/.grip.conf file contain the username and GitHub API token?

See #48 Clarify 403 API "rate limit exceeded" errors in the application

Installation from PyPI is broken

$ mkvirtualenv grip
$ pip install grip
Downloading/unpacking grip
  Running setup.py egg_info for package grip
    Traceback (most recent call last):
      File "<string>", line 14, in <module>
      File "/Users/eric/.virtualenvs/grip/build/grip/setup.py", line 3, in <module>
        import grip as package
      File "grip/__init__.py", line 25, in <module>
        import command
      File "grip/command.py", line 2, in <module>
        from .server import serve
      File "grip/server.py", line 2, in <module>
        import requests
    ImportError: No module named requests
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):

  File "<string>", line 14, in <module>

  File "/Users/eric/.virtualenvs/grip/build/grip/setup.py", line 3, in <module>

    import grip as package

  File "grip/__init__.py", line 25, in <module>

    import command

  File "grip/command.py", line 2, in <module>

    from .server import serve

  File "grip/server.py", line 2, in <module>

    import requests

ImportError: No module named requests

setup.py loads the grip package to obtain various metadata but fails as requests hasn't been installed yet.

Auto-reload

So happy I found this tool - have been using Marked, but it doesn't give an accurate representation of GFM. Thanks!

Anyway, as I was working on my README with the browser next to me, was thinking it would be awesome to have it watch the file for changes, then auto-refresh the browser. Would you accept a PR if I worked on this?

Complete the offline renderer

The --render-offline didn't make the 2.0 release, because it doesn't render the same content as GitHub.

The functionality is there. The CLI option is added back again in the fix-render-offline branch, where work can continue.

Add a favicon

Since there's currently no favicon when run locally, it shows the last project's icon which can be misleading when you have many tabs open.

Any ideas on what it should look like?

tests

very much needed.

404 when trying to grab octicons

127.0.0.1 - - [30/Apr/2014 01:09:21] "GET /assets/octicons-a87554e18586f5215a57fa67c9421a3e088aeafa.woff HTTP/1.1" 404 -
127.0.0.1 - - [30/Apr/2014 01:09:21] "GET /assets/octicons-1a9fcfe5c5246787653e20667b04f5fd666e8884.ttf HTTP/1.1" 404 -
127.0.0.1 - - [30/Apr/2014 01:09:21] "GET /assets/octicons-7f259d1a5d695e9278da60392acbee4b51e8a3ec.svg HTTP/1.1" 404 -

API rate exceeded

When trying to run grip on a document just now, my browser displayed the following instead of the selected document:

Forbidden

API rate limit exceeded for 131.111.84.194. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)

In fact, the source code of the document served is:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>403 Forbidden</title>
<h1>Forbidden</h1>
<p>API rate limit exceeded for 131.111.84.194[truncated]</p>

Is grip running afoul of the Github GFM API limits? Would it be possible to avoid using the Github API (I’d prefer running grip offline anway, but that’s another feature request)? (Ah, I see there’s already an issue for that)

Images not appearing

My README has an embedded image that exists in that same directory, though the image isn't being served.

![screenshot](screenshot.png)

The simple solution might be to have it serve all files from the directory of the Markdown file that was loaded, so that relative URIs (at least in that directory or below) will work.

Version 2.0.0 fails to read default configuration

Running Linux Mint / Python 2.7.4, output of the command grip:

Traceback (most recent call last):
  File "/usr/local/bin/grip", line 9, in <module>
    load_entry_point('grip==2.0.0', 'console_scripts', 'grip')()
  File "/usr/local/lib/python2.6/dist-packages/grip/command.py", line 66, in main
    args['--user'], args['--pass'], False)
  File "/usr/local/lib/python2.6/dist-packages/grip/server.py", line 102, in serve
    app = create_app(path, gfm, context, username, password, render_offline)
  File "/usr/local/lib/python2.6/dist-packages/grip/server.py", line 26, in create_app
    app.config.from_pyfile('settings.py')
  File "/usr/local/lib/python2.6/dist-packages/flask/config.py", line 129, in from_pyfile
    exec(compile(config_file.read(), filename, 'exec'), d.__dict__)
  File "/usr/local/lib/python2.6/dist-packages/grip/settings.py", line 6
    """
       ^
SyntaxError: invalid syntax

Seemed to be fixed by manually removing Windows line endings from the file.

Clarify 403 API "rate limit exceeded" errors in the application

This has come up several times (e.g. #15, #18, #45) and causes people to come here looking for answers.

Instead, Grip should handle this error inside the application. It can either provide instructions on how to run using --user / --pass or even better, a login form to accept the credentials without requiring a restart.

Add authentication to increase GitHub API limit

GitHub imposes a limit of 60 unauthenticated requests per hour. This is really easy to hit when using grip, especially if you're doing other things using the API at the same time. Once your reach this limit, grip no longer functions (you see an error message about rate limiting when you try to render a page).

I'd like to add options to grip to specify GitHub username and password so that grip can perform Basic auth in renderer.py. This bumps the limit to 5000 requests/hour which should be enough for anyone :)

Any thoughts on this change?

I guess I see these being new command line options.

Default port in use

The default port of grip – 5000 – is already in use on my OS X 10.9. When accessing http://localhost:5000, I get a text response, saying

ERROR: Another instance is running

(I get this whenever accessing the address, regardless of whether grip is running.)

It would be good if grip used a different default port, or had a configurable port. At the moment, settings are only read from settings.py and settings_local.py. Having them read from $HOME/.griprc (say) would help.

Links to section headers don't work

The anchor name of a section header such as ## Table 1 has a prefix of user-content- such as user-content-table-1, and so a link to #table-1 doesn't work.

For example, ## Table 1 becomes:

<a name="user-content-table-1" class="anchor" href="#table-1"><span class="octicon octicon-link"></span></a>Table 1</h2>

GitHub does the same thing, but the links on GitHub work, probably due to some magic GitHub script.

Need an internet connection to work

Hey,

is this a "feature" that grip does not work offline?
Browsing the issues I saw some mention of github API in issue #18, which might explain.
I must say that often, I find myself in the public transports without internet and each time I expect grip to run since it renders local content with a local server, and I get disappointed :)

Cheers
Greg

Development setup

Mind adding instructions to the README about how to run the package from the checked-out directory? Thanks!

screen shot 2013-09-26 at 4 08 18 pm

ConnectionError hitting /markdown/raw

Traceback (most recent call last):
  File "/Users/whit537/grip/lib/python2.7/site-packages/flask/app.py", line 1701, in __call__
    return self.wsgi_app(environ, start_response)
  File "/Users/whit537/grip/lib/python2.7/site-packages/flask/app.py", line 1689, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/Users/whit537/grip/lib/python2.7/site-packages/flask/app.py", line 1687, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/whit537/grip/lib/python2.7/site-packages/flask/app.py", line 1360, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/whit537/grip/lib/python2.7/site-packages/flask/app.py", line 1358, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/whit537/grip/lib/python2.7/site-packages/flask/app.py", line 1344, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/whit537/grip/grip/grip/server.py", line 59, in render
    return render_page(text, filename, gfm, context, app.config['STYLE_URLS'])
  File "/Users/whit537/grip/grip/grip/renderer.py", line 37, in render_page
    return index_template.render(content=render_content(text, gfm, context), filename=filename, style_urls=style_urls)
  File "/Users/whit537/grip/grip/grip/renderer.py", line 31, in render_content
    r = requests.post(url, headers=headers, data=data)
  File "/Users/whit537/grip/lib/python2.7/site-packages/requests/api.py", line 98, in post
    return request('post', url, data=data, **kwargs)
  File "/Users/whit537/grip/lib/python2.7/site-packages/requests/safe_mode.py", line 39, in wrapped
    return function(method, url, **kwargs)
  File "/Users/whit537/grip/lib/python2.7/site-packages/requests/api.py", line 51, in request
    return session.request(method=method, url=url, **kwargs)
  File "/Users/whit537/grip/lib/python2.7/site-packages/requests/sessions.py", line 252, in request
    r.send(prefetch=prefetch)
  File "/Users/whit537/grip/lib/python2.7/site-packages/requests/models.py", line 628, in send
    raise ConnectionError(e)
ConnectionError: HTTPSConnectionPool(host='api.github.com', port=443): Max retries exceeded with url: /markdown/raw

Default settings try to use /usr/var as the cache path

This folder is non-existent on Linux Mint 15, Debian 7, and CentOS 7. Prehaps /tmp, ~/.grip or ~/.cache might be better default paths?

Traceback (most recent call last):
  File "/usr/local/bin/grip", line 9, in <module>
    load_entry_point('grip==2.0.0', 'console_scripts', 'grip')()
  File "/usr/local/lib/python2.6/dist-packages/grip/command.py", line 66, in main
    args['--user'], args['--pass'], False)
  File "/usr/local/lib/python2.6/dist-packages/grip/server.py", line 102, in serve
    app = create_app(path, gfm, context, username, password, render_offline)
  File "/usr/local/lib/python2.6/dist-packages/grip/server.py", line 34, in create_app
    os.makedirs(style_cache_path)
  File "/usr/lib/python2.6/os.py", line 150, in makedirs
    makedirs(head, mode)
  File "/usr/lib/python2.6/os.py", line 150, in makedirs
    makedirs(head, mode)
  File "/usr/lib/python2.6/os.py", line 157, in makedirs
    mkdir(name, mode)
OSError: [Errno 13] Permission denied: '/usr/var'

Unexpected paragraphs in lists items are messing their margin up

When using lists (any type of lists), once you introduce a paragraph inside one of the list items (by any mean: explicitly making a new paragraph or introducing a blockquote which will wrap the rest of the list item's text in a paragraph), all the following list items will be wrapped in paragraphs. You'll see it clearly in the attached screenshot.

Also, these paragraphs have a margin-top property that makes the lists look dirty once there are paragraphs inside. In the screenshot, from the Item 3, every Item have a margin-top: 15px applied, while the previous elements don't.

padding-trouble

If you'd like to test on your side, here's the source:

    * Item #1
    * Item #2  
      With a newline inside.
    * Item #3
      
      With another paragraph inside.
    * Item #4
    * Item #5

    Can also be reproduced in numbered lists and with blockquotes.

    1. Item #6
    2. Item #7
    3. Item #8
      
      > With  blockquote inside.
    4. Item #9

While I'm here, thanks a lot for Grip. It's great tool and I'm using it daily to render MD, making my doc reading sessions much more comfy !

Print Style

When printing the border is unnecessary and there is a lot of extra white space from the margin/padding. I've added a few extra css print rules to take care of these issues and will be submitting a pull request for your consideration.

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.