2024-06-21 23:08:58 +05:30
;; Set the package installation directory so that packages aren't stored in the
;; ~/.emacs.d/elpa path.
( require 'package )
( setq package-user-dir ( expand-file-name " ./.packages " ) )
( setq package-archives ' ( ( " melpa " . " https://melpa.org/packages/ " )
2024-08-17 23:54:55 +05:30
( " melpa-stable " . " https://stable.melpa.org/packages/ " )
2024-06-21 23:08:58 +05:30
( " elpa " . " https://elpa.gnu.org/packages/ " ) ) )
;; Initialize the package system
( package-initialize )
( unless package-archive-contents
( package-refresh-contents ) )
2024-08-17 23:54:55 +05:30
;; Install use-package
( unless ( package-installed-p 'use-package )
( package-install 'use-package ) )
( require 'use-package )
;;; see these later
;; Require built-in dependencies
( require 'vc-git )
( require 'ox-publish )
( require 'subr-x )
( require 'cl-lib )
2024-06-21 23:08:58 +05:30
;; Install dependencies
( package-install 'htmlize )
( package-install 'ox-gemini )
;; Load the publishing system
( require 'ox-publish )
( use-package ox-gemini )
2024-08-17 23:54:55 +05:30
;; Install other dependencies
( use-package esxml
:pin " melpa-stable "
:ensure t )
( use-package htmlize
:ensure t )
( use-package webfeeder
:ensure t )
( defvar yt-iframe-format
( concat " <div class= \" video \" > "
" <iframe src= \" https://www.youtube.com/embed/%s \" allowfullscreen></iframe> "
" </div> " ) )
( defun my/embed-video ( video-id )
( format yt-iframe-format video-id ) )
( setq user-full-name " Dibyashanu Pati " )
( setq user-mail-address " dibyashanu@protonmail.com " )
( defvar my/site-url ( if ( string-equal ( getenv " CI " ) " true " )
" https://cosmicflow.space "
" http://localhost:8080 " )
" The URL for the site being generated. " )
( defun my/site-header ( )
( list ` ( header ( @ ( class " site-header " ) )
( div ( @ ( class " container " ) )
( div ( @ ( class " site-title " ) )
( img ( @ ( class " logo " )
( src " /pics/sc_logo.png " )
( alt " Cosmicflow " ) ) ) ) )
( div ( @ ( class " site-masthead " ) )
( div ( @ ( class " container " ) )
( nav ( @ ( class " nav " ) )
( a ( @ ( class " nav-link " ) ( href " / " ) ) " Home " ) " "
2025-03-02 10:10:00 +05:30
( a ( @ ( class " nav-link " ) ( href " /exocortex/ " ) ) " Thought Garden " ) " "
2024-08-17 23:54:55 +05:30
( a ( @ ( class " nav-link " ) ( href " /blogs/ " ) ) " Blog " ) " "
2025-03-02 10:10:00 +05:30
( a ( @ ( class " nav-link " ) ( href " https://cosmicflow.space:3030/ " ) ) " Git " ) " "
2024-08-17 23:54:55 +05:30
( a ( @ ( class " nav-link " ) ( href " /about/ " ) ) " About " ) " "
( a ( @ ( class " nav-link " ) ( href " /contact/ " ) ) " PGP " ) " "
( a ( @ ( class " nav-link " ) ( href " /links/ " ) ) " Links " ) " "
2024-08-19 00:36:52 +05:30
( a ( @ ( class " nav-link " ) ( href " /gallery/ " ) ) " Gallery " ) " "
2024-08-17 23:54:55 +05:30
;; (a (@ (class "nav-link") (href "https://store.systemcrafters.net?utm_source=sc-site-nav")) "Store") " "
( a ( @ ( class " nav-link " ) ( href " /news/ " ) ) " News " ) ) ) ) ) ) )
( defun my/site-footer ( )
( list ` ( footer ( @ ( class " site-footer " ) )
( div ( @ ( class " container " ) )
( div ( @ ( class " row " ) )
( div ( @ ( class " column " ) )
( p ( a ( @ ( href " /privacy_policy/ " ) ) " Privacy Policy " )
" · "
( a ( @ ( href " /credits/ " ) ) " Credits " )
" · "
2025-03-02 14:40:08 +05:30
( a ( @ ( href " https://cosmicflow.space:3030/DibyashanuPati/cosmicflow " ) ) " Source Code " )
2024-08-17 23:54:55 +05:30
;; " · "
;; (a (@ (rel "me") (href "https://fosstodon.org/@daviwil")) "Fediverse"))
2025-01-23 03:54:05 +05:30
( p " © 2024-2025 Dibyashanu Pati - Except where otherwise noted, this work is licensed under http://creativecommons.org/licenses/by/3.0/ "
2024-08-17 23:54:55 +05:30
( img ( @ ( class " column align-left " )
( src " /pics/CCLogoColorPop1.gif " )
( style " width: 40px " )
2025-01-29 00:38:55 +05:30
( alt " Creative Commons " ) ) )
( img ( @ ( class " column align-left " )
( src " /pics/brainmade-88x31-dark.png " )
( style " width: 60px " )
( alt " brainmade.org " ) ) )
)
2024-08-17 23:54:55 +05:30
)
)
) ) ) ) )
( defun get-article-output-path ( org-file pub-dir )
( let ( ( article-dir ( concat pub-dir
( downcase
( file-name-as-directory
( file-name-sans-extension
( file-name-nondirectory org-file ) ) ) ) ) ) )
( if ( string-match " \\ /index.org \\ | \\ /404.org$ " org-file )
pub-dir
( progn
( unless ( file-directory-p article-dir )
( make-directory article-dir t ) )
article-dir ) ) ) )
( defun my/get-commit-hash ( )
" Get the short hash of the latest commit in the current repository. "
( string-trim-right
( with-output-to-string
( with-current-buffer standard-output
( vc-git-command t nil nil " rev-parse " " --short " " HEAD " ) ) ) ) )
( cl-defun my/generate-page ( title
content
info
&key
( publish-date )
( head-extra )
( pre-content )
( exclude-header )
( exclude-footer ) )
( concat
" <!-- Generated from " ( my/get-commit-hash ) " on " ( format-time-string " %Y-%m-%d @ %H:%M " ) " with " org-export-creator-string " --> \n "
" <!DOCTYPE html> "
( sxml-to-xml
` ( html ( @ ( lang " en " ) )
( head
( meta ( @ ( charset " utf-8 " ) ) )
( meta ( @ ( author " Cosmicflow - Dibyashanu Pati " ) ) )
( meta ( @ ( name " viewport " )
( content " width=device-width, initial-scale=1, shrink-to-fit=no " ) ) )
( link ( @ ( rel " icon " ) ( type " image/png " ) ( href " /img/favicon.png " ) ) )
( link ( @ ( rel " alternative " )
( type " application/rss+xml " )
( title " System Crafters News " )
( href " /rss/news.xml " ) ) )
( link ( @ ( rel " stylesheet " ) ( href " /fonts/iosevka-aile/iosevka-aile.css " ) ) )
( link ( @ ( rel " stylesheet " ) ( href " /fonts/jetbrains-mono/jetbrains-mono.css " ) ) )
( link ( @ ( rel " stylesheet " ) ( href " /css/code.css " ) ) )
( link ( @ ( rel " stylesheet " ) ( href " /css/site.css " ) ) )
;; (script (@ (defer "defer")
;; (data-domain "systemcrafters.net")
;; (src "https://plausible.io/js/plausible.js"))
;; ;; Empty string to cause a closing </script> tag
;; "")
;; ,(when head-extra head-extra)
( title , ( concat title " - Cosmicflow " ) ) )
( body ,@ ( unless exclude-header
( my/site-header ) )
( div ( @ ( class " container " ) )
( div ( @ ( class " site-post " ) )
( h1 ( @ ( class " site-post-title " ) )
, title )
, ( when publish-date
` ( p ( @ ( class " site-post-meta " ) ) , publish-date ) )
, ( if-let ( ( video-id ( plist-get info :video ) ) )
( my/embed-video video-id ) )
, ( when pre-content pre-content )
( div ( @ ( id " content " ) )
, content ) )
)
,@ ( unless exclude-footer
( my/site-footer ) ) ) ) ) ) )
( defun my/org-html-template ( contents info )
( my/generate-page ( org-export-data ( plist-get info :title ) info )
contents
info
:publish-date ( org-export-data ( org-export-get-date info " %B %e, %Y " ) info ) ) )
( defun my/org-html-link ( link contents info )
" Removes file extension and changes the path into lowercase file:// links. "
( when ( and ( string= 'file ( org-element-property :type link ) )
( string= " org " ( file-name-extension ( org-element-property :path link ) ) ) )
( org-element-put-property link :path
( downcase
( file-name-sans-extension
( org-element-property :path link ) ) ) ) )
2024-12-06 16:36:42 +05:30
;; (let ((exported-link (org-export-custom-protocol-maybe link contents 'html info)))
;; (cond
;; (exported-link exported-link)
;; ((equal contents nil)
;; (format "<a href=\"%s\">%s</a>"
;; (org-element-property :raw-link link)
;; (org-element-property :raw-link link)))
;; ((string-prefix-p "/" (org-element-property :raw-link link))
;; (format "<a href=\"%s\">%s</a>"
;; (org-element-property :raw-link link)
;; contents))
;; (t (org-export-with-backend 'html link contents info))))
( let ( ( exported-link ( org-export-custom-protocol-maybe link contents 'html info ) ) )
( cond
( exported-link exported-link )
( ( equal contents nil )
( format " <a href= \" %s \" >%s</a> "
( org-element-property :raw-link link )
( org-element-property :raw-link link ) ) )
( ( string-prefix-p " / " ( org-element-property :raw-link link ) )
( format " <a href= \" %s \" >%s</a> "
( org-element-property :raw-link link )
contents ) )
( ( and ( string-match-p ( concat " \\ . " ( regexp-opt ' ( " jpg " " jpeg " " png " " gif " ) ) )
( org-element-property :raw-link link ) )
( not ( equal contents nil ) ) )
( format " <img src= \" %s \" alt= \" %s \" style= \" max-width: 100%%; height: auto; \" > "
( org-element-property :raw-link link )
contents ) )
( t ( org-export-with-backend 'html link contents info ) ) ) )
)
2024-08-17 23:54:55 +05:30
( defun my/make-heading-anchor-name ( headline-text )
( thread-last headline-text
( downcase )
( replace-regexp-in-string " " " - " )
( replace-regexp-in-string " [^[:alnum:]_-] " " " ) ) )
( defun my/org-html-headline ( headline contents info )
( let* ( ( text ( org-export-data ( org-element-property :title headline ) info ) )
( level ( org-export-get-relative-level headline info ) )
( level ( min 7 ( when level ( 1+ level ) ) ) )
( anchor-name ( my/make-heading-anchor-name text ) )
( attributes ( org-element-property :ATTR_HTML headline ) )
( container ( org-element-property :HTML_CONTAINER headline ) )
( container-class ( and container ( org-element-property :HTML_CONTAINER_CLASS headline ) ) ) )
( when attributes
( setq attributes
( format " %s " ( org-html--make-attribute-string
( org-export-read-attribute 'attr_html ` ( nil
( attr_html , ( split-string attributes ) ) ) ) ) ) ) )
( concat
( when ( and container ( not ( string= " " container ) ) )
( format " <%s%s> " container ( if container-class ( format " class= \" %s \" " container-class ) " " ) ) )
( if ( not ( org-export-low-level-p headline info ) )
( format " <h%d%s><a id= \" %s \" class= \" anchor \" href= \" #%s \" >¶</a>%s</h%d>%s "
level
( or attributes " " )
anchor-name
anchor-name
text
level
( or contents " " ) )
( concat
( when ( org-export-first-sibling-p headline info ) " <ul> " )
( format " <li>%s%s</li> " text ( or contents " " ) )
( when ( org-export-last-sibling-p headline info ) " </ul> " ) ) )
( when ( and container ( not ( string= " " container ) ) )
( format " </%s> " ( cl-subseq container 0 ( cl-search " " container ) ) ) ) ) ) )
( defun my/org-html-src-block ( src-block _contents info )
( let* ( ( lang ( org-element-property :language src-block ) )
( code ( org-html-format-code src-block info ) ) )
( format " <pre>%s</pre> " ( string-trim code ) ) ) )
2024-12-06 16:36:42 +05:30
;; (defun my/org-html-special-block (special-block contents info)
;; "Transcode a SPECIAL-BLOCK element from Org to HTML.
;; CONTENTS holds the contents of the block. INFO is a plist
;; holding contextual information."
;; (let* ((block-type (org-element-property :type special-block))
;; (attributes (org-export-read-attribute :attr_html special-block)))
;; (format "<div class=\"%s center\">\n%s\n</div>"
;; block-type
;; (or contents
;; (if (string= block-type "cta")
;; "If you find this guide helpful, please consider supporting System Crafters via the links on the <a href=\"/how-to-help/#support-my-work\">How to Help</a> page!"
;; "")))))
2024-08-17 23:54:55 +05:30
( org-export-define-derived-backend 'site-html 'html
:translate-alist
' ( ( template . my/org-html-template )
( link . my/org-html-link )
( src-block . my/org-html-src-block )
2024-12-06 16:36:42 +05:30
;; (special-block . my/org-html-special-block)
2024-08-17 23:54:55 +05:30
( headline . my/org-html-headline ) )
:options-alist
' ( ( :video " VIDEO " nil nil ) ) )
( defun org-html-publish-to-html ( plist filename pub-dir )
" Publish an org file to HTML, using the FILENAME as the output directory. "
( let ( ( article-path ( get-article-output-path filename pub-dir ) ) )
( cl-letf ( ( ( symbol-function 'org-export-output-file-name )
( lambda ( extension &optional subtreep pub-dir )
;; The 404 page is a special case, it must be named "404.html"
( concat article-path
( if ( string= ( file-name-nondirectory filename ) " 404.org " ) " 404 " " index " )
extension ) ) ) )
( org-publish-org-to 'site-html
filename
( concat " . " ( or ( plist-get plist :html-extension )
" html " ) )
plist
article-path ) ) ) )
( defun my/rss-extract-title ( html-file )
" Extract the title from an HTML file. "
( with-temp-buffer
( insert-file-contents html-file )
( let ( ( dom ( libxml-parse-html-region ( point-min ) ( point-max ) ) ) )
( dom-text ( car ( dom-by-class dom " site-post-title " ) ) ) ) ) )
( defun my/rss-extract-date ( html-file )
" Extract the post date from an HTML file. "
( with-temp-buffer
( insert-file-contents html-file )
( let* ( ( dom ( libxml-parse-html-region ( point-min ) ( point-max ) ) )
( date-string ( dom-text ( car ( dom-by-class dom " site-post-meta " ) ) ) )
( parsed-date ( parse-time-string date-string ) )
( day ( nth 3 parsed-date ) )
( month ( nth 4 parsed-date ) )
( year ( nth 5 parsed-date ) ) )
;; NOTE: Hardcoding this at 8am for now
( encode-time 0 0 8 day month year ) ) ) )
( setq webfeeder-title-function #' my/rss-extract-title
webfeeder-date-function #' my/rss-extract-date )
;; (setq org-publish-use-timestamps-flag nil)
;; (setq org-html-validation-link nil
;; org-html-head-include-scripts nil
;; org-html-head-include-default-style nil
;; org-html-preamble nil
;; org-html-postamble nil
;; org-html-use-infojs nil
;; )
( setq org-publish-use-timestamps-flag t
org-publish-timestamp-directory " ./.org-cache/ "
org-export-with-section-numbers nil
org-export-use-babel nil
org-export-with-smart-quotes t
org-export-with-sub-superscripts nil
org-export-with-tags 'not-in-toc
org-html-htmlize-output-type 'css
org-html-prefer-user-labels t
;; org-html-link-home my/site-url
org-html-link-use-abs-url t
org-html-link-org-files-as-html t
org-html-html5-fancy t
org-html-self-link-headlines t
org-export-with-toc nil
make-backup-files nil )
( setq org-publish-project-alist
( list ' ( " cosmicflow:main "
:base-directory " ./content "
:base-extension " org "
:publishing-directory " ./public/cosmicflow-html "
:publishing-function org-html-publish-to-html
:with-title nil
;;:with-author nil
;;:with-creator nil
;;:email nil
:with-timestamps nil )
' ( " cosmicflow:assets "
:base-directory " ./assets "
:base-extension " css \\ |js \\ |png \\ |jpg \\ |gif \\ |pdf \\ |mp3 \\ |ogg \\ |woff2 \\ |ttf "
:publishing-directory " ./public/cosmicflow-html "
:recursive t
:publishing-function org-publish-attachment )
' ( " cosmicpirates-gmi "
:base-directory " ./content "
:base-extension " org "
:publishing-directory " ./public/cosmicflow-gmi "
:recursive t
:publishing-function org-gemini-publish-to-gemini
:with-author nil
:with-creator nil
:email nil
:with-timestamps nil )
;; ("cosmicpirates-gmi-static"
;; :base-directory "./content/static"
;; :base-extension "css\\|ttf\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|xml\\|html"
;; :publishing-directory "./public/cosmicpirates.space-gmi/static"
;; :recursive t
;; :publishing-function org-publish-attachment
;; export txt file as txt file in org html website publish
;; )
)
2024-06-21 23:08:58 +05:30
)
2024-08-17 23:54:55 +05:30
;; (defun my/publish ()
;; "Publish the entire site."
;; (interactive)
;; (org-publish-all (string-equal (or (getenv "FORCE")
;; (getenv "CI"))
;; "true"))
;; (webfeeder-build "rss/news.xml"
;; "./public"
;; my/site-url
;; (let ((default-directory (expand-file-name "./public/")))
;; (remove "news/index.html"
;; (directory-files-recursively "news"
;; ".*\\.html$")))
;; :builder 'webfeeder-make-rss
;; :title "cosmiflow news"
;; :description "News and Insights from Cosmicflow!"
;; :author "Dibyashanu Pati")
;; )
2024-06-21 23:08:58 +05:30
;; publish the websites
( org-publish-all t )
( message " Build complete! " )