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
Removing books interface.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,8 @@
|
||||
*.pyc
|
||||
db.sqlite3
|
||||
|
||||
env
|
||||
|
||||
|
||||
.DS_Store
|
||||
.idea
|
||||
|
||||
@@ -35,11 +35,6 @@ To enter many examples in the database where the examples are listed in a yaml f
|
||||
./manage.py fill_examples --conf=resources/test_conf.yaml
|
||||
```
|
||||
|
||||
To enter some books in the database, do this:
|
||||
```sh
|
||||
./manage.py fill_books --dir=resources/books/example
|
||||
```
|
||||
|
||||
To launch the server, do this:
|
||||
```sh
|
||||
./manage.py runserver
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
# The manage.py command to enter books in the database.
|
||||
# This is meant to be used by the administrators of the project only.
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from django.core.management.base import BaseCommand
|
||||
|
||||
from compile_server.app.models import Book
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('--remove_all', const=True, default=False,
|
||||
action='store_const',
|
||||
help='remove all books from the database')
|
||||
|
||||
parser.add_argument('--dir', nargs=1, type=str,
|
||||
help='add the book found in the given dir')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
||||
if options.get('remove_all', False):
|
||||
# Remove all books from the database
|
||||
Book.objects.all().delete()
|
||||
|
||||
if options.get('dir', None):
|
||||
d = os.path.abspath(options.get('dir')[0])
|
||||
|
||||
# Consider directory as the book
|
||||
if not os.path.isdir(d):
|
||||
print "{} is not a valid directory".format(d)
|
||||
return
|
||||
|
||||
# Look for '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
|
||||
|
||||
# Check contents of chapters.yaml
|
||||
with open(chapters_yaml, 'rb') as f:
|
||||
try:
|
||||
metadata = yaml.load(f.read())
|
||||
except:
|
||||
print format_traceback
|
||||
print 'Could not decode yaml in {}'.format(chapters_yaml)
|
||||
return
|
||||
for field in ['title', 'description']:
|
||||
if field not in metadata:
|
||||
print 'chapters.yaml should contain a field {}'.format(
|
||||
field)
|
||||
return
|
||||
|
||||
b = Book(description=metadata['description'],
|
||||
directory=d,
|
||||
subpath=os.path.basename(os.path.normpath(d)),
|
||||
title=metadata['title'],
|
||||
author=metadata['author'])
|
||||
b.save()
|
||||
18
compile_server/app/migrations/0005_delete_book.py
Normal file
18
compile_server/app/migrations/0005_delete_book.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.5 on 2018-04-20 14:56
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('app', '0004_book_author'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='Book',
|
||||
),
|
||||
]
|
||||
@@ -48,24 +48,3 @@ class Example(models.Model):
|
||||
|
||||
# An example is a contains a set of resources
|
||||
resources = models.ManyToManyField(Resource)
|
||||
|
||||
|
||||
class Book(models.Model):
|
||||
""" The represents a book """
|
||||
|
||||
# the directory in relation to resources/books
|
||||
# that has the resources for this book
|
||||
directory = models.TextField()
|
||||
|
||||
# This is the name of the book formatted as a url subdomain
|
||||
# This is be the same name of the folder where the book lives under resources
|
||||
subpath = models.TextField()
|
||||
|
||||
# A description of the book
|
||||
description = models.TextField()
|
||||
|
||||
# the title of the book
|
||||
title = models.TextField()
|
||||
|
||||
# the author of the book
|
||||
author = models.TextField()
|
||||
@@ -1,6 +1,6 @@
|
||||
from django.contrib.auth.models import User, Group
|
||||
from rest_framework import serializers
|
||||
from compile_server.app.models import Resource, Example, Book
|
||||
from compile_server.app.models import Resource, Example
|
||||
|
||||
|
||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||
@@ -38,8 +38,3 @@ class ExampleSerializer(serializers.ModelSerializer):
|
||||
model = Example
|
||||
fields = ('name', 'description', 'main')
|
||||
|
||||
|
||||
class BookSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Book
|
||||
fields = ('title', 'description', 'directory', 'subpath')
|
||||
|
||||
1
compile_server/app/static/.gitignore
vendored
1
compile_server/app/static/.gitignore
vendored
@@ -0,0 +1 @@
|
||||
ace-builds
|
||||
@@ -1,291 +0,0 @@
|
||||
body {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.pure-img-responsive {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
Add transition to containers so they can push in and out.
|
||||
*/
|
||||
|
||||
#wrapper,
|
||||
#sidebar,
|
||||
.menu-link {
|
||||
-webkit-transition: all 0.2s ease-out;
|
||||
-moz-transition: all 0.2s ease-out;
|
||||
-ms-transition: all 0.2s ease-out;
|
||||
-o-transition: all 0.2s ease-out;
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
|
||||
/*
|
||||
This is the parent `<div>` that contains the menu and the content area.
|
||||
*/
|
||||
|
||||
#wrapper {
|
||||
position: relative;
|
||||
left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#wrapper.active #sidebar {
|
||||
left: 300px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#wrapper.active .menu-link {
|
||||
left: 300px;
|
||||
}
|
||||
|
||||
/*
|
||||
The content `<div>` is where all your content goes.
|
||||
*/
|
||||
|
||||
#main {
|
||||
margin: 0 0 0 330px;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 0 auto;
|
||||
padding: 0 2em;
|
||||
max-width: 800px;
|
||||
margin-bottom: 50px;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin: 0;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
padding: 2.5em 2em 0;
|
||||
border-bottom: 1.5px solid #eee;
|
||||
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
|
||||
background: white;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
margin: 0.2em 0;
|
||||
font-size: 3em;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.header h2 {
|
||||
font-weight: 300;
|
||||
color: #ccc;
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.content-subhead {
|
||||
margin: 50px 0 20px 0;
|
||||
font-weight: 300;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
The `#sidebar` `<div>` is the parent `<div>` that contains the `.pure-menu` that
|
||||
appears on the left side of the page.
|
||||
*/
|
||||
|
||||
#sidebar {
|
||||
margin-left: -300px;
|
||||
/* "#sidebar" width */
|
||||
width: 300px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
/* so the menu or its navicon stays above all content */
|
||||
background: #191818;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/*
|
||||
All anchors inside the menu should be styled like this.
|
||||
*/
|
||||
|
||||
#sidebar a {
|
||||
color: #999;
|
||||
border: none;
|
||||
padding: 0.6em 0.6em 0.6em 0.6em;
|
||||
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
/*
|
||||
Remove all background/borders, since we are applying them to #sidebar.
|
||||
*/
|
||||
|
||||
#sidebar .pure-menu,
|
||||
#sidebar .pure-menu ul {
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
/*
|
||||
Add that light border to separate items into groups.
|
||||
*/
|
||||
|
||||
#sidebar .pure-menu ul,
|
||||
#sidebar .pure-menu .menu-item-divided {
|
||||
border-top: 1px solid #333;
|
||||
}
|
||||
|
||||
#sidebar ul ul {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
/*
|
||||
Change color of the anchor links on hover/focus.
|
||||
*/
|
||||
|
||||
#sidebar .pure-menu li a:hover,
|
||||
#sidebar .pure-menu li a:focus {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
/*
|
||||
This styles the selected menu item `<li>`.
|
||||
*/
|
||||
|
||||
#sidebar .pure-menu-selected,
|
||||
#sidebar .pure-menu-heading {
|
||||
background: #1f8dd6;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/*
|
||||
This styles a link within a selected menu item `<li>`.
|
||||
*/
|
||||
|
||||
#sidebar .pure-menu-selected a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/*
|
||||
This styles the menu heading.
|
||||
*/
|
||||
|
||||
#sidebar .pure-menu-heading {
|
||||
font-size: 110%;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* -- Dynamic Button For Responsive Menu -------------------------------------*/
|
||||
|
||||
/*
|
||||
The button to open/close the Menu is custom-made and not part of Pure. Here's
|
||||
how it works:
|
||||
*/
|
||||
|
||||
/*
|
||||
`.menu-link` represents the responsive menu toggle that shows/hides on
|
||||
small screens.
|
||||
*/
|
||||
|
||||
.menu-link {
|
||||
position: fixed;
|
||||
display: block;
|
||||
/* show this only on small screens */
|
||||
top: 0;
|
||||
left: 0;
|
||||
/* "#sidebar width" */
|
||||
background: #000;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
font-size: 10px;
|
||||
/* change this value to increase/decrease button size */
|
||||
z-index: 10;
|
||||
width: 2em;
|
||||
height: auto;
|
||||
padding: 2.1em 1.6em;
|
||||
}
|
||||
|
||||
.menu-link:hover,
|
||||
.menu-link:focus {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.menu-link span {
|
||||
position: relative;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.menu-link span,
|
||||
.menu-link span:before,
|
||||
.menu-link span:after {
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
height: 0.2em;
|
||||
}
|
||||
|
||||
.menu-link span:before,
|
||||
.menu-link span:after {
|
||||
position: absolute;
|
||||
margin-top: -0.6em;
|
||||
content: " ";
|
||||
}
|
||||
|
||||
.menu-link span:after {
|
||||
margin-top: 0.6em;
|
||||
}
|
||||
|
||||
|
||||
/* -- Responsive Styles (Media Queries) ------------------------------------- */
|
||||
|
||||
/*
|
||||
Hides the menu at `48em`, but modify this based on your app's needs.
|
||||
*/
|
||||
|
||||
@media (min-width: 1165px) {
|
||||
|
||||
.header,
|
||||
.content {
|
||||
padding-left: 2em;
|
||||
padding-right: 2em;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
padding-left: 150px;
|
||||
/* left col width "#sidebar" */
|
||||
left: 0;
|
||||
}
|
||||
#sidebar {
|
||||
left: 300px;
|
||||
}
|
||||
|
||||
.menu-link {
|
||||
position: fixed;
|
||||
left: 300px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wrapper.active .menu-link {
|
||||
left: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1165px) {
|
||||
/* Only apply this when the window is small. Otherwise, the following
|
||||
case results in extra padding on the left:
|
||||
* Make the window small.
|
||||
* Tap the menu to trigger the active state.
|
||||
* Make the window large again.
|
||||
*/
|
||||
#wrapper.active {
|
||||
position: relative;
|
||||
left: 300px;
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
$( document ).ready( function() {
|
||||
$( document ).on( "scroll", onScroll);
|
||||
|
||||
$( ".toc-link" ).click( function(e) {
|
||||
|
||||
var hid = lid2hid( $( this ).attr( 'id' ) );
|
||||
var div_position = $( hid ).offset().top;
|
||||
var padding = 12;
|
||||
var header_offset = $( "#title_header" ).outerHeight();
|
||||
|
||||
$( 'html, body' ).animate( {
|
||||
scrollTop: (div_position - header_offset - padding)
|
||||
}, 800);
|
||||
|
||||
if ( $( "#sidebar" ).hasClass( 'active' ) )
|
||||
toggleAll(e);
|
||||
});
|
||||
|
||||
$( "#sidebarLink" ).click( toggleAll );
|
||||
$( "#main" ).click( function(e) {
|
||||
if ( $( "#sidebar" ).hasClass( 'active' ) )
|
||||
toggleAll(e);
|
||||
});
|
||||
|
||||
onScroll();
|
||||
|
||||
});
|
||||
|
||||
function lid2hid(lid) {
|
||||
return "#header" + lid.substr(5);
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
var active = "pure-menu-selected"
|
||||
|
||||
$( '#toc a' ).each( function () {
|
||||
var refElement = $( lid2hid( $( this ).attr( 'id' ) ) );
|
||||
var currLink = $( this );
|
||||
|
||||
if ( inView( refElement) ) {
|
||||
$( '#toc ul li a' ).removeClass( active );
|
||||
currLink.addClass( active );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function inView(elem) {
|
||||
var viewport = {};
|
||||
viewport.top = $( window ).scrollTop();
|
||||
viewport.bottom = viewport.top + $( window ).height();
|
||||
|
||||
var bounds = {};
|
||||
bounds.top = $( elem ).offset().top;
|
||||
bounds.bottom = bounds.top + $( elem ).outerHeight();
|
||||
|
||||
return ((bounds.top <= viewport.bottom) && (bounds.bottom >= viewport.top));
|
||||
}
|
||||
|
||||
function toggleAll(e) {
|
||||
var active = 'active';
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
$( "#wrapper" ).toggleClass( active );
|
||||
$( "#sidebar" ).toggleClass( active );
|
||||
$( "#sidebarLink" ).toggleClass( active );
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<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>Book Reader</title>
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/purecss@1.0.0/build/pure-min.css" integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous">
|
||||
|
||||
<link rel="stylesheet" href="{% static "common.css" %}" />
|
||||
<link rel="stylesheet" href="{% static "book_base.css" %}" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="wrapper">
|
||||
{% block reader %}{% endblock %}
|
||||
</div>
|
||||
|
||||
<script src="http://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="{% static "ace-builds/src/ace.js" %}" type="text/javascript" charset="utf-8"></script>
|
||||
|
||||
<script src="{% static "editors.js" %}"></script>
|
||||
<script src="{% static "sidebar.js" %}"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,48 +0,0 @@
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<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>AdaCore Books</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 "book_base.css" %}" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="content">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>AdaCore Books</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for b in books %}
|
||||
<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>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<script src="{% static "ace-builds/src/ace.js" %}" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{% static "jquery-3.2.1.min.js" %}"></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>
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||
<script src="{% static "editors.js" %}"></script>
|
||||
|
||||
<script type=""text/javascript">
|
||||
jQuery(document).ready(function($) {
|
||||
$(".clickable-row").click(function() {
|
||||
window.location = $(this).data("href");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,23 +0,0 @@
|
||||
{% extends 'book_base.html' %} {% block reader %}
|
||||
|
||||
<!-- Menu toggle -->
|
||||
<a href="#sidebar" id="sidebarLink" class="menu-link">
|
||||
<!-- Hamburger icon -->
|
||||
<span></span>
|
||||
</a>
|
||||
|
||||
<div id="sidebar">
|
||||
<div class="pure-menu">
|
||||
<div id="toc">{{ sidebar|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="main">
|
||||
<div id="title_header" class="header">
|
||||
<h1>{{ book_info.title }}</h1>
|
||||
<h2><a href="{{ HTTP_HOST }}/books/">Back to book list</a></h2>
|
||||
</div>
|
||||
<div id="content" class="content">{{ content|safe }}</div>
|
||||
</div>
|
||||
|
||||
{% endblock%}
|
||||
@@ -1,8 +0,0 @@
|
||||
from django import template
|
||||
import markdown
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@register.filter
|
||||
def markdownify(text):
|
||||
return markdown.markdown(text)
|
||||
@@ -1,10 +0,0 @@
|
||||
from django import template
|
||||
import docutils
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@register.filter
|
||||
def rstify(text):
|
||||
html = docutils.core.publish_parts(text, writer_name='html')['html_body']
|
||||
print html
|
||||
return html
|
||||
@@ -4,11 +4,6 @@ from __future__ import unicode_literals
|
||||
from django.shortcuts import render
|
||||
|
||||
# Create your views here.
|
||||
from bs4 import BeautifulSoup
|
||||
from docutils import core
|
||||
import markdown
|
||||
import os
|
||||
import yaml
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
@@ -21,10 +16,9 @@ from rest_framework.response import Response
|
||||
from compile_server.app.serializers import (UserSerializer,
|
||||
GroupSerializer,
|
||||
ResourceSerializer,
|
||||
ExampleSerializer,
|
||||
BookSerializer)
|
||||
ExampleSerializer)
|
||||
|
||||
from compile_server.app.models import Resource, Example, Book
|
||||
from compile_server.app.models import Resource, Example
|
||||
|
||||
|
||||
class UserViewSet(viewsets.ModelViewSet):
|
||||
@@ -113,118 +107,3 @@ def code_embed(request, example_name):
|
||||
def examples_list(request):
|
||||
context = {'examples': Example.objects.all}
|
||||
return render(request, 'examples_list.html', context)
|
||||
|
||||
|
||||
def book_list(request):
|
||||
booklist = {'books': Book.objects.all}
|
||||
return render(request, 'book_list.html', booklist)
|
||||
|
||||
|
||||
def md_filter(text):
|
||||
return markdown.markdown(text)
|
||||
|
||||
|
||||
def rst_filter(text):
|
||||
parts = core.publish_parts(text, writer_name='html')
|
||||
return parts['body_pre_docinfo'] + parts['fragment']
|
||||
|
||||
|
||||
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 pure-menu-link"
|
||||
new_link_tag['id'] = "hlink" + str(i)
|
||||
|
||||
new_li_tag = toc_soup.new_tag('li')
|
||||
new_li_tag['class'] = "pure-menu-item"
|
||||
new_li_tag.append(new_link_tag)
|
||||
ul.append(new_li_tag)
|
||||
|
||||
def append_ul(ul):
|
||||
new_ul = toc_soup.new_tag('ul')
|
||||
new_ul['class'] = "pure-menu-list"
|
||||
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")
|
||||
|
||||
matches = Book.objects.filter(subpath=subpath)
|
||||
if not matches:
|
||||
booklist = {'books': Book.object.all}
|
||||
return render(request, 'book_list.html', booklist)
|
||||
|
||||
bk = matches[0]
|
||||
serializer = BookSerializer(bk)
|
||||
|
||||
book = serializer.data
|
||||
|
||||
# open book info
|
||||
with open(os.path.join(book['directory'], "info.yaml"), 'r') as f:
|
||||
try:
|
||||
bookdata = yaml.load(f.read())
|
||||
except:
|
||||
print format_traceback
|
||||
print 'Could not decode yaml in {}'.format(book['directory'])
|
||||
return
|
||||
|
||||
# store chapters and parts list in htmldata
|
||||
htmldata = {}
|
||||
htmldata['book_info'] = book
|
||||
|
||||
htmldata['content'] = ''
|
||||
|
||||
htmldata['sidebar'] = '<ul class="pure-menu-list"></ul>'
|
||||
|
||||
# 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 = toc_filter(htmldata)
|
||||
|
||||
return render(request, 'readerpage.html', htmldata)
|
||||
|
||||
@@ -55,12 +55,6 @@ urlpatterns = [
|
||||
# Get a list of all the examples
|
||||
url(r'^examples_list/', views.examples_list),
|
||||
|
||||
# URL router for Books
|
||||
url(r'^books/(.+)', views.book_router),
|
||||
|
||||
# URL router for Book landing
|
||||
url(r'^books', views.book_list),
|
||||
|
||||
# The landing page
|
||||
url(r'', views.examples_list),
|
||||
]
|
||||
|
||||
@@ -54,16 +54,3 @@ for a in $list; do ./manage.py fill_examples --dir=resources/Compile_And_Prove_D
|
||||
|
||||
./manage.py fill_examples --remove_all
|
||||
./manage.py fill_exmaples --conf=resources/test_conf.yaml
|
||||
|
||||
################
|
||||
# Import books #
|
||||
################
|
||||
|
||||
# TODO: add a facility to do this
|
||||
|
||||
# Setup:
|
||||
cd resources/books ; git clone https://github.com/Robert-Tice/Ada_For_The_CPP_Java_Developer.git ; git clone https://github.com/Robert-Tice/Ada_for_the_C_Programmer_Book.git
|
||||
|
||||
./manage.py fill_books --remove_all
|
||||
list="Ada_for_the_C_Programmer_Book Ada_For_The_CPP_Java_Developer"
|
||||
for a in $list; do ./manage.py fill_books --dir=resources/books/$a ; done
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
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"
|
||||
- "part2-chapter1.rst"
|
||||
...
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
Part 1 Chapter 1
|
||||
=========================
|
||||
|
||||
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 Editor
|
||||
------------
|
||||
This is a test of inserting code blocks in the markdown
|
||||
|
||||
<div example_editor="Hello world runnable example" inline="true">
|
||||
<div class="resource" region="editable_1">
|
||||
Put_Line ("Hello, World Editable 1");
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div example_editor="Hello world runnable example" inline="true" readonly="true">
|
||||
<div class="resource" region="editable_1">
|
||||
for I in 1 .. 10 loop
|
||||
Put_Line ("Hello, World " & I'Img);
|
||||
end loop;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Fusce molestie commodo nisi, bibendum dictum purus vehicula vel. Nulla mattis lobortis ipsum ac ornare. Integer sed erat vel mauris volutpat sodales nec auctor nulla. Aliquam ac adipiscing erat. Aliquam erat volutpat. Aenean fringilla congue odio non mattis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Quisque porta vehicula diam, et placerat eros iaculis et. Cras nec ante ipsum, eu cursus sem. Suspendisse nec orci neque, ac egestas sapien.
|
||||
|
||||
Pellentesque augue neque, bibendum eu elementum non, aliquam non nunc. Sed eget dolor vel nibh tincidunt viverra. Pellentesque elementum magna id dolor sodales ut feugiat ligula volutpat. Proin ultricies, quam id viverra dictum, velit nulla varius eros, fringilla vestibulum felis arcu at felis. Vivamus neque metus, gravida non dictum vehicula, pulvinar a tortor. In tristique ullamcorper diam vel ultrices. Nam lobortis lectus eget tortor ullamcorper et suscipit sapien placerat. Cras urna neque, laoreet at dictum vel, elementum sed dolor. Duis sem eros, tincidunt quis venenatis in, facilisis non dolor. Phasellus leo diam, semper in tempus et, tempor vel sapien. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
|
||||
|
||||
Mauris et eros erat, elementum iaculis velit. Donec nec quam felis, sed consequat velit. Nam dolor velit, bibendum vitae convallis id, semper sit amet diam. Integer auctor ultrices metus luctus mattis. Nulla sagittis suscipit arcu, et consequat ipsum dignissim eu. Nulla laoreet libero eget erat fermentum id porttitor odio blandit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nullam eget nunc eget tortor pretium sodales. Curabitur dapibus tristique lorem nec dignissim. Nullam pretium laoreet arcu ut semper. Nam ac risus et lacus auctor tempor. Curabitur bibendum, est tristique fermentum mattis, quam libero rutrum enim, at interdum dolor nisi ac nisi. Morbi ac tellus sem. In ornare vehicula risus sit amet venenatis. Pellentesque magna tellus, suscipit ac dapibus ut, rhoncus nec ante. Nullam ac purus eu massa vestibulum luctus a sed erat.
|
||||
|
||||
Nam lobortis aliquam scelerisque. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce auctor nisl feugiat nunc iaculis malesuada. Vestibulum neque nunc, adipiscing lacinia vehicula ut, blandit at diam. Pellentesque lobortis, justo non sollicitudin vestibulum, est tortor mattis sem, at pulvinar ante felis non ligula. Integer consequat congue adipiscing. Proin ut sodales nunc. Ut eleifend venenatis aliquam. Phasellus et viverra mauris. Quisque commodo sodales feugiat. Proin dignissim mollis quam, vel tristique velit sodales in. Aliquam egestas euismod venenatis.
|
||||
|
||||
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.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user