2017-04-12 16:55:22 +00:00
|
|
|
--[[--
|
2013-10-18 20:38:07 +00:00
|
|
|
This is a registry for document providers
|
|
|
|
]]--
|
2017-04-12 16:55:22 +00:00
|
|
|
|
2023-05-28 05:04:25 +00:00
|
|
|
local DocSettings = require("docsettings")
|
2017-04-12 16:55:22 +00:00
|
|
|
local logger = require("logger")
|
2018-02-02 20:21:52 +00:00
|
|
|
local util = require("util")
|
2017-04-12 16:55:22 +00:00
|
|
|
|
2013-10-18 20:38:07 +00:00
|
|
|
local DocumentRegistry = {
|
2014-08-28 12:59:42 +00:00
|
|
|
registry = {},
|
|
|
|
providers = {},
|
2023-11-05 05:24:18 +00:00
|
|
|
known_providers = {}, -- hash table of registered providers { provider_key = provider }
|
2018-02-10 17:36:18 +00:00
|
|
|
filetype_provider = {},
|
2021-01-17 08:22:48 +00:00
|
|
|
mimetype_ext = {},
|
2023-06-12 06:08:56 +00:00
|
|
|
image_ext = {
|
|
|
|
gif = true,
|
|
|
|
jpeg = true,
|
|
|
|
jpg = true,
|
|
|
|
png = true,
|
|
|
|
svg = true,
|
|
|
|
tif = true,
|
|
|
|
tiff = true,
|
|
|
|
webp = true,
|
|
|
|
},
|
2013-10-18 20:38:07 +00:00
|
|
|
}
|
|
|
|
|
2023-11-05 05:24:18 +00:00
|
|
|
local function getSuffix(file)
|
|
|
|
return util.getFileNameSuffix(file):lower()
|
|
|
|
end
|
|
|
|
|
[feat] DocumentRegistry: add getProviders() and preferred by weight (#3651)
This is step one toward "open with".
References https://github.com/koreader/koreader/issues/3345
* Fix up some mimetypes
* Add XHTML to supported filetypes
* Add a few image files to MuPDF
* ".bmp",
* ".gif",
* ".hdp",
* ".j2k",
* ".jp2",
* ".jpeg",
* ".jpg",
* ".jpx",
* ".jxr",
* ".pam",
* ".pbm",
* ".pgm",
* ".png",
* ".pnm",
* ".ppm",
* ".tif",
* ".tiff",
* ".wdp",
2018-01-31 19:49:21 +00:00
|
|
|
function DocumentRegistry:addProvider(extension, mimetype, provider, weight)
|
2018-11-29 18:29:14 +00:00
|
|
|
extension = string.lower(extension)
|
[feat] DocumentRegistry: add getProviders() and preferred by weight (#3651)
This is step one toward "open with".
References https://github.com/koreader/koreader/issues/3345
* Fix up some mimetypes
* Add XHTML to supported filetypes
* Add a few image files to MuPDF
* ".bmp",
* ".gif",
* ".hdp",
* ".j2k",
* ".jp2",
* ".jpeg",
* ".jpg",
* ".jpx",
* ".jxr",
* ".pam",
* ".pbm",
* ".pgm",
* ".png",
* ".pnm",
* ".ppm",
* ".tif",
* ".tiff",
* ".wdp",
2018-01-31 19:49:21 +00:00
|
|
|
table.insert(self.providers, {
|
|
|
|
extension = extension,
|
|
|
|
mimetype = mimetype,
|
|
|
|
provider = provider,
|
|
|
|
weight = weight or 100,
|
|
|
|
})
|
2018-02-10 17:36:18 +00:00
|
|
|
self.filetype_provider[extension] = true
|
2021-01-17 08:22:48 +00:00
|
|
|
-- We regard the first extension registered for a mimetype as canonical.
|
Clarify our OOP semantics across the codebase (#9586)
Basically:
* Use `extend` for class definitions
* Use `new` for object instantiations
That includes some minor code cleanups along the way:
* Updated `Widget`'s docs to make the semantics clearer.
* Removed `should_restrict_JIT` (it's been dead code since https://github.com/koreader/android-luajit-launcher/pull/283)
* Minor refactoring of LuaSettings/LuaData/LuaDefaults/DocSettings to behave (mostly, they are instantiated via `open` instead of `new`) like everything else and handle inheritance properly (i.e., DocSettings is now a proper LuaSettings subclass).
* Default to `WidgetContainer` instead of `InputContainer` for stuff that doesn't actually setup key/gesture events.
* Ditto for explicit `*Listener` only classes, make sure they're based on `EventListener` instead of something uselessly fancier.
* Unless absolutely necessary, do not store references in class objects, ever; only values. Instead, always store references in instances, to avoid both sneaky inheritance issues, and sneaky GC pinning of stale references.
* ReaderUI: Fix one such issue with its `active_widgets` array, with critical implications, as it essentially pinned *all* of ReaderUI's modules, including their reference to the `Document` instance (i.e., that was a big-ass leak).
* Terminal: Make sure the shell is killed on plugin teardown.
* InputText: Fix Home/End/Del physical keys to behave sensibly.
* InputContainer/WidgetContainer: If necessary, compute self.dimen at paintTo time (previously, only InputContainers did, which might have had something to do with random widgets unconcerned about input using it as a baseclass instead of WidgetContainer...).
* OverlapGroup: Compute self.dimen at *init* time, because for some reason it needs to do that, but do it directly in OverlapGroup instead of going through a weird WidgetContainer method that it was the sole user of.
* ReaderCropping: Under no circumstances should a Document instance member (here, self.bbox) risk being `nil`ed!
* Kobo: Minor code cleanups.
2022-10-06 00:14:48 +00:00
|
|
|
-- Provided we order the calls to addProvider() correctly,
|
|
|
|
-- that means epub instead of epub3, etc.
|
2021-01-17 08:22:48 +00:00
|
|
|
self.mimetype_ext[mimetype] = self.mimetype_ext[mimetype] or extension
|
2023-11-05 05:24:18 +00:00
|
|
|
if self.known_providers[provider.provider] == nil then
|
|
|
|
self.known_providers[provider.provider] = provider
|
|
|
|
end
|
2018-02-10 17:36:18 +00:00
|
|
|
end
|
|
|
|
|
2023-11-05 05:24:18 +00:00
|
|
|
-- Register an auxiliary (non-document) provider.
|
|
|
|
-- Aux providers are modules (eg TextViewer) or plugins (eg TextEditor).
|
|
|
|
-- It does not implement the Document API.
|
|
|
|
-- For plugins the hash table value does not contain file handler,
|
|
|
|
-- but only a provider_key (provider.provider) to call the corresponding
|
|
|
|
-- plugin in FileManager:openFile().
|
|
|
|
function DocumentRegistry:addAuxProvider(provider)
|
|
|
|
self.known_providers[provider.provider] = provider
|
2018-07-28 18:30:39 +00:00
|
|
|
end
|
|
|
|
|
2018-02-10 17:36:18 +00:00
|
|
|
--- Returns true if file has provider.
|
|
|
|
-- @string file
|
2023-11-05 05:24:18 +00:00
|
|
|
-- @bool include_aux include auxiliary (non-document) providers
|
2018-02-10 17:36:18 +00:00
|
|
|
-- @treturn boolean
|
2023-11-05 05:24:18 +00:00
|
|
|
function DocumentRegistry:hasProvider(file, mimetype, include_aux)
|
2021-01-17 08:22:48 +00:00
|
|
|
if mimetype and self.mimetype_ext[mimetype] then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
if not file then return false end
|
|
|
|
|
2023-11-05 05:24:18 +00:00
|
|
|
-- registered document provider
|
|
|
|
local filename_suffix = getSuffix(file)
|
|
|
|
if self.filetype_provider[filename_suffix] then
|
2018-02-10 17:36:18 +00:00
|
|
|
return true
|
|
|
|
end
|
2023-11-05 05:24:18 +00:00
|
|
|
-- associated document or auxiliary provider for file type
|
|
|
|
local filetype_provider_key = G_reader_settings:readSetting("provider", {})[filename_suffix]
|
|
|
|
local provider = filetype_provider_key and self.known_providers[filetype_provider_key]
|
|
|
|
if provider and (not provider.order or include_aux) then -- excluding auxiliary by default
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
-- associated document provider for this file
|
2019-10-23 21:15:30 +00:00
|
|
|
if DocSettings:hasSidecarFile(file) then
|
2021-03-06 21:44:18 +00:00
|
|
|
return DocSettings:open(file):has("provider")
|
2019-10-23 21:15:30 +00:00
|
|
|
end
|
2018-02-10 17:36:18 +00:00
|
|
|
return false
|
2013-10-18 20:38:07 +00:00
|
|
|
end
|
|
|
|
|
2023-11-05 05:24:18 +00:00
|
|
|
--- Returns the preferred registered document handler or fallback provider.
|
2017-04-12 16:55:22 +00:00
|
|
|
-- @string file
|
2023-11-05 05:24:18 +00:00
|
|
|
-- @treturn table provider
|
2013-10-18 20:38:07 +00:00
|
|
|
function DocumentRegistry:getProvider(file)
|
[feat] DocumentRegistry: add getProviders() and preferred by weight (#3651)
This is step one toward "open with".
References https://github.com/koreader/koreader/issues/3345
* Fix up some mimetypes
* Add XHTML to supported filetypes
* Add a few image files to MuPDF
* ".bmp",
* ".gif",
* ".hdp",
* ".j2k",
* ".jp2",
* ".jpeg",
* ".jpg",
* ".jpx",
* ".jxr",
* ".pam",
* ".pbm",
* ".pgm",
* ".png",
* ".pnm",
* ".ppm",
* ".tif",
* ".tiff",
* ".wdp",
2018-01-31 19:49:21 +00:00
|
|
|
local providers = self:getProviders(file)
|
|
|
|
if providers then
|
2023-11-05 05:24:18 +00:00
|
|
|
-- associated provider
|
|
|
|
local provider_key = DocumentRegistry:getAssociatedProviderKey(file)
|
|
|
|
local provider = provider_key and self.known_providers[provider_key]
|
|
|
|
if provider and not provider.order then -- excluding auxiliary
|
|
|
|
return provider
|
2018-02-02 20:21:52 +00:00
|
|
|
end
|
|
|
|
-- highest weighted provider
|
[feat] DocumentRegistry: add getProviders() and preferred by weight (#3651)
This is step one toward "open with".
References https://github.com/koreader/koreader/issues/3345
* Fix up some mimetypes
* Add XHTML to supported filetypes
* Add a few image files to MuPDF
* ".bmp",
* ".gif",
* ".hdp",
* ".j2k",
* ".jp2",
* ".jpeg",
* ".jpg",
* ".jpx",
* ".jxr",
* ".pam",
* ".pbm",
* ".pgm",
* ".png",
* ".pnm",
* ".ppm",
* ".tif",
* ".tiff",
* ".wdp",
2018-01-31 19:49:21 +00:00
|
|
|
return providers[1].provider
|
|
|
|
end
|
2023-11-05 05:24:18 +00:00
|
|
|
return self:getFallbackProvider()
|
[feat] DocumentRegistry: add getProviders() and preferred by weight (#3651)
This is step one toward "open with".
References https://github.com/koreader/koreader/issues/3345
* Fix up some mimetypes
* Add XHTML to supported filetypes
* Add a few image files to MuPDF
* ".bmp",
* ".gif",
* ".hdp",
* ".j2k",
* ".jp2",
* ".jpeg",
* ".jpg",
* ".jpx",
* ".jxr",
* ".pam",
* ".pbm",
* ".pgm",
* ".png",
* ".pnm",
* ".ppm",
* ".tif",
* ".tiff",
* ".wdp",
2018-01-31 19:49:21 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
--- Returns the registered document handlers.
|
|
|
|
-- @string file
|
|
|
|
-- @treturn table providers, or nil
|
|
|
|
function DocumentRegistry:getProviders(file)
|
|
|
|
local providers = {}
|
|
|
|
|
2019-08-23 17:53:53 +00:00
|
|
|
--- @todo some implementation based on mime types?
|
2014-03-13 13:52:43 +00:00
|
|
|
for _, provider in ipairs(self.providers) do
|
2020-03-13 20:29:13 +00:00
|
|
|
local added = false
|
2014-11-04 17:56:19 +00:00
|
|
|
local suffix = string.sub(file, -string.len(provider.extension) - 1)
|
2014-11-04 18:56:11 +00:00
|
|
|
if string.lower(suffix) == "."..provider.extension then
|
2021-03-06 21:44:18 +00:00
|
|
|
for i = #providers, 1, -1 do
|
|
|
|
local prov_prev = providers[i]
|
2020-03-13 20:29:13 +00:00
|
|
|
if prov_prev.provider == provider.provider then
|
|
|
|
if prov_prev.weight >= provider.weight then
|
|
|
|
added = true
|
|
|
|
else
|
|
|
|
table.remove(providers, i)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2021-03-06 21:44:18 +00:00
|
|
|
-- if extension == provider.extension then
|
[feat] DocumentRegistry: add getProviders() and preferred by weight (#3651)
This is step one toward "open with".
References https://github.com/koreader/koreader/issues/3345
* Fix up some mimetypes
* Add XHTML to supported filetypes
* Add a few image files to MuPDF
* ".bmp",
* ".gif",
* ".hdp",
* ".j2k",
* ".jp2",
* ".jpeg",
* ".jpg",
* ".jpx",
* ".jxr",
* ".pam",
* ".pbm",
* ".pgm",
* ".png",
* ".pnm",
* ".ppm",
* ".tif",
* ".tiff",
* ".wdp",
2018-01-31 19:49:21 +00:00
|
|
|
-- stick highest weighted provider at the front
|
2020-03-13 20:29:13 +00:00
|
|
|
if not added and #providers >= 1 and provider.weight > providers[1].weight then
|
[feat] DocumentRegistry: add getProviders() and preferred by weight (#3651)
This is step one toward "open with".
References https://github.com/koreader/koreader/issues/3345
* Fix up some mimetypes
* Add XHTML to supported filetypes
* Add a few image files to MuPDF
* ".bmp",
* ".gif",
* ".hdp",
* ".j2k",
* ".jp2",
* ".jpeg",
* ".jpg",
* ".jpx",
* ".jxr",
* ".pam",
* ".pbm",
* ".pgm",
* ".png",
* ".pnm",
* ".ppm",
* ".tif",
* ".tiff",
* ".wdp",
2018-01-31 19:49:21 +00:00
|
|
|
table.insert(providers, 1, provider)
|
2020-03-13 20:29:13 +00:00
|
|
|
elseif not added then
|
[feat] DocumentRegistry: add getProviders() and preferred by weight (#3651)
This is step one toward "open with".
References https://github.com/koreader/koreader/issues/3345
* Fix up some mimetypes
* Add XHTML to supported filetypes
* Add a few image files to MuPDF
* ".bmp",
* ".gif",
* ".hdp",
* ".j2k",
* ".jp2",
* ".jpeg",
* ".jpg",
* ".jpx",
* ".jxr",
* ".pam",
* ".pbm",
* ".pgm",
* ".png",
* ".pnm",
* ".ppm",
* ".tif",
* ".tiff",
* ".wdp",
2018-01-31 19:49:21 +00:00
|
|
|
table.insert(providers, provider)
|
|
|
|
end
|
2014-03-13 13:52:43 +00:00
|
|
|
end
|
|
|
|
end
|
[feat] DocumentRegistry: add getProviders() and preferred by weight (#3651)
This is step one toward "open with".
References https://github.com/koreader/koreader/issues/3345
* Fix up some mimetypes
* Add XHTML to supported filetypes
* Add a few image files to MuPDF
* ".bmp",
* ".gif",
* ".hdp",
* ".j2k",
* ".jp2",
* ".jpeg",
* ".jpg",
* ".jpx",
* ".jxr",
* ".pam",
* ".pbm",
* ".pgm",
* ".png",
* ".pnm",
* ".ppm",
* ".tif",
* ".tiff",
* ".wdp",
2018-01-31 19:49:21 +00:00
|
|
|
|
|
|
|
if #providers >= 1 then
|
|
|
|
return providers
|
|
|
|
end
|
2013-10-18 20:38:07 +00:00
|
|
|
end
|
|
|
|
|
2023-11-05 05:24:18 +00:00
|
|
|
function DocumentRegistry:getProviderFromKey(provider_key)
|
|
|
|
return self.known_providers[provider_key]
|
|
|
|
end
|
|
|
|
|
|
|
|
function DocumentRegistry:getFallbackProvider()
|
|
|
|
for _, provider in ipairs(self.providers) do
|
|
|
|
if provider.extension == "txt" then
|
|
|
|
return provider.provider
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function DocumentRegistry:getAssociatedProviderKey(file, all)
|
|
|
|
-- all: nil - first not empty, false - this file, true - file type
|
|
|
|
|
|
|
|
if not file then -- get the full list of associated providers
|
|
|
|
return G_reader_settings:readSetting("provider")
|
|
|
|
end
|
|
|
|
|
|
|
|
-- provider for this file
|
|
|
|
local provider_key
|
|
|
|
if all ~= true then
|
|
|
|
if DocSettings:hasSidecarFile(file) then
|
|
|
|
provider_key = DocSettings:open(file):readSetting("provider")
|
|
|
|
if provider_key or all == false then
|
|
|
|
return provider_key
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if all == false then return end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- provider for file type
|
|
|
|
local providers = G_reader_settings:readSetting("provider")
|
|
|
|
provider_key = providers and providers[getSuffix(file)]
|
|
|
|
if provider_key and self.known_providers[provider_key] then
|
|
|
|
return provider_key
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Returns array: registered auxiliary providers sorted by order.
|
|
|
|
function DocumentRegistry:getAuxProviders()
|
|
|
|
local providers = {}
|
|
|
|
for _, provider in pairs(self.known_providers) do
|
|
|
|
if provider.order then -- aux
|
|
|
|
table.insert(providers, provider)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if #providers >= 1 then
|
|
|
|
table.sort(providers, function(a, b) return a.order < b.order end)
|
|
|
|
return providers
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-09-01 14:39:47 +00:00
|
|
|
--- Get mapping of file extensions to providers
|
|
|
|
-- @treturn table mapping file extensions to a list of providers
|
|
|
|
function DocumentRegistry:getExtensions()
|
|
|
|
local t = {}
|
|
|
|
for _, provider in ipairs(self.providers) do
|
|
|
|
local ext = provider.extension
|
|
|
|
t[ext] = t[ext] or {}
|
|
|
|
table.insert(t[ext], provider)
|
|
|
|
end
|
|
|
|
return t
|
|
|
|
end
|
|
|
|
|
2018-02-02 20:21:52 +00:00
|
|
|
--- Sets the preferred registered document handler.
|
|
|
|
-- @string file
|
|
|
|
-- @bool all
|
|
|
|
function DocumentRegistry:setProvider(file, provider, all)
|
2023-11-05 05:24:18 +00:00
|
|
|
provider = provider or {} -- call with nil to reset
|
2018-02-02 20:21:52 +00:00
|
|
|
-- per-document
|
|
|
|
if not all then
|
2023-05-28 05:04:25 +00:00
|
|
|
local doc_settings = DocSettings:open(file)
|
|
|
|
doc_settings:saveSetting("provider", provider.provider)
|
|
|
|
doc_settings:flush()
|
2018-02-02 20:21:52 +00:00
|
|
|
-- global
|
|
|
|
else
|
2023-11-05 05:24:18 +00:00
|
|
|
local filetype_provider = G_reader_settings:readSetting("provider", {})
|
|
|
|
filetype_provider[getSuffix(file)] = provider.provider
|
2018-02-02 20:21:52 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-01-17 08:22:48 +00:00
|
|
|
function DocumentRegistry:mimeToExt(mimetype)
|
|
|
|
return self.mimetype_ext[mimetype]
|
|
|
|
end
|
|
|
|
|
2021-05-17 20:59:29 +00:00
|
|
|
--- Returns a new Document instance on success
|
2018-02-02 20:21:52 +00:00
|
|
|
function DocumentRegistry:openDocument(file, provider)
|
2017-04-26 19:46:46 +00:00
|
|
|
-- force a GC, so that any previous document used memory can be reused
|
|
|
|
-- immediately by this new document without having to wait for the
|
|
|
|
-- next regular gc. The second call may help reclaming more memory.
|
|
|
|
collectgarbage()
|
|
|
|
collectgarbage()
|
2014-08-28 12:59:42 +00:00
|
|
|
if not self.registry[file] then
|
2018-02-02 20:21:52 +00:00
|
|
|
provider = provider or self:getProvider(file)
|
|
|
|
|
2014-08-28 12:59:42 +00:00
|
|
|
if provider ~= nil then
|
2014-08-29 09:17:08 +00:00
|
|
|
local ok, doc = pcall(provider.new, provider, {file = file})
|
|
|
|
if ok then
|
|
|
|
self.registry[file] = {
|
|
|
|
doc = doc,
|
|
|
|
refs = 1,
|
|
|
|
}
|
|
|
|
else
|
2016-12-29 08:10:38 +00:00
|
|
|
logger.warn("cannot open document", file, doc)
|
2014-08-29 09:17:08 +00:00
|
|
|
end
|
2014-08-28 12:59:42 +00:00
|
|
|
end
|
|
|
|
else
|
|
|
|
self.registry[file].refs = self.registry[file].refs + 1
|
2021-05-20 17:09:54 +00:00
|
|
|
logger.dbg("DocumentRegistry: Increased refcount to", self.registry[file].refs, "for", file)
|
2014-08-28 12:59:42 +00:00
|
|
|
end
|
2014-08-29 09:17:08 +00:00
|
|
|
if self.registry[file] then
|
|
|
|
return self.registry[file].doc
|
|
|
|
end
|
2014-08-28 12:59:42 +00:00
|
|
|
end
|
|
|
|
|
2021-05-17 20:59:29 +00:00
|
|
|
--- Does *NOT* finalize a Document instance, call its :close() instead if that's what you're looking for!
|
|
|
|
--- (i.e., nothing but Document:close should call this!)
|
2014-08-28 12:59:42 +00:00
|
|
|
function DocumentRegistry:closeDocument(file)
|
|
|
|
if self.registry[file] then
|
|
|
|
self.registry[file].refs = self.registry[file].refs - 1
|
|
|
|
if self.registry[file].refs == 0 then
|
|
|
|
self.registry[file] = nil
|
|
|
|
return 0
|
|
|
|
else
|
|
|
|
return self.registry[file].refs
|
|
|
|
end
|
|
|
|
else
|
2021-05-20 17:09:54 +00:00
|
|
|
error("Tried to close an unregistered file.")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Queries the current refcount for a given file
|
|
|
|
function DocumentRegistry:getReferenceCount(file)
|
|
|
|
if self.registry[file] then
|
|
|
|
return self.registry[file].refs
|
|
|
|
else
|
|
|
|
return nil
|
2013-10-18 20:38:07 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-06-12 06:08:56 +00:00
|
|
|
function DocumentRegistry:isImageFile(file)
|
2023-11-05 05:24:18 +00:00
|
|
|
return self.image_ext[getSuffix(file)] and true or false
|
2023-06-12 06:08:56 +00:00
|
|
|
end
|
|
|
|
|
2013-10-18 20:38:07 +00:00
|
|
|
-- load implementations:
|
2014-11-04 17:57:09 +00:00
|
|
|
require("document/credocument"):register(DocumentRegistry)
|
2013-10-18 20:38:07 +00:00
|
|
|
require("document/pdfdocument"):register(DocumentRegistry)
|
|
|
|
require("document/djvudocument"):register(DocumentRegistry)
|
2013-10-22 15:19:08 +00:00
|
|
|
require("document/picdocument"):register(DocumentRegistry)
|
2023-11-05 05:24:18 +00:00
|
|
|
-- auxiliary built-in
|
|
|
|
require("ui/widget/imageviewer"):register(DocumentRegistry)
|
|
|
|
require("ui/widget/textviewer"):register(DocumentRegistry)
|
|
|
|
-- auxiliary from plugins
|
2013-10-18 20:38:07 +00:00
|
|
|
|
|
|
|
return DocumentRegistry
|