require "lfs"
require "eluadoc"
-- Uncomment this when generating offline docs
-- local is_offline = true
-- Languages in the system
-- NOTE: "en" must ALWAYS be the first entry in this array!
-- NOTE: all languages must be given in lowercase only!
languages = { "en", "pt" }
-- Reverse lookup (language to idx) dictionary
local langidx = {}
for k, v in ipairs( languages ) do
langidx[ v ] = k
end
-------------------------------------------------------------------------------
-- Indexes into our menu table (defined in docdata.lua)
name_idx, link_idx, submenu_idx , title_idx = 1, 2, 3, 4
-------------------------------------------------------------------------------
-- "getstr" support (return strings in different languages)
-- If defaults to english (but gives a warning) if the string isn't found in the given language
-- This table keeps the strings we already emitted warnings for
-- After all, we don't want to drive the user crazy
local warned = {}
function getstr( str, lang )
-- Get the language index from langidx
local idx = langidx[ lang ]
if not idx then error( string.format( "Invalid language %s", lang ) ) end
-- Look from the string in the "translations" table
local where
for _, v in ipairs( translations ) do
if v[ 1 ] == str then
where = v
break
end
end
if not where then error( string.format( "String %s not found in translations" , str ) ) end
-- Try to return the value in the specified language
-- If not possible, return the value in english, but issue a warning first
local res = where[ idx ]
if not res then
res = where[ 1 ]
if not warned[ str ] then
print( string.format( "*** WARNING: translation for '%s' in language '%s' not found!", str, lang ) )
warned[ str ] = true
end
end
return res
end
-------------------------------------------------------------------------------
-- Generic helper functions
-- Remove anchor from a link of the form a/b.../baselink.html#anchor
local function get_base_link( name )
return ( name:gsub( "#.*", "" ) )
end
-- Get the menu field for a given item and language
-- Returns the english name is the field for the specified language can't be found
local function get_menu_field( menuitem, lang, fieldidx )
if not menuitem[ fieldidx ] then
return nil
else
if type( menuitem[ fieldidx ] ) == "string" then
return menuitem[ fieldidx ]
else
local lidx = langidx[ lang ]
return menuitem[ fieldidx ][ lidx ] or menuitem[ fieldidx ][ 1 ]
end
end
end
-- Get the menu name for a given menu item and a language
-- Returns the english name if the name for the specified language can't be found
local function get_menu_name( menuitem, lang )
return get_menu_field( menuitem, lang, name_idx )
end
-- Get the link for a given menu item and a language
-- Returns the english name if the name for the specified language can't be found
-- If the link field doesn't exists, the name is returned instead
local function get_menu_title( menuitem, lang )
return get_menu_field( menuitem, lang, title_idx ) or get_menu_field( menuitem, lang, name_idx )
end
-- Set "print" to print indented (with 2 spaces)
local oldprint
local function indent_print()
oldprint = print
print = function( ... ) io.write( " " ); oldprint( ... ) end
end
-- Restore the "regular" print function
local function regular_print()
print = oldprint
end
-------------------------------------------------------------------------------
-- File/directory operations helpers
-- Copy the given file to the 'dest' directory
-- Doesn't do error checking
local function copy_file( fname, dst )
local destname = fname
if fname:find( "/" ) then
-- Get only the filename from the path
local sidx
for f = #fname, 1, -1 do
if fname:sub( f, f ) == "/" then
sidx = f
break
end
end
destname = fname:sub( sidx + 1 )
end
local fsrc = io.open( fname, "rb" )
local fdst = io.open( string.format( "%s/%s", dst, destname ), "wb" )
local data = fsrc:read( "*a" )
fdst:write( data )
fsrc:close()
fdst:close()
end
-- Copy the 'src' directory to the 'dst' directory, going recursively through
-- its content. Doesn't do error checking.
local function copy_dir_rec( src, dst )
for f in lfs.dir( src ) do
local oldf = string.format( "%s/%s", src, f )
local attrs = lfs.attributes( oldf )
if attrs.mode == 'directory' and f ~= "." and f ~= ".." and f ~= ".svn" then
local newdir = string.format( "%s/%s", dst, f )
lfs.mkdir( newdir )
copy_dir_rec( oldf, newdir )
elseif attrs.mode == 'file' then
copy_file( oldf, dst )
end
end
end
-- Remove a directory recusively
-- USE WITH CARE!! Doesn't do much checks :)
local function rm_dir_rec( dirname )
for f in lfs.dir( dirname ) do
local ename = string.format( "%s/%s", dirname, f )
local attrs = lfs.attributes( ename )
if attrs.mode == 'directory' and f ~= '.' and f ~= '..' then
rm_dir_rec( ename )
elseif attrs.mode == 'file' or attrs.mode == 'named pipe' or attrs.mode == 'link' then
os.remove( ename )
end
end
lfs.rmdir( dirname )
end
-- Copy a directory to another directory
local function copy_dir( src, dst )
local newdir = string.format( "%s/%s", dst, src )
lfs.mkdir( newdir )
copy_dir_rec( src, newdir )
end
-------------------------------------------------------------------------------
-- Build the list of files that must be processed starting from the menu data
-- Traverse a second (or higher) level menu and add relevant information to flist
local function traverse_list( item, parentid, flist )
if not item[ link_idx ] then return end
local base = get_base_link( item[ link_idx ] )
if base ~= "" and not flist[ base ] then
flist[ base ] = { parentid = parentid, item = item }
end
if item[ submenu_idx ] then
for i = 1, #item[ submenu_idx ] do
traverse_list( item[ submenu_idx ][ i ], parentid, flist )
end
end
end
-- Iterate over the menu list, building the list of files that must be
-- processed by the doc generator. Returns a dictionary with list, parent_id
-- pairs where parent_id is the parent menu of link in themenu
local function get_file_list()
local flist = {}
for i = 1, #themenu do
traverse_list( themenu[ i ], i, flist )
end
return flist
end
-- Returns true if the given string begins with the given substring, false otherwise
-- The comparation is case-insensitive
local function beginswith( str, prefix )
return str:sub( 1, #prefix ):lower() == prefix:lower()
end
-------------------------------------------------------------------------------
-- Build the navigation data for a given page
-- Helper function: format a link starting from language and link
-- Links marked as "#" ("null" links) are left alone
local function get_link( lang, link )
return link == "#" and "#" or string.format( "%s_%s", lang, link )
end
-- Helper for gen_html_nav: generate the submenu(s) for a given top level menu item
local function gen_submenus( item, lang, level )
level = level or 1
local data = ''
local lidx = langidx[ lang ]
local arrptr = ''
for i = 1, #item do
local l = item[ i ]
if l[ submenu_idx ] then
data = data .. string.rep( " ", level * 2 + 8 ) .. string.format( '
(.-)
', "%1
" )
orig = orig:gsub( 'target="_blank"', "" )
-- Generate actual data
local header = string.format( [[