Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Math support #369

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ To customize Grip, create `~/.grip/settings.py`, then add one or more of the fol
- `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
- `MATH_JAX_URL`: URL used for loading the MathJax library. `https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-chtml.min.js` 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
Expand Down Expand Up @@ -316,7 +317,7 @@ Runs a local server and renders the Readme file located
at `path` when visited in the browser.

```python
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)
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, render_math=False, api_url=None, math_jax_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
Expand All @@ -330,7 +331,9 @@ serve(path=None, host=None, port=None, user_content=False, context=None, usernam
- `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
- `render_math`: Whether to render mathematical equations with MathJax, `False` 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.
- `math_jax_url`: A different URL for loading the MathJax library.
- `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
Expand All @@ -342,7 +345,7 @@ serve(path=None, host=None, port=None, user_content=False, context=None, usernam
Writes the specified Readme file to an HTML file with styles and assets inlined.

```python
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, grip_class=None)
export(path=None, user_content=False, context=None, username=None, password=None, render_offline=False, render_wide=False, render_inline=True, render_math=False, out_filename=None, api_url=None, math_jax_url=None, title=None, quiet=None, grip_class=None)
```

- `path`: The filename to render, or the directory containing your Readme file, defaulting to the current working directory
Expand All @@ -354,8 +357,10 @@ export(path=None, user_content=False, context=None, username=None, password=None
- `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`)
- `render_math`: Whether to render mathematical equations with MathJax, `False` by default
- `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.
- `math_jax_url`: A different URL for loading the MathJax library.
- `title`: The page title, derived from `path` by default
- `quiet`: Do not print to the terminal
- `grip_class`: Use a custom [Grip class](#class-gripflask)
Expand All @@ -368,7 +373,7 @@ This is the same app used by `serve` and `export` and initializes the cache,
using the cached styles when available.

```python
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)
create_app(path=None, user_content=False, context=None, username=None, password=None, render_offline=False, render_wide=False, render_inline=False, render_math=False, api_url=None, math_jax_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
Expand All @@ -380,7 +385,9 @@ create_app(path=None, user_content=False, context=None, username=None, password=
- `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
- `render_math`: Whether to render mathematical equations with MathJax, `False` 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.
- `math_jax_url`: A different URL for loading the MathJax library.
- `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](#class-gripflask)
Expand Down Expand Up @@ -424,7 +431,7 @@ Renders the markdown from the specified path or text, without caching,
and returns an HTML page that resembles the GitHub Readme view.

```python
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, grip_class=None)
render_page(path=None, user_content=False, context=None, username=None, password=None, render_offline=False, render_wide=False, render_inline=False, render_math=False, api_url=None, math_jax_url=None, title=None, text=None, quiet=None, grip_class=None)
```

- `path`: The path to use for the page title, rendering `'README.md'` if None
Expand All @@ -436,7 +443,9 @@ render_page(path=None, user_content=False, context=None, username=None, password
- `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
- `render_math`: Whether to render mathematical equations with MathJax, `False` 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.
- `math_jax_url`: A different URL for loading the MathJax library.
- `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
Expand Down Expand Up @@ -470,7 +479,7 @@ main(argv=None, force_utf8=True)
A Flask application that can serve a file or directory containing a README.

```python
Grip(source=None, auth=None, renderer=None, assets=None, render_wide=None, render_inline=None, title=None, autorefresh=None, quiet=None, grip_url=None, static_url_path=None, instance_path=None, **kwargs)
Grip(source=None, auth=None, renderer=None, assets=None, render_wide=None, render_inline=None, render_math=None, math_jax_url=None, title=None, autorefresh=None, quiet=None, grip_url=None, static_url_path=None, instance_path=None, **kwargs)
```

##### default_renderer
Expand Down Expand Up @@ -705,6 +714,14 @@ The default app_url value:
DEFAULT_API_URL = 'https://api.github.com'
```

#### DEFAULT_MATH_JAX_URL

The default math\_jax\_url value:

```python
DEFAULT_MATH_JAX_URL = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-chtml.min.js'
```


Testing
-------
Expand Down
36 changes: 19 additions & 17 deletions grip/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@

def 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,
autorefresh=None, quiet=None, grip_class=None):
render_inline=False, render_math=False, api_url=None,
math_jax_url=None, title=None, text=None, autorefresh=None,
quiet=None, grip_class=None):
"""
Creates a Grip application with the specified overrides.
"""
Expand Down Expand Up @@ -43,20 +44,20 @@ def create_app(path=None, user_content=False, context=None, username=None,

# Create the customized app with default asset manager
return grip_class(source, auth, renderer, None, render_wide,
render_inline, title, autorefresh, quiet)
render_inline, render_math, math_jax_url, title, autorefresh, quiet)


def 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, quiet=None, grip_class=None):
username=None, password=None, render_offline=False, render_wide=False,
render_inline=False, render_math=False, api_url=None, math_jax_url=None,
title=None, autorefresh=True, browser=False, quiet=None, grip_class=None):
"""
Starts a server to render the specified file or directory containing
a README.
"""
app = create_app(path, user_content, context, username, password,
render_offline, render_wide, render_inline, api_url,
title, None, autorefresh, quiet, grip_class)
render_offline, render_wide, render_inline, render_math,
api_url, math_jax_url, title, None, autorefresh, quiet, grip_class)
app.run(host, port, open_browser=browser)


Expand All @@ -72,18 +73,18 @@ def clear_cache(grip_class=None):
def 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,
grip_class=None):
render_math=False, api_url=None, math_jax_url=None, title=None, text=None,
quiet=None, grip_class=None):
"""
Renders the specified markup text to an HTML page and returns it.
"""
return create_app(path, user_content, context, username, password,
render_offline, render_wide, render_inline, api_url,
title, text, False, quiet, grip_class).render()
render_offline, render_wide, render_inline, render_math,
api_url, math_jax_url, title, text, False, quiet, grip_class).render()


def render_content(text, user_content=False, context=None, username=None,
password=None, render_offline=False, api_url=None):
password=None, render_offline=False, api_url=None, math_jax_url=None):
"""
Renders the specified markup and returns the result.
"""
Expand All @@ -96,8 +97,9 @@ def render_content(text, user_content=False, context=None, username=None,

def 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=False, grip_class=None):
render_wide=False, render_inline=True, render_math=False,
out_filename=None, api_url=None, math_jax_url=None, title=None, quiet=False,
grip_class=None):
"""
Exports the rendered HTML to a file.
"""
Expand All @@ -114,8 +116,8 @@ def export(path=None, user_content=False, context=None,
print('Exporting to', out_filename, file=sys.stderr)

page = render_page(path, user_content, context, username, password,
render_offline, render_wide, render_inline, api_url,
title, None, quiet, grip_class)
render_offline, render_wide, render_inline, render_math,
api_url, math_jax_url, title, None, quiet, grip_class)

if export_to_stdout:
try:
Expand Down
52 changes: 46 additions & 6 deletions grip/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
from .assets import GitHubAssetManager, ReadmeAssetManager
from .browser import start_browser_when_ready
from .constants import (
DEFAULT_GRIPHOME, DEFAULT_GRIPURL, STYLE_ASSET_URLS_INLINE_FORMAT)
DEFAULT_GRIPHOME, DEFAULT_GRIPURL, STYLE_ASSET_URLS_INLINE_FORMAT,
DEFAULT_MATH_JAX_URL)
from .exceptions import AlreadyRunningError, ReadmeNotFoundError
from .readers import DirectoryReader
from .renderers import GitHubRenderer, ReadmeRenderer
Expand All @@ -41,17 +42,19 @@ class Grip(Flask):
A Flask application that can serve the specified file or directory
containing a README.
"""
def __init__(self, source=None, auth=None, renderer=None,
assets=None, render_wide=None, render_inline=None, title=None,
autorefresh=None, quiet=None, grip_url=None,
static_url_path=None, instance_path=None, **kwargs):
def __init__(self, source=None, auth=None, renderer=None, assets=None,
render_wide=None, render_inline=None, render_math=None,
math_jax_url = None, title=None, autorefresh=None, quiet=None,
grip_url=None, static_url_path=None, instance_path=None, **kwargs):
# Defaults
if source is None or isinstance(source, str_type):
source = DirectoryReader(source)
if render_wide is None:
render_wide = False
if render_inline is None:
render_inline = False
if render_math is None:
render_math = False

# Defaults from ENV
if grip_url is None:
Expand Down Expand Up @@ -82,6 +85,12 @@ def __init__(self, source=None, auth=None, renderer=None,
if ex.errno != errno.ENOTDIR:
raise

if math_jax_url is None:
math_jax_url = self.config['MATH_JAX_URL']
if math_jax_url is None:
math_jax_url = DEFAULT_MATH_JAX_URL
self.math_jax_url = math_jax_url

# Defaults from settings
if autorefresh is None:
autorefresh = self.config['AUTOREFRESH']
Expand All @@ -104,6 +113,7 @@ def __init__(self, source=None, auth=None, renderer=None,
self.renderer = renderer
self.assets = assets
self.render_wide = render_wide
self.render_math = render_math
self.render_inline = render_inline
self.title = title
self.quiet = quiet
Expand Down Expand Up @@ -141,7 +151,11 @@ def __init__(self, source=None, auth=None, renderer=None,

# Initialize views
self._styles_retrieved = False
self._scripts_retrieved = False
self.before_request(self._retrieve_styles)
if self.renderer.user_content and self.render_math:
self.before_request(self._retrieve_assets)
self.render_math = False
self.add_url_rule(asset_route, 'asset', self._render_asset)
self.add_url_rule(asset_subpath, 'asset', self._render_asset)
self.add_url_rule('/', 'render', self._render_page)
Expand Down Expand Up @@ -217,7 +231,9 @@ def _render_page(self, subpath=None):
title=self.title, content=content, favicon=favicon,
user_content=self.renderer.user_content,
wide_style=self.render_wide, style_urls=self.assets.style_urls,
styles=self.assets.styles, autorefresh_url=autorefresh_url)
styles=self.assets.styles, autorefresh_url=autorefresh_url,
render_math=self.render_math, math_jax_url=self.math_jax_url,
script_urls=self.assets.script_urls)

def _render_refresh(self, subpath=None):
if not self.autorefresh:
Expand Down Expand Up @@ -351,6 +367,30 @@ def _retrieve_styles(self):
if self.render_inline:
self._inline_styles()

def _retrieve_assets(self):
"""
Retrieves the scripts URLs from the source and caches them. This
is called before the first request is dispatched.
"""
asset_url_path = url_for('asset')
if (request.path.startswith(asset_url_path) and
request.path.endswith(".js") or request.path.endswith(".woff")):
path_start_index = len(request.url_root)+len(asset_url_path)-1
self.assets.cache_asset(request.url[path_start_index:])

if self._scripts_retrieved:
return
self._scripts_retrieved = True

try:
self.assets.retrieve_scripts(url_for('asset'))
except Exception as ex:
if self.debug:
print(format_exc(), file=sys.stderr)
else:
print(' * Error: could not retrieve scripts:', ex,
file=sys.stderr)

def default_renderer(self):
"""
Returns the default renderer using the current config.
Expand Down
Loading