Ability to set the base URL for formats other than HTML? #13000
Replies: 4 comments 7 replies
-
Can you detail what you mean? What local file paths exactly? Using a Quarto Website, if you include a PDF, it will be downloadable from a URL that includes the site URL. For example Lua quick reference guide linked from https://quarto.org/docs/extensions/lua.html
A link to the document deployed in the same folder or nested folder is usually relatively included, and the site URL where the document is deployed will be used.
I see the pandoc issue is discussing root path for image. Is that the use case for site-url for single document ?
Some metadata are passed.
It would really help us if you can share a real case example of Thank you ! |
Beta Was this translation helpful? Give feedback.
-
Sure! There might be some misunderstanding so I've made a minimal demo site to make it clear. The source code can be found at sun123zxy/quarto-discussion-13000. The actual case here is to provide both a web page version and a PDF version of a QMD file in a website project, that is, having both In the index page of the demo site, there are two links and an image. The first link is
Above shows that in a website project, links in the formats other than HTML are not handled identically with those in HTML --- not prefixed by a base URL (thus referring to local file path), and no special treatment for links to
Maybe that's why images work well in the above demo? Note that this Pandoc issue is also discussing the root path for links.
Regrettably I haven't really come up with a specific use case. I thought this was somehow an intermediate step to resolve the above issue. If it is not, feel free to ignore this :) Thank you for your time! |
Beta Was this translation helpful? Give feedback.
-
|
See the following filter to replace explicit reference. Lua code--- Off-Page Cross-Links - Lua Filter
--- @module "offpage-crosslinks"
--- @license MIT
--- @copyright 2026 Mickaël Canouil
--- @author Mickaël Canouil
--- @version 0.1.0
--- @brief Rewrite cross-page links for non-HTML formats using site-url.
--- @description In non-HTML output formats, relative links to other pages
--- in a Quarto website or book project are broken. This filter rewrites
--- those links to absolute URLs using the project's site-url, so readers
--- can follow them to the live HTML site.
-- ============================================================================
-- MODULE-LEVEL VARIABLES
-- ============================================================================
--- @type string|nil The resolved site URL from project metadata
local site_url = nil
-- ============================================================================
-- HELPER FUNCTIONS (PRIVATE)
-- ============================================================================
--- Read site-url from QUARTO_EXECUTE_INFO project metadata.
--- Tries website.site-url first, then book.site-url.
--- Workaround for https://github.com/quarto-dev/quarto-cli/issues/13029
--- where project-level metadata (website/book) is not available in the
--- document Meta passed to Lua filters.
--- @return string|nil The site-url value, or nil if unavailable
local function get_site_url_from_execute_info()
local path = os.getenv('QUARTO_EXECUTE_INFO')
if not path then return nil end
local file = io.open(path, 'r')
if not file then return nil end
local content = file:read('*a')
file:close()
if not content or content == '' then return nil end
local ok, info = pcall(quarto.json.decode, content)
if not ok or not info then return nil end
local format_meta = info['format'] and info['format']['metadata']
if not format_meta then return nil end
if format_meta['website'] and format_meta['website']['site-url'] then
return format_meta['website']['site-url']
elseif format_meta['book'] and format_meta['book']['site-url'] then
return format_meta['book']['site-url']
end
return nil
end
--- Read site-url from document metadata as a fallback.
--- Tries website.site-url, then book.site-url.
--- @param meta table The document metadata table
--- @return string|nil The site-url value, or nil if not found
local function get_site_url_from_meta(meta)
local website = meta['website']
if website and website['site-url'] then
return pandoc.utils.stringify(website['site-url'])
end
local book = meta['book']
if book and book['site-url'] then
return pandoc.utils.stringify(book['site-url'])
end
return nil
end
--- Check whether a link target is a relative cross-page link.
--- Returns true for targets that point to .html or .qmd files
--- without an absolute URI scheme.
--- @param target string The link target URL
--- @return boolean True if the target is a relative page link
local function is_relative_page_link(target)
if not target or target == '' then return false end
if target:match('^#') then return false end
if target:match('^%a[%a%d+%-%.]*:') then return false end
if target:match('%.html[#?]') or target:match('%.html$') then return true end
if target:match('%.qmd[#?]') or target:match('%.qmd$') then return true end
return false
end
--- Rewrite a relative page link target to an absolute URL.
--- Normalises .qmd extensions to .html, strips leading ./, and
--- prepends the site-url.
--- @param target string The original relative link target
--- @param base_url string The site-url to prepend
--- @return string The rewritten absolute URL
local function rewrite_target(target, base_url)
local rewritten = target:gsub('%.qmd([#?])', '.html%1'):gsub('%.qmd$', '.html')
rewritten = rewritten:gsub('^%./', '')
local separator = base_url:match('/$') and '' or '/'
return base_url .. separator .. rewritten
end
-- ============================================================================
-- FILTER EXPORT
-- ============================================================================
return {
{
-- Resolve site-url from project metadata.
-- Skips entirely for HTML formats where cross-page links already work.
Meta = function(meta)
if quarto.doc.is_format('html') then return nil end
site_url = get_site_url_from_execute_info()
if not site_url then
site_url = get_site_url_from_meta(meta)
end
if not site_url then
quarto.log.warning('offpage-crosslinks: site-url not found in project metadata.')
end
return nil
end
},
{
-- Rewrite relative cross-page links to absolute URLs.
Link = function(el)
if not site_url then return nil end
if not is_relative_page_link(el.target) then return nil end
el.target = rewrite_target(el.target, site_url)
return el
end
}
} |
Beta Was this translation helpful? Give feedback.
-
|
Duplicate of: |
Beta Was this translation helpful? Give feedback.

Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Description
In a website project we have the metadata
site-urlto indicate the base URL of the site. This is well implemented in the HTML format, but it would be useful to have a similar feature for other formats like PDF.For a use case, consider a website project with PDF versions of the content. PDF files are intended to be downloaded and viewed offline, but without a base URL, the relative links in the PDF files point to local file paths, which is clearly not what we want. More generally, it calls for an option to set the base URL for an independent document, not necessarily by
site-url, which is only available in a website project.To the best of my knowledge, there's no built-in way to set a base URL for formats other than HTML in Quarto. Actually this had been discussed in a Pandoc Issue, though currently there're only manmade Lua filter resolutions. Speaking of
site-url, it's also awkward for Lua filter to workaround, because Quarto's project metadata is not passed to the Pandoc context.It would be nice if above is supported by Quarto in some form. Correct me if I'm missing something obvious. Thanks!
Beta Was this translation helpful? Give feedback.
All reactions