lua generator
This commit is contained in:
parent
b931ab0070
commit
c5fe6f2833
|
@ -0,0 +1,488 @@
|
||||||
|
meta = {
|
||||||
|
domain = "compudanzas.net",
|
||||||
|
title = "compudanzas",
|
||||||
|
description = "explorations of computing at a human scale",
|
||||||
|
fecha = os.date("%Y-%m-%d")
|
||||||
|
}
|
||||||
|
|
||||||
|
webdir = "webtest" -- web output directory
|
||||||
|
gemdir = "gemtest" -- gemini output directory
|
||||||
|
templates = {
|
||||||
|
webEn = {
|
||||||
|
header = { path = "pageheader.html", template = ""},
|
||||||
|
footer = { path = "pagefooter.html", template = ""},
|
||||||
|
incoming = { path = "pageincoming.html", template = ""}
|
||||||
|
},
|
||||||
|
gemEn = {
|
||||||
|
header = { path = "pageheader.gmi", template = ""},
|
||||||
|
footer = { path = "pagefooter.gmi", template = ""},
|
||||||
|
incoming = { path = "pageincoming.gmi", template = ""}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
pages = {}
|
||||||
|
|
||||||
|
function slugify( s )
|
||||||
|
return (string.gsub( s, "%s", "_" ))
|
||||||
|
end
|
||||||
|
|
||||||
|
function spacify( s ) -- opposite of slugify (?)
|
||||||
|
return (string.gsub( s, "_", " "))
|
||||||
|
end
|
||||||
|
|
||||||
|
function fillTemplate( template, pagemeta )
|
||||||
|
return ( string.gsub( template, "({.-})", function (key)
|
||||||
|
local var = string.sub(key,2,-2) -- remove { }
|
||||||
|
return meta[var] or pagemeta[var]
|
||||||
|
end) )
|
||||||
|
end
|
||||||
|
|
||||||
|
function getHeader( line ) -- returns title, level
|
||||||
|
local head, title = string.match(line,"^(#+)%s*(.-)$")
|
||||||
|
return title, #head
|
||||||
|
end
|
||||||
|
|
||||||
|
function getLink( line ) -- returns dest, text
|
||||||
|
return string.match( line, "^=>%s*(%S-)%s+(.-)$")
|
||||||
|
end
|
||||||
|
|
||||||
|
function isImagePath( text )
|
||||||
|
return text:match(".jpg$") or text:match(".gif$") or text:match(".png$")
|
||||||
|
end
|
||||||
|
|
||||||
|
function sanitize( line ) -- replace relevant html entities
|
||||||
|
return line:gsub("<","<"):gsub(">",">")
|
||||||
|
end
|
||||||
|
|
||||||
|
function closeTags()
|
||||||
|
local close = ""
|
||||||
|
if flags.list then
|
||||||
|
close = "</ul>\n"
|
||||||
|
flags.list = false
|
||||||
|
elseif flags.p then
|
||||||
|
close = "</p>\n"
|
||||||
|
flags.p = false
|
||||||
|
elseif flags.gallery then
|
||||||
|
close = "</gallery>\n"
|
||||||
|
flags.gallery = false
|
||||||
|
end
|
||||||
|
|
||||||
|
return close
|
||||||
|
end
|
||||||
|
|
||||||
|
function insertIncoming( pagename, incomingname )
|
||||||
|
if incomingname == "pages" then return false end
|
||||||
|
|
||||||
|
local incoming = pages[pagename].incoming
|
||||||
|
for i = 1, #incoming do
|
||||||
|
if incoming[i] == incomingname then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert( incoming, incomingname)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function firstPass()
|
||||||
|
-- load templates
|
||||||
|
for _,t in pairs(templates) do
|
||||||
|
-- read templates
|
||||||
|
for k,subtemp in pairs( t ) do
|
||||||
|
local f = assert(io.open(string.format("templates/%s",subtemp.path),"r"))
|
||||||
|
subtemp.template = f:read("a")
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- for each page:
|
||||||
|
-- convert gmo to gmi and html
|
||||||
|
-- and calculate incoming links
|
||||||
|
for name,page in pairs(pages) do
|
||||||
|
local pagemeta = pages[name]
|
||||||
|
|
||||||
|
local gmopath = string.format("src/%s.gmo", pagemeta.slug)
|
||||||
|
|
||||||
|
-- open file
|
||||||
|
local f = assert( io.open(gmopath, "r") )
|
||||||
|
|
||||||
|
-- initialize flags
|
||||||
|
flags = { list = false, pre = false , p = false, gallery = false }
|
||||||
|
|
||||||
|
-- table to store the lines to write to file
|
||||||
|
local lines = { web = {}, gem = {} }
|
||||||
|
|
||||||
|
-- convert one line at a time
|
||||||
|
local count = 1
|
||||||
|
for line in f:lines() do
|
||||||
|
-- the output line:
|
||||||
|
local out = { gem = line, web = nil}
|
||||||
|
|
||||||
|
if count == 1 then -- extract title
|
||||||
|
pagemeta.ptitle = string.match(line, "^#+%s*(.-)$")
|
||||||
|
elseif count == 2 then -- language
|
||||||
|
if line == "" then
|
||||||
|
pagemeta.lang = "en,es-MX" -- default
|
||||||
|
else
|
||||||
|
pagemeta.lang, pagemeta.trlang, pagemeta.trname = string.match("^lang=(.-)%s(.-)->(.-)$")
|
||||||
|
end
|
||||||
|
elseif count == 3 then -- obtain page description
|
||||||
|
pagemeta.pdescription,n = string.gsub(line,"[{}]","")
|
||||||
|
end
|
||||||
|
|
||||||
|
if count <=2 then goto nextline end -- skip normal processing for the first lines
|
||||||
|
|
||||||
|
-- CONVERT LINES
|
||||||
|
if string.match( line, "^```") then -- preformated
|
||||||
|
if flags.pre then
|
||||||
|
out.web = "</pre>"
|
||||||
|
else
|
||||||
|
out.web = "<pre>"
|
||||||
|
end
|
||||||
|
flags.pre = not flags.pre
|
||||||
|
goto insert -- skip more checks
|
||||||
|
end
|
||||||
|
|
||||||
|
if flags.pre then
|
||||||
|
out.web = sanitize( line )
|
||||||
|
goto insert
|
||||||
|
end
|
||||||
|
|
||||||
|
if string.match( line, "^%+") then -- + append html
|
||||||
|
out.gem = nil
|
||||||
|
out.web = string.sub(line,3) -- remove "+ "
|
||||||
|
|
||||||
|
elseif string.match( line, "^&") then -- & append gemtext
|
||||||
|
out.gem = string.sub(line,3) -- remove "& "
|
||||||
|
|
||||||
|
elseif string.match( line, "^$") then -- empty line
|
||||||
|
out.web = closeTags()
|
||||||
|
|
||||||
|
elseif string.match( line, "^#+") then -- HEADERS
|
||||||
|
-- TODO create nav
|
||||||
|
local title, level = getHeader( line )
|
||||||
|
|
||||||
|
local close = closeTags()
|
||||||
|
out.web = string.format("%s<h%d>%s</h%d>",close,level,title,level)
|
||||||
|
|
||||||
|
elseif string.match( line, "^>") then -- BLOCKQUOTE
|
||||||
|
local close = closeTags()
|
||||||
|
out.web = string.format("%s<blockquote>%s</blockquote>", close, string.sub(line,3))
|
||||||
|
|
||||||
|
elseif string.match( line, "^%*") then -- LIST ITEMS
|
||||||
|
local li = string.format("<li>%s</li>", string.sub(line,3)) -- remove "* "
|
||||||
|
if not flags.list then -- start list
|
||||||
|
out.web = string.format("<ul>\n%s", li)
|
||||||
|
flags.list = true
|
||||||
|
else -- append list element
|
||||||
|
out.web = li
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif string.match( line, "^=>") then -- LINKS
|
||||||
|
local dest, text = getLink( line )
|
||||||
|
if string.match( dest, "^%./") then --local links
|
||||||
|
local t = string.match( text, "^{(.-)}$" )
|
||||||
|
if t ~= nil then -- wikilink
|
||||||
|
local close = closeTags()
|
||||||
|
out.web = string.format("%s<p><a href='%s' class='arrow'>%s</a></p>",close,dest,t)
|
||||||
|
|
||||||
|
elseif isImagePath( dest ) then -- images
|
||||||
|
local img = string.format('<img src="%s" alt="%s" loading="lazy"/>',dest,text)
|
||||||
|
if not flags.gallery then
|
||||||
|
local close = closeTags()
|
||||||
|
out.web = string.format("%s<gallery>\n%s", close, img)
|
||||||
|
flags.gallery = true
|
||||||
|
else
|
||||||
|
out.web = img
|
||||||
|
end
|
||||||
|
|
||||||
|
else -- other files
|
||||||
|
local close = closeTags()
|
||||||
|
out.web = string.format("%s<p><a href='%s'>%s</a></p>",close,dest,text)
|
||||||
|
end
|
||||||
|
|
||||||
|
else -- external links
|
||||||
|
out.web = string.format('<p><a href="%s" rel="external noreferrer noopener" target=_blank class="arrow">%s</a></p>', dest, text)
|
||||||
|
end
|
||||||
|
|
||||||
|
else -- PARAGRAPHS
|
||||||
|
-- web
|
||||||
|
-- search and replace wikilinks
|
||||||
|
local webline = string.gsub( line, "{(.-)}", function (wikiname)
|
||||||
|
return string.format("<a href='./%s.html'>%s</a>", pages[wikiname].slug, wikiname)
|
||||||
|
end)
|
||||||
|
if not flags.p then
|
||||||
|
out.web = string.format("<p>%s", webline)
|
||||||
|
flags.p = true
|
||||||
|
else
|
||||||
|
out.web = string.format("<br/>\n%s",webline)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- gem
|
||||||
|
local gemlinks = {}
|
||||||
|
local gemline = string.gsub( line, "{(.-)}", function (wikiname)
|
||||||
|
table.insert(gemlinks, string.format("=> ./%s.gmi %s",pages[wikiname].slug, wikiname))
|
||||||
|
return wikiname
|
||||||
|
end)
|
||||||
|
|
||||||
|
out.gem = gemline
|
||||||
|
-- append links if there were any
|
||||||
|
if #gemlinks > 0 then
|
||||||
|
out.gem = out.gem.."\n"..table.concat(gemlinks,"\n")
|
||||||
|
end
|
||||||
|
end -- paragraphs
|
||||||
|
|
||||||
|
::insert:: -- insert line in table
|
||||||
|
for k,l in pairs(out) do
|
||||||
|
if l ~= nil then
|
||||||
|
table.insert( lines[k], l )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- skip incoming links calculation if <pre> mode
|
||||||
|
if flags.pre then goto nextline end
|
||||||
|
|
||||||
|
-- calculate incoming links from outgoing
|
||||||
|
for outname in string.gmatch( line, "{([^ ]?.-[^ ]?)}" ) do
|
||||||
|
insertIncoming( outname, name )
|
||||||
|
end
|
||||||
|
|
||||||
|
::nextline::
|
||||||
|
count = count + 1
|
||||||
|
end -- end for line in f:lines()
|
||||||
|
|
||||||
|
-- finalize html
|
||||||
|
local close = closeTags()
|
||||||
|
if isPre then
|
||||||
|
table.insert( lines.web, "</pre>" )
|
||||||
|
elseif close~="" then
|
||||||
|
table.insert( lines.web, close )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set templates
|
||||||
|
pagemeta.outs.web.templates = templates.webEn
|
||||||
|
pagemeta.outs.gem.templates = templates.gemEn
|
||||||
|
|
||||||
|
-- fill templates and write results
|
||||||
|
for key, out in pairs(pagemeta.outs) do
|
||||||
|
local fo = assert( io.open( out.path, "w" ) )
|
||||||
|
fo:write( fillTemplate(out.templates.header.template, pagemeta) )
|
||||||
|
fo:write( table.concat( lines[key],"\n" )) -- content
|
||||||
|
fo:write( "\n" )
|
||||||
|
fo:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- close source file
|
||||||
|
f:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function secondPass() -- write incoming links and footer
|
||||||
|
|
||||||
|
for name,page in pairs(pages) do
|
||||||
|
local pagemeta = page
|
||||||
|
|
||||||
|
local doIncoming = true
|
||||||
|
if #pagemeta.incoming > 0 then
|
||||||
|
local gemlines = {}
|
||||||
|
local weblines = { "<p>" }
|
||||||
|
|
||||||
|
-- format list of incoming links
|
||||||
|
for i = 1, #pagemeta.incoming do
|
||||||
|
name = pagemeta.incoming[i]
|
||||||
|
slug = pages[name].slug
|
||||||
|
table.insert( gemlines, string.format("=> ./%s.gmi %s",slug,name) )
|
||||||
|
table.insert( weblines, string.format("<a href='./%s.html'>%s</a> ",slug,name) )
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(weblines,"</p>")
|
||||||
|
|
||||||
|
page.gemincoming = table.concat( gemlines, "\n" )
|
||||||
|
page.webincoming = table.concat( weblines )
|
||||||
|
|
||||||
|
else
|
||||||
|
doIncoming = false
|
||||||
|
print( string.format("{%s} is an orphan!", name) )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- fill incoming and footer templates and write results
|
||||||
|
for key, out in pairs(pagemeta.outs) do
|
||||||
|
local fo = assert( io.open( out.path, "a" ) )
|
||||||
|
if doIncoming then
|
||||||
|
fo:write( fillTemplate(out.templates.incoming.template, pagemeta) )
|
||||||
|
end
|
||||||
|
fo:write( fillTemplate(out.templates.footer.template, pagemeta) )
|
||||||
|
fo:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function initPageMetadata( name ) -- return a table with metadata
|
||||||
|
local meta = {
|
||||||
|
incoming = {},
|
||||||
|
slug = slugify(name), name = name,
|
||||||
|
ptitle = "", pdescription = "",
|
||||||
|
updatedate = "",
|
||||||
|
navcontent = "",
|
||||||
|
gemincoming = "", webincoming = "",
|
||||||
|
}
|
||||||
|
meta.outs = {
|
||||||
|
web = { path = string.format("%s/%s.html", webdir, meta.slug) },
|
||||||
|
gem = { path = string.format("%s/%s.gmi", gemdir, meta.slug) }
|
||||||
|
}
|
||||||
|
-- get update date for file
|
||||||
|
local stat = io.popen(string.format("stat -c %%y src/%s.gmo", meta.slug),"r")
|
||||||
|
local dat = stat:read("l")
|
||||||
|
stat:close()
|
||||||
|
meta.updatedate = string.sub(dat, 1, 10) -- YYYY-MM-DD
|
||||||
|
return meta
|
||||||
|
end
|
||||||
|
|
||||||
|
function genIndex()
|
||||||
|
local indexpath = "src/pages.gmo"
|
||||||
|
|
||||||
|
-- initialize and open index file
|
||||||
|
os.execute(string.format("cp templates/index.gmi %s",indexpath))
|
||||||
|
local index = assert( io.open(indexpath,"a" ) )
|
||||||
|
|
||||||
|
-- get gmo files in chronological order
|
||||||
|
local gmofiles = io.popen("ls -t src/*gmo")
|
||||||
|
for filename in gmofiles:lines() do
|
||||||
|
local basename = string.sub(filename, 5, -5) -- remove src/ and .gmo
|
||||||
|
local name = spacify(basename)
|
||||||
|
-- create an entry for each file
|
||||||
|
local entry = string.format("=> ./%s.gmi {%s}\n", basename, name)
|
||||||
|
index:write(entry)
|
||||||
|
|
||||||
|
-- also initialize each name in the pages table
|
||||||
|
-- initialize page metadata
|
||||||
|
pages[ name ] = initPageMetadata( name )
|
||||||
|
|
||||||
|
end
|
||||||
|
gmofiles:close()
|
||||||
|
index:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
function genLog()
|
||||||
|
-- generate the following log files:
|
||||||
|
-- * twtxt gemini and web
|
||||||
|
-- * atom feed gemini and web
|
||||||
|
-- * gmo log
|
||||||
|
-- * gmisub
|
||||||
|
|
||||||
|
local logsrc = assert( io.open( "src/log.txt", "r" ) )
|
||||||
|
|
||||||
|
local logs = {
|
||||||
|
gemtw = { path = string.format("%s/tw.txt",gemdir), head="templates/twheader.txt" },
|
||||||
|
webtw = { path = string.format("%s/tw.txt",webdir), head="templates/twheader.txt" },
|
||||||
|
gmolog = { path = "src/log.gmo", head="templates/logheader.gmi" },
|
||||||
|
gematom = { path = string.format("%s/atom.xml",gemdir), head="templates/gematomheader.txt" },
|
||||||
|
webatom = { path = string.format("%s/atom.xml",webdir), head="templates/webatomheader.txt" },
|
||||||
|
gemfeed = { path = string.format("%s/feed.gmi",gemdir), head="templates/feedheader.gmi" }
|
||||||
|
}
|
||||||
|
|
||||||
|
-- create and open logs
|
||||||
|
for _,log in pairs(logs) do
|
||||||
|
os.execute(string.format("cp %s %s",log.head,log.path))
|
||||||
|
log.f = assert( io.open( log.path, "a" ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
logs.gematom.f:write(string.format("<updated>%sT12:00:00Z</updated>\n",fecha))
|
||||||
|
logs.webatom.f:write(string.format("<updated>%sT12:00:00Z</updated>\n",fecha))
|
||||||
|
|
||||||
|
|
||||||
|
-- process each line of log.txt
|
||||||
|
for line in logsrc:lines() do
|
||||||
|
local pattern = "^(.-)%s(.-)%s{(.-)}$"
|
||||||
|
local timestamp, text, wikilink = string.match(line,pattern)
|
||||||
|
local slug = slugify(wikilink)
|
||||||
|
local date = string.sub(timestamp,1,10) -- YYYY-MM-DD
|
||||||
|
|
||||||
|
-- gmo log
|
||||||
|
local gmoformat = "## %s\n%s\n=> ./%s.gmi {%s}\n\n"
|
||||||
|
logs.gmolog.f:write(string.format(gmoformat, date, text, slug, wikilink))
|
||||||
|
|
||||||
|
-- twtxt
|
||||||
|
local weburl = string.format("https://%s/%s.html",domain,slug)
|
||||||
|
local gemurl = string.format("gemini://%s/%s.gmi",domain,slug)
|
||||||
|
local twtxtformat = "%s\t%s | %s\n"
|
||||||
|
logs.webtw.f:write(string.format(twtxtformat, timestamp, text, weburl))
|
||||||
|
logs.gemtw.f:write(string.format(twtxtformat, timestamp, text, gemurl))
|
||||||
|
|
||||||
|
-- atom
|
||||||
|
local weburldate = string.format("https://%s/%s.html#%s",domain,slug,date)
|
||||||
|
local atomformat = [[
|
||||||
|
|
||||||
|
<entry>
|
||||||
|
<title>%s</title>
|
||||||
|
<updated>%s</updated>
|
||||||
|
<link rel='alternate' href='%s'/>
|
||||||
|
<id>%s</id>
|
||||||
|
</entry>
|
||||||
|
]]
|
||||||
|
logs.webatom.f:write(string.format(atomformat, text, timestamp, weburldate, weburldate))
|
||||||
|
logs.gematom.f:write(string.format(atomformat, text, timestamp, gemurl, gemurl))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--close logs
|
||||||
|
logs.webatom.f:write("</feed>\n")
|
||||||
|
logs.gematom.f:write("</feed>\n")
|
||||||
|
for _,log in pairs(logs) do
|
||||||
|
log.f:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
logsrc:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- THE SCRIPT
|
||||||
|
|
||||||
|
-- create directories
|
||||||
|
os.execute(string.format("mkdir -p %s/static %s/img %s/img tmp",webdir,webdir,gemdir))
|
||||||
|
|
||||||
|
print(meta.fecha)
|
||||||
|
|
||||||
|
-- clean up
|
||||||
|
print("limpiando archivos previos...")
|
||||||
|
os.execute(string.format("find %s -iname *.html -exec rm {} \\;", webdir))
|
||||||
|
os.execute(string.format("find %s -iname *.gmi -exec rm {} \\;", gemdir))
|
||||||
|
os.execute("find tmp -iname *.gmo -exec rm {} \\;")
|
||||||
|
|
||||||
|
-- copy images
|
||||||
|
print("copiando imágenes y otros archivos...")
|
||||||
|
local imgs = io.popen("ls src/img/")
|
||||||
|
for img in imgs:lines() do
|
||||||
|
os.execute(string.format("cp -vu src/img/%s %s/img/", img, webdir))
|
||||||
|
os.execute(string.format("cp -vu src/img/%s %s/img/", img, gemdir))
|
||||||
|
end
|
||||||
|
imgs:close()
|
||||||
|
|
||||||
|
-- copy stylesheet and misc files
|
||||||
|
os.execute(string.format("cp -vu templates/estilo.css %s/static/",webdir))
|
||||||
|
|
||||||
|
local miscfiles = { "src/llave_sejo.asc" }
|
||||||
|
for k = 1, #miscfiles do
|
||||||
|
os.execute(string.format("cp -vu %s %s/", miscfiles[k], webdir))
|
||||||
|
os.execute(string.format("cp -vu %s %s/", miscfiles[k], gemdir))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- generate log files
|
||||||
|
print("generando log...")
|
||||||
|
genLog()
|
||||||
|
|
||||||
|
-- generate index
|
||||||
|
print("generando índice de páginas...")
|
||||||
|
genIndex()
|
||||||
|
|
||||||
|
-- start first pass
|
||||||
|
-- converting from gmo to gmi and html and calculating incoming links
|
||||||
|
print("convirtiendo páginas...")
|
||||||
|
firstPass()
|
||||||
|
-- second pass, write incoming links
|
||||||
|
print("escribiendo incoming links...")
|
||||||
|
secondPass()
|
||||||
|
|
||||||
|
print("listx!")
|
|
@ -0,0 +1,100 @@
|
||||||
|
/* links externos */
|
||||||
|
a[rel^=external]:after{ content: "↗"; }
|
||||||
|
a{
|
||||||
|
color: #857;
|
||||||
|
}
|
||||||
|
a:visited{
|
||||||
|
color: #404;
|
||||||
|
}
|
||||||
|
a.icon{
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
/* gemtext-like format */
|
||||||
|
/* h1:before{ content: "# "; }
|
||||||
|
h2:before{ content: "## "; }
|
||||||
|
h3:before{ content: "### "; }*/
|
||||||
|
a.arrow:before{ content: "⇒ "; }
|
||||||
|
body{
|
||||||
|
color: #100;
|
||||||
|
max-width:36em;
|
||||||
|
margin:0 auto;
|
||||||
|
font-size:18px;
|
||||||
|
padding: 1em;
|
||||||
|
font-family:sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer{
|
||||||
|
font-size: x-small;
|
||||||
|
padding-top:2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer img{
|
||||||
|
margin:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre{
|
||||||
|
background-color: #edd;
|
||||||
|
color: #433;
|
||||||
|
padding:1em;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote{
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
main h1{
|
||||||
|
margin-top: 1.5em;
|
||||||
|
font-size: xx-large;
|
||||||
|
}
|
||||||
|
main h2{
|
||||||
|
font-size: x-large;
|
||||||
|
margin-left:0.3em;
|
||||||
|
}
|
||||||
|
main h3{
|
||||||
|
font-size: larger;
|
||||||
|
margin-left:1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
gallery{
|
||||||
|
display:flex;
|
||||||
|
flex-direction:row;
|
||||||
|
flex-wrap:wrap;
|
||||||
|
justify-content:space-evenly;
|
||||||
|
align-content:center;
|
||||||
|
}
|
||||||
|
img{
|
||||||
|
margin:10px;
|
||||||
|
border-radius:5px;
|
||||||
|
max-width: 320px;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav{ font-size:smaller; }
|
||||||
|
nav li{ padding:0.2em; }
|
||||||
|
main li{ padding:0.5em; }
|
||||||
|
|
||||||
|
table {
|
||||||
|
font-size: smaller;
|
||||||
|
max-width: 90%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 1em auto;
|
||||||
|
text-align:left;
|
||||||
|
}
|
||||||
|
table th {
|
||||||
|
border-bottom: 1px solid black;
|
||||||
|
padding: 0.1em 1em;
|
||||||
|
}
|
||||||
|
table td {
|
||||||
|
padding: 0.1em 1em;
|
||||||
|
}
|
||||||
|
td.num{
|
||||||
|
text-align:right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* desktop */
|
||||||
|
@media screen and (min-width: 600px) {
|
||||||
|
nav li{
|
||||||
|
display:inline;
|
||||||
|
}
|
||||||
|
img{ max-width: 100%; }
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
# compudanzas
|
||||||
|
|
||||||
|
our gemsub feed
|
||||||
|
|
||||||
|
see also:
|
||||||
|
=> ./log.gmi log
|
||||||
|
|
||||||
|
# entries
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<feed xmlns='http://www.w3.org/2005/Atom'>
|
||||||
|
|
||||||
|
<id>gemini://compudanzas.net/</id>
|
||||||
|
<title>compudanzas</title>
|
||||||
|
<author><name>sejo</name></author>
|
||||||
|
<generator>genlog</generator>
|
||||||
|
<link href='gemini://compudanzas.net/atom.xml' rel='self'/>
|
||||||
|
<link href='gemini://compudanzas.net/log.gmi' rel='alternate'/>
|
|
@ -0,0 +1,4 @@
|
||||||
|
# index of pages
|
||||||
|
|
||||||
|
most recently modified, above:
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
# compudanzas log
|
||||||
|
|
||||||
|
updates of the project
|
||||||
|
|
||||||
|
=> ./tw.txt [twtxt]
|
||||||
|
=> ./atom.xml [atom feed]
|
||||||
|
& => ./feed.gmi [gemsub feed]
|
||||||
|
|
||||||
|
# entries
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
# meta
|
||||||
|
=> ./home.gmi {title}
|
||||||
|
=> ./contact.gmi contact
|
||||||
|
=> https://wiki.p2pfoundation.net/Peer_Production_License text, images, and code are shared with the peer production license
|
|
@ -0,0 +1,15 @@
|
||||||
|
</main>
|
||||||
|
<footer>
|
||||||
|
<p>
|
||||||
|
<a href='https://tildegit.org/sejo/compudanzas/src/branch/main/src/{slug}.gmo' rel='external noreferrer noopener' target=_blank>source file</a> —
|
||||||
|
most recent update:
|
||||||
|
<time datetime='{updatedate}'>1{updatedate}</time> —
|
||||||
|
<a href='gemini://{domain}/{slug}.gmi' rel='external noreferrer noopener' target=_blank>view in gemini://</a>
|
||||||
|
</p>
|
||||||
|
<hr/>
|
||||||
|
<p><a href='./about.html'>about</a> <a href='./contact.html'>contact</a> <a href='./support.html'>support</a></p>
|
||||||
|
<p><a class='icon' href='./home.html' title='compudanzas'><img src='./img/iconocompudanzas_32.png' width=32 height=32 alt='icono de compudanzas'/></a>
|
||||||
|
<a href='https://webring.xxiivv.com/#random' target='_blank' title='webring' class='icon'><img src='./img/icon.black.svg' width='32' height='32' alt='xxiivv webring'/></a></p>
|
||||||
|
<p>texts, images, and code are shared with the <a href='https://wiki.p2pfoundation.net/Peer_Production_License' target=_blank rel='external noreferrer noopener' title='Peer Production License'>peer production license</a></p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
|
@ -0,0 +1,2 @@
|
||||||
|
# {ptitle}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns='http://www.w3.org/1999/xhtml' lang='{lang}'>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||||
|
<meta content='initial-scale=1.0' name='viewport'/>
|
||||||
|
<link rel='me' href='https://sunbeam.city/@compudanzas'>
|
||||||
|
<link rel='me' href='https://post.lurk.org/@compudanzas'>
|
||||||
|
<link rel='me' href='https://merveilles.town/@sejo'>
|
||||||
|
<link rel='stylesheet' href='./static/estilo.css'>
|
||||||
|
<link rel='icon' href='./img/iconocompudanzas_16.png' type='image/png' sizes='16x16'>
|
||||||
|
<link rel='icon' href='./img/iconocompudanzas_32.png' type='image/png' sizes='32x32'>
|
||||||
|
<link rel='icon' href='./img/iconocompudanzas_64.png' type='image/png' sizes='64x64'>
|
||||||
|
<meta property='og:type' content='website' />
|
||||||
|
<meta property='og:image' content='https://compudanzas.net/img/iconocompudanzas_128_w.png'>
|
||||||
|
<meta property='og:title' content='{title} — {ptitle}'>
|
||||||
|
<meta property='og:description' content='{pdescription}'>
|
||||||
|
<meta name='description' content='{pdescription}'>
|
||||||
|
<meta property='og:url' content='https://compudanzas.net/{slug}.html'>
|
||||||
|
<title>{title} — {ptitle}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<p><a class='icon' href='./home.html' title='{title}'><img src='./img/iconocompudanzas_32.png' style='margin:0' alt='icono de compudanzas'/></a></p>
|
||||||
|
<h1>{ptitle}</h1>
|
||||||
|
</header>
|
||||||
|
<nav>
|
||||||
|
{navcontent}
|
||||||
|
</nav>
|
||||||
|
<main>
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
# incoming links
|
||||||
|
{gemincoming}
|
|
@ -0,0 +1,4 @@
|
||||||
|
<section id='incoming'>
|
||||||
|
<h1>incoming links</h1>
|
||||||
|
{webincoming}
|
||||||
|
</section>
|
|
@ -0,0 +1 @@
|
||||||
|
# nick = compudanzas
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<feed xmlns='http://www.w3.org/2005/Atom'>
|
||||||
|
|
||||||
|
<id>https://compudanzas.net/</id>
|
||||||
|
<title>compudanzas</title>
|
||||||
|
<author><name>sejo</name></author>
|
||||||
|
<generator>genlog</generator>
|
||||||
|
<link href='https://compudanzas.net/atom.xml' rel='self'/>
|
||||||
|
<link href='https://compudanzas.net/log.html' rel='alternate'/>
|
Loading…
Reference in New Issue