-
Notifications
You must be signed in to change notification settings - Fork 0
/
onerc.el
242 lines (231 loc) · 11.4 KB
/
onerc.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
;; Variables
(defvar domain "django-liveview.andros.dev")
;; Utils
(defun make-title (title)
"If title is empty, return the website name. Otherwise, return the title with the website name."
(concat (when (not (string-empty-p title)) (concat title " | ")) "Django LiveView"))
(defun one-ox-link (link desc info)
"Transcode a LINK object from Org to HTML.
DESC is the description part of the link, or the empty string.
INFO is a plist holding contextual information."
(let* ((type (org-element-property :type link))
(path (org-element-property :path link))
(raw-link (org-element-property :raw-link link))
(custom-type-link
(let ((export-func (org-link-get-parameter type :export)))
(and (functionp export-func)
(funcall export-func path desc 'one-ox info))))
(href (cond
((string= type "custom-id") path)
((string= type "fuzzy")
(let ((beg (org-element-property :begin link)))
(signal 'one-link-broken
`(,raw-link
"fuzzy links not supported"
,(format "goto-char: %s" beg)))))
((string= type "file")
(or
;; ./assets/images/image-1.png --> /images/image-1.png
;; ./public/blog/page-1.md --> /blog/page-1.md
(and (string-match "\\`\\./\\(assets\\|public\\)" path)
(replace-match "" nil nil path))
(let ((beg (org-element-property :begin link)))
(signal 'one-link-broken
`(,raw-link ,(format "goto-char: %s" beg))))))
(t raw-link)))
(class (if-let ((parent (org-export-get-parent-element link))
(class (plist-get (org-export-read-attribute :attr_html parent)
:class)))
(concat " class=\"" class "\" ")
" ")))
(or custom-type-link
(and
(string-match one-ox-link-image-extensions path)
(format "<p><img%ssrc=\"%s\" alt=\"%s\" /></p>"
class href (or (org-string-nw-p desc) href)) )
(format "<a%shref=\"%s\">%s</a>"
class href (or (org-string-nw-p desc) href)))))
;; Layouts
(defun render-layout-html (title description navigator-active tree-content)
"Render the HTML layout with the given title, description and content."
(let ((full-title (make-title title))
(class-name-navigator-active "nav-main--active"))
(jack-html
"<!DOCTYPE html>"
`(:html (@ :lang "en")
(:head
;; Yandex.Metrika counter
(:script (@ :type "text/javascript") "(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, 'script', 'https://mc.yandex.ru/metrika/tag.js', 'ym');
ym(95556716, 'init', {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});")
(:noscript
(:div (:img (@ :src "https://mc.yandex.ru/watch/95556716" :style "position:absolute; left:-9999px;" :alt ""))))
;; Generals
(:meta (@ :charset "utf-8"))
(:link (@ :rel "icon" :type "image/png" :href "/img/favicon.png"))
(:meta (@ :name "viewport" :content "width=device-width,initial-scale=1.0, shrink-to-fit=no"))
(:meta (@ :name "author" :content "Andros Fenollosa"))
(:meta (@ :name "generator" :content "One.el"))
;; SEO
(:title ,full-title)
(:meta (@ :name "description" :content ,description))
(:meta (@ :name "og:image" :content "https://django-liveview.andros.dev/img/og-image.webp"))
;; Fonts
(:link (@ :rel "preconnect" :href "https://fonts.googleapis.com"))
(:link (@ :rel "preconnect" :href "https://fonts.gstatic.com" :crossorigin t))
(:link (@ :rel "stylesheet" :href "https://fonts.googleapis.com/css2?family=Fira+Code&family=Open+Sans:wght@400;700&display=swap"))
;; CSS
(:link (@ :rel "stylesheet" :type "text/css" :href "https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css"))
(:link (@ :rel "stylesheet" :type "text/css" :href ,(concat "/css/main.css?cache=" (format-time-string "%s")))))
(:body
(:header.header
(:div.container
(:nav.nav-main
(:ul.nav__list.nav-main__list
(:li.nav-main__item
(:a.nav-main__link.nav-main__link--logo (@ :href "/") (:img.nav-main__logo (@ :alt "Django LiveView" :src "/img/logo.webp"))))
(:li.nav-main__item
(:a.button.nav-main__link (@ :href "/docs/install/" :class ,(when (string= "docs" navigator-active) class-name-navigator-active)) "Docs"))
(:li.nav-main__item
(:a.button.nav-main__link (@ :href "/tutorials/" :class ,(when (string= "tutorials" navigator-active) class-name-navigator-active)) "Tutorials"))
(:li.nav-main__item
(:a.button.nav-main__link (@ :href "https://django-liveview-demo.andros.dev/" :target "_blank") "Demo"))
(:li.nav-main__item
(:a.button.nav-main__link (@ :href "/books/" :class ,(when (string= "books" navigator-active) class-name-navigator-active)) "Books"))
(:li.nav-main__item
(:a.button.nav-main__link (@ :href "/source-code/" :class ,(when (string= "source code" navigator-active) class-name-navigator-active)) "Source code"))))))
,tree-content
(:footer.footer
(:div.container
(:ul.footer_nav
(:li (:i (@ :aria-label "bug") "🪲") " Bugs: " (:a.link (@ :href "https://github.com/Django-LiveView/docs/blob/main/one.org" :target "_blank") "Documentation"))
(:li (:i (@ :aria-label "chat") "💬") " Get help: "(:a.link (@ :href "xmpp:[email protected]?join" :target "_blank") "Jabber/XMPP group "))
(:li (:i (@ :aria-label "chat") "🐘") " Follow me: " (:a.link (@ :href "https://activity.andros.dev/@andros" :target "_blank") "ActivityPub/Fediverse "))
(:li (:span (@ :aria-hidden "true") "💰 ") " Support the project: " (:a.link (@ :href "https://liberapay.com/androsfenollosa/" :target "_blank") "Liberapay")))
(:p "Created with " (:i (@ :aria-label "love") "❤️") " by " (:a.link (@ :href "https://andros.dev/" :target "_blank") "Andros Fenollosa") " with " (:a.link (@ :href "https://one.tonyaldon.com/" :target "_blank") "one.el"))
(:p "🐍 " ,(format-time-string "%Y")))))))))
(defun one-custom-default-page (page-tree pages _global)
"Default render function by home page."
(let* ((title (org-element-property :raw-value page-tree))
(description (org-element-property :DESCRIPTION page-tree))
(navigator-active (org-element-property :NAVIGATOR-ACTIVE page-tree))
(path (org-element-property :CUSTOM_ID page-tree))
(content (org-export-data-with-backend
(org-element-contents page-tree)
'one-ox nil))
(website-name (one-default-website-name pages))
(nav (one-default-nav path pages)))
(render-layout-html
title
description
navigator-active
(jack-html `(:main.main
(:section
(:div.container ,content)))))))
(defun one-custom-default-home (page-tree pages _global)
"Default render function by home page."
(let* ((title (org-element-property :TITLE page-tree))
(path (org-element-property :CUSTOM_ID page-tree))
(description (org-element-property :DESCRIPTION page-tree))
(navigator-active (org-element-property :NAVIGATOR-ACTIVE page-tree))
(content (org-export-data-with-backend
(org-element-contents page-tree)
'one-ox nil))
(website-name (one-default-website-name pages))
(nav (one-default-nav path pages)))
(render-layout-html
title
description
navigator-active
(jack-html `(:main.main
(:section.hero
(:div.container
(:hgroup.hero__hgroup
(:h1.hero__title "Django LiveView")
(:h2.hero__subtitle "Framework for creating Realtime SPAs using HTML over the Wire technology")
(:img.image.hero__logo (@ :alt "pet" :src "img/pet.webp")))))
(:section.home
(:div.container ,content)))))))
(defun one-custom-default-doc (page-tree pages _global)
"Default render function by home page."
(let* ((title (org-element-property :raw-value page-tree))
(description (org-element-property :DESCRIPTION page-tree))
(navigator-active (org-element-property :NAVIGATOR-ACTIVE page-tree))
(path (org-element-property :CUSTOM_ID page-tree))
(content (org-export-data-with-backend
(org-element-contents page-tree)
'one-ox nil))
(website-name (one-default-website-name pages))
(nav (one-default-nav path pages)))
(render-layout-html
title
description
navigator-active
(jack-html `(:div.container.docs
(:aside.aside-docs
(:nav.nav-docs
(:ul.nav__list.nav__list--docs.nav-docs__list
(:li.nav-docs__item
(:a.nav-docs__link (@ :href "/docs/install/") "Install"))
(:li.nav-docs__item
(:a.nav-docs__link (@ :href "/docs/actions/") "Actions"))
(:li.nav-docs__item
(:a.nav-docs__link (@ :href "/docs/views/") "Views"))
(:li.nav-docs__item
(:a.nav-docs__link (@ :href "/docs/routing/") "Routing"))
(:li.nav-docs__item
(:a.nav-docs__link (@ :href "/docs/forms/") "Forms"))
(:li.nav-docs__item
(:a.nav-docs__link (@ :href "/docs/history/") "History"))
(:li.nav-docs__item
(:a.nav-docs__link (@ :href "/docs/internationalization/") "Internationalization"))
(:li.nav-docs__item
(:a.nav-docs__link (@ :href "/docs/loading/") "Loading"))
(:li.nav-docs__item
(:a.nav-docs__link (@ :href "/docs/lost-connection/") "Lost connection"))
(:li.nav-docs__item
(:a.nav-docs__link (@ :href "/docs/deploy/") "Deploy"))
(:li.nav-docs__item
(:a.nav-docs__link (@ :href "/docs/faq/") "FAQ"))
)))
(:main.main.main--docs
,content))))))
(defun one-custom-default-tutorials (page-tree pages _global)
"Default render function by tutorials page."
(let* ((title (org-element-property :raw-value page-tree))
(description (org-element-property :DESCRIPTION page-tree))
(navigator-active (org-element-property :NAVIGATOR-ACTIVE page-tree))
(path (org-element-property :CUSTOM_ID page-tree))
(content (org-export-data-with-backend
(org-element-contents page-tree)
'one-ox nil))
(website-name (one-default-website-name pages))
(nav (one-default-nav path pages)))
(render-layout-html
title
description
navigator-active
(jack-html `(:main.main
(:section.tutorials
(:div.container ,content)))))))
;; Sitemap
(defun make-sitemap (pages tree global)
"Produce file ./public/sitemap.txt"
(with-temp-file "./public/sitemap.txt"
(insert
(mapconcat 'identity (mapcar
(lambda (page)
(let* ((path (plist-get page :one-path))
(link (concat "https://" domain path)))
link
))
pages) "\n"))))
(add-hook 'one-hook 'make-sitemap)