if not modules then modules = { } end modules ['back-exp-imp-tag'] = { version = 1.001, comment = "companion to back-exp.mkiv", author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", copyright = "PRAGMA ADE / ConTeXt Development Team", license = "see context related readme files" } -- Because we run into the 200 locals limit we now split the file into smaller -- parts. local tonumber = tonumber local todimen = number.todimen local sortedkeys, sortedhash, setmetatableindex, concat, insert = table.sortedkeys, table.sortedhash, table.setmetatableindex, table.concat, table.insert local settings_to_hash = utilities.parsers.settings_to_hash local lpegmatch = lpeg.match local formatters = string.formatters local references = structures.references local structurestags = structures.tags local taglist = structurestags.taglist local specifications = structurestags.specifications local properties = structurestags.properties local locatedtag = structurestags.locatedtag local backend = structurestags.backend local setattribute = backend.setattribute local extras = backend.extras local checks = backend.checks local fixes = backend.fixes local listdata = backend.listdata local finalizers = backend.finalizers local usedstyles = backend.usedstyles -- for now local usedimages = backend.usedimages -- for now local referencehash = backend.referencehash local destinationhash = backend.destinationhash local implement = interfaces.implement do local itemgroups = { } local function setitemgroup(packed,level,symbol) itemgroups[locatedtag("itemgroup")] = { packed = packed, symbol = symbol, level = level, } end local function setitem(kind) itemgroups[locatedtag("item")] = { kind = kind, } end function extras.itemgroup(di,element,n,fulltag) local hash = itemgroups[fulltag] if hash then setattribute(di,"packed",hash.packed and "yes" or nil) setattribute(di,"symbol",hash.symbol) setattribute(di,"level",hash.level) end end function extras.item(di,element,n,fulltag) local hash = itemgroups[fulltag] if hash then local kind = hash.kind if kind and kind ~= "" then setattribute(di,"kind",kind) end end end implement { name = "settagitemgroup", actions = setitemgroup, arguments = { "boolean", "integer", "string" } } implement { name = "settagitem", actions = setitem, arguments = "string" } structurestags.setitemgroup = setitemgroup structurestags.setitem = setitem end do local registered = structures.sections.registered local function resolve(di,element,n,fulltag) local data = listdata[fulltag] if data then extras.addreference(di,data.references) return true else local data = di.data if data then for i=1,#data do local di = data[i] if di then local ft = di.fulltag if ft and resolve(di,element,n,ft) then return true end end end end end end function extras.section(di,element,n,fulltag) local r = registered[specifications[fulltag].detail] if r then setattribute(di,"level",r.level) end resolve(di,element,n,fulltag) end local floats = { } local function setfloat(options,method) floats[locatedtag("float")] = { options = options, method = method, } end function extras.float(di,element,n,fulltag) local hash = floats[fulltag] if hash then local method = hash.method if not method or method == "" then method = "here" end setattribute(di,"method",method) local options = hash.options if options and options ~= "" then options = settings_to_hash(options) options[method] = nil options = concat(sortedkeys(options),",") if #options > 0 then setattribute(di,"options",options) end end end resolve(di,element,n,fulltag) end implement { name = "settagfloat", actions = setfloat, arguments = "2 strings", } structurestags.setfloat = setfloat end do local registered = { } local function setformulacontent(n) registered[locatedtag("formulacontent")] = { n = n, } end function extras.formulacontent(di,element,n,fulltag) local r = registered[fulltag] if r then setattribute(di,"n",r.n) end end implement { name = "settagformulacontent", actions = setformulacontent, arguments = "integer", } structurestags.setformulacontent = setformulacontent end do local symbols = { } local function settagdelimitedsymbol(symbol) symbols[locatedtag("delimitedsymbol")] = { symbol = symbol, } end function extras.delimitedsymbol(di,element,n,fulltag) local hash = symbols[fulltag] if hash then setattribute(di,"symbol",hash.symbol or nil) end end implement { name = "settagdelimitedsymbol", actions = settagdelimitedsymbol, arguments = "string" } structurestags.settagdelimitedsymbol = settagdelimitedsymbol end do local symbols = { } local function settagsubsentencesymbol(symbol) symbols[locatedtag("subsentencesymbol")] = { symbol = symbol, } end function extras.subsentencesymbol(di,element,n,fulltag) local hash = symbols[fulltag] if hash then setattribute(di,"symbol",hash.symbol or nil) end end implement { name = "settagsubsentencesymbol", actions = settagsubsentencesymbol, arguments = "string" } structurestags.settagsubsentencesymbol = settagsubsentencesymbol end do local synonyms = { } local sortings = { } local function setsynonym(tag) synonyms[locatedtag("synonym")] = tag end function extras.synonym(di,element,n,fulltag) local tag = synonyms[fulltag] if tag then setattribute(di,"tag",tag) end end local function setsorting(tag) sortings[locatedtag("sorting")] = tag end function extras.sorting(di,element,n,fulltag) local tag = sortings[fulltag] if tag then setattribute(di,"tag",tag) end end implement { name = "settagsynonym", actions = setsynonym, arguments = "string" } implement { name = "settagsorting", actions = setsorting, arguments = "string" } structurestags.setsynonym = setsynonym structurestags.setsorting = setsorting end do local descriptions = { } local symbols = { } local linked = { } -- we could move the notation itself to the first reference (can be an option) local function setnotation(tag,n) -- needs checking (is tag needed) -- we can also use the internals hash or list local nd = structures.notes.get(tag,n) if nd then local references = nd.references descriptions[references and references.internal] = locatedtag("description") end end local function setnotationsymbol(tag,n) -- needs checking (is tag needed) local nd = structures.notes.get(tag,n) -- todo: use listdata instead if nd then local references = nd.references symbols[references and references.internal] = locatedtag("descriptionsymbol") end end function finalizers.descriptions(tree) local n = 0 for id, tag in sortedhash(descriptions) do local sym = symbols[id] if sym then n = n + 1 linked[tag] = n linked[sym] = n end end end function extras.description(di,element,n,fulltag) local id = linked[fulltag] if id then setattribute(di,"insert",id) end end function extras.descriptionsymbol(di,element,n,fulltag) local id = linked[fulltag] if id then setattribute(di,"insert",id) end end implement { name = "settagnotation", actions = setnotation, arguments = { "string", "integer" } } implement { name = "settagnotationsymbol", actions = setnotationsymbol, arguments = { "string", "integer" } } structurestags.setnotation = setnotation structurestags.setnotationsymbol = setnotationsymbol end do local strippedtag = structurestags.strip -- we assume global styles local highlight = { } local construct = { } usedstyles.highlight = highlight usedstyles.construct = construct local function sethighlight(name,style,color,mode) if not highlight[name] then highlight[name] = { style = style, color = color, mode = mode == 1 and "display" or nil, } end end local function setconstruct(name,style,color,mode) if not construct[name] then construct[name] = { style = style, color = color, mode = mode == 1 and "display" or nil, } end end implement { name = "settagconstruct", actions = setconstruct, arguments = { "string", "string", "integer", "integer" } } implement { name = "settaghighlight", actions = sethighlight, arguments = { "string", "string", "integer", "integer" } } structurestags.sethighlight = sethighlight structurestags.setconstruct = setconstruct end do local f_id = formatters["%s-%s"] local image = { } usedimages.image = image structurestags.usewithcare.images = image local function setfigure(name,used,page,width,height,label) local fulltag = locatedtag("image") local spec = specifications[fulltag] if spec then local page = tonumber(page) image[fulltag] = { id = f_id(spec.tagname,spec.tagindex), name = name, used = used, page = page and page > 1 and page or nil, width = todimen(width, "cm","%0.3F%s"), height = todimen(height,"cm","%0.3F%s"), label = label, } else -- we ignore images in layers in the background / pagebody end end function extras.image(di,element,n,fulltag) local data = image[fulltag] if data then setattribute(di,"name",data.name) setattribute(di,"page",data.page) setattribute(di,"id",data.id) setattribute(di,"width",data.width) setattribute(di,"height",data.height) setattribute(di,"label",data.height) end end implement { name = "settagfigure", actions = setfigure, arguments = { "string", "string", "string", "dimen", "dimen", "string" } } structurestags.setfigure = setfigure end do local combinations = { } local function setcombination(nx,ny) combinations[locatedtag("combination")] = { nx = nx, ny = ny, } end function extras.combination(di,element,n,fulltag) local data = combinations[fulltag] if data then setattribute(di,"nx",data.nx) setattribute(di,"ny",data.ny) end end implement { name = "settagcombination", actions = setcombination, arguments = { "integer", "integer" } } structurestags.setcombination = setcombination end do local function hascontent(data) for i=1,#data do local di = data[i] if not di or di.tg == "ignore" then -- else local content = di.content if content == " " then -- elseif content then return true else local d = di.data if d and #d > 0 and hascontent(d) then return true end end end end end local tabledata = { } local function settablecell(rows,columns,align) if align > 0 or rows > 1 or columns > 1 then -- or kind > 0 tabledata[locatedtag("tablecell")] = { rows = rows, columns = columns, align = align, } end end local function gettablecell(fulltag) return tabledata[fulltag] end function extras.tablecell(di,element,n,fulltag) local hash = tabledata[fulltag] if hash then local columns = hash.columns if columns and columns > 1 then setattribute(di,"columns",columns) end local rows = hash.rows if rows and rows > 1 then setattribute(di,"rows",rows) end local align = hash.align if not align or align == 0 then -- normal elseif align == 1 then -- use numbertoalign here setattribute(di,"align","flushright") elseif align == 2 then setattribute(di,"align","middle") elseif align == 3 then setattribute(di,"align","flushleft") end end end local tabulatedata = { } local function settabulatecell(align,kind) if align > 0 or kind > 0 then tabulatedata[locatedtag("tabulatecell")] = { align = align, kind = kind, -- 1 = bold head } end end local function gettabulatecell(fulltag) return tabulatedata[fulltag] end function extras.tabulate(di,element,n,fulltag) local data = di.data for i=1,#data do local di = data[i] if di.tg == "tabulaterow" and not hascontent(di.data) then di.element = "" -- or simply remove end end end function extras.tabulatecell(di,element,n,fulltag) local hash = tabulatedata[fulltag] if hash then local align = hash.align if not align or align == 0 then -- normal elseif align == 1 then setattribute(di,"align","flushleft") elseif align == 2 then setattribute(di,"align","flushright") elseif align == 3 then setattribute(di,"align","middle") end local kind = hash.kind if kind == 1 then setattribute(di,"kind","strong") elseif kind == 2 then setattribute(di,"kind","equals") end end end implement { name = "settagtablecell", actions = settablecell, arguments = { "integer", "integer", "integer" } } implement { name = "settagtabulatecell", actions = settabulatecell, arguments = { "integer", "integer" }, } structurestags.settablecell = settablecell structurestags.gettablecell = gettablecell structurestags.settabulatecell = settabulatecell structurestags.gettabulatecell = gettabulatecell end do -- todo: internal is already hashed local p_stripper = lpeg.patterns.stripper local function setregister(tag,n) -- check if tag is needed local data = structures.registers.get(tag,n) if data then referencehash[locatedtag("registerlocation")] = data end end function extras.registerlocation(di,element,n,fulltag) local data = referencehash[fulltag] if type(data) == "table" then extras.addinternal(di,data.references) return true else -- needs checking, probably bookmarks end end function extras.registerpages(di,element,n,fulltag) -- ignorebreaks local data = di.data for i=1,#data do local d = data[i] if d.content == " " then d.content = "" end end end function extras.registerseparator(di,element,n,fulltag) -- ignorespaces local data = di.data for i=1,#data do local d = data[i] local c = d.content if type(c) == "string" then d.content = lpegmatch(p_stripper,c) end end end implement { name = "settagregister", actions = setregister, arguments = { "string", "integer" } } structurestags.setregister = setregister end do -- todo: internal is already hashed local function setlist(n) local data = structures.lists.getresult(n) if data then referencehash[locatedtag("listitem")] = data end end function extras.listitem(di,element,n,fulltag) local data = referencehash[fulltag] if data then extras.addinternal(di,data.references) return true end end implement { name = "settaglist", actions = setlist, arguments = "integer" } structurestags.setlist = setlist end do local usedpublications = { } local tagsindatasets = setmetatableindex("table") local serialize = false local function setpublication(dataset,tag,rendering) usedpublications[locatedtag("publication")] = { dataset = dataset, tag = tag, rendering = rendering } tagsindatasets[dataset][tag] = true if not serialize then structures.tags.registerextradata("btx",function() local t = { ""} for dataset, used in sortedhash(tagsindatasets) do t[#t+1] = publications.converttoxml(dataset,true,false,true,false,true,true) end t[#t+1] = "" return concat(t,"\n") end) end end function extras.publication(di,element,n,fulltag) local hash = usedpublications[fulltag] if hash then setattribute(di,"dataset",hash.dataset) setattribute(di,"tag",hash.tag) end end implement { name = "settagpublication", actions = setpublication, arguments = "2 strings" } structurestags.setpublication = setpublication end do local usedparagraphs = { } local function setparagraph(align) if align ~= "" then usedparagraphs[locatedtag("paragraph")] = { align = align, } end end function extras.paragraph(di,element,n,fulltag) local hash = usedparagraphs[fulltag] if hash then setattribute(di,"align",hash.align) end end implement { name = "settagparagraph", actions = setparagraph, arguments = "string" } structurestags.setparagraph = setparagraph end do local marginanchors = { } local margincontent = { } function checks.margintext(di) local i = marginanchors[di.fulltag] margincontent[i] = di end function checks.marginanchor(di) local i = marginanchors[di.fulltag] local d = margincontent[i] -- di.attribute = d.attribute di.data = d.data di.detail = d.detail di.element = d.element di.fulltag = d.fulltag di.nature = d.nature di.samepar = true di.tg = d.tg -- d.skip = "ignore" end implement { name = "settagmargintext", arguments = "integer", actions = function(n) marginanchors[locatedtag("margintext")] = n end } implement { name = "settagmarginanchor", arguments = "integer", actions = function(n) marginanchors[locatedtag("marginanchor")] = n end } end do function fixes.linenumber(di,data,i) local ni = data[i+1] if ni then if ni.data then while true do local d = ni.data[1] if d then local e = d.element if e then if e == "line" or e == "verbatimline" then insert(d.data,1,di) data[i] = false return else ni = d end else return end else return end end end end end end do local usedcodepoints = { } local function checkcodepoint(di,element,n,fulltag) local unicode = usedcodepoints[fulltag] if unicode then setattribute(di,"codepoint",unicode) end end local function setcodepoint(tag,unicode) usedcodepoints[locatedtag(tag)] = unicode if not extras[tag] then extras[tag] = checkcodepoint end end implement { name = "settagcodepoint", actions = setcodepoint, arguments = { "argument", "integer" }, } structurestags.setcodepoint = setcodepoint end