diff options
author | luxagraf <sng@luxagraf.net> | 2019-05-03 11:38:24 -0500 |
---|---|---|
committer | luxagraf <sng@luxagraf.net> | 2019-05-03 11:38:24 -0500 |
commit | 0e59ad7de18bffcf6a62f9ee61275b4951c27358 (patch) | |
tree | 514fca6efb90db53ca3061aa4ab8ba7d2a33cffe | |
parent | 86fcf7ed710f41fc5324b638d092af54f4bb756f (diff) |
finished up initial design work
28 files changed, 716 insertions, 464 deletions
diff --git a/app/blog/admin.py b/app/blog/admin.py index 6a4749f..b3093f6 100644 --- a/app/blog/admin.py +++ b/app/blog/admin.py @@ -18,8 +18,9 @@ class EntryAdmin(admin.ModelAdmin): 'sub_title', 'body_markdown', ('pub_date', 'status'), + 'tags', 'meta_description', - ('slug', 'enable_comments', 'has_code'), + 'slug', ), 'classes': ( 'show', @@ -27,19 +28,6 @@ class EntryAdmin(admin.ModelAdmin): 'wide' ) }), - ('meta', { - 'fields': ( - 'originally_published_by', - 'originally_published_by_url', - 'afterword', - ('field_notes', 'books'), - ), - 'classes': ( - 'hide', - 'extrapretty', - 'wide' - ) - }), ) class Media: diff --git a/app/blog/models.py b/app/blog/models.py index 3d1ae30..61ac407 100644 --- a/app/blog/models.py +++ b/app/blog/models.py @@ -27,7 +27,6 @@ class Entry(models.Model): status = models.IntegerField(choices=PUB_STATUS, default=0) meta_description = models.CharField(max_length=256, null=True, blank=True) tags = TaggableManager(through=TaggedItems, blank=True, help_text='Topics Covered') - featured_image = models.ForeignKey(LuxImage, on_delete=models.CASCADE, null=True, blank=True) category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True, blank=True) class Meta: @@ -39,7 +38,7 @@ class Entry(models.Model): return self.title def get_absolute_url(self): - return reverse('essays:detail', kwargs={"slug": self.slug}) + return reverse("blog:detail", kwargs={"year": self.pub_date.year, "month": self.pub_date.strftime("%m"), "slug": self.slug}) def comment_period_open(self): return self.enable_comments and datetime.datetime.today() - datetime.timedelta(30) <= self.pub_date diff --git a/app/blog/urls.py b/app/blog/urls.py index da3e1fd..0e9a55c 100644 --- a/app/blog/urls.py +++ b/app/blog/urls.py @@ -5,24 +5,35 @@ from . import views app_name = "blog" urlpatterns = [ - #path( - # r'topic/<str:slug>', - # views.TopicListView.as_view(), - # name="list_topics" - #), - path( - r'<str:slug>', + re_path( + r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[-\w]+).txt$', + views.EntryDetailViewTXT.as_view(), + name="detail-txt" + ), + re_path( + r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[-\w]+)$', views.EntryDetailView.as_view(), name="detail" ), - path( - r'<str:slug>', - views.EntryDetailViewTXT.as_view(), - name="detail-txt" + re_path( + r'^(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', + views.EntryMonthArchiveView.as_view(month_format='%m'), + name="list_month" + ), + re_path( + r'(?P<year>\d{4})/$', + views.EntryYearArchiveView.as_view(), + name="list_year" + ), + re_path( + r'^(?P<page>\d+)/$', + views.EntryListView.as_view(), + name="list" ), - path( + re_path( r'', views.EntryListView.as_view(), - name="list", + {'page': 1}, + name="list" ), ] diff --git a/app/blog/views.py b/app/blog/views.py index 56bd823..cf0fdf6 100644 --- a/app/blog/views.py +++ b/app/blog/views.py @@ -1,9 +1,13 @@ +from operator import attrgetter +from itertools import chain from django.views.generic import ListView from django.views.generic.detail import DetailView +from django.views.generic.dates import YearArchiveView, MonthArchiveView from django.contrib.syndication.views import Feed from .models import Entry +from links.models import Link class EntryListView(ListView): @@ -22,6 +26,36 @@ class EntryDetailViewTXT(EntryDetailView): template_name = "entry_detail.txt" +class EntryYearArchiveView(YearArchiveView): + queryset = Entry.objects.filter(status__exact=1).select_related() + date_field = "pub_date" + make_object_list = True + allow_future = True + + +class EntryMonthArchiveView(MonthArchiveView): + queryset = Entry.objects.filter(status__exact=1).select_related() + date_field = "pub_date" + allow_future = True + + +class HomePageView(ListView): + model = Entry + template_name = "homepage.html" + + def get_queryset(self, **kwargs): + entry_list = Entry.objects.filter(status=1) + link_list = Link.objects.filter(status=1) + result_list = sorted( + chain(entry_list, link_list), + key=attrgetter('pub_date') + ) + return reversed(result_list) + + + + + ''' class TopicListView(ListView): template_name = 'archives/src_home.html' diff --git a/app/links/__init__.py b/app/links/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/links/__init__.py diff --git a/app/links/admin.py b/app/links/admin.py new file mode 100644 index 0000000..9ee9fbf --- /dev/null +++ b/app/links/admin.py @@ -0,0 +1,32 @@ +from django.contrib import admin + +from utils.widgets import LGEntryForm + +from .models import Link + + +@admin.register(Link) +class EntryAdmin(admin.ModelAdmin): + form = LGEntryForm + list_display = ('title', 'pub_date', 'status') + list_filter = ('pub_date', 'status') + prepopulated_fields = {"slug": ('title',)} + fieldsets = ( + ('Link', { + 'fields': ( + 'title', + 'body_markdown', + 'slug', + 'link_url', + ('pub_date', 'status'), + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + }), + ) + + class Media: + js = ('next-prev-links.js') diff --git a/app/links/build.py b/app/links/build.py new file mode 100644 index 0000000..392e991 --- /dev/null +++ b/app/links/build.py @@ -0,0 +1,22 @@ +import os +from builder.base import BuildNew +from django.urls import reverse +from . import models + + +class BuildEssays(BuildNew): + + def build(self): + self.build_list_view() + self.build_detail_view() + # These are the unique classes for this model: + #self.build_feed("src:feed") + + def build_list_view(self): + response = self.client.get('/essays/') + self.write_file('essays/', response.content) + + +def essaybuilder(): + j = BuildEssays("essays", "essay") + j.build() diff --git a/app/links/migrations/0001_initial.py b/app/links/migrations/0001_initial.py new file mode 100644 index 0000000..be54329 --- /dev/null +++ b/app/links/migrations/0001_initial.py @@ -0,0 +1,43 @@ +# Generated by Django 2.1.7 on 2019-03-30 17:07 + +from django.db import migrations, models +import django.db.models.deletion +import taggit.managers + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('photos', '0001_initial'), + ('taxonomy', '__first__'), + ] + + operations = [ + migrations.CreateModel( + name='Entry', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('sub_title', models.CharField(blank=True, max_length=200)), + ('dek', models.TextField(blank=True)), + ('slug', models.SlugField(unique_for_date='pub_date')), + ('body_html', models.TextField(blank=True)), + ('body_markdown', models.TextField()), + ('pub_date', models.DateTimeField(verbose_name='Date published')), + ('last_updated', models.DateTimeField(auto_now=True)), + ('enable_comments', models.BooleanField(default=False)), + ('status', models.IntegerField(choices=[(0, 'Draft'), (1, 'Published')], default=0)), + ('meta_description', models.CharField(blank=True, max_length=256, null=True)), + ('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='taxonomy.Category')), + ('featured_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='photos.LuxImage')), + ('tags', taggit.managers.TaggableManager(blank=True, help_text='Topics Covered', through='taxonomy.TaggedItems', to='taxonomy.LuxTag', verbose_name='Tags')), + ], + options={ + 'get_latest_by': 'pub_date', + 'verbose_name_plural': 'Essays', + 'ordering': ('-pub_date',), + }, + ), + ] diff --git a/app/links/migrations/0002_auto_20190501_1054.py b/app/links/migrations/0002_auto_20190501_1054.py new file mode 100644 index 0000000..b4ca5d1 --- /dev/null +++ b/app/links/migrations/0002_auto_20190501_1054.py @@ -0,0 +1,44 @@ +# Generated by Django 2.1.7 on 2019-05-01 15:54 + +from django.db import migrations, models +import taggit.managers + + +class Migration(migrations.Migration): + + dependencies = [ + ('taxonomy', '0001_initial'), + ('links', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Link', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('link_url', models.URLField(max_length=400)), + ('pub_date', models.DateTimeField(verbose_name='Date published')), + ('slug', models.SlugField(unique_for_date='pub_date')), + ('body_html', models.TextField(blank=True)), + ('body_markdown', models.TextField()), + ('status', models.IntegerField(choices=[(0, 'Draft'), (1, 'Published')], default=0)), + ('tags', taggit.managers.TaggableManager(blank=True, help_text='Topics Covered', through='taxonomy.TaggedItems', to='taxonomy.LuxTag', verbose_name='Tags')), + ], + ), + migrations.RemoveField( + model_name='entry', + name='category', + ), + migrations.RemoveField( + model_name='entry', + name='featured_image', + ), + migrations.RemoveField( + model_name='entry', + name='tags', + ), + migrations.DeleteModel( + name='Entry', + ), + ] diff --git a/app/links/migrations/__init__.py b/app/links/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/links/migrations/__init__.py diff --git a/app/links/models.py b/app/links/models.py new file mode 100644 index 0000000..518ba33 --- /dev/null +++ b/app/links/models.py @@ -0,0 +1,46 @@ +from django.db import models +from django.urls import reverse +from django.contrib.sitemaps import Sitemap + +from taggit.managers import TaggableManager + +from taxonomy.models import TaggedItems +from utils.util import render_images, markdown_to_html + + +class Link(models.Model): + title = models.CharField(max_length=200) + link_url = models.URLField(max_length=400) + pub_date = models.DateTimeField('Date published') + slug = models.SlugField(unique_for_date='pub_date') + tags = TaggableManager(through=TaggedItems, blank=True, help_text='Topics Covered') + body_html = models.TextField(blank=True) + body_markdown = models.TextField() + PUB_STATUS = ( + (0, 'Draft'), + (1, 'Published'), + ) + status = models.IntegerField(choices=PUB_STATUS, default=0) + + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse("links:detail", kwargs={"year": self.pub_date.year, "month": self.pub_date.strftime("%m"), "slug": self.slug}) + + def save(self): + md = render_images(self.body_markdown) + self.body_html = markdown_to_html(md) + super(Link, self).save() + + +class LinkedSitemap(Sitemap): + changefreq = "weekly" + priority = 0.8 + protocol = "https" + + def items(self): + return Link.objects.filter(status=1) + + def lastmod(self, obj): + return obj.pub_date diff --git a/app/links/urls.py b/app/links/urls.py new file mode 100644 index 0000000..fb18532 --- /dev/null +++ b/app/links/urls.py @@ -0,0 +1,39 @@ +from django.urls import path, re_path + +from . import views + +app_name = "links" + +urlpatterns = [ + re_path( + r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[-\w]+).txt$', + views.EntryDetailViewTXT.as_view(), + name="detail-txt" + ), + re_path( + r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[-\w]+)$', + views.EntryDetailView.as_view(), + name="detail" + ), + re_path( + r'^(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', + views.EntryMonthArchiveView.as_view(month_format='%m'), + name="list_month" + ), + re_path( + r'(?P<year>\d{4})/$', + views.EntryYearArchiveView.as_view(), + name="list_year" + ), + re_path( + r'^(?P<page>\d+)/$', + views.EntryListView.as_view(), + name="list" + ), + re_path( + r'', + views.EntryListView.as_view(), + {'page': 1}, + name="list" + ), +] diff --git a/app/links/views.py b/app/links/views.py new file mode 100644 index 0000000..64cc5f7 --- /dev/null +++ b/app/links/views.py @@ -0,0 +1,65 @@ +from django.views.generic import ListView +from django.views.generic.detail import DetailView +from django.views.generic.dates import YearArchiveView, MonthArchiveView +from django.contrib.syndication.views import Feed + + +from .models import Link + + +class EntryListView(ListView): + model = Link + + def get_queryset(self, **kwargs): + qs = Link.objects.filter(status=1) + return qs + + +class EntryDetailView(DetailView): + model = Link + + +class EntryDetailViewTXT(EntryDetailView): + template_name = "entry_detail.txt" + + + +class EntryYearArchiveView(YearArchiveView): + queryset = Link.objects.filter(status__exact=1).select_related() + date_field = "pub_date" + make_object_list = True + allow_future = True + + +class EntryMonthArchiveView(MonthArchiveView): + queryset = Link.objects.filter(status__exact=1).select_related() + date_field = "pub_date" + allow_future = True + + + + + +''' +class TopicListView(ListView): + template_name = 'archives/src_home.html' + + def queryset(self): + return Post.objects.filter(topics__slug=self.kwargs['slug']) + + def get_context_data(self, **kwargs): + # Call the base implementation first to get a context + context = super(TopicListView, self).get_context_data(**kwargs) + context['topic'] = Topic.objects.get(slug__exact=self.kwargs['slug']) + return context + + +class SrcRSSFeedView(Feed): + title = "luxagraf:src Code and Technology" + link = "/src/" + description = "Latest postings to luxagraf.net/src" + description_template = 'feeds/blog_description.html' + + def items(self): + return Post.objects.filter(status__exact=1).order_by('-pub_date')[:10] +''' diff --git a/config/base_urls.py b/config/base_urls.py index ed7da2d..cbc9517 100644 --- a/config/base_urls.py +++ b/config/base_urls.py @@ -4,7 +4,8 @@ from django.conf.urls.static import static from django.conf import settings from django.contrib.sitemaps.views import sitemap -from pages.views import PageDetailView, HomePageDetailView +from pages.views import PageDetailView +from blog.views import HomePageView #import builder.views import utils.views import builder.views @@ -18,9 +19,11 @@ urlpatterns = [ path(r'admin/', admin.site.urls), #path(r'luximages/insert/', utils.views.insert_image), #path(r'sitemap.xml', sitemap, {'sitemaps': sitemaps}), + path(r'essays/', include('blog.urls')), + path(r'linked/', include('links.urls')), path(r'<slug>', PageDetailView.as_view()), path(r'<path>/<slug>/', PageDetailView.as_view()), - path(r'', HomePageDetailView.as_view()), + path(r'', HomePageView.as_view()), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/config/requirements.txt b/config/requirements.txt index a75a0c8..be0d327 100644 --- a/config/requirements.txt +++ b/config/requirements.txt @@ -14,6 +14,7 @@ ipython==7.4.0 ipython-genutils==0.2.0 jedi==0.13.3 Jinja2==2.10 +jsmin==2.2.2 lxml==4.3.3 Markdown==3.1 MarkupSafe==1.1.1 diff --git a/design/sass/_content.scss b/design/sass/_content.scss index 9a81b64..598d63e 100644 --- a/design/sass/_content.scss +++ b/design/sass/_content.scss @@ -1,236 +1,74 @@ -.hero-wrapper { - @include fancy_sans; - padding: 5rem 0 0; - &:after { - @include faded_line_after; - margin-top: 4rem; - margin-bottom: 4rem; - padding: 0; - } -} -.circle-pic { - border-radius: 50%; - border: 5px solid #000; -} -.btn { - @include fontsize(14); - display: inline-block; - border-radius: 4px; - @include fancy_sans; - @include smcaps; - -webkit-appearance: none; - text-decoration: none; - cursor: pointer; - background: $link_color; - color: #fff !important; - border: 1px solid $link_color; - padding: 7px 9px; - white-space: nowrap; - &:hover { - background: $link_hover_color; - border: 1px solid $link_hover_color; - } +.content-narrow { + margin-top: 3rem; + @include constrain_narrow; } -.btn-small { - @include fontsize(10); - @include smcaps; -} -.btn-hollow { - @include fontsize(17); - padding: 6px 8px; - border: none; //1px solid $body_font_light; - color: $link_color !important; - outline: $link_color !important; - background: white; - border: 1px solid $link_color; - &:hover { - background: $link_color !important; - color: white !important; - } -} -.hed-alpha { - @include fancy_serif; - line-height: 1.2; - font-weight: 600; -} -.hed-beta { - line-height: 1.4; -} -.hed-gamma { - line-height: 1.4; - @include fontsize(20); - @include fancy_sans; - text-align: center; - letter-spacing: 1px; - margin: 0 auto; -} -.hed-delta { - @include fancy_sans; - @include fontsize(22); - font-weight: bold; - margin-bottom: .5em; -} -.hed-epsilon { - @include fontsize(14); - @include fancy_sans; - text-transform: uppercase; - letter-spacing: 1px; - font-weight: bold; - color: $body_font_light; - line-height: 1.2; - text-align: center; - margin: 0; +.post-header { + @extend %clearfix; + padding-bottom: 2.6rem; + border-bottom: 1px solid #efefef; } .hed-border { display: inline-block; border-bottom: 3px solid #efefef; width: auto; } -.hero { - .hero-pic { - max-width: 50%; - margin: 1.5rem auto; - } - h3.hed-alpha { - @include fontsize(24); - } - .hed-beta { - @include fancy_sans; - @include fontsize(22); - margin: .5rem auto; - text-align: center; - &:last-of-type:after { - @include faded_line_after; - margin-top: 2rem; - margin-bottom: 2rem; - } - } - @include breakpoint(beta) { - display: flex; - align-items: flex-start; - align-content: flex-start; - .hero-text { - margin-left: 5rem; - & > * { - text-align: left; - } - } - p { - width: 90%; - @include fontsize(20); - } - .btn { - margin-top: 1.5rem; - } - } -} -.home { - h4 { - @include fancy_sans; - text-align: center; - letter-spacing: 1px; - } - hr { - border-top: 3px solid #efefef; - margin: 5em auto; - width: 40%; - } -} -.border-wrapper { - margin: 2rem auto 0; -} -.home-logos { - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: center; - width: 100%; - li { - margin: 0 .5rem; - } - img { - max-width: 80px; - } +.flex { @include breakpoint(gamma) { - @include constrain_wide; - margin: 0 auto; - img { - max-width: 120px; - } + display: flex; + justify-content: center ; } } - -.home-border-wrapper { - @include breakpoint(beta) { - margin-top: 4rem; - .btn { - margin-bottom: 4rem; - } - } - &:before { - @include faded_line_after; - margin-top: 0; - margin-bottom: 5rem; +article ul { + list-style-type: none; + @include fontsize(22); + li:before { + content: ""; + border: 2px #000 solid !important; + border-radius: 50px; + margin-top: 16px; + margin-left: -12px; + position: absolute; } } -.card-image { - max-height: 10rem; - overflow: hidden; - border: 4px $body_font_color solid; - img { - width: 100%; - margin-top: -14%; +.archive-list { + @include constrain_narrow; + text-align: left; + ul { + padding: 0; + list-style-type: none; } -} -.home-card-wrapper { - @include breakpoint(beta) { - margin-top: 4rem; - .btn { - margin-bottom: 4rem; + a { + text-decoration: none; + color: lighten($body_font_color, 20); + &:hover { + color: $link_color; } } - &:after { - @include faded_line_after; - margin-top: 0; - margin-bottom: 5rem; - } -} -.card { - margin: 4rem auto; p { - margin-top: .5rem; - @include fontsize(18); - } - h5 { - @include fontsize(24); - text-align: center; - margin: 1rem 0 0 0; - } - &:after { - @include faded_line_after; - } - &:last-of-type:after { - display: none; - } - @include breakpoint(beta) { - flex-grow: 1; - flex-shrink: 1; - flex-basis: 0; - margin-top: 0; - margin-right: 2rem; - &:last-of-type { - margin-right: 0; - } - &:after { - display: none; - } + margin: 0; + @include fontsize(20); + font-style: italic; } } -.flex { - @include breakpoint(gamma) { - display: flex; - justify-content: center ; +.post-linewrapper { + margin-top: 1rem; + padding-top: 1rem; + display: inline-block; + margin-left: 0; + border-top: 2px solid darken($body_color, 8); + float: left; +} + +.star { + color: transparent; + text-shadow: 0 0 0 lighten($body_font_color, 50); + text-decoration: none; + @include fontsize(22); + padding: 0 6px 3px 6px; + font-family: "Hiragino Kaku Gothic Pro", "Osaka", "Zapf Dingbats"; + &:hover { + background: darken(#fff, 10); } } diff --git a/design/sass/_fonts.scss b/design/sass/_fonts.scss index 77f6f7c..b80bc6b 100644 --- a/design/sass/_fonts.scss +++ b/design/sass/_fonts.scss @@ -33,3 +33,17 @@ font-style: normal; } +@font-face { + font-family: 'sortsmill'; + src: url('/media/fonts/oflgoudystmtt-webfont.woff2') format('woff2'); + src: url('/media/fonts/oflgoudystmtt-webfont.woff') format('woff'); + font-weight: 400; + font-style: normal; +} +@font-face { + font-family: 'sortsmill'; + src: url('/media/fonts/oflgoudystmtt-italic-webfont.woff2') format('woff2'); + src: url('/media/fonts/oflgoudystmtt-italic-webfont.woff') format('woff'); + font-weight: 400; + font-style: italic; +} diff --git a/design/sass/_footer.scss b/design/sass/_footer.scss index 1ff56b9..d326d4a 100644 --- a/design/sass/_footer.scss +++ b/design/sass/_footer.scss @@ -1,54 +1,50 @@ footer { - margin-top: 5em; + @include constrain_wide; + margin-top: 6rem; + margin-bottom: 1rem; @include breakpoint(gamma) { max-width: 960; + margin-top: 8rem; + margin-bottom: 3rem; } &:before { - @include breakpoint(beta) { - @include faded_line_after; - margin-bottom: 1.2em; - } - } - .footer-nav { - list-style-type: none !important; - margin-left: 0 !important; - border-top: 1px $body_font_color dotted; - border-bottom: 1px $body_font_color dotted; - padding: .5rem 0; - @include breakpoint(beta) { - border: none; - } + @include faded_line_after; + margin-bottom: 2em; } - li { - display: inline; - margin: 0 .25em; - &:after { - content: "\00b7"; - color: #999999; - padding-left: 0.75em; + .footer-nav-menu { + padding: 0; + text-align: center; + margin-bottom: 1rem; + li { + display: inline; + margin: 0 auto; + &:after { + content: "/"; + color: #999999; + padding-left: 0.75em; + } + a { + color: $secondary-link-color; + text-decoration: none; + } } - a { - color: $secondary-link-color; - text-decoration: none; + li:last-of-type { + margin-right: 0; + &:after { + content: " "; + } } - ul { display:inline;} - } - li:last-of-type { - margin-right: 0; - &:after { - content: " "; + @include breakpoint(beta) { + float: right; + text-align: left; } } p { - @include fontsize(10); text-align: center; - margin-top: 1.5em; - margin-bottom: 1.5em; + a { text-decoration: none; } + @include breakpoint(beta) { + float: left; + text-align: left; + } } } -#license { - @include fancy_sans; - @include fontsize(12); - text-transform: none; - letter-spacing: normal; -} diff --git a/design/sass/_global.scss b/design/sass/_global.scss index 719d23a..8e3e435 100644 --- a/design/sass/_global.scss +++ b/design/sass/_global.scss @@ -1,18 +1,17 @@ html { border-top: 0.25em solid $body_font_color; } - body { margin: 0 auto; padding: 0; overflow-x: hidden; font:$body_p_font; color: $body_font_color; - text-align: center; - background-color: transparent + text-align: left; + background-color: $body_color; } ul { - padding: 0; + text-align: left; } // eliminate touch delay on mobile safari a, button, input, select, textarea, label, summary { @@ -46,9 +45,10 @@ p { } } time { - @include smcaps; - @include fontsize(11); display: block; + text-transform: uppercase; + letter-spacing: 1px; + @include fontsize(11); span { @include fontsize(13); } @@ -63,6 +63,12 @@ pre { line-height: 1.5; } } +p code { + font-family: Inconsolata, Consolas, Courier New, monospace; + font-size: 96%; + background: darken($body_color, 8); + padding: 1px 3px; +} object, embed, video { max-width: 100%; width: 100%; @@ -75,9 +81,9 @@ audio { blockquote { @include fontsize(18); display: block; - border-top: 4px solid lighten($body_font_light, 20); - border-bottom: 4px solid lighten($body_font_light, 20); margin: 3rem 0; + padding-left: 1rem; + border-left: 2px solid lighten($body_font_color, 40); position: relative; text-align: left; font-style: italic; @@ -85,6 +91,9 @@ blockquote { display: block; text-align: right; } + p { + @include fontsize(18); + } @include breakpoint(alpha){ @include fontsize(20); line-height: 1.5; @@ -92,21 +101,12 @@ blockquote { @include breakpoint(beta){ @include fontsize(22); line-height: 1.6; + margin-left: 1rem; + p { + @include fontsize(20); + } } } -blockquote:before { - @include fancy_sans; - @include fontsize(68); - content: '\201C'; - position: absolute; - top: -1.35rem; - left: 50%; - transform: translate(-50%, -50%); - width: 3rem; - height: 2rem; - color: #666; - text-align: center; -} hr { border: 0; height: 1px; @@ -129,7 +129,7 @@ figcaption, figcaption a { line-height: 1.9; padding: .3rem .5rem .3rem 0; color: #666; - border-bottom: 1px lighten($body_font_light, 20) solid; + border-bottom: 1px lighten($body_font_color, 40) solid; margin-bottom: 1rem; } figcaption a:visited { @@ -161,6 +161,8 @@ h3 { } h4 { @include fontsize(20); + @include fancy_sans; + font-weight: bold; text-align: left; @include breakpoint(gamma){ @include fontsize(22); @@ -175,19 +177,50 @@ h5 { line-height: 1.4; } } -.subhead { - font-size: 26px !important; +//************** Universals ************************ +.hed-primary { + @include fancy_serif; + @include fontsize(28); + margin: .25rem 0; + line-height: 1.2; + font-weight: 400; + @include breakpoint(delta) { + @include fontsize(32); + margin-top: 0; + } +} +.hed-secondary { + @include fancy_serif; + @include fontsize(20); + margin: 0; font-style: italic; - margin-top: 0; - margin-bottom: 0; + line-height: 1.2; } -.subhead + p { - margin-top: .75rem !important; +.hed-tertiary, .nav-menu { + @include fancy_sans; + @include fontsize(14); + font-weight: bold; + text-transform: uppercase; + letter-spacing: 1px; + margin: 0; + line-height: 1.3; + color: lighten($body_font_color, 40); + a { + color: lighten($body_font_color, 40); + } } -.essay-intro .subhead + p:first-of-type { - margin-top: .75rem !important; +.blok { + display: block; + margin: 0; + text-transform: uppercase; + letter-spacing: 1px; + @include fontsize(13); + @include fancy_sans; + letter-spacing: 1px; + font-weight: bold; + color: lighten($body_font_color, 40); + text-align: left; } -//************** Universals ************************ .hide { display: none; } diff --git a/design/sass/_header.scss b/design/sass/_header.scss index 431897e..c5d9ed1 100644 --- a/design/sass/_header.scss +++ b/design/sass/_header.scss @@ -1,31 +1,8 @@ -.header-wrapper { -} - -#logo { - a { - @include fontsize(32); - line-height: 1; - text-decoration: none; - display: block; - font-weight: 300; - font-family: 'carrois_gothicregular', Helvetica, sans-serif; - color: $body_font_color; - } - .tagline { - display: block; - @include fancy_sans; - @include smcaps; - @include fontsize(12); - font-style: normal; - margin-left: 2px; - } -} .site-banner { @extend %clearfix; margin: 0 auto; @include constrain_wide; - @include smcaps; - nav { + .nav-menu { border-top: 1px #444444 dotted; border-bottom: 1px #444444 dotted; //box-shadow: 0 3px 8px 0 #e6e6e6 @@ -35,22 +12,18 @@ margin-left: -20px; margin-top: 1em; padding: 0.25em 0.5em; - a { + a { + @include fontsize(15); text-decoration: none; - color: #505050; - &:visited { - color: #505050 - } + font-weight: bold; + color: lighten($body_font_color, 30); } ul { - @include smcaps; - @include fancy_sans; - @include fontsize(15); max-width: 100%; - font-weight: 600; margin-top: 0.5em; margin-bottom: 0.5em !important; padding: 0; + text-align: center; @include constrain(85%); } li { @@ -68,8 +41,6 @@ } } } - @include breakpoint(beta) { - } } @include breakpoint(beta) { height: 90px; @@ -101,22 +72,22 @@ margin-top: -30px; } } - nav { + .nav-menu { float: right; border: none; margin: 22px 0 0 0; padding: 0; ul { max-width: 50em; + text-align: left; } } } } - .header-wrapper { @extend %clearfix; @include breakpoint(beta) { - border-bottom: 1px #f3efef solid; + border-bottom: 1px darken(#fff, 10) solid; position: relative; } @include breakpoint(gamma) { @@ -133,3 +104,35 @@ max-width: $max_width; } } +#logo { + a { + @include fontsize(34); + line-height: 1; + text-decoration: none; + display: block; + font-weight: 300; + font-family: 'carrois_gothicregular', Helvetica, sans-serif; + text-transform: uppercase; + color: $body_font_color; + text-align: center; + margin-top: 1.3rem; + @include breakpoint(beta) { + text-align: left; + @include fontsize(32); + } + } + .tagline { + display: block; + text-transform: uppercase; + letter-spacing: 1px; + @include fancy_sans; + @include fontsize(13); + font-style: normal; + margin-left: 2px; + text-align: center; + @include breakpoint(beta) { + text-align: left; + @include fontsize(12); + } + } +} diff --git a/design/sass/_mixins.scss b/design/sass/_mixins.scss index f12888e..6bd5e1b 100644 --- a/design/sass/_mixins.scss +++ b/design/sass/_mixins.scss @@ -1,21 +1,15 @@ - +$body_color: darken(#fff, 3); $body_p_font: normal 100% / 1.5 Georgia, Cambria, "Times New Roman", Times, serif; $body_font_color: #222; $link_color: #b53a04; -$body_font_light: #787474; $secondary-link-color: #838383; -$narrow-beta-width: 720px; -$narrow-max-width: 750px; +$narrow-beta-width: 680px; +$narrow-max-width: 720px; $max_width: 1140px; $link_hover_color: #b53a04; $home-palette-primary: #14cfe7; -@mixin smcaps { - @include fancy_sans; - text-transform: uppercase; - letter-spacing: 1px; -} @function calc-rem($size) { $remsize: $size/16; @return #{$remsize}rem; @@ -35,7 +29,7 @@ $home-palette-primary: #14cfe7; font-family: mffnweb, Helvetica, sans-serif; } @mixin fancy-serif { - font-family: mffweb, Georgia, 'Times New Roman', serif; + font-family: mffweb, 'PT Serif', Georgia, 'Times New Roman', serif; } %clearfix { *zoom: 1; @@ -50,12 +44,6 @@ $home-palette-primary: #14cfe7; } } -@mixin transparent_class { - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=90)"; - filter: alpha(opacity = 90); - opacity: 0.9; -} - @mixin faded_line_after { display: block; content: ""; diff --git a/design/templates/base.html b/design/templates/base.html index 41a8033..9be4f51 100644 --- a/design/templates/base.html +++ b/design/templates/base.html @@ -7,17 +7,16 @@ <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" - content="{% block metadescription %}Scott Gilbertson is a Technical Writer, Copywriter and Editor helping your company increase its online content to boost your traffic and attract new leads. {% endblock %}"> + content="{% block metadescription %}{% endblock %}"> <meta name="author" content="Scott Gilbertson"> <link rel="alternate" type="application/rss+xml" title="RSS feed" - href="/rss/"> + href="/rss"> {%block stylesheet%}<link rel="stylesheet" href="/media/screenv1.css?{% now "u" %}" media="screen">{%endblock%} <link rel="shortcut icon" href="favicon.ico" type="image/x-icon"> - <!--<link rel="manifest" href="/manifest.webmanifest" /> --> {%block extrahead%}{%endblock%} </head> <body {%block bodyid%}{%endblock%}{%block bodyevents%}{%endblock%}> @@ -26,30 +25,30 @@ <header class="site-banner"> <div id="logo"> <a href="/" title="Home">Libregraf</a> - <span class="tagline">Let's Tell Your Story</span> + <span class="tagline">Free Software & nerdery</span> </div> - <nav> + <nav class="nav-menu"> <ul> - <li><a href="/hire-me" title="">Hire Me</a></li> - <li><a href="/about" title="">About Scott</a></li> - <!--<li><a href="/portfolio" title="">Portfolio</a></li> - <li><a href="/praise" title="">Praise</a></li> - <li><a href="/contact" title="">Contact</a></li> - <li><a href="/blog/" title="">Blog</a></li>--> + <li><a href="/essays/" title="Previous articles">Archive</a></li> + <li><a href="/linked/" title="Thoughts on Free, open source and Libre software news">Links</a></li> + <li><a href="/about" title="About this site and the tools I use to make it">About</a></li> + <li><a href="/contact" title="How to get in touch regarding Libregraf">Contact</a></li> </ul> </nav> </header> </div> {% block content %}{% endblock %} {% block extrabody %}{% endblock %} - <footer class="bl"> - <p id="license"> + <footer> + <ul class="nav-menu footer-nav-menu"> + <li><a href="/contact" title="How to get in touch regarding Libregraf">Contact</a></li> + <li><a href="/rss" title="RSS feed">RSS</a></li> + <li><a href="" title="Libregraf on twitter">Twitter</a></li> + </ul> + <p class="hed-tertiary"> © {% now "Y" %} - <span class="h-card"><a class="p-name u-url" href="https://luxagraf.net/">Scott Gilbertson</a><data class="p-nickname" value="luxagraf"></data><data class="p-locality" value="Athens"></data><data class="p-region" value="Georgia"></data><data class="p-country-name" value="United States"></data></span>. + <span class="h-card"><a class="p-name u-url" href="https://libregraf.net/">Scott Gilbertson</a><data class="p-nickname" value="libregraf"></data><data class="p-locality" value="Athens"></data><data class="p-region" value="Georgia"></data><data class="p-country-name" value="United States"></data></span>. </p> - <ul class="footer-nav"> - <li><a href="/contact" title="contact luxagraf">Contact</a></li> - </ul> </footer> </div> {% block js %}{% endblock%} diff --git a/design/templates/blog/entry_detail.html b/design/templates/blog/entry_detail.html new file mode 100644 index 0000000..ad4eda8 --- /dev/null +++ b/design/templates/blog/entry_detail.html @@ -0,0 +1,62 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{%block bodyid%}id="essay-archive" class="archive"{%endblock%} + +{% block content %} +<div class="content-narrow"> + <article class="h-entry hentry entry-content content" itemscope itemType="http://schema.org/BlogPosting"> + <header id="header" class="post-header"> + <h1 class="p-name hed-primary" itemprop="headline">{{object.title|smartypants|safe}}</h1> + {% if object.sub_title %}<h2 class="p-summary hed-secondary">{{object.sub_title|smartypants|safe}}</h2>{%endif%} + <div class="post-linewrapper"> + <h5 class="hed-tertiary">Filed Under: {% for tag in object.tags.all %}<a href="/essays/tags/{{tag.slug}}" title="View all essays about {{tag}}">{{tag}}</a>{%if forloop.last%}{%else%}, {%endif%}{% endfor %}</h5> + <time class="dt-published published dt-updated hed-tertiary" datetime="{{object.pub_date|date:'c'}}" itemprop="datePublished">{{object.pub_date|date:"F"}} <span>{{object.pub_date|date:"j, Y"}}</span></time> + <span class="hide" itemprop="author" itemscope itemtype="http://schema.org/Person">by <a class="p-author h-card" href="/about"><span itemprop="name">Scott Gilbertson</span></a></span> + </div> + </header> + <div id="article" class="e-content entry-content" itemprop="articleBody"> + {{object.body_html|safe|smartypants}} + </div> + </article> + {% with object.get_next_published as next %} + {% with object.get_previous_published as prev %} + <div class="nav-wrapper"> + <nav id="page-navigation" {%if wildlife or object.field_notes.all or object.books.all %}{%else%}class="page-border-top"{%endif%}> + <ul>{% if prev%} + <li id="prev"><span class="bl">Previous:</span> + <a href="{{ prev.get_absolute_url }}" rel="prev" title=" {{prev.title}}">{{prev.title|safe}}</a> + </li>{%endif%}{% if next%} + <li id="next"><span class="bl">Next:</span> + <a href="{{ next.get_absolute_url }}" rel="next" title=" {{next.title}}">{{next.title|safe}}</a> + </li>{%endif%} + </ul> + </nav>{%endwith%}{%endwith%} + </div> + {% if object.related.all %}<div class="article-afterward related"> + <h6 class="hedtinycaps">You might also enjoy</h6> + <ul class="article-card-list">{% for object in related %} + <li class="article-card-mini"><a href="{{object.get_absolute_url}}" title="{{object.title}}"> + <div class="post-image post-mini-image"> + {% if object.featured_image %} + {% include "lib/img_archive.html" with image=object.featured_image nolightbox=True %} + {% elif object.image %} + {% include "lib/img_archive.html" with image=object.image nolightbox=True %} + {% else %} + <img src="{{object.get_image_url}}" alt="{{ object.title }}" class="u-photo post-image" itemprop="image" />{%endif%} + </div> + <h4 class="p-name entry-title post-title" itemprop="headline">{% if object.title %}{{object.title|safe|smartypants|widont}}{% else %}{{object.common_name}}{%endif%}</h4> + {% if object.subtitle%}<h5 class="post-subtitle">{{object.subtitle|safe|smartypants}}</h5>{%endif%} + <p class="p-author author hide" itemprop="author"><span class="byline-author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">Scott Gilbertson</span></span></p> + <p class="post-summary"> + <span class="p-location h-adr adr post-location" itemprop="contentLocation" itemscope itemtype="http://schema.org/Place"> + {% if object.location.country_name == "United States" %}{{object.location.state_name}}{%else%}{{object.location.country_name}}{%endif%} + </span> + – + <time class="dt-published published dt-updated post-date" datetime="{{object.pub_date|date:'c'}}"><span>{{object.pub_date|date:" Y"}}</span></time> + </p> + </a> + </li> + {% endfor %}</ul> + </div>{%endif%} +</div> +{% endblock %} diff --git a/design/templates/blog/entry_list.html b/design/templates/blog/entry_list.html new file mode 100644 index 0000000..0931ac4 --- /dev/null +++ b/design/templates/blog/entry_list.html @@ -0,0 +1,18 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{%block bodyid%}id="essay-archive" class="archive"{%endblock%} + +{% block content %} + <main role="main" id="essay-archive" class="essay-archive archive-list"> + <h1 class="topic-hed">Essays</h1> + <ul>{% for object in object_list %} + <li class="h-entry hentry" itemscope itemType="http://schema.org/Article"> + <span class="date dt-published hed-tertiary">{{object.pub_date|date:"F Y"}}</span> + <a class="u-url" href="{{object.get_absolute_url}}"> + <h2 class="p-name hed-primary">{{object.title|safe|smartypants|widont}}</h2> + <p class="p-summary hed-secondary">{% if object.sub_title %}{{object.sub_title|safe|smartypants}}{%else%}{{object.metadescription}}{%endif%}</p> + </a> + </li> + {%endfor%}</ul> + </main> +{% endblock %} diff --git a/design/templates/homepage.html b/design/templates/homepage.html index ed47bdb..ca8d3b5 100644 --- a/design/templates/homepage.html +++ b/design/templates/homepage.html @@ -2,87 +2,21 @@ {% load typogrify_tags %} {% block sitename %} <head itemscope itemtype="http://schema.org/WebSite"> - <title itemprop='name'>Everyone has a story - I'll help you tell yours</title> + <title itemprop='name'>Libregraf: Free software, open source, and web nerdery</title> <link rel="canonical" href="https://libregraf.net/" itemprop="url" /> {% endblock %} -{%block bodyid%}id="home" class="home"{%endblock%} - +{%block bodyid%}id="home" class="archive home"{%endblock%} {% block content %} -<div class="content-wrapper hero-wrapper"> - <div class="content hero"> - <div class="hero-pic"> - <img src="/media/bio.jpg" class="circle-pic" alt="Scott Gilbertson" /> - </div> - <div class="hero-text"> - <h1 class="hed-alpha">Need Content That Converts?</h1> - <h2 class="hed-beta">Let's find the weak spots in your content and strengthen them.</h2> - <h2 class="hed-beta">I'll create the content you need to amp up your traffic, leads and sales.</h2> - <h3 class="hed-alpha">My writing attracts, engages and converts.</h3> - <p>Whether you’re an entrepreneur, small business, or large company, my custom tailored content can catapult your online visibility and give you the traffic boost you need to attract new leads.</p> - <p><a href="/hire-me" class="btn btn-hollow">Let's Get Started</a></p> - </div> - </div> -</div> -<div class="content-wrapper"> - <div class="content"> - <h4 class="hed-gamma hed-border">How Can I Help You?</h4> - <p class="narrow">Since the dawn of the Internet I've been helping people discover the power of stories. Stories pull customers in, stories drive traffic. You don't need “marketing,” you need good stories. Here's a few ways I can help tell your story.</p> - <div class="home-card-wrapper"> - <div class="flex"> - <div class="card card-tiny"> - <div class="card-image"> - <img src="/media/img/typing.jpg" alt="hands typing code on laptop" /> - </div> - <h5 class="hed-delta">Technical Writing</h5> - <p>My specialty is making the technical easy to understand. I've used my expertise as a developer to write documentation, tutorials, and white papers. I’ve helped companies like Opera Software, Postmarkapp, Sifter tell their story to developers and users. Lets tell your story.</p> - </div> - <div class="card card-tiny"> - <div class="card-image"> - <img src="/media/img/content.jpg" alt="hands typing code on laptop" /> - </div> - <h5 class="hed-delta">Content Marketing</h5> - <p>Content marketing is marketing-speak for telling stories that captivate your audience. Whether you already have a blog or are starting from scratch, I can help refine your strategies and create content focused on achieving measurable results.</p> - </div> - <div class="card card-tiny"> - <div class="card-image"> - <img src="/media/img/pen.jpg" alt="pen editing papers" /> - </div> - <h5 class="hed-delta">Copywriting & Copy editing</h5> - <p>Maybe you've already written your story, but could use a hand polishing it up. Whether you need some need some fine tuning of what you already have, or need some help organizing and streamlining your story, I can help.</p> - </div> - </div> - <a href="/hire-me" class="btn btn-hollow btn-link">Hire Me!</a> - <a href="https://google.com/" class="btn btn-hollow btn-link">Go Cheap</a> - </div> - </div> -</div> -<div class="content-wrapper"> - <h6 class="hed-gamma hed-border">Companies I've helped</h6> - <div class="border-wrapper"> - <ul class="list-inline home-logos"> - <li><a href="https://wired.com/" title="Wired.com"><img src="/media/img/wired.png" alt="Wired logo" /></a></li> - <li><a href="https://opera.com/" title="Opera.com"><img src="/media/img/opera.png" alt="Opera Web Browser logo" /></a></li> - <li><a href="https://arstechnica.com/" title="ArsTechnica.com"><img src="/media/img/ars.png" alt="Ars logo" /></a></li> - <li><a href="https://sifterapp.com/" title="Sifter.com"><img src="/media/img/sifter.png" alt="Sifter logo" /></a></li> - <li><a href="https://www.boostmobile.com/" title="boostmobile"><img src="/media/img/boost.png" alt="Boost Mobile logo" /></a></li> - <li><a href="https://webmonkey.com/" title="Webmonkey.com"><img src="/media/img/webmonkey.jpg" alt="Webmonkey logo" /></a></li> - <!--<li><a href="" title=""><img src="/media/img/budgettravel.jpg" alt="Budget Travel logo" /></li>--> - <li><a href="https://postmarkapp.com/" title="Postmark"><img src="/media/img/postmark.png" alt="Postmarkapp logo" /></a></li> - <li><a href="https://theregister.co.uk/" title="The register"><img src="/media/img/register.png" alt="Register logo" /></a></li> - </ul> - </div> -</div> - -<div class="content-wrapper"> - <div class="content"> - <div class="home-border-wrapper"> - <h6 class="hed-gamma hed-border">What Clients Say</h6> - </div> - </div> +<div class="content-narrow"> +{% for obj in object_list %} +<article class="h-entry hentry" itemscope itemType="http://schema.org/Article"> + <span class="date dt-published hed-tertiary">{{obj.pub_date|date:"F d, Y"}}</span> + <h3 class="p-name hed-primary"><a class="u-repost-of" href="{{obj.link_url}}" title="Read the original story">{{obj.title|safe|smartypants|widont}}</a> <a class="hed-star u-url" href="{{obj.get_absolute_url}}">★</a></h3> + <div class="p-summary">{{obj.body_html|safe|smartypants}}</div> +</article> +{% if forloop.last %}{%else%}<hr />{%endif%} +{% endfor %} </div> {% endblock %} - -#### Copywriting & Copy editing -Whether you need some writing done from scratch or just need some fine tuning of what you already have, I can help. diff --git a/design/templates/links/link_detail.html b/design/templates/links/link_detail.html new file mode 100644 index 0000000..500dfcb --- /dev/null +++ b/design/templates/links/link_detail.html @@ -0,0 +1,13 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{%block bodyid%}id="essay-archive" class="archive"{%endblock%} + +{% block content %} +<div class="content-narrow"> +<article class="h-entry hentry" itemscope itemType="http://schema.org/Article"> + <span class="date dt-published blok">{{object.pub_date|date:"F d, Y"}}</span> + <h3 class="hed-primary"><a class="u-url" href="{{object.link_url}}" title="Read the original story">{{object.title|safe|smartypants|widont}}</a></h3> + <div class="p-summary">{{object.body_html|safe|smartypants}}</div> +</article> +</div> +{% endblock %} diff --git a/design/templates/links/link_list.html b/design/templates/links/link_list.html new file mode 100644 index 0000000..f38771a --- /dev/null +++ b/design/templates/links/link_list.html @@ -0,0 +1,15 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{%block bodyid%}id="essay-archive" class="archive"{%endblock%} + +{% block content %} +<div class="content-narrow"> +{% for obj in object_list %} +<article class="h-entry hentry" itemscope itemType="http://schema.org/Article"> + <span class="date dt-published blok">{{obj.pub_date|date:"F d, Y"}}</span> + <h3 class="p-name hed-primary"><a class="u-repost-of" href="{{obj.link_url}}" title="Read the original story">{{obj.title|safe|smartypants|widont}}</a> <a class="star u-url" href="{{obj.get_absolute_url}}">★</a></h3> + <div class="p-summary">{{obj.body_html|safe|smartypants}}</div> +</article> +{% endfor %} +</div> +{% endblock %} diff --git a/design/templates/pages/page.html b/design/templates/pages/page.html new file mode 100644 index 0000000..095ccd1 --- /dev/null +++ b/design/templates/pages/page.html @@ -0,0 +1,12 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{%block bodyid%}id="page" class="detail"{%endblock%} + +{% block content %} +<div class="content-narrow"> +<article class="h-entry hentry" itemscope itemType="http://schema.org/Article"> + <h3 class="hed-primary">{{object.title|safe|smartypants|widont}}</h3> + <div class="e-content">{{object.body_html|safe|smartypants}}</div> +</article> +</div> +{% endblock %} |