Org Mode releases custom picture gallery tutorial

This tutorial details how to take advantage of the Org Mode publishing feature to create and publish a custom image gallery by combining special block definitions, Emacs Lisp filter functions, and an external CSS/JavaScript gallery library. The article will guide readers through the conversion from Org tags to the final HTML structure, and provide code examples and integration steps to help users achieve highly customized image display effects and improve the interactivity and visual appeal of static websites.
Org Mode implementation strategy for publishing picture galleries
Org Mode is a powerful structured document editing tool, and its publishing capabilities make it ideal for generating static websites. However, publishing complex image galleries (such as lightbox effects or image carousels) directly through Org Mode is not its core functionality. This article will introduce a flexible and extensible method to implement custom image galleries in the Org Mode publishing process by defining Org Mode special blocks, writing Emacs Lisp filter functions to transform HTML structures, and integrating external CSS/JavaScript gallery libraries.
The advantage of this approach is that it is modular and highly customizable, allowing the user to precisely control the final HTML output according to the needs of the chosen gallery library. The entire process can be divided into three main steps:
- Define Org Mode special block : used to mark the picture gallery area in Org documents.
- Implement an Emacs Lisp filter function : convert the default HTML structure generated by Org Mode into the specific markup required by the gallery library.
- Integrate external CSS/JavaScript gallery libraries : Introduce front-end libraries to provide interactive gallery functionality.
Step 1: Define the Org Mode special block
In order to clearly identify the image gallery content in the Org document, we can make use of the Special Blocks function of Org Mode. This not only improves the readability of the document, but also provides clear boundaries for subsequent HTML conversion.
Org tag example:
#BEGIN_gallery [[file:images/test.png][Test Image]] [[file:images/psx.jpg][PlayStation]] [[file:images/IMG_1047.jpg][Telephone]] [[file:images/pants.png][Pants]] #END_gallery
In this example, we use #BEGIN_gallery and #END_gallery to wrap a set of image links. Each link contains the image path and description text. This concise markup has the following advantages:
- Semantic clarity : Make it clear that this is a gallery of images.
- Backward compatibility : Even in browsers without JavaScript or CSS, these links will display normally as normal image links and text descriptions, providing a good user experience degradation.
- Flexibility : You can choose different image link formats according to your needs, such as [[file:images/test.png]] (image only) or [[file:images/full.png][file:images/thumb.png]] (full-size image separated from thumbnail), but for the filter function of this tutorial, we choose the form [[file:images/path/image.jpg][description text]].
Step 2: Implement Emacs Lisp filter function
The Org Mode publishing process converts its special block content into HTML. In order to make these HTML fragments conform to the requirements of a specific gallery library, we need a filter function to modify the HTML generated by Org Mode by default. Here, we use Emacs Lisp's advice mechanism to enhance the org-html-special-block function to perform custom conversions when processing gallery type special blocks.
The core function of the filter function is:
- Identify the gallery special block.
- Parse its internal HTML content (Org Mode has converted [[file:images/test.png][test image]] to test image).
- Convert these links into the specific structure required by the gallery library, such as adding CSS classes, converting the text description into the
tag's alt attribute, and inserting the thumbnail path into the
tag's src attribute.
Emacs Lisp filter function example:
(defun my-html-gallery-links (args)
(let ((special-block (nth 0 args))
(contents (nth 1 args))
(info (nth 2 args)))
(if (string= (org-element-property :type special-block) "gallery")
(progn
(with-temp-buffer
(insert contents)
(goto-char (point-min))
;; Find and modify links, add imagelightbox class (while (re-search-forward "<a href="%5C%22file://%5C%5C(.*%5C%5C)%5C%22">" (point-max) t)
(setq image_filename (match-string 1))
(replace-match
(concat
"</a><a href="%5C%22%22" image_filename set class for use by javascript lightbox library>"))
(backward-char 1)
;; Replace text description with image thumbnail and move description to alt attribute (re-search-forward ">\\(.*\\)\</a>" (point-max) t)
(replace-match
(concat
"><img src="/static/imghw/default1.png" data-src="thumbs/IMG_1047.jpg" class="lazy" assume thumbnails are stored in the thumbs directory image_filename alt='\""'>")))
(setq contents
(buffer-substring-no-properties (point-min) (point-max))))
(list special-block contents info))
args)))
;; Add filter functions to org-html-special-block's :filter-args advice (advice-add 'org-html-special-block :filter-args #'my-html-gallery-links)
Code analysis:
- The my-html-gallery-links function receives parameters of org-html-special-block, including the special block object, its content and Org export information.
- It checks whether the type of the special block is "gallery".
- In the case of a gallery block, the function operates on its HTML content in a temporary buffer:
- The first re-search-forward looks for links of the form . file:// is the prefix added by Org Mode to the local file path when exporting. Pay attention to the matching.
- replace-match corrects the link's href attribute to a relative path and adds class="imagelightbox", which is how many lightbox libraries identify image links.
- The second re-search-forward looks for the textual description inside the link (e.g. >test image).
- replace-match replaces the text description with the
tag, where the src attribute points to the thumbnail path (assuming the thumbnail is located in the thumbs/ directory), and the alt attribute uses the original text description.
- Ultimately, the function returns the modified special block content, which Org Mode will use for publishing.
Comparison before and after HTML conversion:
- Before filtering (generated by Org Mode by default):
<a href="images/IMG_1047.jpg">Telephone</a>
- After filtering (processed by my-html-gallery-links):
<a href="images/IMG_1047.jpg" class="imagelightbox"><img src="/static/imghw/default1.png" data-src="thumbs/IMG_1047.jpg" class="lazy" alt="Org Mode releases custom picture gallery tutorial"></a>
Things to note:
- Thumbnail path : The example assumes that the thumbnail is located in the thumbs/ directory. You need to make sure that these thumbnail files actually exist in the directory and are copied correctly to the target site when publishing. More complex filtering functions can even be integrated with tools such as ImageMagick to automatically generate thumbnails during the publishing process.
- Regular expression : Please adjust the regular expression according to your Org Mode export settings and the specific format of the image link to ensure an accurate match.
Step 3: Integrate external CSS/JavaScript gallery libraries
The final step is to introduce a front-end gallery library to parse the HTML structure we generated and provide interactive functionality. There are many excellent gallery libraries on the market to choose from, such as Lightbox, ImageLightbox, Bootstrap Carousel, etc. This tutorial uses Osvaldas' ImageLightbox as an example because it is lightweight and easy to integrate.
Integration steps:
- Download the library files : Download ImageLightbox's JavaScript (imagelightbox.js) and CSS files (imagelightbox.css, or custom styles) to the static resource directory of your Org Mode project (for example, res/).
- Configure the Org Mode release project : In your Org Mode release project configuration, you need to do two things:
- Copy static resources : Make sure imagelightbox.js, jquery-3.6.1.js (ImageLightbox depends on jQuery), and your custom CSS files are copied to the publish directory. This is usually done via the :components attribute.
- Inject HTML header code : Use the :html-head attribute to inject and <script> tags into the <head> section of each generated page.</script>
Org Mode publishing configuration example (:html-head section in org-publish-project-alist):
(setq org-publish-project-alist
'(("my-website"
:base-directory "~/org-website/"
:publishing-directory "~/public_html/"
:components ("notes" "static")
("notes"
:base-directory "~/org-website/notes/"
:base-extension "org"
:publishing-directory "~/public_html/"
:recursive t
:html-extension "html"
:html-head "<link rel='\"stylesheet\"' href="%5C%22/res/org.css%5C%22" type='\"text/css\"'>
<script type='\"text/javascript\"' src="%5C%22/res/jquery-3.6.1.js%5C%22"></script>
<script type='\"text/javascript\"' src="%5C%22/res/imagelightbox.js%5C%22"></script>
<script type='\"text/javascript\"'> $(function () { $( 'a.imagelightbox' ).imageLightbox(); }); </script>"
:exclude "private.org")
("static"
:base-directory "~/org-website/res/"
:base-extension "css\\|js\\|png\\|jpg\\|gif\\|svg"
:publishing-directory "~/public_html/res/"
:recursive t
:exclude "tmp.txt"))))
html-head code analysis:
- : Introduce your custom CSS file, which may contain styles for the gallery.
- : Introduce jQuery library, ImageLightbox depends on it.
- : Introduce the ImageLightbox library file.
- : This is the initialization code of ImageLightbox. After the DOM is loaded, it selects all tags with the imagelightbox class and applies the ImageLightbox functionality to them.
Gallery type adaptation:
The examples in this tutorial focus on the lightbox effect. If you want to implement a carousel effect, such as Bootstrap Carousel, you need to adjust the HTML structure generated by the filter function to comply with the requirements of the library. Typically, this means wrapping the image link in a specific div element and adding the appropriate class and id attributes. For example, a Bootstrap Carousel might require the following structure:
<div id="myCarousel" class="carousel slide" data-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="/static/imghw/default1.png" data-src="path/to/image1.jpg" class="lazy" alt="Org Mode releases custom picture gallery tutorial">
</div>
<div class="carousel-item">
<img src="/static/imghw/default1.png" data-src="path/to/image2.jpg" class="lazy" alt="Description 2">
</div>
<!-- More pictures-->
</div>
<!-- Navigation buttons, etc.-->
</div>
Your filter function needs to generate such a div structure, not a simple combination. This demonstrates the high flexibility of Emacs Lisp filter functions, which can be customized to the needs of any front-end library.
Summarize
Through the above three steps - defining Org Mode special blocks, writing Emacs Lisp filter functions and integrating external CSS/JavaScript gallery libraries - we successfully added the ability to customize image galleries to Org Mode static website publishing capabilities. This approach takes full advantage of the scalability of Org Mode, allowing users to implement complex and interactive web page elements while maintaining the simplicity of Org documents.
Key points to consider:
- File Management : Ensure that all images (both thumbnails and full-size images) and JavaScript/CSS resources are placed correctly in the publish directory.
- Performance Optimization : For large numbers of images, consider optimizing the images (compression, resizing) or even integrating image processing tools in the filter function to automate this process.
- User experience : Always consider user experience degradation options without JavaScript or CSS to ensure content remains accessible.
Mastering this customized publishing process will greatly expand your possibilities for building feature-rich static websites using Org Mode.
The above is the detailed content of Org Mode releases custom picture gallery tutorial. For more information, please follow other related articles on the PHP Chinese website!
Hot AI Tools
Undress AI Tool
Undress images for free
AI Clothes Remover
Online AI tool for removing clothes from photos.
Undresser.AI Undress
AI-powered app for creating realistic nude photos
ArtGPT
AI image generator for creative art from text prompts.
Stock Market GPT
AI powered investment research for smarter decisions
Hot Article
Popular tool
Notepad++7.3.1
Easy-to-use and free code editor
SublimeText3 Chinese version
Chinese version, very easy to use
Zend Studio 13.0.1
Powerful PHP integrated development environment
Dreamweaver CS6
Visual web development tools
SublimeText3 Mac version
God-level code editing software (SublimeText3)
Hot Topics
20514
7
13627
4
How to correctly migrate jQuery's drag and drop events to native JavaScript
Mar 06, 2026 pm 05:15 PM
This article explains in detail the key pitfalls when migrating jQuery drag-and-drop logic (such as dragover/dragleave) to Vanilla JS - especially the problem of misuse of e.originalEvent causing dataTransfer failure, and provides directly runnable fixes and best practices.
How to make the images in a div fill with no margins while retaining the inner margins of the text
Mar 07, 2026 pm 10:54 PM
This article explains how to keep the overall padding of the container so that the internal images are displayed close to the edge of the container, while the text content still maintains normal padding - the core is to separate the style scope and achieve precise layout through positioning and box model control.
Solve the problem of unexpected offset of Flex container due to the font size change of the first child element
Mar 09, 2026 pm 08:15 PM
When the first child element of a Flex container dynamically adjusts the font-size, the container will be vertically offset along the inline baseline; while a normal block-level container will change in height due to the linkage between line height and font measurement. The root cause lies in the baseline alignment mechanism of the Flex container. By default, the baseline of the first child is the container baseline. This can be completely solved through vertical-align: top or explicit baseline control.
Chart.js complete implementation solution for dynamically switching chart types (line chart, bar chart, pie chart)
Mar 12, 2026 pm 08:51 PM
This article explains in detail how to safely and reliably dynamically switch chart types (line/bar/pie) in Chart.js, and solve the problem of Cannot read properties of undefined errors caused by mismatched data structures and rendering exceptions after type switching. The core lies in destroying old instances, deep copying configurations, and accurately rebuilding data structures by type.
A complete guide to using the keyboard to control the smooth movement of HTML elements
Mar 13, 2026 pm 10:18 PM
This article explains in detail why transform: translate() combined with the keydown event cannot move elements, and provides a reliable solution based on CSS positioning and JavaScript, covering absolute positioning settings, coordinate update logic, code robustness optimization, and common pitfalls.
How to properly override default styles and implement custom CSS layouts in Divi theme builder
Mar 14, 2026 am 12:00 AM
This article explains in detail the root cause of style failure when applying custom CSS in the WordPress Divi theme builder. It provides practical solutions for improving selector specificity, accurately positioning elements, and rational use of !important, as well as debugging tips and code optimization examples.
How to dynamically pass HTML form data to analytics.track() method
Mar 13, 2026 pm 10:57 PM
This article explains in detail how to safely and efficiently extract user input from HTML forms and structure it into JavaScript objects as attribute parameters of analytics.track() to avoid hard coding and syntax errors and support flexible expansion.
A general solution for implementing multiple groups of radio-select switching forms using data-id and event delegation
Mar 03, 2026 pm 11:39 PM
This article introduces a robust solution based on event delegation and data-id attributes, which solves the problem that multiple radio buttons (radio) cannot cooperatively control the display and hiding of the corresponding form. It supports the expansion of any number of options, avoids hard-coded ID judgments, and improves maintainability and scalability.





