You've already forked code_examples_server
mirror of
https://github.com/AdaCore/code_examples_server.git
synced 2026-02-12 12:45:18 -08:00
Moving structure of reader renderer to enable single page or multiple page documents. The toc gets computed on the fly by parsing the html for headers and links are added for document scroll hotlinking.
This commit is contained in:
@@ -33,7 +33,7 @@ class Command(BaseCommand):
|
||||
return
|
||||
|
||||
# Look for 'chapters.yaml'
|
||||
chapters_yaml = os.path.join(d, 'chapters.yaml')
|
||||
chapters_yaml = os.path.join(d, 'info.yaml')
|
||||
if not os.path.isfile(chapters_yaml):
|
||||
print 'There is no "chapters.yaml" in {}'.format(d)
|
||||
return
|
||||
@@ -55,5 +55,6 @@ class Command(BaseCommand):
|
||||
b = Book(description=metadata['description'],
|
||||
directory=d,
|
||||
subpath=os.path.basename(os.path.normpath(d)),
|
||||
title=metadata['title'])
|
||||
title=metadata['title'],
|
||||
author=metadata['author'])
|
||||
b.save()
|
||||
|
||||
21
compile_server/app/migrations/0004_book_author.py
Normal file
21
compile_server/app/migrations/0004_book_author.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.5 on 2018-02-20 17:13
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0003_book'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='author',
|
||||
field=models.TextField(default=''),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
@@ -65,4 +65,7 @@ class Book(models.Model):
|
||||
description = models.TextField()
|
||||
|
||||
# the title of the book
|
||||
title = models.TextField()
|
||||
title = models.TextField()
|
||||
|
||||
# the author of the book
|
||||
author = models.TextField()
|
||||
@@ -11,7 +11,7 @@ body {
|
||||
|
||||
p {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
font-size: 1.1em;
|
||||
font-size: 0.9em;
|
||||
font-weight: 300;
|
||||
line-height: 1.7em;
|
||||
color: #999;
|
||||
@@ -56,7 +56,7 @@ a, a:hover, a:focus {
|
||||
#sidebar {
|
||||
min-width: 250px;
|
||||
max-width: 250px;
|
||||
background: #7386D5;
|
||||
background: #333333;
|
||||
color: #fff;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
@@ -67,7 +67,6 @@ a, a:hover, a:focus {
|
||||
|
||||
#sidebar .sidebar-header {
|
||||
padding: 20px;
|
||||
background: #6d7fcc;
|
||||
}
|
||||
|
||||
#sidebar ul.components {
|
||||
@@ -82,7 +81,7 @@ a, a:hover, a:focus {
|
||||
|
||||
#sidebar ul li a {
|
||||
padding: 10px;
|
||||
font-size: 1.1em;
|
||||
font-size: 0.9em;
|
||||
display: block;
|
||||
}
|
||||
#sidebar ul li a:hover {
|
||||
@@ -92,7 +91,7 @@ a, a:hover, a:focus {
|
||||
|
||||
#sidebar ul li.active > a, a[aria-expanded="true"] {
|
||||
color: #fff;
|
||||
background: #6d7fcc;
|
||||
background: #777777;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +111,7 @@ a[aria-expanded="true"]::before {
|
||||
content: '\e260';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ul ul a {
|
||||
font-size: 0.9em !important;
|
||||
padding-left: 30px !important;
|
||||
@@ -140,13 +139,14 @@ a.article, a.article:hover {
|
||||
background: #6d7fcc !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* ---------------------------------------------------
|
||||
CONTENT STYLE
|
||||
----------------------------------------------------- */
|
||||
#content {
|
||||
#reader_content {
|
||||
margin: 20px;
|
||||
padding: 20px;
|
||||
min-height: 100vh;
|
||||
transition: all 0.3s;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
@media (min-width:768px){.container{width:503px}}@media (min-width:992px){.container{width:723px}}@media (min-width:1200px){.container{width:923px}}@media (min-width:1432px){.container{width:1170px}}body{padding-top:70px;min-height:200vh}.navbar-fixed-left,.navbar-fixed-right{position:fixed;top:0;width:100%;z-index:1030}@media (min-width:768px) and (min-width:768px){.navbar-fixed-left,.navbar-fixed-right{width:232px;height:100vh;border-radius:0}.navbar-fixed-left .container,.navbar-fixed-right .container{padding-right:0;padding-left:0;width:auto}.navbar-fixed-left .navbar-header,.navbar-fixed-right .navbar-header{padding-left:15px;padding-right:15px}.navbar-fixed-left .navbar-collapse,.navbar-fixed-right .navbar-collapse{padding-right:0;padding-left:0;max-height:none}.navbar-fixed-left .navbar-collapse .navbar-nav,.navbar-fixed-right .navbar-collapse .navbar-nav{float:none!important}.navbar-fixed-left .navbar-collapse .navbar-nav>li,.navbar-fixed-right .navbar-collapse .navbar-nav>li{width:100%}.navbar-fixed-left .navbar-collapse .navbar-nav>li.dropdown .dropdown-menu,.navbar-fixed-right .navbar-collapse .navbar-nav>li.dropdown .dropdown-menu{top:0}.navbar-fixed-left .navbar-collapse .navbar-nav.navbar-right,.navbar-fixed-right .navbar-collapse .navbar-nav.navbar-right{margin-right:0}}@media (min-width:768px){body{padding-top:0;padding-left:232px}.navbar-fixed-left{right:auto!important;left:0!important;border-width:0 1px 0 0!important}.navbar-fixed-left .dropdown .dropdown-menu{left:100%;right:auto;border-radius:0 3px 3px 0}.navbar-fixed-left .dropdown .dropdown-toggle .caret{border-top:4px solid transparent;border-left:4px solid;border-bottom:4px solid transparent;border-right:none}}
|
||||
110
compile_server/app/static/sidebar.css
Normal file
110
compile_server/app/static/sidebar.css
Normal file
@@ -0,0 +1,110 @@
|
||||
@media (min-width:768px) {
|
||||
.container {
|
||||
width: 503px
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width:992px) {
|
||||
.container {
|
||||
width: 723px
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width:1200px) {
|
||||
.container {
|
||||
width: 923px
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width:1432px) {
|
||||
.container {
|
||||
width: 1170px
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: 70px;
|
||||
min-height: 200vh
|
||||
}
|
||||
|
||||
.navbar-fixed-left,
|
||||
.navbar-fixed-right {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 1030;
|
||||
}
|
||||
|
||||
#toc {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#toc:hover, #toc:active, #toc:focus {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@media (min-width:768px) and (min-width:768px) {
|
||||
.navbar-fixed-left,
|
||||
.navbar-fixed-right {
|
||||
width: 232px;
|
||||
height: 100vh;
|
||||
border-radius: 0
|
||||
}
|
||||
.navbar-fixed-left .container,
|
||||
.navbar-fixed-right .container {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: auto
|
||||
}
|
||||
.navbar-fixed-left .navbar-header,
|
||||
.navbar-fixed-right .navbar-header {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px
|
||||
}
|
||||
.navbar-fixed-left .navbar-collapse,
|
||||
.navbar-fixed-right .navbar-collapse {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
max-height: none
|
||||
}
|
||||
.navbar-fixed-left .navbar-collapse .navbar-nav,
|
||||
.navbar-fixed-right .navbar-collapse .navbar-nav {
|
||||
float: none!important
|
||||
}
|
||||
.navbar-fixed-left .navbar-collapse .navbar-nav>li,
|
||||
.navbar-fixed-right .navbar-collapse .navbar-nav>li {
|
||||
width: 100%
|
||||
}
|
||||
.navbar-fixed-left .navbar-collapse .navbar-nav>li.dropdown .dropdown-menu,
|
||||
.navbar-fixed-right .navbar-collapse .navbar-nav>li.dropdown .dropdown-menu {
|
||||
top: 0
|
||||
}
|
||||
.navbar-fixed-left .navbar-collapse .navbar-nav.navbar-right,
|
||||
.navbar-fixed-right .navbar-collapse .navbar-nav.navbar-right {
|
||||
margin-right: 0
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width:768px) {
|
||||
body {
|
||||
padding-top: 0;
|
||||
padding-left: 232px
|
||||
}
|
||||
.navbar-fixed-left {
|
||||
right: auto!important;
|
||||
left: 0!important;
|
||||
border-width: 0 1px 0 0!important
|
||||
}
|
||||
.navbar-fixed-left .dropdown .dropdown-menu {
|
||||
left: 100%;
|
||||
right: auto;
|
||||
border-radius: 0 3px 3px 0
|
||||
}
|
||||
.navbar-fixed-left .dropdown .dropdown-toggle .caret {
|
||||
border-top: 4px solid transparent;
|
||||
border-left: 4px solid;
|
||||
border-bottom: 4px solid transparent;
|
||||
border-right: none
|
||||
}
|
||||
}
|
||||
@@ -1,40 +1,13 @@
|
||||
$( document ).ready(function() {
|
||||
$( '.sidebar-link' ).click(function(event) {
|
||||
var linkid = event.target.id;
|
||||
var page_number = linkid.substr(12)
|
||||
var divsearch = "#page_anchor_" + page_number;
|
||||
$(document).ready( function() {
|
||||
|
||||
if($( divsearch ).length) {
|
||||
$( 'html, body' ).animate({
|
||||
scrollTop: $( divsearch ).offset().top
|
||||
}, 500);
|
||||
}
|
||||
else {
|
||||
infinite_scroll(divsearch);
|
||||
}
|
||||
$( ".toc_link" ).click( function() {
|
||||
|
||||
var lid = $( this ).attr( 'id' );
|
||||
var hid = "#header" + lid.substr(5);
|
||||
|
||||
$( 'html, body' ).animate( {
|
||||
scrollTop: $( hid ).offset().top
|
||||
}, 800);
|
||||
});
|
||||
|
||||
function infinite_scroll(search_elem) {
|
||||
$('html, body').animate({
|
||||
scrollTop: $( document ).height()
|
||||
}, 500, function() {
|
||||
if(!$( search_elem ).length) {
|
||||
infinite_scroll(search_elem);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
var infinite = new Waypoint.Infinite({
|
||||
element: $( '.infinite-container' )[0],
|
||||
onBeforePageLoad: function () {
|
||||
$( '.loading' ).show();
|
||||
},
|
||||
onAfterPageLoad: function ($items) {
|
||||
$( '.loading' ).hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
@@ -4,15 +4,11 @@
|
||||
<head>
|
||||
<meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>Ada for the C Programmer</title>
|
||||
<title>Book Reader</title>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="{% static "navbar-fixed-left.min.css" %}" />
|
||||
<link rel="stylesheet" href="{% static "common.css" %}" />
|
||||
<link rel="stylesheet" href="{% static "book_base.css" %}" />
|
||||
|
||||
<script src="{% static "jquery-3.2.1.min.js" %}"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/jquery.waypoints.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/shortcuts/infinite.min.js"></script>
|
||||
<link rel="stylesheet" href="{% static "sidebar.css" %}" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -23,6 +19,7 @@
|
||||
|
||||
</div>
|
||||
|
||||
<script src="{% static "jquery-3.2.1.min.js" %}"></script>
|
||||
<script src="{% static "ace-builds/src/ace.js" %}" type="text/javascript" charset="utf-8"></script>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<tr class='clickable-row' data-href="{{ HTTP_HOST }}/books/{{ b.subpath }}">
|
||||
<td>{{ b.title }}</td>
|
||||
<td>{{ b.description }}</td>
|
||||
<td>{{ b.author }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@@ -33,7 +34,7 @@
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||
<script src="{% static "editors.js" %}"></script>
|
||||
<script src="{% static "sidebar.js" %}"></script>
|
||||
|
||||
<script type=""text/javascript">
|
||||
jQuery(document).ready(function($) {
|
||||
$(".clickable-row").click(function() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{% extends 'book_base.html' %}
|
||||
|
||||
{% block sidebar %}
|
||||
<nav class="navbar navbar-inverse navbar-fixed-left">
|
||||
<nav id="sidebar" class="navbar navbar-inverse navbar-fixed-left">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
@@ -14,28 +14,7 @@
|
||||
<a href="{{ HTTP_HOST }}/books/">Back to book list</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
{% for p in parts %}
|
||||
{% if forloop.counter == sel_part %}
|
||||
<li class="active">
|
||||
{% else %}
|
||||
<li>
|
||||
{% endif %}
|
||||
<a href="#partSubmenu{{ forloop.counter }}">{{ p.title }}</a>
|
||||
<ul id="partSubmenu{{ forloop.counter }}">
|
||||
{% for c in p.chapters %}
|
||||
{% if forloop.counter == sel_chapter %}
|
||||
<li class="active">
|
||||
{% else %}
|
||||
<li>
|
||||
{% endif %}
|
||||
<a id="sidebar-page{{ c.page }}" class="sidebar-link" href="#">{{ c.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div id="toc">{{ sidebar|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -1,31 +1,6 @@
|
||||
{% load markdown_filter %}
|
||||
{% load rst_filter %}
|
||||
|
||||
{% block reader %}
|
||||
|
||||
<div id="content">
|
||||
|
||||
<div class="infinite-container">
|
||||
|
||||
<div class="infinite-item">
|
||||
<div id="page_anchor_{{ chapter_obj.number }}" class="waypoint_anchor"></div>
|
||||
{% if mdcontent %}
|
||||
{{ mdcontent|markdownify|safe }}
|
||||
{% elif rstcontent %}
|
||||
{{ rstcontent|rstify|safe }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="loading" style="display: none;">
|
||||
Loading...
|
||||
</div>
|
||||
|
||||
{% if chapter_obj.has_next %}
|
||||
<a class="infinite-more-link" href="{{ HTTP_HOST }}/books/{{ book_info.subpath }}?page={{ chapter_obj.next_page_number }}">Next</a>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{{ content|safe }}
|
||||
</div>
|
||||
{% endblock%}
|
||||
@@ -5,4 +5,6 @@ register = template.Library()
|
||||
|
||||
@register.filter
|
||||
def rstify(text):
|
||||
return docutils.core.publish_parts(text, writer_name='html')['html_body']
|
||||
html = docutils.core.publish_parts(text, writer_name='html')['html_body']
|
||||
print html
|
||||
return html
|
||||
|
||||
@@ -4,14 +4,15 @@ from __future__ import unicode_literals
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
import docutils
|
||||
import markdown
|
||||
import os
|
||||
import yaml
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from django.contrib.auth.models import User, Group
|
||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||
|
||||
from django.views.decorators.clickjacking import xframe_options_exempt
|
||||
from rest_framework import viewsets, status
|
||||
@@ -119,6 +120,62 @@ def book_list(request):
|
||||
return render(request, 'book_list.html', booklist)
|
||||
|
||||
|
||||
def md_filter(text):
|
||||
return markdown.markdown(text)
|
||||
|
||||
|
||||
def rst_filter(text):
|
||||
return docutils.core.publish_parts(text, writer_name='html')['html_body']
|
||||
|
||||
|
||||
def toc_filter(htmldata):
|
||||
def append_li(ul, i, h):
|
||||
h['id'] = "header" + str(i)
|
||||
new_link_tag = toc_soup.new_tag('a', href='#')
|
||||
new_link_tag.string = h.string
|
||||
new_link_tag['class'] = "toc_link"
|
||||
new_link_tag['id'] = "hlink" + str(i)
|
||||
|
||||
new_li_tag = toc_soup.new_tag('li')
|
||||
new_li_tag.append(new_link_tag)
|
||||
ul.append(new_li_tag)
|
||||
|
||||
def append_ul(ul):
|
||||
new_ul = toc_soup.new_tag('ul')
|
||||
ul.append(new_ul)
|
||||
return new_ul
|
||||
|
||||
|
||||
prev_level = 1
|
||||
|
||||
reader_soup = BeautifulSoup(htmldata['content'], "html.parser")
|
||||
toc_soup = BeautifulSoup(htmldata['sidebar'], "html.parser")
|
||||
|
||||
current_ul = toc_soup.ul
|
||||
|
||||
headers = reader_soup.find_all(['h1', 'h2'])
|
||||
|
||||
for i, h in enumerate(headers):
|
||||
cur_level = int(h.name[1:])
|
||||
|
||||
if cur_level < prev_level:
|
||||
outer_ul = current_ul.find_parent('ul')
|
||||
if outer_ul is not None:
|
||||
prev_level = cur_level
|
||||
current_ul = outer_ul
|
||||
|
||||
elif cur_level > prev_level:
|
||||
prev_level = cur_level
|
||||
current_ul = append_ul(current_ul)
|
||||
|
||||
append_li(current_ul, i, h)
|
||||
|
||||
|
||||
htmldata['content'] = str(reader_soup)
|
||||
htmldata['sidebar'] = str(toc_soup)
|
||||
return htmldata
|
||||
|
||||
|
||||
def book_router(request, subpath):
|
||||
resources_base_path = os.path.join(settings.RESOURCES_DIR, "books")
|
||||
|
||||
@@ -132,8 +189,8 @@ def book_router(request, subpath):
|
||||
|
||||
book = serializer.data
|
||||
|
||||
# open chapters list of book
|
||||
with open(os.path.join(book['directory'], "chapters.yaml"), 'r') as f:
|
||||
# open book info
|
||||
with open(os.path.join(book['directory'], "info.yaml"), 'r') as f:
|
||||
try:
|
||||
bookdata = yaml.load(f.read())
|
||||
except:
|
||||
@@ -142,52 +199,28 @@ def book_router(request, subpath):
|
||||
return
|
||||
|
||||
# store chapters and parts list in htmldata
|
||||
htmldata = bookdata
|
||||
htmldata = {}
|
||||
htmldata['book_info'] = book
|
||||
|
||||
# strip chapters out of list into new list for prev, next references
|
||||
chapter_list = []
|
||||
for p in bookdata['parts']:
|
||||
chapter_list.extend(p['chapters'])
|
||||
htmldata['content'] = ''
|
||||
|
||||
paginator = Paginator(chapter_list, 1)
|
||||
page = request.GET.get('page', 1)
|
||||
htmldata['sidebar'] = '<ul></ul>'
|
||||
|
||||
try:
|
||||
chapter_obj = paginator.page(page)
|
||||
except PageNotAnInteger:
|
||||
# If page is not an integer, deliver first page.
|
||||
chapter_obj = paginator.page(1)
|
||||
except EmptyPage:
|
||||
# If page is out of range (e.g. 9999), deliver last page of results.
|
||||
chapter_obj = paginator.page(paginator.num_pages)
|
||||
# get list of pages from info.yaml, convert to html, and concat into string
|
||||
for page in bookdata['pages']:
|
||||
filepath = os.path.join(book['directory'], page)
|
||||
filename, file_ext = os.path.splitext(filepath)
|
||||
if os.path.isfile(filepath):
|
||||
with open(filepath, 'r') as f:
|
||||
content = f.read()
|
||||
if file_ext == '.md':
|
||||
htmldata['content'] += md_filter(content)
|
||||
elif file_ext == '.rst':
|
||||
htmldata['content'] += rst_filter(content)
|
||||
else:
|
||||
with open(os.path.join(resources_base_path, "under-construction.md")) as f:
|
||||
htmldata['content'] += md_filter(f.read())
|
||||
|
||||
htmldata['chapter_obj'] = chapter_obj
|
||||
htmldata = toc_filter(htmldata)
|
||||
|
||||
chapter = chapter_obj.object_list[0]
|
||||
|
||||
mdcontent_page = os.path.join(book['directory'],
|
||||
"pages",
|
||||
"%s.md" % (chapter["url"]))
|
||||
rstcontent_page = os.path.join(book['directory'],
|
||||
"pages",
|
||||
"%s.rst" % (chapter["url"]))
|
||||
|
||||
# check for markdown version
|
||||
if os.path.isfile(mdcontent_page):
|
||||
with open(mdcontent_page, 'r') as f:
|
||||
htmldata['mdcontent'] = f.read()
|
||||
elif os.path.isfile(rstcontent_page):
|
||||
with open(rstcontent_page, 'r') as f:
|
||||
htmldata['rstcontent'] = f.read()
|
||||
else:
|
||||
with open(os.path.join(resources_base_path,
|
||||
"under-construction.md")) as f:
|
||||
htmldata['mdcontent'] = f.read()
|
||||
|
||||
if request.is_ajax():
|
||||
template = 'readerpage.html'
|
||||
else:
|
||||
template = 'book_sidebar.html'
|
||||
|
||||
return render(request, template, htmldata)
|
||||
return render(request, 'book_sidebar.html', htmldata)
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
title: "Example Book"
|
||||
description: "This is an example book that is a placeholder."
|
||||
parts:
|
||||
- title: "Part 1"
|
||||
chapters:
|
||||
- title: "Chapter 1"
|
||||
url: "part1-chapter1"
|
||||
page: 1
|
||||
- title: "Chapter 2"
|
||||
url: "part1-chapter2"
|
||||
page: 2
|
||||
- title: "Part 2"
|
||||
chapters:
|
||||
- title: "Chapter 1"
|
||||
url: "part2-chapter1"
|
||||
page: 3
|
||||
- title: "Chapter 2"
|
||||
url: "part2-chapter2"
|
||||
page: 4
|
||||
...
|
||||
|
||||
11
resources/books/example/info.yaml
Normal file
11
resources/books/example/info.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: "Example Book"
|
||||
description: "This is an example book that is a placeholder."
|
||||
author: "Joe Schmo"
|
||||
pages:
|
||||
- "part1-chapter1.md"
|
||||
- "part1-chapter2.rst"
|
||||
- "part2-chapter1.md"
|
||||
- "part2-chapter2.rst"
|
||||
...
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Part 1 Chapter 2
|
||||
=========================
|
||||
*****************
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id massa felis. Nam eget risus sit amet ante tempor lacinia. Mauris ut nunc sem. Cras mattis, nibh quis fermentum porttitor, arcu tortor porttitor magna, ac adipiscing quam urna at lectus. Ut at dolor in elit tempor ultrices sagittis sed lacus. Nullam a lectus mauris. Pellentesque molestie, leo in auctor semper, magna sem mattis tellus, a consectetur nisl tellus volutpat quam. Etiam ultricies risus sed sapien convallis aliquet. Curabitur vehicula purus vitae justo commodo facilisis. Quisque at porta ipsum. Sed purus leo, mattis sed ultricies ac, ultricies eget lacus. Sed ac nibh est. Suspendisse sed orci nisl. Vestibulum ultrices metus sapien, sed interdum nunc. In arcu neque, sollicitudin ut porta eu, viverra at elit. Nam accumsan condimentum metus nec accumsan. Nunc porta consectetur nisi in ornare. Vestibulum tempor mollis dui quis luctus. Aliquam dolor enim, tristique a blandit eu, auctor ut odio.
|
||||
|
||||
Test
|
||||
~~~~
|
||||
======
|
||||
|
||||
This is a test of inserting code blocks in the RST
|
||||
|
||||
Reference in New Issue
Block a user