def themeHasConfigXML(style): themePath = Path(G.application.config.stylesDir / style) themeXMLFile = themePath.joinpath("config.xml") themeHasXML = False if themeXMLFile.exists(): themeHasXML = True return themeHasXML
def handleExport(self, client, exportType, filename): """ Called by js. Exports the current package to one of the above formats 'exportType' can be one of 'singlePage' 'webSite' 'zipFile' 'textFile' or 'scorm' 'filename' is a file for scorm pages, and a directory for websites """ webDir = Path(self.config.webDir) stylesDir = webDir.joinpath('style', self.package.style) exportDir = Path(filename).dirname() if exportDir and not exportDir.exists(): client.alert(_(u'Cannot access directory named ') + unicode(exportDir) + _(u'. Please use ASCII names.')) return if exportType == 'singlePage': self.exportSinglePage(client, filename, webDir, stylesDir) elif exportType == 'webSite': self.exportWebSite(client, filename, stylesDir) elif exportType == 'zipFile': self.exportWebZip(client, filename, stylesDir) elif exportType == 'textFile': self.exportText(client, filename) elif exportType == "scorm": self.exportScorm(client, filename, stylesDir, "scorm1.2") elif exportType == "scorm2004": self.exportScorm(client, filename, stylesDir, "scorm2004") else: self.exportIMS(client, filename, stylesDir)
def _process(self, request): """ Delegates processing of args to blocks """ # Still need to call parent (mainpage.py) process # because the idevice pane needs to know that new idevices have been # added/edited.. self.parent.process(request) if ("action" in request.args and request.args["action"][0] == u"saveChange"): log.debug(u"process savachange:::::") self.package.save() log.debug(u"package name: " + self.package.name) for block in self.blocks: block.process(request) # now that each block and corresponding elements have been processed, # it's finally safe to remove any images/etc which made it into # tinyMCE's previews directory, as they have now had their # corresponding resources created: webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') for root, dirs, files in os.walk(previewDir, topdown=False): for name in files: os.remove(os.path.join(root, name)) log.debug(u"After authoringPage process" + repr(request.args))
def __renderHeader(self): #TinyMCE lang (user preference) myPreferencesPage = self.webServer.preferences """Generates the header for AuthoringPage""" html = common.docType() ################################################################################# ################################################################################# html += u'<html xmlns="http://www.w3.org/1999/xhtml" lang="'+myPreferencesPage.getSelectedLanguage()+'">\n' html += u'<head>\n' html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe.css\" />" # Use the Style's base.css file if it exists themePath = Path(G.application.config.stylesDir/self.package.style) themeBaseCSS = themePath.joinpath("base.css") if themeBaseCSS.exists(): html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/base.css\" />" % self.package.style else: html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/base.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe_wikipedia.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_effects/exe_effects.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_highlighter/exe_highlighter.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_games/exe_games.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/content.css\" />" % self.package.style if G.application.config.assumeMediaPlugins: html += u"<script type=\"text/javascript\">var exe_assume_media_plugins = true;</script>\n" #JR: anado una variable con el estilo estilo = u'/style/%s/content.css' % self.package.style html += common.getJavaScriptStrings() # The games require additional strings html += common.getGamesJavaScriptStrings() html += u"<script type=\"text/javascript\">" html += u"var exe_style = '%s';top.exe_style = exe_style;" % estilo # editorpane.py uses exe_style_dirname to auto-select the current style (just a provisional solution) html += u"var exe_style_dirname = '%s'; top.exe_style_dirname = exe_style_dirname;" % self.package.style html += u"var exe_package_name='"+self.package.name+"';" html += 'var exe_export_format="'+common.getExportDocType()+'".toLowerCase();' html += 'var exe_editor_mode="'+myPreferencesPage.getEditorMode()+'";' html += 'var exe_editor_version="'+myPreferencesPage.getEditorVersion()+'";' html += '</script>\n' html += u'<script type="text/javascript" src="../jsui/native.history.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/authoring.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_jquery.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_lightbox/exe_lightbox.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_effects/exe_effects.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_highlighter/exe_highlighter.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_games/exe_games.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/common.js"></script>\n' html += '<script type="text/javascript">document.write(unescape("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>'; html += '<script type="text/javascript">document.write(unescape("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_settings_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>'; html += u'<title>"+_("eXe : elearning XHTML editor")+"</title>\n' html += u'<meta http-equiv="content-type" content="text/html; ' html += u' charset=UTF-8" />\n' style = G.application.config.styleStore.getStyle(self.package.style) if style.hasValidConfig: html += style.get_edition_extra_head() html += u'</head>\n' return html
def __renderHeader(self): #TinyMCE lang (user preference) myPreferencesPage = self.webServer.preferences """Generates the header for AuthoringPage""" html = common.docType() ################################################################################# ################################################################################# html += u'<html xmlns="http://www.w3.org/1999/xhtml" lang="' + myPreferencesPage.getSelectedLanguage( ) + '">\n' html += u'<head>\n' html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe.css\" />" # Use the Style's base.css file if it exists themePath = Path(G.application.config.stylesDir / self.package.style) themeBaseCSS = themePath.joinpath("base.css") if themeBaseCSS.exists(): html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/base.css\" />" % self.package.style else: html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/base.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe_wikipedia.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_effects/exe_effects.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_highlighter/exe_highlighter.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_games/exe_games.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/content.css\" />" % self.package.style if G.application.config.assumeMediaPlugins: html += u"<script type=\"text/javascript\">var exe_assume_media_plugins = true;</script>\n" #JR: anado una variable con el estilo estilo = u'/style/%s/content.css' % self.package.style html += common.getJavaScriptStrings() # The games require additional strings html += common.getGamesJavaScriptStrings() html += u"<script type=\"text/javascript\">" html += u"var exe_style = '%s';" % estilo html += u"var exe_package_name='" + self.package.name + "';" html += 'var exe_export_format="' + common.getExportDocType( ) + '".toLowerCase();' html += 'var exe_editor_mode="' + myPreferencesPage.getEditorMode( ) + '";' html += '</script>\n' html += u'<script type="text/javascript" src="../jsui/native.history.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/authoring.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_jquery.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_lightbox/exe_lightbox.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_effects/exe_effects.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_highlighter/exe_highlighter.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_games/exe_games.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/common.js"></script>\n' html += '<script type="text/javascript">document.write(unescape("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>' html += '<script type="text/javascript">document.write(unescape("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_settings_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>' html += u'<title>"+_("eXe : elearning XHTML editor")+"</title>\n' html += u'<meta http-equiv="content-type" content="text/html; ' html += u' charset=UTF-8" />\n' style = G.application.config.styleStore.getStyle(self.package.style) if style.hasValidConfig: html += style.get_edition_extra_head() html += u'</head>\n' return html
def handleTinyMCEmath( self, client, tinyMCEwin, tinyMCEwin_name, tinyMCEfield, latex_source, math_fontsize, preview_image_filename, preview_math_srcfile, ): """ Based off of handleTinyMCEimageChoice(), handleTinyMCEmath() is similar in that it places a .gif math image (and a corresponding .tex LaTeX source file) into the previews dir. Rather than copying the image from a user-selected directory, though, this routine actually generates the math image using mimetex. """ server_filename = "" callback_errors = "" errors = 0 webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath("previews") if not previewDir.exists(): log.debug("image previews directory does not yet exist; " + "creating as %s " % previewDir) previewDir.makedirs() elif not previewDir.isdir(): client.alert(_(u"Preview directory %s is a file, cannot replace it") % previewDir) log.error( "Couldn't preview tinyMCE-chosen image: " + "Preview dir %s is a file, cannot replace it" % previewDir ) callback_errors = "Preview dir is a file, cannot replace" errors += 1 if latex_source <> "": math_filename = previewDir.joinpath(preview_math_srcfile) math_filename_str = math_filename.abspath().encode("utf-8") log.info("handleTinyMCEmath: using LaTeX source: " + latex_source) log.debug("writing LaTeX source into '" + math_filename_str + "'.") math_file = open(math_filename, "wb") math_file.write(latex_source) math_file.flush() math_file.close() try: use_latex_sourcefile = math_filename_str tempFileName = compile(use_latex_sourcefile, math_fontsize, latex_is_file=True) except Exception, e: client.alert(_("MimeTeX compile failed!\n%s" % str(e))) log.error("handleTinyMCEmath unable to compile LaTeX using " + "mimetex, error = " + str(e)) raise server_filename = previewDir.joinpath(preview_image_filename) log.debug( "handleTinyMCEmath copying math image from '" + tempFileName + "' to '" + server_filename.abspath().encode("utf-8") + "'." ) shutil.copyfile(tempFileName, server_filename.abspath().encode("utf-8")) Path(tempFileName).remove()
def handleExport(self, client, exportType, filename, print_callback=''): """ Called by js. Exports the current package to one of the above formats 'exportType' can be one of 'singlePage' 'webSite' 'zipFile' 'ipod' 'textFile' or 'scorm' 'filename' is a file for scorm pages, and a directory for websites """ webDir = Path(self.config.webDir) stylesDir = webDir.joinpath('style', self.package.style) exportDir = Path(filename).dirname() if exportDir and not exportDir.exists(): client.alert(_(u'Cannot access directory named ') + unicode(exportDir) + _(u'. Please use ASCII names.')) return """ adding the print feature in using the same export functionality: """ if exportType == 'singlePage' or exportType == 'printSinglePage': printit = 0 if exportType == 'printSinglePage': printit = 1 exported_dir = self.exportSinglePage(client, filename, webDir, \ stylesDir, printit) # the above will return None if the desired exported directory # already exists (printing always goes to a new temp dir, though): if printit == 1 and not exported_dir is None: web_printdir = self.get_printdir_relative2web(exported_dir) # now that this has ben exported, go ahead and trigger # the requested printing callback: client.call(print_callback, filename, exported_dir, \ web_printdir) elif exportType == 'webSite': self.exportWebSite(client, filename, stylesDir) elif exportType == 'zipFile': filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportWebZip(client, filename, stylesDir) elif exportType == 'textFile': self.exportText(client, filename) elif exportType == 'ipod': self.exportIpod(client, filename) elif exportType == "scorm": filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "scorm1.2") elif exportType == "scorm2004": filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "scorm2004") elif exportType == "commoncartridge": filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "commoncartridge") else: filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportIMS(client, filename, stylesDir)
def copyFiles(self, package): """ Copy all the files used by the website. """ # Copy the style files to the output dir # But not nav.css if os.path.isdir(self.stylesDir): styleFiles = [self.stylesDir / '..' / 'popup_bg.gif'] styleFiles += self.stylesDir.files("*.*") if "nav.css" in styleFiles: styleFiles.remove("nav.css") self.stylesDir.copylist(styleFiles, self.outputDir) # copy the package's resource files package.resourceDir.copyfiles(self.outputDir) listCSSFiles = getFilesCSSToMinify('singlepage', self.stylesDir) exportMinFileCSS(listCSSFiles, self.outputDir) # copy script files. my_style = G.application.config.styleStore.getStyle(package.style) # jQuery if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(self.outputDir / 'exe_jquery.js') else: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(self.outputDir / 'exe_jquery.js') dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir / 'exe_html5.js') jsFile.copyfile(self.outputDir / 'exe_html5.js') # Minify common.js file listFiles = getFilesJSToMinify('singlepage', self.scriptsDir) exportMinFileJS(listFiles, self.outputDir) # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir / 'favicon.ico') faviconFile.copyfile(self.outputDir / 'favicon.ico') #JR Metemos los reproductores necesarios self.compruebaReproductores(self.page.node) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence ext = 'html' if G.application.config.cutFileName == "1": ext = 'htm' (self.templatesDir / 'fdl' + '.' + ext).copyfile(self.outputDir / 'fdl' + '.' + ext)
def handleTinyMCEimageChoice(self, client, tinyMCEwin, tinyMCEwin_name, \ tinyMCEfield, local_filename, preview_filename): """ Once an image is selected in the file browser that is spawned by the TinyMCE image dialog, copy this file (which is local to the user's machine) into the server space, under a preview directory (after checking if this exists, and creating it if necessary). Note that this IS a "cheat", in violation of the client-server separation, but can be done since we know that the eXe server is actually sitting on the client host. """ server_filename = "" callback_errors = "" errors = 0 webDir = Path(self.config.webDir) previewDir = webDir.joinpath('previews') if not previewDir.exists(): log.debug("image previews directory does not yet exist; " \ + "creating as %s " % previewDir) previewDir.makedirs() elif not previewDir.isdir(): client.alert( \ _(u'Preview directory %s is a file, cannot replace it') \ % previewDir) log.error("Couldn't preview tinyMCE-chosen image: "+ "Preview dir %s is a file, cannot replace it" \ % previewDir) callback_errors = "Preview dir is a file, cannot replace" errors += 1 if errors == 0: localImagePath = Path(local_filename) if not localImagePath.exists() or not localImagePath.isfile(): client.alert( \ _(u'Image file %s is not found, cannot preview it') \ % localImagePath) log.error("Couldn't find tinyMCE-chosen image: %s" \ % localImagePath) callback_errors = "Image file %s not found, cannot preview" \ % localImagePath errors += 1 try: server_filename = previewDir.joinpath(preview_filename); log.debug("handleTinyMCEimageChoice copying image from \'"\ + local_filename + "\' to \'" \ + server_filename.abspath().encode('utf-8') + "\'."); shutil.copyfile(local_filename, \ server_filename.abspath().encode('utf-8')); except Exception, e: client.alert(_('SAVE FAILED!\n%s' % str(e))) log.error("handleTinyMCEimageChoice unable to copy local image "\ +"file to server prevew, error = " + str(e)) raise
def handleExport(self, client, exportType, filename, print_callback=""): """ Called by js. Exports the current package to one of the above formats 'exportType' can be one of 'singlePage' 'webSite' 'zipFile' 'ipod' 'textFile' or 'scorm' 'filename' is a file for scorm pages, and a directory for websites """ webDir = Path(self.config.webDir) stylesDir = webDir.joinpath("style", self.package.style) exportDir = Path(filename).dirname() if exportDir and not exportDir.exists(): client.alert(_(u"Cannot access directory named ") + unicode(exportDir) + _(u". Please use ASCII names.")) return """ adding the print feature in using the same export functionality: """ if exportType == "singlePage" or exportType == "printSinglePage": printit = 0 if exportType == "printSinglePage": printit = 1 exported_dir = self.exportSinglePage(client, filename, webDir, stylesDir, printit) if printit == 1 and not exported_dir is None: web_printdir = self.get_printdir_relative2web(exported_dir) client.call(print_callback, filename, exported_dir, web_printdir) elif exportType == "webSite": self.exportWebSite(client, filename, stylesDir) elif exportType == "zipFile": filename = self.b4save(client, filename, ".zip", _(u"EXPORT FAILED!")) self.exportWebZip(client, filename, stylesDir) elif exportType == "textFile": self.exportText(client, filename) elif exportType == "ipod": self.exportIpod(client, filename) elif exportType == "scorm": filename = self.b4save(client, filename, ".zip", _(u"EXPORT FAILED!")) self.exportScorm(client, filename, stylesDir, "scorm1.2") elif exportType == "scorm2004": filename = self.b4save(client, filename, ".zip", _(u"EXPORT FAILED!")) self.exportScorm(client, filename, stylesDir, "scorm2004") elif exportType == "commoncartridge": filename = self.b4save(client, filename, ".zip", _(u"EXPORT FAILED!")) self.exportScorm(client, filename, stylesDir, "commoncartridge") else: filename = self.b4save(client, filename, ".zip", _(u"EXPORT FAILED!")) self.exportIMS(client, filename, stylesDir)
def _process(self, request): """ Delegates processing of args to blocks """ self.parent.process(request) if ("action" in request.args and request.args["action"][0] == u"saveChange"): log.debug(u"process savachange:::::") self.package.save() log.debug(u"package name: " + self.package.name) for block in self.blocks: block.process(request) webDir = Path(G.application.config.webDir) previewDir = webDir.joinpath('previews') for root, dirs, files in os.walk(previewDir, topdown=False): for name in files: os.remove(os.path.join(root, name)) log.debug(u"After authoringPage process" + repr(request.args))
def handleExport(self, client, exportType, filename, print_callback=''): """ Called by js. Exports the current package to one of the above formats 'exportType' can be one of 'singlePage' 'webSite' 'zipFile' 'textFile' or 'scorm' 'filename' is a file for scorm pages, and a directory for websites """ webDir = Path(self.config.webDir) stylesDir = webDir.joinpath('style', self.package.style) exportDir = Path(filename).dirname() if exportDir and not exportDir.exists(): client.alert(_(u'Cannot access directory named ') + unicode(exportDir) + _(u'. Please use ASCII names.')) return """ if exportType == 'singlePage': r3m0: adding the print feature in using the same export functionality: """ if exportType == 'singlePage' or exportType == 'printSinglePage': printit = 0 if exportType == 'printSinglePage': printit = 1 exported_dir = self.exportSinglePage(client, filename, webDir, stylesDir, printit) if printit == 1: client.call(print_callback, filename, exported_dir) elif exportType == 'webSite': self.exportWebSite(client, filename, stylesDir) elif exportType == 'zipFile': filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportWebZip(client, filename, stylesDir) elif exportType == 'textFile': self.exportText(client, filename) elif exportType == "scorm": filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "scorm1.2") elif exportType == "scorm2004": filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "scorm2004") else: filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportIMS(client, filename, stylesDir)
def __renderHeader(self): #TinyMCE lang (user preference) myPreferencesPage = self.webServer.preferences """Generates the header for AuthoringPage""" html = common.docType() ################################################################################# ################################################################################# html += u'<html xmlns="http://www.w3.org/1999/xhtml" lang="'+myPreferencesPage.getSelectedLanguage()+'">\n' html += u'<head>\n' html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe.css\" />" # Use the Style's base.css file if it exists themePath = Path(G.application.config.stylesDir/self.package.style) themeBaseCSS = themePath.joinpath("base.css") if themeBaseCSS.exists(): html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/base.css\" />" % self.package.style else: html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/base.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe_wikipedia.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/content.css\" />" % self.package.style if G.application.config.assumeMediaPlugins: html += u"<script type=\"text/javascript\">var exe_assume_media_plugins = true;</script>\n" #JR: anado una variable con el estilo estilo = u'/style/%s/content.css' % self.package.style html += common.getJavaScriptStrings() html += u"<script type=\"text/javascript\">var exe_style = '%s';</script>\n" % estilo html += u"<script type=\"text/javascript\">var exe_package_name='"+self.package.name+"';</script>\n" html += u'<script type="text/javascript" src="../jsui/native.history.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/authoring.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_jquery.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_lightbox.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/common.js"></script>\n' html += '<script type="text/javascript">document.write(unescape("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>'; html += '<script type="text/javascript">document.write(unescape("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_settings_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>'; html += u'<title>"+_("eXe : elearning XHTML editor")+"</title>\n' html += u'<meta http-equiv="content-type" content="text/html; ' html += u' charset=UTF-8" />\n' html += u'</head>\n' return html
def _process(self, request): """ Delegates processing of args to blocks """ # Still need to call parent (mainpage.py) process # because the idevice pane needs to know that new idevices have been # added/edited.. self.parent.process(request) for block in self.blocks: block.process(request) # now that each block and corresponding elements have been processed, # it's finally safe to remove any images/etc which made it into # tinyMCE's previews directory, as they have now had their # corresponding resources created: webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') for root, dirs, files in os.walk(previewDir, topdown=False): for name in files: if sys.platform[:3] == "win": for i in range(3): try: os.remove(os.path.join(root, name)) break except exceptions.WindowsError: time.sleep(0.3) else: os.remove(os.path.join(root, name)) topNode = self.package.currentNode if "action" in request.args: if request.args["action"][0] == u"changeNode": topNode = self.package.findNode(request.args["object"][0]) elif "currentNode" in request.args: topNode = self.package.findNode(request.args["currentNode"][0]) elif "currentNode" in request.args: topNode = self.package.findNode(request.args["currentNode"][0]) log.debug(u"After authoringPage process" + repr(request.args)) return topNode
def copyFiles(self, package, outputDir): """ Copy all the files used by the website. """ if os.path.isdir(self.stylesDir): # Copy the style files to the output dir styleFiles = [self.stylesDir/'..'/'popup_bg.gif'] styleFiles += self.stylesDir.files("*.*") self.stylesDir.copylist(styleFiles, outputDir) # copy the package's resource files for resourceFile in package.resourceDir.walkfiles(): file = package.resourceDir.relpathto(resourceFile) if ("/" in file): Dir = Path(outputDir/file[:file.rindex("/")]) if not Dir.exists(): Dir.makedirs() resourceFile.copy(outputDir/Dir) else: resourceFile.copy(outputDir) listCSSFiles=getFilesCSSToMinify('website', self.stylesDir) exportMinFileCSS(listCSSFiles, outputDir) # copy script files. my_style = G.application.config.styleStore.getStyle(package.style) # jQuery listFiles=[] listOutFiles=[] if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') else: listFiles+=[self.scriptsDir/'exe_jquery.js'] listOutFiles+=[outputDir/'exe_jquery.js'] # Minify common.js file listFiles=getFilesJSToMinify('website', self.scriptsDir) exportMinFileJS(listFiles, outputDir) # Create lang file langFile = open(outputDir + '/common_i18n.js', "w") langFile.write(common.getJavaScriptStrings(False)) langFile.close() #dT = common.getExportDocType() dT=common.getExportDocType(); if dT == "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(outputDir/'favicon.ico') # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasElpLink = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False hasABCMusic = False listIdevicesFiles = [] for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasElpLink and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips and hasABCMusic): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasElpLink: hasElpLink = common.ideviceHasElpLink(idevice,package) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if not hasABCMusic: hasABCMusic = common.ideviceHasABCMusic(idevice) if hasattr(idevice, "_iDeviceDir"): listIdevicesFiles.append((Path(idevice._iDeviceDir)/'export')) common.exportJavaScriptIdevicesFiles(page.node.idevices, outputDir); if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'mojomagnify.js') videofile.copyfile(outputDir/'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir/'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir/'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir/'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir/'exe_games') exeGames.copyfiles(outputDir) # Add game js string to common_i18n langGameFile = open(outputDir + '/common_i18n.js', "a") langGameFile.write(common.getGamesJavaScriptStrings(False)) langGameFile.close() if hasElpLink or package.get_exportElp(): # Export the elp file currentPackagePath = Path(package.filename) currentPackagePath.copyfile(outputDir/package.name+'.elp') if hasABCMusic: pluginScripts = (self.scriptsDir/'tinymce_4/js/tinymce/plugins/abcmusic/export') pluginScripts.copyfiles(outputDir) if hasWikipedia: wikipediaCSS = (self.cssDir/'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir/'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir/'mediaelement') mediaelement.copyfiles(outputDir) dT = common.getExportDocType() if dT != "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir/'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd') (outputDir/'content.data').write_bytes(encodeObject(package)) (outputDir/'contentv3.xml').write_bytes(encodeObjectToXML(package)) ext = 'html' if G.application.config.cutFileName == "1": ext = 'htm' if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl' + '.' + ext).copyfile(outputDir/'fdl' + '.' + ext)
def __renderHeader(self): #TinyMCE lang (user preference) myPreferencesPage = self.webServer.preferences """Generates the header for AuthoringPage""" html = common.docType() ################################################################################# ################################################################################# html += u'<html xmlns="http://www.w3.org/1999/xhtml" lang="' + myPreferencesPage.getSelectedLanguage( ) + '">\n' html += u'<head>\n' html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe.css\" />" # Use the Style's base.css file if it exists themePath = Path(G.application.config.stylesDir / self.package.style) themeBaseCSS = themePath.joinpath("base.css") if themeBaseCSS.exists(): html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/base.css\" />" % self.package.style else: html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/base.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe_wikipedia.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_effects/exe_effects.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_highlighter/exe_highlighter.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/exe_games/exe_games.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/scripts/tinymce_4/js/tinymce/plugins/abcmusic/export/exe_abcmusic.css\" />" #93 (to do) html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/content.css\" />" % self.package.style if G.application.config.assumeMediaPlugins: html += u"<script type=\"text/javascript\">var exe_assume_media_plugins = true;</script>\n" #JR: anado una variable con el estilo estilo = u'/style/%s/content.css' % self.package.style html += common.getJavaScriptStrings() # The games require additional strings html += common.getGamesJavaScriptStrings() html += u"<script type=\"text/javascript\">" html += u"var exe_style = '%s';top.exe_style = exe_style;" % estilo # editorpane.py uses exe_style_dirname to auto-select the current style (just a provisional solution) html += u"var exe_style_dirname = '%s'; top.exe_style_dirname = exe_style_dirname;" % self.package.style html += u"var exe_package_name='" + self.package.name + "';" html += 'var exe_export_format="' + common.getExportDocType( ) + '".toLowerCase();' html += 'var exe_editor_mode="' + myPreferencesPage.getEditorMode( ) + '";' html += 'var exe_editor_version="' + myPreferencesPage.getEditorVersion( ) + '";' html += '</script>\n' html += u'<script type="text/javascript" src="../jsui/native.history.js"></script>\n' htmlLang = G.application.config.locale if self.package.dublinCore.language != "": htmlLang = self.package.dublinCore.language for subDir in G.application.config.localeDir.dirs(): if (subDir / 'LC_MESSAGES' / 'exe.mo').exists(): if str( subDir.basename() ) == htmlLang and htmlLang != myPreferencesPage.getSelectedLanguage( ): html += u'<script type="text/javascript" src="../jsui/i18n/' + htmlLang + '.js"></script>\n' html += u'<script type="text/javascript">var exe_elp_lang="' + htmlLang + '";</script>\n' html += u'<script type="text/javascript" src="/scripts/authoring.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_jquery.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_lightbox/exe_lightbox.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_effects/exe_effects.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_highlighter/exe_highlighter.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_games/exe_games.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/tinymce_4/js/tinymce/plugins/abcmusic/export/exe_abcmusic.js"></script>\n' #93 (to do) html += u'<script type="text/javascript" src="/scripts/common.js"></script>\n' html += '<script type="text/javascript">document.write(unescape("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>' html += '<script type="text/javascript">document.write(unescape("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_settings_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>' html += common.printJavaScriptIdevicesScripts('edition', self) html += u'<title>"+_("eXe : elearning XHTML editor")+"</title>\n' html += u'<meta http-equiv="content-type" content="text/html; ' html += u' charset=UTF-8" />\n' style = G.application.config.styleStore.getStyle(self.package.style) if style.hasValidConfig(): html += style.get_edition_extra_head() html += common.getExtraHeadContent(self.package) html += u'</head>\n' return html
def handleExport(self, client, exportType, filename, print_callback=''): """ Called by js. Exports the current package to one of the above formats 'exportType' can be one of 'singlePage' 'webSite' 'zipFile' 'ipod' 'textFile' or 'scorm' 'filename' is a file for scorm pages, and a directory for websites """ webDir = Path(self.config.webDir) stylesDir = webDir.joinpath('style', self.package.style) exportDir = Path(filename).dirname() if exportDir and not exportDir.exists(): client.alert( _(u'Cannot access directory named ') + unicode(exportDir) + _(u'. Please use ASCII names.')) return """ adding the print feature in using the same export functionality: """ if exportType == 'singlePage' or exportType == 'printSinglePage': printit = 0 if exportType == 'printSinglePage': printit = 1 exported_dir = self.exportSinglePage(client, filename, webDir, \ stylesDir, printit) # the above will return None if the desired exported directory # already exists (printing always goes to a new temp dir, though): if printit == 1 and not exported_dir is None: web_printdir = self.get_printdir_relative2web(exported_dir) # now that this has ben exported, go ahead and trigger # the requested printing callback: client.call(print_callback, filename, exported_dir, \ web_printdir) elif exportType == 'webSite': self.exportWebSite(client, filename, stylesDir) elif exportType == 'zipFile': filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportWebZip(client, filename, stylesDir) elif exportType == 'textFile': self.exportText(client, filename) elif exportType == 'ipod': self.exportIpod(client, filename) elif exportType == "scorm": filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "scorm1.2") elif exportType == "scorm2004": filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "scorm2004") elif exportType == "commoncartridge": filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportScorm(client, filename, stylesDir, "commoncartridge") else: filename = self.b4save(client, filename, '.zip', _(u'EXPORT FAILED!')) self.exportIMS(client, filename, stylesDir)
def handleTinyMCEimageChoice(self, client, tinyMCEwin, tinyMCEwin_name, \ tinyMCEfield, local_filename, preview_filename): """ Once an image is selected in the file browser that is spawned by the TinyMCE image dialog, copy this file (which is local to the user's machine) into the server space, under a preview directory (after checking if this exists, and creating it if necessary). Note that this IS a "cheat", in violation of the client-server separation, but can be done since we know that the eXe server is actually sitting on the client host. """ server_filename = "" callback_errors = "" errors = 0 log.debug('handleTinyMCEimageChoice: image local = ' + local_filename + ', base=' + os.path.basename(local_filename)) webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') if not previewDir.exists(): log.debug("image previews directory does not yet exist; " \ + "creating as %s " % previewDir) previewDir.makedirs() elif not previewDir.isdir(): client.alert( \ _(u'Preview directory %s is a file, cannot replace it') \ % previewDir) log.error("Couldn't preview tinyMCE-chosen image: "+ "Preview dir %s is a file, cannot replace it" \ % previewDir) callback_errors = "Preview dir is a file, cannot replace" errors += 1 if errors == 0: log.debug('handleTinyMCEimageChoice: originally, local_filename=' + local_filename) local_filename = unicode(local_filename, 'utf-8') log.debug('handleTinyMCEimageChoice: in unicode, local_filename=' + local_filename) localImagePath = Path(local_filename) log.debug( 'handleTinyMCEimageChoice: after Path, localImagePath= ' + localImagePath) if not localImagePath.exists() or not localImagePath.isfile(): client.alert( \ _(u'Local file %s is not found, cannot preview it') \ % localImagePath) log.error("Couldn't find tinyMCE-chosen image: %s" \ % localImagePath) callback_errors = "Image file %s not found, cannot preview" \ % localImagePath errors += 1 try: # joinpath needs its join arguments to already be in Unicode: #preview_filename = toUnicode(preview_filename); # but that's okay, cuz preview_filename is now URI safe, right? log.debug('URIencoded preview filename=' + preview_filename) server_filename = previewDir.joinpath(preview_filename) log.debug("handleTinyMCEimageChoice copying image from \'"\ + local_filename + "\' to \'" \ + server_filename.abspath() + "\'.") shutil.copyfile(local_filename, \ server_filename.abspath()) # new optional description file to provide the # actual base filename, such that once it is later processed # copied into the resources directory, it can be done with # only the basename. Otherwise the resource filenames # are too long for some users, preventing them from making # backup CDs of the content, for example. # # Remember that the full path of the # file is only used here as an easy way to keep the names # unique WITHOUT requiring a roundtrip call from the Javascript # to this server, and back again, a process which does not # seem to work with tinyMCE in the mix. BUT, once tinyMCE's # part is done, and this image processed, it can be returned # to just its basename, since the resource parts have their # own unique-ification mechanisms already in place. descrip_file_path = Path(server_filename + ".exe_info") log.debug("handleTinyMCEimageChoice creating preview " \ + "description file \'" \ + descrip_file_path.abspath() + "\'.") descrip_file = open(descrip_file_path, 'wb') # safety measures against TinyMCE, otherwise it will # later take ampersands and entity-escape them into '&', # and filenames with hash signs will not be found, etc.: unspaced_filename = local_filename.replace(' ', '_') unhashed_filename = unspaced_filename.replace('#', '_num_') unamped_local_filename = unhashed_filename.replace('&', '_and_') log.debug("and setting new file basename as: " + unamped_local_filename) my_basename = os.path.basename(unamped_local_filename) descrip_file.write((u"basename=" + my_basename).encode('utf-8')) descrip_file.flush() descrip_file.close() except Exception, e: client.alert(_('SAVE FAILED!\n%s' % str(e))) log.error("handleTinyMCEimageChoice unable to copy local image "\ +"file to server prevew, error = " + str(e)) raise
def convertToFreeText(self): """ Actually do the Converting of MathsIdevice -> FreeTextIdevice, now that FreeText can hold embeddded images. """ new_content = "" imageResource_exists = False if not self.content.gifResource is None: if os.path.exists(self.content.gifResource.path) and \ os.path.isfile(self.content.gifResource.path): imageResource_exists = True else: log.warn("Couldn't find Maths image when upgrading "\ + self.content.gifResource.storageName) if imageResource_exists: new_content += "<img src=\"resources/" \ + self.content.gifResource.storageName + "\" " math_resource_url="resources/" \ + self.content.gifResource.storageName + ".tex\" " new_content += "exe_math_latex=\"" + math_resource_url + "\" " new_content += "exe_math_size=\"" + repr(self.content.fontsize) \ + "\" " new_content += "/> \n" elif self.content.gifResource: new_content += "<BR>\n[WARNING: missing image: " \ + self.content.gifResource.storageName + "]\n" replacementIdev = FreeTextIdevice(new_content) replacementIdev.content.content_wo_resourcePaths = \ replacementIdev.content.MassageContentForRenderView( \ replacementIdev.content.content_w_resourcePaths) self.parentNode.addIdevice(replacementIdev) replacementIdev.content.setParentNode() if imageResource_exists: from exe.engine.galleryidevice import GalleryImage full_image_path = self.content.gifResource.path new_GalleryImage = GalleryImage(replacementIdev.content, \ '', full_image_path, mkThumbnail=False) webDir = Path(G.application.tempWebDir) source_tex_name = self.content.gifResource.storageName+".tex" math_path = webDir.joinpath(source_tex_name) math_filename_str = math_path.abspath().encode('utf-8') log.debug("convertToFreeText: writing LaTeX source into \'" \ + math_filename_str + "\'.") math_file = open(math_filename_str, 'wb') math_file.write(self.content.latex) math_file.flush() math_file.close() new_GalleryLatex = GalleryImage(replacementIdev.content, \ '', math_filename_str, mkThumbnail=False) new_GalleryLatexResource = new_GalleryLatex._imageResource mathsrc_resource_path = new_GalleryLatexResource._storageName mathsrc_resource_url = new_GalleryLatex.resourcesUrl \ + mathsrc_resource_path if (mathsrc_resource_url != math_resource_url): log.warn('The math source was resource-ified differently ' \ + 'than expected, to: ' + mathsrc_resource_url \ + '; the source will need to be recreated.') else: log.debug('math source was resource-ified properly to: ' \ + mathsrc_resource_url) while ( self.parentNode.idevices.index(replacementIdev) \ > ( (self.parentNode.idevices.index(self) + 1))): replacementIdev.movePrev() self.delete()
def handleTinyMCEimageChoice(self, client, tinyMCEwin, tinyMCEwin_name, \ tinyMCEfield, local_filename, preview_filename): """ Once an image is selected in the file browser that is spawned by the TinyMCE image dialog, copy this file (which is local to the user's machine) into the server space, under a preview directory (after checking if this exists, and creating it if necessary). Note that this IS a "cheat", in violation of the client-server separation, but can be done since we know that the eXe server is actually sitting on the client host. """ server_filename = "" callback_errors = "" errors = 0 log.debug('handleTinyMCEimageChoice: image local = ' + local_filename + ', base=' + os.path.basename(local_filename)) webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') if not previewDir.exists(): log.debug("image previews directory does not yet exist; " \ + "creating as %s " % previewDir) previewDir.makedirs() elif not previewDir.isdir(): client.alert( \ _(u'Preview directory %s is a file, cannot replace it') \ % previewDir) log.error("Couldn't preview tinyMCE-chosen image: "+ "Preview dir %s is a file, cannot replace it" \ % previewDir) callback_errors = "Preview dir is a file, cannot replace" errors += 1 if errors == 0: log.debug('handleTinyMCEimageChoice: originally, local_filename=' + local_filename) local_filename = unicode(local_filename, 'utf-8') log.debug('handleTinyMCEimageChoice: in unicode, local_filename=' + local_filename) localImagePath = Path(local_filename) log.debug('handleTinyMCEimageChoice: after Path, localImagePath= ' + localImagePath); if not localImagePath.exists() or not localImagePath.isfile(): client.alert( \ _(u'Local file %s is not found, cannot preview it') \ % localImagePath) log.error("Couldn't find tinyMCE-chosen image: %s" \ % localImagePath) callback_errors = "Image file %s not found, cannot preview" \ % localImagePath errors += 1 try: # joinpath needs its join arguments to already be in Unicode: #preview_filename = toUnicode(preview_filename); # but that's okay, cuz preview_filename is now URI safe, right? log.debug('URIencoded preview filename=' + preview_filename); server_filename = previewDir.joinpath(preview_filename); log.debug("handleTinyMCEimageChoice copying image from \'"\ + local_filename + "\' to \'" \ + server_filename.abspath() + "\'."); shutil.copyfile(local_filename, \ server_filename.abspath()); # new optional description file to provide the # actual base filename, such that once it is later processed # copied into the resources directory, it can be done with # only the basename. Otherwise the resource filenames # are too long for some users, preventing them from making # backup CDs of the content, for example. # # Remember that the full path of the # file is only used here as an easy way to keep the names # unique WITHOUT requiring a roundtrip call from the Javascript # to this server, and back again, a process which does not # seem to work with tinyMCE in the mix. BUT, once tinyMCE's # part is done, and this image processed, it can be returned # to just its basename, since the resource parts have their # own unique-ification mechanisms already in place. descrip_file_path = Path(server_filename+".exe_info") log.debug("handleTinyMCEimageChoice creating preview " \ + "description file \'" \ + descrip_file_path.abspath() + "\'."); descrip_file = open(descrip_file_path, 'wb') # safety measures against TinyMCE, otherwise it will # later take ampersands and entity-escape them into '&', # and filenames with hash signs will not be found, etc.: unspaced_filename = local_filename.replace(' ','_') unhashed_filename = unspaced_filename.replace('#', '_num_') unamped_local_filename = unhashed_filename.replace('&', '_and_') log.debug("and setting new file basename as: " + unamped_local_filename); my_basename = os.path.basename(unamped_local_filename) descrip_file.write((u"basename="+my_basename).encode('utf-8')) descrip_file.flush() descrip_file.close() except Exception, e: client.alert(_('SAVE FAILED!\n%s' % str(e))) log.error("handleTinyMCEimageChoice unable to copy local image "\ +"file to server prevew, error = " + str(e)) raise
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # copy the package's resource files for resourceFile in package.resourceDir.walkfiles(): file = package.resourceDir.relpathto(resourceFile) if ("/" in file): Dir = Path(outputDir/file[:file.rindex("/")]) if not Dir.exists(): Dir.makedirs() resourceFile.copy(outputDir/Dir) else: resourceFile.copy(outputDir) # copy the package's resource files, only non existant in outputDir # outputDirFiles = outputDir.files() # for rfile in package.resourceDir.files(): # if rfile not in outputDirFiles: # rfile.copy(outputDir) # copy the package's resource files, only indexed in package.resources # for md5 in package.resources.values(): # for resource in md5: # resource.path.copy(outputDir) # Export the package content # Import the Scorm Page class , if the secure mode is off. If the style has it's own page class # use that, else use the default one. if self.styleSecureMode=="0": if (self.styleDir/"scormpage.py").exists(): global ScormPage module = imp.load_source("ScormPage",self.styleDir/"scormpage.py") ScormPage = module.ScormPage self.pages = [ ScormPage("index", 1, package.root, scormType=self.scormType, metadataType=self.metadataType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir, self.pages) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType, self.metadataType) modifiedMetaData = manifest.save("imsmanifest.xml") # Create lang file langFile = open(outputDir + '/common_i18n.js', "w") langFile.write(common.getJavaScriptStrings(False)) langFile.close() if self.hasForum: manifest.save("discussionforum.xml") # Copy the style files to the output dir styleFiles = [self.styleDir/'..'/'popup_bg.gif'] # And with all the files of the style we avoid problems: styleFiles += self.styleDir.files("*.*") if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) listCSSFiles=getFilesCSSToMinify('scorm', self.styleDir) exportMinFileCSS(listCSSFiles, outputDir) # Copy the scripts dT = common.getExportDocType() if dT == "HTML5": #listFiles+=[self.scriptsDir/'exe_html5.js'] #listOutFiles+=[outputDir/'exe_html5.js'] jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') # jQuery my_style = G.application.config.styleStore.getStyle(page.node.package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: #listFiles+=[self.scriptsDir/'exe_jquery.js'] #listOutFiles+=[outputDir/'exe_jquery.js'] jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') else: #listFiles+=[self.scriptsDir/'exe_jquery.js'] #listOutFiles+=[outputDir/'exe_jquery.js'] jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') if self.scormType == "commoncartridge" or self.scormType == "scorm2004" or self.scormType == "scorm1.2": listFiles=getFilesJSToMinify('scorm', self.scriptsDir) exportMinFileJS(listFiles, outputDir) if self.scormType == "scorm2004" or self.scormType == "scorm1.2": self.scriptsDir.copylist(('SCORM_API_wrapper.js', 'SCOFunctions.js'), outputDir) # about SCHEMAS: schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir/"scorm1.2" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'lom.xsd', 'lomCustom.xsd', 'ims_xml.xsd'), outputDir) elif self.scormType == "scorm2004": schemasDir = self.schemasDir/"scorm2004" schemasDir.copylist(('adlcp_v1p3.xsd', 'adlnav_v1p3.xsd', 'adlseq_v1p3.xsd', 'datatypes.dtd', 'imscp_v1p1.xsd', 'imsssp_v1p0.xsd', 'imsss_v1p0.xsd', 'imsss_v1p0auxresource.xsd', 'imsss_v1p0control.xsd', 'imsss_v1p0delivery.xsd', 'imsmd_rootv1p2p1.xsd', 'imsss_v1p0limit.xsd', 'imsss_v1p0objective.xsd', 'imsss_v1p0random.xsd', 'imsss_v1p0rollup.xsd', 'imsss_v1p0seqrule.xsd', 'imsss_v1p0util.xsd', 'ims_xml.xsd', 'lom.xsd', 'lomCustom.xsd', 'xml.xsd', 'XMLSchema.dtd'), outputDir) try: import shutil, errno shutil.copytree(schemasDir/"common", outputDir/"common") shutil.copytree(schemasDir/"extend", outputDir/"extend") shutil.copytree(schemasDir/"unique", outputDir/"unique") shutil.copytree(schemasDir/"vocab", outputDir/"vocab") except OSError as exc: if exc.errno == errno.ENOTDIR: shutil.copy(schemasDir, outputDir) else: raise # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasElpLink = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False hasABCMusic = False listIdevicesFiles = [] for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasElpLink and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips and hasABCMusic): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasElpLink: hasElpLink = common.ideviceHasElpLink(idevice,package) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if not hasABCMusic: hasABCMusic = common.ideviceHasABCMusic(idevice) if hasattr(idevice, "_iDeviceDir"): listIdevicesFiles.append((Path(idevice._iDeviceDir)/'export')) common.exportJavaScriptIdevicesFiles(page.node.idevices, outputDir); if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'mojomagnify.js') videofile.copyfile(outputDir/'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir/'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir/'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir/'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir/'exe_games') exeGames.copyfiles(outputDir) # Add game js string to common_i18n langGameFile = open(outputDir + '/common_i18n.js', "a") langGameFile.write(common.getGamesJavaScriptStrings(False)) langGameFile.close() if hasElpLink or package.get_exportElp(): # Export the elp file currentPackagePath = Path(package.filename) currentPackagePath.copyfile(outputDir/package.name+'.elp') if hasWikipedia: wikipediaCSS = (self.cssDir/'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir/'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir/'mediaelement') mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir/'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasABCMusic: pluginScripts = (self.scriptsDir/'tinymce_4/js/tinymce/plugins/abcmusic/export') pluginScripts.copyfiles(outputDir) ext = ".html" if G.application.config.cutFileName == "1": ext = ".htm" if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl' + ext).copyfile(outputDir/'fdl' + ext) if hasattr(package, 'scowsinglepage') and package.scowsinglepage: page = SinglePage("singlepage_index", 1, package.root) page.save(outputDir/"singlepage_index" + ext) # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(outputDir/'favicon.ico') if hasattr(package, 'scowwebsite') and package.scowwebsite: website = WebsiteExport(self.config, self.styleDir, outputDir, "website_") website.export(package) (self.styleDir/'nav.css').copyfile(outputDir/'nav.css') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(outputDir/'favicon.ico') if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd') (outputDir/'content.data').write_bytes(encodeObject(package)) (outputDir/'contentv3.xml').write_bytes(encodeObjectToXML(package)) # Zip it up! self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree() return modifiedMetaData
def __renderHeader(self): #TinyMCE lang (user preference) myPreferencesPage = self.webServer.preferences """Generates the header for AuthoringPage""" html = common.docType() ################################################################################# ################################################################################# html += u'<html xmlns="http://www.w3.org/1999/xhtml" lang="'+myPreferencesPage.getSelectedLanguage()+'">\n' html += u'<head>\n' html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe.css\" />" # Use the Style's base.css file if it exists themePath = Path(G.application.config.stylesDir/self.package.style) themeBaseCSS = themePath.joinpath("base.css") if themeBaseCSS.exists(): html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/base.css\" />" % self.package.style else: html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/base.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/exe_wikipedia.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/imgAreaSelect/imgareaselect-default.css\" />" html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/style/%s/content.css\" />" % self.package.style html += u"<link rel=\"stylesheet\" type=\"text/css\" href=\"/css/jquery-ui-1.10.4.custom/ui-lightness/jquery-ui-1.10.4.custom.min.css\" />" if G.application.config.tinyMCEVersion != "4": html += u"<link rel='stylesheet' type='text/css' href='/scripts/tinymce_3.5.7/jscripts/tiny_mce/themes/advanced/skins/default/ui.css' />" if G.application.config.assumeMediaPlugins: html += u"<script type=\"text/javascript\">var exe_assume_media_plugins = true;</script>\n" #JR: anado una variable con el estilo estilo = u'/style/%s/content.css' % self.package.style html += common.getJavaScriptStrings() html += u"<script type=\"text/javascript\">" html += u"var exe_style = '%s';" % estilo html += u"var exe_package_name='"+self.package.name+"';" html += 'var exe_export_format="'+common.getExportDocType()+'".toLowerCase();' html += 'var exe_editor_mode="'+myPreferencesPage.getEditorMode()+'";' #MD Set the correct tinymce version to use tinymce_src = None if G.application.config.tinyMCEVersion == "3": tinymce_src = {"wysiwyg_path" : "/scripts/tinymce_3.5.7/jscripts/tiny_mce/tiny_mce.js", "wysiwyg_settings_path" : "/scripts/tinymce_3.5.7_settings.js"} else: tinymce_src = {"wysiwyg_path" : "/scripts/tinymce/tinymce.full.min.js", "wysiwyg_settings_path" : "/scripts/tinymce_settings.js"} html += 'var eXeLearning_settings = ' html += json.dumps(tinymce_src) + ";\n" html += '</script>\n' html += u'<script type="text/javascript" src="../jsui/native.history.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/authoring.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_jquery.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/jquery-ui-1.10.4.custom.min.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_lightbox.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/common.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/jquery.imgareaselect.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/exe_imgmaparea.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/authoring_defaultprompts.js"></script>\n' html += u'<script type="text/javascript" src="/scripts/authoring_feedback_checkboxes.js"></script>\n' html += '<script type="text/javascript">document.write(unescape("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>'; html += '<script type="text/javascript">document.write(unescape("%3Cscript src=\'" + eXeLearning_settings.wysiwyg_settings_path + "\' type=\'text/javascript\'%3E%3C/script%3E"));</script>'; html += u'<title>"+_("eXe : elearning XHTML editor")+"</title>\n' html += u'<meta http-equiv="content-type" content="text/html; ' html += u' charset=UTF-8" />\n' html += u'</head>\n' return html
def copyFiles(self, package, outputDir): """ Copy all the files used by the website. """ if os.path.isdir(self.stylesDir): # Copy the style files to the output dir styleFiles = [self.stylesDir / '..' / 'popup_bg.gif'] styleFiles += self.stylesDir.files("*.*") self.stylesDir.copylist(styleFiles, outputDir) # copy the package's resource files for resourceFile in package.resourceDir.walkfiles(): file = package.resourceDir.relpathto(resourceFile) if ("/" in file): Dir = Path(outputDir / file[:file.rindex("/")]) if not Dir.exists(): Dir.makedirs() resourceFile.copy(outputDir / Dir) else: resourceFile.copy(outputDir) listCSSFiles = getFilesCSSToMinify('website', self.stylesDir) exportMinFileCSS(listCSSFiles, outputDir) # copy script files. my_style = G.application.config.styleStore.getStyle(package.style) # jQuery listFiles = [] listOutFiles = [] if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(outputDir / 'exe_jquery.js') else: listFiles += [self.scriptsDir / 'exe_jquery.js'] listOutFiles += [outputDir / 'exe_jquery.js'] # Minify common.js file listFiles = getFilesJSToMinify('website', self.scriptsDir) exportMinFileJS(listFiles, outputDir) # Create lang file langFile = open(outputDir + '/common_i18n.js', "w") langFile.write(common.getJavaScriptStrings(False)) langFile.close() #dT = common.getExportDocType() dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir / 'exe_html5.js') jsFile.copyfile(outputDir / 'exe_html5.js') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir / 'favicon.ico') faviconFile.copyfile(outputDir / 'favicon.ico') # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False hasABCMusic = False listIdevicesFiles = [] for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips and hasABCMusic): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if not hasABCMusic: hasABCMusic = common.ideviceHasABCMusic(idevice) if hasattr(idevice, "_iDeviceDir"): listIdevicesFiles.append( (Path(idevice._iDeviceDir) / 'export')) if hasFlowplayer: videofile = (self.templatesDir / 'flowPlayer.swf') videofile.copyfile(outputDir / 'flowPlayer.swf') controlsfile = (self.templatesDir / 'flowplayer.controls.swf') controlsfile.copyfile(outputDir / 'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir / 'mojomagnify.js') videofile.copyfile(outputDir / 'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir / 'xspf_player.swf') videofile.copyfile(outputDir / 'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir / 'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir / 'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir / 'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir / 'exe_games') exeGames.copyfiles(outputDir) # Add game js string to common_i18n langGameFile = open(outputDir + '/common_i18n.js', "a") langGameFile.write(common.getGamesJavaScriptStrings(False)) langGameFile.close() if hasABCMusic: pluginScripts = (self.scriptsDir / 'tinymce_4/js/tinymce/plugins/abcmusic/export') pluginScripts.copyfiles(outputDir) if hasWikipedia: wikipediaCSS = (self.cssDir / 'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir / 'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir / 'mediaelement') mediaelement.copyfiles(outputDir) dT = common.getExportDocType() if dT != "HTML5": jsFile = (self.scriptsDir / 'exe_html5.js') jsFile.copyfile(outputDir / 'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir / 'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd') (outputDir / 'content.data').write_bytes(encodeObject(package)) (outputDir / 'contentv3.xml').write_bytes( encodeObjectToXML(package)) ext = 'html' if G.application.config.cutFileName == "1": ext = 'htm' if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl' + '.' + ext).copyfile(outputDir / 'fdl' + '.' + ext) for iDeviceFiles in set(listIdevicesFiles): iDeviceFiles.copyfiles(outputDir)
def process_previewed_images(self, content, page_id, idevice_id): """ to build up the corresponding resources from any images (etc.) added in by the tinyMCE image-browser plug-in, which will have put them into src="../previews/" Now updated to include special math images as well, as generated by our custom exemath plugin to TinyMCE. These are to follow the naming convention of "eXe_LaTeX_math_#.gif" (where the # is only guaranteed to be unique per Preview session, and can therefore end up being resource-ified into "eXe_LaTeX_math_#.#.gif"). Furthermore, they are to be paired with a source LateX file which is to be of the same name, followed by .tex, e.g., "eXe_LaTeX_math_#.gif.tex" (and to maintain this pairing, as a resource will need to be named "eXe_LaTeX_math_#.#.gif.tex" if applicable, where this does differ slightly from what could be its automatic unique-ified resource-ification of: "eXe_LaTeX_math_#.gif.#.tex"!!!) """ new_content = content # first, clear out any empty images. # Image and the new Math are unfortunately capable # of submitting an empty image, which will show as: # <img src="/" /> # (note that at least the media plugin still embeds a full # and valid empty-media tag, so no worries about them.) # These should be stopped in the plugin itself, but until then: empty_image_str = "<img src=\"/\" />" if new_content.find(empty_image_str) >= 0: new_content = new_content.replace(empty_image_str, ""); log.warn("Empty image tag(s) removed from content"); # By this point, tinyMCE's javascript file browser handler: # common.js's: chooseImage_viaTinyMCE() # has already copied the file into the web-server's relative # directory "/previews", BUT, something in tinyMCE's handler # switches "/previews" to "../previews", so beware..... # # At least it does NOT quote anything, and shows it as, for example: # <img src="../previews/%Users%r3m0w%Pictures%Remos_MiscPix% \ # SampleImage.JPG" height="161" width="215" /> # old quoting-handling is still included in the following parsing, # which HAD allowed users to manually enter src= "file://..." URLs, # but with the image now copied into previews, such URLS are no more. # DESIGN NOTE: eventually the following processing should be # enhanced to look at the HTML tags passed in, and ensure that # what is being found as 'src="../previews/.."' is really within # an IMG tag, etc. # For now, though, this easy parsing is working well: # JR search_str = "src=\"../previews/" search_str = "src=\"/previews/" # BEWARE OF THE ABOVE in regards to ProcessPreviewedMedia(), # which takes advantage of the fact that the embedded media # actually gets stored as src="previews/". # If this little weirdness of Images being stored as src="../previews/" # even changes to src="previews/", so more processing will be needed! found_pos = new_content.find(search_str) while found_pos >= 0: end_pos = new_content.find('\"', found_pos + len(search_str)) if end_pos == -1: # now unlikely that this has already been quoted out, # since the search_str INCLUDES a \", but check anyway: end_pos = new_content.find('"', found_pos + 1) else: # okay, the end position \" was found, BUT beware of this # strange case, where the image file:/// URLs # were entered manually in one part of it # (and therefore escaped to "), AND another quote occurs # further below (perhaps even in a non-quoted file:/// via # a tinyMCE browser, but really from anything!) # So..... see if a " is found in the file-name, and # if so, back the end_pos up to there. # NOTE: until actually looking at the HTML tags, and/or # we might be able to do this more programmatically by # first seeing HOW the file:// is initially quoted, # whether by a \" or by ", but for now, # just check this one. end_pos2 = new_content.find('"', found_pos + 1) if end_pos2 > 0 and end_pos2 < end_pos: end_pos = end_pos2 if end_pos >= found_pos: # next, extract the actual file url, to be replaced later # by the local resource file: file_url_str = new_content[found_pos:end_pos] # and to get the actual file path, # rather than the complete URL: # first compensate for how TinyMCE HTML-escapes accents: pre_input_file_name_str = file_url_str[len(search_str):] log.debug("ProcessPreviewedImages: found escaped file = " \ + pre_input_file_name_str) converter = HtmlToText(pre_input_file_name_str) input_file_name_str = converter.convertToText() log.debug("ProcessPreviewedImages: unescaped filename = " \ + input_file_name_str) webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') server_filename = previewDir.joinpath(input_file_name_str); # and now, extract just the filename string back out of that: file_name_str = server_filename.abspath().encode('utf-8'); # Be sure to check that this file even exists before even # attempting to create a corresponding GalleryImage resource: if os.path.exists(file_name_str) \ and os.path.isfile(file_name_str): # Although full filenames (including flatted representations # of their source directory tree) were used to help keep the # filenames here in previewDir unique, this does cause # problems with the filenames being too long, if they # are kept that way. # So.... if an optional .exe_info file is coupled to # this one, go ahead and read in its original basename, # in order to rename the file back to something shorter. # After all, the resource process has its own uniqueifier. # test for the optional .exe_info: basename_value = os.path.basename(file_name_str) descrip_file_path = Path(server_filename + ".exe_info") if os.path.exists(descrip_file_path) \ and os.path.isfile(descrip_file_path): descrip_file = open(descrip_file_path, 'rb') basename_info = descrip_file.read().decode('utf-8') log.debug("ProcessPreviewedImages: decoded basename = " \ + basename_info) # split out the value of this "basename=file" key basename_key_str = "basename=" basename_found_pos = basename_info.find(basename_key_str) # should be right there at the very beginning: if basename_found_pos == 0: basename_value = \ basename_info[len(basename_key_str):] #now we add the file to the package... new_entry = self.add_user_file_to_idevice(idevice_id, file_name_str, new_basename = basename_value) new_content = new_content.replace(file_url_str, "src=\"%s" % new_entry[1]) found_pos = new_content.find(search_str, found_pos + 1) return new_content
class CmdlineExporter(object): extensions = {'xml': '.xml', 'scorm': '.zip', 'ims': '.zip', 'website': '', 'webzip': '.zip', 'singlepage': '', 'xliff': '.xlf' } def __init__(self, config, options): self.config = config self.options = options self.web_dir = Path(self.config.webDir) self.styles_dir = None def do_export(self, inputf, outputf): if hasattr(self, 'export_' + self.options["export"]): LOG.debug("Exporting to type %s, in: %s, out: %s, overwrite: %s" \ % (self.options["export"], inputf, outputf, str(self.options["overwrite"]))) if not outputf: if self.options["export"] in ('website', 'singlepage'): outputf = inputf.rsplit(".elp")[0] else: outputf = inputf + self.extensions[self.options["export"]] outputfp = Path(outputf) if outputfp.exists() and not self.options["overwrite"]: error = _(u'"%s" already exists.\nPlease try again \ with a different filename') % outputf raise Exception(error.encode(sys.stdout.encoding)) else: if outputfp.exists() and self.options["overwrite"]: if outputfp.isdir(): for filen in outputfp.walkfiles(): filen.remove() outputfp.rmdir() else: outputfp.remove() pkg = Package.load(inputf) LOG.debug("Package %s loaded" % (inputf)) if not pkg: error = _(u"Invalid input package") raise Exception(error.encode(sys.stdout.encoding)) self.styles_dir = self.web_dir.joinpath('style', pkg.style) LOG.debug("Styles dir: %s" % (self.styles_dir)) getattr(self, 'export_' + self.options["export"])(pkg, outputf) return outputf else: raise Exception(_(u"Export format not implemented")\ .encode(sys.stdout.encoding)) def export_xml(self, pkg, outputf): open(outputf, "w").write(encodeObjectToXML(pkg)) def export_scorm(self, pkg, outputf): scormExport = ScormExport(self.config, self.styles_dir, outputf, 'scorm1.2') pkg.scowsinglepage = self.options['single-page'] pkg.scowwebsite = self.options['website'] pkg.scowsource = self.options['editable'] scormExport.export(pkg) def export_scorm2004(self, pkg, outputf): scormExport = ScormExport(self.config, self.styles_dir, outputf, 'scorm2004') pkg.scowsinglepage = self.options['single-page'] pkg.scowwebsite = self.options['website'] pkg.scowsource = self.options['editable'] scormExport.export(pkg) def export_ims(self, pkg, outputf): imsExport = IMSExport(self.config, self.styles_dir, outputf) imsExport.export(pkg) def export_website(self, pkg, outputf): outputfp = Path(outputf) outputfp.makedirs() websiteExport = WebsiteExport(self.config, self.styles_dir, outputf) websiteExport.export(pkg) def export_webzip(self, pkg, outputf): websiteExport = WebsiteExport(self.config, self.styles_dir, outputf) websiteExport.exportZip(pkg) def export_singlepage(self, pkg, outputf, print_flag=0): images_dir = self.web_dir.joinpath('images') scripts_dir = self.web_dir.joinpath('scripts') css_dir = self.web_dir.joinpath('css') templates_dir = self.web_dir.joinpath('templates') singlePageExport = SinglePageExport(self.styles_dir, outputf, \ images_dir, scripts_dir, css_dir, templates_dir) singlePageExport.export(pkg, print_flag) def export_xliff(self, pkg, outputf): xliff = XliffExport(self.config, outputf, \ source_copied_in_target=self.options["copy-source"], \ wrap_cdata=self.options["wrap-cdata"]) xliff.export(pkg)
def handleTinyMCEimageChoice( self, client, tinyMCEwin, tinyMCEwin_name, tinyMCEfield, local_filename, preview_filename ): """ Once an image is selected in the file browser that is spawned by the TinyMCE image dialog, copy this file (which is local to the user's machine) into the server space, under a preview directory (after checking if this exists, and creating it if necessary). Note that this IS a "cheat", in violation of the client-server separation, but can be done since we know that the eXe server is actually sitting on the client host. """ server_filename = "" callback_errors = "" errors = 0 log.debug( "handleTinyMCEimageChoice: image local = " + local_filename + ", base=" + os.path.basename(local_filename) ) webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath("previews") if not previewDir.exists(): log.debug("image previews directory does not yet exist; " + "creating as %s " % previewDir) previewDir.makedirs() elif not previewDir.isdir(): client.alert(_(u"Preview directory %s is a file, cannot replace it") % previewDir) log.error( "Couldn't preview tinyMCE-chosen image: " + "Preview dir %s is a file, cannot replace it" % previewDir ) callback_errors = "Preview dir is a file, cannot replace" errors += 1 if errors == 0: log.debug("handleTinyMCEimageChoice: originally, local_filename=" + local_filename) local_filename = unicode(local_filename, "utf-8") log.debug("handleTinyMCEimageChoice: in unicode, local_filename=" + local_filename) localImagePath = Path(local_filename) log.debug("handleTinyMCEimageChoice: after Path, localImagePath= " + localImagePath) if not localImagePath.exists() or not localImagePath.isfile(): client.alert(_(u"Local file %s is not found, cannot preview it") % localImagePath) log.error("Couldn't find tinyMCE-chosen image: %s" % localImagePath) callback_errors = "Image file %s not found, cannot preview" % localImagePath errors += 1 try: log.debug("URIencoded preview filename=" + preview_filename) server_filename = previewDir.joinpath(preview_filename) log.debug( "handleTinyMCEimageChoice copying image from '" + local_filename + "' to '" + server_filename.abspath() + "'." ) shutil.copyfile(local_filename, server_filename.abspath()) descrip_file_path = Path(server_filename + ".exe_info") log.debug( "handleTinyMCEimageChoice creating preview " + "description file '" + descrip_file_path.abspath() + "'." ) descrip_file = open(descrip_file_path, "wb") unspaced_filename = local_filename.replace(" ", "_") unhashed_filename = unspaced_filename.replace("#", "_num_") unamped_local_filename = unhashed_filename.replace("&", "_and_") log.debug("and setting new file basename as: " + unamped_local_filename) my_basename = os.path.basename(unamped_local_filename) descrip_file.write((u"basename=" + my_basename).encode("utf-8")) descrip_file.flush() descrip_file.close() except Exception, e: client.alert(_("SAVE FAILED!\n%s" % str(e))) log.error( "handleTinyMCEimageChoice unable to copy local image " + "file to server prevew, error = " + str(e) ) raise
def copyFiles(self, package, outputDir): """ Copy all the files used by the website. """ if os.path.isdir(self.stylesDir): # Copy the style sheet files to the output dir styleFiles = [self.stylesDir / '..' / 'base.css'] styleFiles += [self.stylesDir / '..' / 'popup_bg.gif'] styleFiles += self.stylesDir.files("*.css") styleFiles += self.stylesDir.files("*.jpg") styleFiles += self.stylesDir.files("*.gif") styleFiles += self.stylesDir.files("*.png") styleFiles += self.stylesDir.files("*.js") styleFiles += self.stylesDir.files("*.html") styleFiles += self.stylesDir.files("*.ico") styleFiles += self.stylesDir.files("*.ttf") styleFiles += self.stylesDir.files("*.eot") styleFiles += self.stylesDir.files("*.otf") styleFiles += self.stylesDir.files("*.woff") self.stylesDir.copylist(styleFiles, outputDir) # copy the package's resource files package.resourceDir.copyfiles(outputDir) # copy script files. my_style = G.application.config.styleStore.getStyle(package.style) # jQuery if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(outputDir / 'exe_jquery.js') else: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(outputDir / 'exe_jquery.js') jsFile = (self.scriptsDir / 'common.js') jsFile.copyfile(outputDir / 'common.js') #dT = common.getExportDocType() dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir / 'exe_html5.js') jsFile.copyfile(outputDir / 'exe_html5.js') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir / 'favicon.ico') faviconFile.copyfile(outputDir / 'favicon.ico') # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if hasFlowplayer: videofile = (self.templatesDir / 'flowPlayer.swf') videofile.copyfile(outputDir / 'flowPlayer.swf') controlsfile = (self.templatesDir / 'flowplayer.controls.swf') controlsfile.copyfile(outputDir / 'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir / 'mojomagnify.js') videofile.copyfile(outputDir / 'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir / 'xspf_player.swf') videofile.copyfile(outputDir / 'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir / 'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir / 'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir / 'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir / 'exe_games') exeGames.copyfiles(outputDir) if hasWikipedia: wikipediaCSS = (self.cssDir / 'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir / 'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir / 'mediaelement') mediaelement.copyfiles(outputDir) dT = common.getExportDocType() if dT != "HTML5": jsFile = (self.scriptsDir / 'exe_html5.js') jsFile.copyfile(outputDir / 'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir / 'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd') (outputDir / 'content.data').write_bytes(encodeObject(package)) (outputDir / 'contentv3.xml').write_bytes( encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl.html').copyfile(outputDir / 'fdl.html')
def copyFiles(self, package): """ Copy all the files used by the website. """ # Copy the style sheet files to the output dir # But not nav.css if os.path.isdir(self.stylesDir): # Copy the style sheet files to the output dir styleFiles = [self.stylesDir / '..' / 'base.css'] styleFiles += [self.stylesDir / '..' / 'popup_bg.gif'] styleFiles += self.stylesDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.stylesDir.files("*.jpg") styleFiles += self.stylesDir.files("*.gif") styleFiles += self.stylesDir.files("*.png") styleFiles += self.stylesDir.files("*.js") styleFiles += self.stylesDir.files("*.html") styleFiles += self.stylesDir.files("*.ico") styleFiles += self.stylesDir.files("*.ttf") styleFiles += self.stylesDir.files("*.eot") styleFiles += self.stylesDir.files("*.otf") styleFiles += self.stylesDir.files("*.woff") self.stylesDir.copylist(styleFiles, self.outputDir) # copy the package's resource files package.resourceDir.copyfiles(self.outputDir) # copy script files. my_style = G.application.config.styleStore.getStyle(package.style) # jQuery if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(self.outputDir / 'exe_jquery.js') else: jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(self.outputDir / 'exe_jquery.js') jsFile = (self.scriptsDir / 'common.js') jsFile.copyfile(self.outputDir / 'common.js') jsFile = (self.scriptsDir / 'lernmodule_net.js') jsFile.copyfile(self.outputDir / 'lernmodule_net.js') jsFile = (self.scriptsDir / 'lernmodule_net_custom.js') jsFile.copyfile(self.outputDir / 'lernmodule_net_custom.js') dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir / 'exe_html5.js') jsFile.copyfile(self.outputDir / 'exe_html5.js') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir / 'favicon.ico') faviconFile.copyfile(self.outputDir / 'favicon.ico') #JR Metemos los reproductores necesarios self.compruebaReproductores(self.page.node) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl.html').copyfile(self.outputDir / 'fdl.html')
def convertToFreeText(self): """ Actually do the Converting of MathsIdevice -> FreeTextIdevice, now that FreeText can hold embeddded images. """ new_content = "" # ensure that an image resource still exists on this ImageWithText, # before trying to add it into the FreeText idevice. # Why? corrupt packages have been seen missing resources... # (usually in with extra package objects as well, probably # from old code doing faulty Extracts, or somesuch nonesense) imageResource_exists = False if not self.content.gifResource is None: if os.path.exists(self.content.gifResource.path) and \ os.path.isfile(self.content.gifResource.path): imageResource_exists = True else: log.warn("Couldn't find Maths image when upgrading "\ + self.content.gifResource.storageName) if imageResource_exists: new_content += "<img src=\"resources/" \ + self.content.gifResource.storageName + "\" " # create the expected math resource url for comparison later, # once we do actually create it: math_resource_url="resources/" \ + self.content.gifResource.storageName + ".tex\" " new_content += "exe_math_latex=\"" + math_resource_url + "\" " new_content += "exe_math_size=\"" + repr(self.content.fontsize) \ + "\" " # no height or width for math images, eh? nope. new_content += "/> \n" elif self.content.gifResource: new_content += "<BR>\n[WARNING: missing image: " \ + self.content.gifResource.storageName + "]\n" replacementIdev = FreeTextIdevice(new_content) ########### # now, copy that content field's content into its _w_resourcePaths, # and properly remove the resource directory via Massage.... # for its _wo_resourcePaths: # note that replacementIdev's content field's content # is automatically set at its constructor (above), # as is the default content_w_resourcePaths (a copy of content) # AND the default content_wo_resourcePaths (a copy of content), # so only need to update the content_wo_resourcePaths: replacementIdev.content.content_wo_resourcePaths = \ replacementIdev.content.MassageContentForRenderView( \ replacementIdev.content.content_w_resourcePaths) # Design note: ahhhhh, the above is a good looking reason to possibly # have the MassageContentForRenderView() method # just assume its content_w_resourcePaths as the input # and write the output to its content_wo_resourcePaths..... ####### # next step, add the new IDevice into the same node as this one self.parentNode.addIdevice(replacementIdev) # in passing GalleryImage into the FieldWithResources, # that content field needs to be sure to have an updated # parentNode, courtesy of its idevice: replacementIdev.content.setParentNode() # and semi-manually add/create the current image # resource into the FreeTextIdevice's TextAreaField, content. # the content text will have already been taken care of above, # including the ideal <img src=...> including resources path, # but still need the actual image resource: if imageResource_exists: # Not sure why this can't be imported up top, but it gives # ImportError: cannot import name GalleryImages, # so here it be: from exe.engine.galleryidevice import GalleryImage full_image_path = self.content.gifResource.path # with empty caption: new_GalleryImage = GalleryImage(replacementIdev.content, \ '', full_image_path, mkThumbnail=False) # and.... write the latex_source out into the preview_math_srcfile # such that it can then be passed into the compile command. # Using the desired name (image.gif.tex), write it into tempWebDir: webDir = Path(G.application.tempWebDir) source_tex_name = self.content.gifResource.storageName + ".tex" math_path = webDir.joinpath(source_tex_name) math_filename_str = math_path.abspath().encode('utf-8') log.debug("convertToFreeText: writing LaTeX source into \'" \ + math_filename_str + "\'.") math_file = open(math_filename_str, 'wb') # do we need to append a \n here?: math_file.write(self.content.latex) math_file.flush() math_file.close() # finally, creating a resource for the latex_source as well: new_GalleryLatex = GalleryImage(replacementIdev.content, \ '', math_filename_str, mkThumbnail=False) new_GalleryLatexResource = new_GalleryLatex._imageResource mathsrc_resource_path = new_GalleryLatexResource._storageName # and re-concatenate from the global resources name, # to build the webUrl to the resource: mathsrc_resource_url = new_GalleryLatex.resourcesUrl \ + mathsrc_resource_path # AND compare with the newly built resource_url from above, # to ensure that we've got what we had expected, jah! if (mathsrc_resource_url != math_resource_url): log.warn('The math source was resource-ified differently ' \ + 'than expected, to: ' + mathsrc_resource_url \ + '; the source will need to be recreated.') # right. we COULD go ahead and change the exe_math_latex # attribute to point to the actual mathsrc_resource_url, # EXCEPT that the entire exemath plugin is currently built # with the idea that the source .tex file will always be named # as the mathimage.gif.tex, and this exe_math_latex tag # is really just letting the rest of the world know that # there IS corresponding source expected there. # If exemath is to ever change and use the actual contents # of this exe_math_latex tag (rather than just appended .tex), # then this could be revisited here. else: log.debug('math source was resource-ified properly to: ' \ + mathsrc_resource_url) # and move the new idevice up to the position following this node! while ( self.parentNode.idevices.index(replacementIdev) \ > ( (self.parentNode.idevices.index(self) + 1))): replacementIdev.movePrev() # finally: delete THIS idevice itself, deleting it from the node self.delete()
class CmdlineExporter(object): extensions = { 'xml': '.xml', 'scorm': '.zip', 'ims': '.zip', 'website': '', 'webzip': '.zip', 'singlepage': '', 'xliff': '.xlf' } def __init__(self, config, options): self.config = config self.options = options self.web_dir = Path(self.config.webDir) self.styles_dir = None def do_export(self, inputf, outputf): if hasattr(self, 'export_' + self.options["export"]): LOG.debug("Exporting to type %s, in: %s, out: %s, overwrite: %s" \ % (self.options["export"], inputf, outputf, str(self.options["overwrite"]))) if not outputf: if self.options["export"] in ('website', 'singlepage'): outputf = inputf.rsplit(".elp")[0] else: outputf = inputf + self.extensions[self.options["export"]] outputfp = Path(outputf) if outputfp.exists() and not self.options["overwrite"]: error = _(u'"%s" already exists.\nPlease try again \ with a different filename') % outputf raise Exception(error.encode(sys.stdout.encoding)) else: if outputfp.exists() and self.options["overwrite"]: if outputfp.isdir(): for filen in outputfp.walkfiles(): filen.remove() outputfp.rmdir() else: outputfp.remove() pkg = Package.load(inputf) LOG.debug("Package %s loaded" % (inputf)) if not pkg: error = _(u"Invalid input package") raise Exception(error.encode(sys.stdout.encoding)) self.styles_dir = self.web_dir.joinpath('style', pkg.style) LOG.debug("Styles dir: %s" % (self.styles_dir)) getattr(self, 'export_' + self.options["export"])(pkg, outputf) return outputf else: raise Exception(_(u"Export format not implemented")\ .encode(sys.stdout.encoding)) def export_xml(self, pkg, outputf): open(outputf, "w").write(encodeObjectToXML(pkg)) def export_scorm(self, pkg, outputf): scormExport = ScormExport(self.config, self.styles_dir, outputf, 'scorm1.2') pkg.scowsinglepage = self.options['single-page'] pkg.scowwebsite = self.options['website'] pkg.scowsource = self.options['editable'] scormExport.export(pkg) def export_ims(self, pkg, outputf): imsExport = IMSExport(self.config, self.styles_dir, outputf) imsExport.export(pkg) def export_website(self, pkg, outputf): outputfp = Path(outputf) outputfp.makedirs() websiteExport = WebsiteExport(self.config, self.styles_dir, outputf) websiteExport.export(pkg) def export_webzip(self, pkg, outputf): websiteExport = WebsiteExport(self.config, self.styles_dir, outputf) websiteExport.exportZip(pkg) def export_singlepage(self, pkg, outputf, print_flag=0): images_dir = self.web_dir.joinpath('images') scripts_dir = self.web_dir.joinpath('scripts') templates_dir = self.web_dir.joinpath('templates') singlePageExport = SinglePageExport(self.styles_dir, outputf, \ images_dir, scripts_dir, templates_dir) singlePageExport.export(pkg, print_flag) def export_xliff(self, pkg, outputf): xliff = XliffExport(self.config, outputf, \ source_copied_in_target=self.options["copy-source"], \ wrap_cdata=self.options["wrap-cdata"]) xliff.export(pkg)
def copyFiles(self, package): """ Copy all the files used by the website. """ # Copy the style sheet files to the output dir # But not nav.css if os.path.isdir(self.stylesDir): # Copy the style sheet files to the output dir styleFiles = [self.stylesDir/'..'/'base.css'] styleFiles += [self.stylesDir/'..'/'popup_bg.gif'] styleFiles += self.stylesDir.files("*.css") if "nav.css" in styleFiles: styleFiles.remove("nav.css") styleFiles += self.stylesDir.files("*.jpg") styleFiles += self.stylesDir.files("*.gif") styleFiles += self.stylesDir.files("*.png") styleFiles += self.stylesDir.files("*.js") styleFiles += self.stylesDir.files("*.html") styleFiles += self.stylesDir.files("*.ico") styleFiles += self.stylesDir.files("*.ttf") styleFiles += self.stylesDir.files("*.eot") styleFiles += self.stylesDir.files("*.otf") styleFiles += self.stylesDir.files("*.woff") self.stylesDir.copylist(styleFiles, self.outputDir) # copy the package's resource files package.resourceDir.copyfiles(self.outputDir) # copy script files. my_style = G.application.config.styleStore.getStyle(package.style) # jQuery if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(self.outputDir/'exe_jquery.js') else: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(self.outputDir/'exe_jquery.js') jsFile = (self.scriptsDir/'common.js') jsFile.copyfile(self.outputDir/'common.js') jsFile = (self.scriptsDir/'lernmodule_net.js') jsFile.copyfile(self.outputDir/'lernmodule_net.js') dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(self.outputDir/'exe_html5.js') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(self.outputDir/'favicon.ico') #JR Metemos los reproductores necesarios self.compruebaReproductores(self.page.node) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl.html').copyfile(self.outputDir/'fdl.html')
def ideviceHeader(e, style, mode): dT = getExportDocType() lb = "\n" # Line breaks # Default HTML tags: sectionTag = "div" articleTag = "div" headerTag = "div" titleTag = "h2" if dT == "HTML5": sectionTag = "section" articleTag = "article" headerTag = "header" titleTag = "h1" themePath = Path(G.application.config.stylesDir / style) themeXMLFile = themePath.joinpath("config.xml") themeHasXML = themeHasConfigXML(style) w = "" # Common wrapper o = "" # Old HTML (themes with no config.xml file) h = "" # New HTML w2 = "" eEm = "" if e.idevice.emphasis > 0: w2 = "<" + sectionTag + ' class="iDevice_inner">' + lb w2 += "<" + sectionTag + ' class="iDevice_content_wrapper">' + lb eEm = " em_iDevice" if mode == "preview" and themeHasXML: w += "<" + sectionTag + ' class="iDevice_wrapper ' + e.idevice.klass + eEm + '" id="id' + e.id + '">' + lb w += u"<" + articleTag + ' class="iDevice emphasis' + unicode(e.idevice.emphasis) + '" ' if mode == "preview": w += u"ondblclick=\"submitLink('edit', " + e.id + ', 0);"' w += ">" + lb if e.idevice.emphasis > 0: h += "<" + headerTag + ' class="iDevice_header"' if e.idevice.icon: displayIcon = True # The following lines should be replaced by something like: """ if hasattr(e.idevice, 'originalicon'): if e.idevice.icon==e.idevice.originalicon: displayIcon = False """ k = e.idevice.klass i = e.idevice.icon if ( (k == "ListaIdevice" and i == "question") or (k == "CasestudyIdevice" and i == "casestudy") or (k == "GalleryIdevice" and i == "gallery") or (k == "ClozeIdevice" and i == "question") or (k == "ReflectionIdevice" and i == "reflection") or (k == "QuizTestIdevice" and i == "question") or (k == "TrueFalseIdevice" and i == "question") or (k == "MultiSelectIdevice" and i == "question") or (k == "MultichoiceIdevice" and i == "question") ): displayIcon = False # /end iconPath = "/style/" + style + "/icon_" + e.idevice.icon + ".gif" if mode == "view": iconPath = "icon_" + e.idevice.icon + ".gif" myIcon = themePath.joinpath("icon_" + e.idevice.icon + ".gif") if myIcon.exists(): o += u'<img alt="" class="iDevice_icon" src="' + iconPath + '" />' if (e.idevice.icon + "Idevice") != e.idevice.klass: if myIcon.exists() and displayIcon: h += ' style="background-image:url(' + iconPath + ')"' else: log.debug("Idevice %s at node %s has no icon" % (e.idevice._title, e.idevice.parentNode._title)) t = e.idevice.title fullT = u"<" + titleTag + ' class="iDeviceTitle">' + t + "</" + titleTag + ">" if t == "": fullT = u'<span class="iDeviceTitle"> </span>' o += u"<" + titleTag + ' class="iDeviceTitle">' + t + "</" + titleTag + ">" h += ">" h += fullT h += "</" + headerTag + ">" + lb if e.idevice.emphasis <= 0: h = "" o = "" if themeHasXML: return w + h + w2 else: return w + o + w2
def copyFiles(self, package): """ Copy all the files used by the website. """ # Copy the style files to the output dir # But not nav.css if os.path.isdir(self.stylesDir): styleFiles = [self.stylesDir/'..'/'popup_bg.gif'] styleFiles += self.stylesDir.files("*.*") if "nav.css" in styleFiles: styleFiles.remove("nav.css") self.stylesDir.copylist(styleFiles, self.outputDir) # copy the package's resource files for resourceFile in package.resourceDir.walkfiles(): file = package.resourceDir.relpathto(resourceFile) if ("/" in file): Dir = Path(self.outputDir/file[:file.rindex("/")]) if not Dir.exists(): Dir.makedirs() resourceFile.copy(self.outputDir/Dir) else: resourceFile.copy(self.outputDir) listCSSFiles=getFilesCSSToMinify('singlepage', self.stylesDir) exportMinFileCSS(listCSSFiles, self.outputDir) # copy script files. my_style = G.application.config.styleStore.getStyle(package.style) # jQuery if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(self.outputDir/'exe_jquery.js') else: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(self.outputDir/'exe_jquery.js') dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(self.outputDir/'exe_html5.js') # Minify common.js file listFiles=getFilesJSToMinify('singlepage', self.scriptsDir) exportMinFileJS(listFiles, self.outputDir) # Create lang file langFile = open(self.outputDir + '/common_i18n.js', "w") langFile.write(common.getJavaScriptStrings(False)) langFile.close() # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(self.outputDir/'favicon.ico') #JR Metemos los reproductores necesarios self.compruebaReproductores(self.page.node) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence ext = 'html' if G.application.config.cutFileName == "1": ext = 'htm' (self.templatesDir/'fdl' + '.' + ext).copyfile(self.outputDir/'fdl' + '.' + ext)
def handleTinyMCEmath(self, client, tinyMCEwin, tinyMCEwin_name, \ tinyMCEfield, latex_source, math_fontsize, \ preview_image_filename, preview_math_srcfile): """ Based off of handleTinyMCEimageChoice(), handleTinyMCEmath() is similar in that it places a .gif math image (and a corresponding .tex LaTeX source file) into the previews dir. Rather than copying the image from a user-selected directory, though, this routine actually generates the math image using mimetex. """ server_filename = "" callback_errors = "" errors = 0 webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') if not previewDir.exists(): log.debug("image previews directory does not yet exist; " \ + "creating as %s " % previewDir) previewDir.makedirs() elif not previewDir.isdir(): client.alert( \ _(u'Preview directory %s is a file, cannot replace it') \ % previewDir) log.error("Couldn't preview tinyMCE-chosen image: "+ "Preview dir %s is a file, cannot replace it" \ % previewDir) callback_errors = "Preview dir is a file, cannot replace" errors += 1 #if errors == 0: # localImagePath = Path(local_filename) # if not localImagePath.exists() or not localImagePath.isfile(): # client.alert( \ # _(u'Image file %s is not found, cannot preview it') \ # % localImagePath) # log.error("Couldn't find tinyMCE-chosen image: %s" \ # % localImagePath) # callback_errors = "Image file %s not found, cannot preview" \ # % localImagePath # errors += 1 # the mimetex usage code was swiped from the Math iDevice: if latex_source <> "": # first write the latex_source out into the preview_math_srcfile, # such that it can then be passed into the compile command: math_filename = previewDir.joinpath(preview_math_srcfile) math_filename_str = math_filename.abspath().encode('utf-8') log.info("handleTinyMCEmath: using LaTeX source: " + latex_source) log.debug("writing LaTeX source into \'" \ + math_filename_str + "\'.") math_file = open(math_filename, 'wb') # do we need to append a \n here?: math_file.write(latex_source) math_file.flush() math_file.close() try: use_latex_sourcefile = math_filename_str tempFileName = compile(use_latex_sourcefile, math_fontsize, \ latex_is_file=True) except Exception, e: client.alert(_('MimeTeX compile failed!\n%s' % str(e))) log.error("handleTinyMCEmath unable to compile LaTeX using "\ +"mimetex, error = " + str(e)) raise # copy the file into previews server_filename = previewDir.joinpath(preview_image_filename); log.debug("handleTinyMCEmath copying math image from \'"\ + tempFileName + "\' to \'" \ + server_filename.abspath().encode('utf-8') + "\'."); shutil.copyfile(tempFileName, \ server_filename.abspath().encode('utf-8')); # Delete the temp file made by compile Path(tempFileName).remove()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # copy the package's resource files package.resourceDir.copyfiles(outputDir) # copy the package's resource files, only non existant in outputDir # outputDirFiles = outputDir.files() # for rfile in package.resourceDir.files(): # if rfile not in outputDirFiles: # rfile.copy(outputDir) # copy the package's resource files, only indexed in package.resources # for md5 in package.resources.values(): # for resource in md5: # resource.path.copy(outputDir) # Export the package content # Import the Scorm Page class , if the secure mode is off. If the style has it's own page class # use that, else use the default one. if self.styleSecureMode == "0": if (self.styleDir / "scormpage.py").exists(): global ScormPage module = imp.load_source("ScormPage", self.styleDir / "scormpage.py") ScormPage = module.ScormPage self.pages = [ScormPage("index", 1, package.root, scormType=self.scormType, metadataType=self.metadataType)] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType, self.metadataType) manifest.save("imsmanifest.xml") if self.hasForum: manifest.save("discussionforum.xml") # Copy the style sheet files to the output dir styleFiles = [self.styleDir / ".." / "base.css"] styleFiles += [self.styleDir / ".." / "popup_bg.gif"] # And with all the files of the style we avoid problems: styleFiles += self.styleDir.files("*.*") if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) # Copy the scripts dT = common.getExportDocType() if dT == "HTML5": jsFile = self.scriptsDir / "exe_html5.js" jsFile.copyfile(outputDir / "exe_html5.js") # jQuery my_style = G.application.config.styleStore.getStyle(page.node.package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = self.scriptsDir / "exe_jquery.js" jsFile.copyfile(outputDir / "exe_jquery.js") else: jsFile = self.scriptsDir / "exe_jquery.js" jsFile.copyfile(outputDir / "exe_jquery.js") if self.scormType == "commoncartridge": jsFile = self.scriptsDir / "common.js" jsFile.copyfile(outputDir / "common.js") if self.scormType == "scorm2004" or self.scormType == "scorm1.2": self.scriptsDir.copylist(("SCORM_API_wrapper.js", "SCOFunctions.js", "common.js"), outputDir) # about SCHEMAS: schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir / "scorm1.2" schemasDir.copylist( ( "imscp_rootv1p1p2.xsd", "imsmd_rootv1p2p1.xsd", "adlcp_rootv1p2.xsd", "lom.xsd", "lomCustom.xsd", "ims_xml.xsd", ), outputDir, ) elif self.scormType == "scorm2004": schemasDir = self.schemasDir / "scorm2004" schemasDir.copylist( ( "adlcp_v1p3.xsd", "adlnav_v1p3.xsd", "adlseq_v1p3.xsd", "datatypes.dtd", "imscp_v1p1.xsd", "imsssp_v1p0.xsd", "imsss_v1p0.xsd", "imsss_v1p0auxresource.xsd", "imsss_v1p0control.xsd", "imsss_v1p0delivery.xsd", "imsmd_rootv1p2p1.xsd", "imsss_v1p0limit.xsd", "imsss_v1p0objective.xsd", "imsss_v1p0random.xsd", "imsss_v1p0rollup.xsd", "imsss_v1p0seqrule.xsd", "imsss_v1p0util.xsd", "ims_xml.xsd", "lom.xsd", "lomCustom.xsd", "xml.xsd", "XMLSchema.dtd", ), outputDir, ) try: import shutil, errno shutil.copytree(schemasDir / "common", outputDir / "common") shutil.copytree(schemasDir / "extend", outputDir / "extend") shutil.copytree(schemasDir / "unique", outputDir / "unique") shutil.copytree(schemasDir / "vocab", outputDir / "vocab") except OSError as exc: if exc.errno == errno.ENOTDIR: shutil.copy(schemasDir, outputDir) else: raise # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if ( hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasWikipedia and hasInstructions and hasMediaelement ): isBreak = True break if not hasFlowplayer: if "flowPlayer.swf" in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if "mojomagnify.js" in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if "xspf_player.swf" in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasWikipedia: if "WikipediaIdevice" == idevice.klass: hasWikipedia = True if not hasInstructions: if ( "TrueFalseIdevice" == idevice.klass or "MultichoiceIdevice" == idevice.klass or "VerdaderofalsofpdIdevice" == idevice.klass or "EleccionmultiplefpdIdevice" == idevice.klass ): hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if hasFlowplayer: videofile = self.templatesDir / "flowPlayer.swf" videofile.copyfile(outputDir / "flowPlayer.swf") controlsfile = self.templatesDir / "flowplayer.controls.swf" controlsfile.copyfile(outputDir / "flowplayer.controls.swf") if hasMagnifier: videofile = self.templatesDir / "mojomagnify.js" videofile.copyfile(outputDir / "mojomagnify.js") if hasXspfplayer: videofile = self.templatesDir / "xspf_player.swf" videofile.copyfile(outputDir / "xspf_player.swf") if hasGallery: imageGalleryCSS = self.cssDir / "exe_lightbox.css" imageGalleryCSS.copyfile(outputDir / "exe_lightbox.css") imageGalleryJS = self.scriptsDir / "exe_lightbox.js" imageGalleryJS.copyfile(outputDir / "exe_lightbox.js") self.imagesDir.copylist( ( "exe_lightbox_close.png", "exe_lightbox_loading.gif", "exe_lightbox_next.png", "exe_lightbox_prev.png", ), outputDir, ) if hasWikipedia: wikipediaCSS = self.cssDir / "exe_wikipedia.css" wikipediaCSS.copyfile(outputDir / "exe_wikipedia.css") if hasInstructions: common.copyFileIfNotInStyle("panel-amusements.png", self, outputDir) common.copyFileIfNotInStyle("stock-stop.png", self, outputDir) if hasMediaelement: mediaelement = self.scriptsDir / "mediaelement" mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = self.scriptsDir / "exe_html5.js" if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / "fdl.html").copyfile(outputDir / "fdl.html") if hasattr(package, "scowsinglepage") and package.scowsinglepage: page = SinglePage("singlepage_index", 1, package.root) page.save(outputDir / "singlepage_index.html") # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = self.imagesDir / "favicon.ico" faviconFile.copyfile(outputDir / "favicon.ico") if hasattr(package, "scowwebsite") and package.scowwebsite: website = WebsiteExport(self.config, self.styleDir, outputDir, "website_") website.export(package) (self.styleDir / "nav.css").copyfile(outputDir / "nav.css") # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = self.imagesDir / "favicon.ico" faviconFile.copyfile(outputDir / "favicon.ico") if hasattr(package, "exportSource") and package.exportSource: (G.application.config.webDir / "templates" / "content.xsd").copyfile(outputDir / "content.xsd") (outputDir / "content.data").write_bytes(encodeObject(package)) (outputDir / "contentv3.xml").write_bytes(encodeObjectToXML(package)) # Zip it up! self.filename.safeSave(self.doZip, _("EXPORT FAILED!\nLast succesful export is %s."), outputDir) # Clean up the temporary dir outputDir.rmtree()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # copy the package's resource files for resourceFile in package.resourceDir.walkfiles(): file = package.resourceDir.relpathto(resourceFile) if ("/" in file): Dir = Path(outputDir / file[:file.rindex("/")]) if not Dir.exists(): Dir.makedirs() resourceFile.copy(outputDir / Dir) else: resourceFile.copy(outputDir) # copy the package's resource files, only non existant in outputDir # outputDirFiles = outputDir.files() # for rfile in package.resourceDir.files(): # if rfile not in outputDirFiles: # rfile.copy(outputDir) # copy the package's resource files, only indexed in package.resources # for md5 in package.resources.values(): # for resource in md5: # resource.path.copy(outputDir) # Export the package content # Import the Scorm Page class , if the secure mode is off. If the style has it's own page class # use that, else use the default one. if self.styleSecureMode == "0": if (self.styleDir / "scormpage.py").exists(): global ScormPage module = imp.load_source("ScormPage", self.styleDir / "scormpage.py") ScormPage = module.ScormPage self.pages = [ ScormPage("index", 1, package.root, scormType=self.scormType, metadataType=self.metadataType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir, self.pages) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType, self.metadataType) modifiedMetaData = manifest.save("imsmanifest.xml") # Create lang file langFile = open(outputDir + '/common_i18n.js', "w") langFile.write(common.getJavaScriptStrings(False)) langFile.close() if self.hasForum: manifest.save("discussionforum.xml") # Copy the style files to the output dir styleFiles = [self.styleDir / '..' / 'popup_bg.gif'] # And with all the files of the style we avoid problems: styleFiles += self.styleDir.files("*.*") if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) listCSSFiles = getFilesCSSToMinify('scorm', self.styleDir) exportMinFileCSS(listCSSFiles, outputDir) # Copy the scripts dT = common.getExportDocType() if dT == "HTML5": #listFiles+=[self.scriptsDir/'exe_html5.js'] #listOutFiles+=[outputDir/'exe_html5.js'] jsFile = (self.scriptsDir / 'exe_html5.js') jsFile.copyfile(outputDir / 'exe_html5.js') # jQuery my_style = G.application.config.styleStore.getStyle( page.node.package.style) if my_style.hasValidConfig(): if my_style.get_jquery() == True: #listFiles+=[self.scriptsDir/'exe_jquery.js'] #listOutFiles+=[outputDir/'exe_jquery.js'] jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(outputDir / 'exe_jquery.js') else: #listFiles+=[self.scriptsDir/'exe_jquery.js'] #listOutFiles+=[outputDir/'exe_jquery.js'] jsFile = (self.scriptsDir / 'exe_jquery.js') jsFile.copyfile(outputDir / 'exe_jquery.js') if self.scormType == "commoncartridge" or self.scormType == "scorm2004" or self.scormType == "scorm1.2": listFiles = getFilesJSToMinify('scorm', self.scriptsDir) exportMinFileJS(listFiles, outputDir) if self.scormType == "scorm2004" or self.scormType == "scorm1.2": self.scriptsDir.copylist( ('SCORM_API_wrapper.js', 'SCOFunctions.js'), outputDir) # about SCHEMAS: schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir / "scorm1.2" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'lom.xsd', 'lomCustom.xsd', 'ims_xml.xsd'), outputDir) elif self.scormType == "scorm2004": schemasDir = self.schemasDir / "scorm2004" schemasDir.copylist( ('adlcp_v1p3.xsd', 'adlnav_v1p3.xsd', 'adlseq_v1p3.xsd', 'datatypes.dtd', 'imscp_v1p1.xsd', 'imsssp_v1p0.xsd', 'imsss_v1p0.xsd', 'imsss_v1p0auxresource.xsd', 'imsss_v1p0control.xsd', 'imsss_v1p0delivery.xsd', 'imsmd_rootv1p2p1.xsd', 'imsss_v1p0limit.xsd', 'imsss_v1p0objective.xsd', 'imsss_v1p0random.xsd', 'imsss_v1p0rollup.xsd', 'imsss_v1p0seqrule.xsd', 'imsss_v1p0util.xsd', 'ims_xml.xsd', 'lom.xsd', 'lomCustom.xsd', 'xml.xsd', 'XMLSchema.dtd'), outputDir) try: import shutil, errno shutil.copytree(schemasDir / "common", outputDir / "common") shutil.copytree(schemasDir / "extend", outputDir / "extend") shutil.copytree(schemasDir / "unique", outputDir / "unique") shutil.copytree(schemasDir / "vocab", outputDir / "vocab") except OSError as exc: if exc.errno == errno.ENOTDIR: shutil.copy(schemasDir, outputDir) else: raise # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasElpLink = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False hasABCMusic = False listIdevicesFiles = [] for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasElpLink and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips and hasABCMusic): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasElpLink: hasElpLink = common.ideviceHasElpLink(idevice, package) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if not hasABCMusic: hasABCMusic = common.ideviceHasABCMusic(idevice) if hasattr(idevice, "_iDeviceDir"): listIdevicesFiles.append( (idevice.get_jsidevice_dir() / 'export')) common.exportJavaScriptIdevicesFiles(page.node.idevices, outputDir) if hasFlowplayer: videofile = (self.templatesDir / 'flowPlayer.swf') videofile.copyfile(outputDir / 'flowPlayer.swf') controlsfile = (self.templatesDir / 'flowplayer.controls.swf') controlsfile.copyfile(outputDir / 'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir / 'mojomagnify.js') videofile.copyfile(outputDir / 'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir / 'xspf_player.swf') videofile.copyfile(outputDir / 'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir / 'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir / 'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir / 'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir / 'exe_games') exeGames.copyfiles(outputDir) # Add game js string to common_i18n langGameFile = open(outputDir + '/common_i18n.js', "a") langGameFile.write(common.getGamesJavaScriptStrings(False)) langGameFile.close() if hasElpLink or package.get_exportElp(): # Export the elp file currentPackagePath = Path(package.filename) currentPackagePath.copyfile(outputDir / package.name + '.elp') if hasWikipedia: wikipediaCSS = (self.cssDir / 'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir / 'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir / 'mediaelement') mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = (self.scriptsDir / 'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir / 'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasABCMusic: pluginScripts = (self.scriptsDir / 'tinymce_4/js/tinymce/plugins/abcmusic/export') pluginScripts.copyfiles(outputDir) ext = ".html" if G.application.config.cutFileName == "1": ext = ".htm" if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir / 'fdl' + ext).copyfile(outputDir / 'fdl' + ext) if hasattr(package, 'scowsinglepage') and package.scowsinglepage: page = SinglePage("singlepage_index", 1, package.root) page.save(outputDir / "singlepage_index" + ext) # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir / 'favicon.ico') faviconFile.copyfile(outputDir / 'favicon.ico') if hasattr(package, 'scowwebsite') and package.scowwebsite: website = WebsiteExport(self.config, self.styleDir, outputDir, "website_") website.export(package) (self.styleDir / 'nav.css').copyfile(outputDir / 'nav.css') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir / package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir / 'favicon.ico') faviconFile.copyfile(outputDir / 'favicon.ico') if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir / 'templates' / 'content.xsd').copyfile(outputDir / 'content.xsd') (outputDir / 'content.data').write_bytes(encodeObject(package)) (outputDir / 'contentv3.xml').write_bytes( encodeObjectToXML(package)) # Zip it up! self.filename.safeSave( self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree() return modifiedMetaData
def ideviceHeader(e, style, mode): dT = getExportDocType() lb = "\n" #Line breaks #Default HTML tags: articleTag = "div" headerTag = "div" titleTag = "h2" if dT == "HTML5": articleTag = "article" headerTag = "header" titleTag = "h1" themePath = Path(G.application.config.stylesDir / style) themeXMLFile = themePath.joinpath("config.xml") themeHasXML = themeHasConfigXML(style) w = '' # Common wrapper o = '' # Old HTML (themes with no config.xml file) h = '' # New HTML w2 = '' eEm = '' if e.idevice.emphasis > 0: w2 = '<div class="iDevice_inner">' + lb w2 += '<div class="iDevice_content_wrapper">' + lb eEm = ' em_iDevice' if mode == "preview" and themeHasXML: w += '<' + articleTag + ' class="iDevice_wrapper ' + e.idevice.klass + eEm + '" id="id' + e.id + '">' + lb w += u"<div class=\"iDevice emphasis" + unicode(e.idevice.emphasis) + "\" " if mode == "preview": w += u"ondblclick=\"submitLink('edit', " + e.id + ", 0);\"" w += ">" + lb if e.idevice.emphasis > 0: h += '<' + headerTag + ' class="iDevice_header"' if e.idevice.icon: displayIcon = True # The following lines should be replaced by something like: ''' if hasattr(e.idevice, 'originalicon'): if e.idevice.icon==e.idevice.originalicon: displayIcon = False ''' k = e.idevice.klass i = e.idevice.icon if (k == 'ListaIdevice' and i == 'question') or ( k == 'CasestudyIdevice' and i == 'casestudy' ) or (k == 'GalleryIdevice' and i == 'gallery') or ( k == 'ClozeIdevice' and i == 'question' ) or (k == 'ReflectionIdevice' and i == 'reflection') or ( k == 'QuizTestIdevice' and i == 'question') or ( k == 'TrueFalseIdevice' and i == 'question') or ( k == 'MultiSelectIdevice' and i == 'question') or (k == 'MultichoiceIdevice' and i == 'question'): displayIcon = False # /end iconPath = '/style/' + style + '/icon_' + e.idevice.icon + '.gif' if mode == "view": iconPath = 'icon_' + e.idevice.icon + '.gif' myIcon = themePath.joinpath("icon_" + e.idevice.icon + ".gif") if myIcon.exists(): o += u'<img alt="" class="iDevice_icon" src="' + iconPath + '" />' if (e.idevice.icon + "Idevice") != e.idevice.klass: if myIcon.exists() and displayIcon: h += ' style="background-image:url(' + iconPath + ')"' else: log.debug("Idevice %s at node %s has no icon" % (e.idevice._title, e.idevice.parentNode._title)) t = e.idevice.title fullT = u'<' + titleTag + ' class="iDeviceTitle">' + t + '</' + titleTag + '>' if (t == ""): fullT = u'<span class="iDeviceTitle"> </span>' o += u"<" + titleTag + " class=\"iDeviceTitle\">" + t + "</" + titleTag + ">" h += '>' h += fullT h += '</' + headerTag + '>' + lb if e.idevice.emphasis <= 0: h = "" o = "" if themeHasXML: return w + h + w2 else: return w + o + w2
def handleTinyMCEmath(self, client, tinyMCEwin, tinyMCEwin_name, \ tinyMCEfield, latex_source, math_fontsize, \ preview_image_filename, preview_math_srcfile): """ Based off of handleTinyMCEimageChoice(), handleTinyMCEmath() is similar in that it places a .gif math image (and a corresponding .tex LaTeX source file) into the previews dir. Rather than copying the image from a user-selected directory, though, this routine actually generates the math image using mimetex. """ server_filename = "" callback_errors = "" errors = 0 webDir = Path(G.application.tempWebDir) previewDir = webDir.joinpath('previews') if not previewDir.exists(): log.debug("image previews directory does not yet exist; " \ + "creating as %s " % previewDir) previewDir.makedirs() elif not previewDir.isdir(): client.alert( \ _(u'Preview directory %s is a file, cannot replace it') \ % previewDir) log.error("Couldn't preview tinyMCE-chosen image: "+ "Preview dir %s is a file, cannot replace it" \ % previewDir) callback_errors = "Preview dir is a file, cannot replace" errors += 1 #if errors == 0: # localImagePath = Path(local_filename) # if not localImagePath.exists() or not localImagePath.isfile(): # client.alert( \ # _(u'Image file %s is not found, cannot preview it') \ # % localImagePath) # log.error("Couldn't find tinyMCE-chosen image: %s" \ # % localImagePath) # callback_errors = "Image file %s not found, cannot preview" \ # % localImagePath # errors += 1 # the mimetex usage code was swiped from the Math iDevice: if latex_source <> "": # first write the latex_source out into the preview_math_srcfile, # such that it can then be passed into the compile command: math_filename = previewDir.joinpath(preview_math_srcfile) math_filename_str = math_filename.abspath().encode('utf-8') log.info("handleTinyMCEmath: using LaTeX source: " + latex_source) log.debug("writing LaTeX source into \'" \ + math_filename_str + "\'.") math_file = open(math_filename, 'wb') # do we need to append a \n here?: math_file.write(latex_source) math_file.flush() math_file.close() try: use_latex_sourcefile = math_filename_str tempFileName = compile(use_latex_sourcefile, math_fontsize, \ latex_is_file=True) except Exception, e: client.alert(_('MimeTeX compile failed!\n%s' % str(e))) log.error("handleTinyMCEmath unable to compile LaTeX using "\ +"mimetex, error = " + str(e)) raise # copy the file into previews server_filename = previewDir.joinpath(preview_image_filename) log.debug("handleTinyMCEmath copying math image from \'"\ + tempFileName + "\' to \'" \ + server_filename.abspath().encode('utf-8') + "\'.") shutil.copyfile(tempFileName, \ server_filename.abspath().encode('utf-8')) # Delete the temp file made by compile Path(tempFileName).remove()
def export(self, package): """ Export SCORM package """ # First do the export to a temporary directory outputDir = TempDirPath() self.metadataType = package.exportMetadataType # copy the package's resource files package.resourceDir.copyfiles(outputDir) # copy the package's resource files, only non existant in outputDir # outputDirFiles = outputDir.files() # for rfile in package.resourceDir.files(): # if rfile not in outputDirFiles: # rfile.copy(outputDir) # copy the package's resource files, only indexed in package.resources # for md5 in package.resources.values(): # for resource in md5: # resource.path.copy(outputDir) # Export the package content # Import the Scorm Page class , if the secure mode is off. If the style has it's own page class # use that, else use the default one. if self.styleSecureMode=="0": if (self.styleDir/"scormpage.py").exists(): global ScormPage module = imp.load_source("ScormPage",self.styleDir/"scormpage.py") ScormPage = module.ScormPage self.pages = [ ScormPage("index", 1, package.root, scormType=self.scormType, metadataType=self.metadataType) ] self.generatePages(package.root, 2) uniquifyNames(self.pages) for page in self.pages: page.save(outputDir) if not self.hasForum: for idevice in page.node.idevices: if hasattr(idevice, "isForum"): if idevice.forum.lms.lms == "moodle": self.hasForum = True break # Create the manifest file manifest = Manifest(self.config, outputDir, package, self.pages, self.scormType, self.metadataType) manifest.save("imsmanifest.xml") if self.hasForum: manifest.save("discussionforum.xml") # Copy the style sheet files to the output dir styleFiles = [self.styleDir/'..'/'base.css'] styleFiles += [self.styleDir/'..'/'popup_bg.gif'] # And with all the files of the style we avoid problems: styleFiles += self.styleDir.files("*.*") if self.scormType == "commoncartridge": for sf in styleFiles[:]: if sf.basename() not in manifest.dependencies: styleFiles.remove(sf) self.styleDir.copylist(styleFiles, outputDir) # Copy the scripts dT = common.getExportDocType() if dT == "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') # jQuery my_style = G.application.config.styleStore.getStyle(page.node.package.style) if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') else: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') if self.scormType == "commoncartridge": jsFile = (self.scriptsDir/'common.js') jsFile.copyfile(outputDir/'common.js') if self.scormType == "scorm2004" or self.scormType == "scorm1.2": self.scriptsDir.copylist(('SCORM_API_wrapper.js', 'SCOFunctions.js', 'lernmodule_net.js', 'lernmodule_net_custom.js', 'common.js'), outputDir) # about SCHEMAS: schemasDir = "" if self.scormType == "scorm1.2": schemasDir = self.schemasDir/"scorm1.2" schemasDir.copylist(('imscp_rootv1p1p2.xsd', 'imsmd_rootv1p2p1.xsd', 'adlcp_rootv1p2.xsd', 'lom.xsd', 'lomCustom.xsd', 'ims_xml.xsd'), outputDir) elif self.scormType == "scorm2004": schemasDir = self.schemasDir/"scorm2004" schemasDir.copylist(('adlcp_v1p3.xsd', 'adlnav_v1p3.xsd', 'adlseq_v1p3.xsd', 'datatypes.dtd', 'imscp_v1p1.xsd', 'imsssp_v1p0.xsd', 'imsss_v1p0.xsd', 'imsss_v1p0auxresource.xsd', 'imsss_v1p0control.xsd', 'imsss_v1p0delivery.xsd', 'imsmd_rootv1p2p1.xsd', 'imsss_v1p0limit.xsd', 'imsss_v1p0objective.xsd', 'imsss_v1p0random.xsd', 'imsss_v1p0rollup.xsd', 'imsss_v1p0seqrule.xsd', 'imsss_v1p0util.xsd', 'ims_xml.xsd', 'lom.xsd', 'lomCustom.xsd', 'xml.xsd', 'XMLSchema.dtd'), outputDir) try: import shutil, errno shutil.copytree(schemasDir/"common", outputDir/"common") shutil.copytree(schemasDir/"extend", outputDir/"extend") shutil.copytree(schemasDir/"unique", outputDir/"unique") shutil.copytree(schemasDir/"vocab", outputDir/"vocab") except OSError as exc: if exc.errno == errno.ENOTDIR: shutil.copy(schemasDir, outputDir) else: raise # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasWikipedia and hasInstructions and hasMediaelement): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'mojomagnify.js') videofile.copyfile(outputDir/'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: imageGalleryCSS = (self.cssDir/'exe_lightbox.css') imageGalleryCSS.copyfile(outputDir/'exe_lightbox.css') imageGalleryJS = (self.scriptsDir/'exe_lightbox.js') imageGalleryJS.copyfile(outputDir/'exe_lightbox.js') self.imagesDir.copylist(('exe_lightbox_close.png', 'exe_lightbox_loading.gif', 'exe_lightbox_next.png', 'exe_lightbox_prev.png'), outputDir) if hasWikipedia: wikipediaCSS = (self.cssDir/'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir/'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir/'mediaelement') mediaelement.copyfiles(outputDir) if dT != "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') if self.scormType == "scorm1.2" or self.scormType == "scorm2004": if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html') if hasattr(package, 'scowsinglepage') and package.scowsinglepage: page = SinglePage("singlepage_index", 1, package.root) page.save(outputDir/"singlepage_index.html") # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(outputDir/'favicon.ico') if hasattr(package, 'scowwebsite') and package.scowwebsite: website = WebsiteExport(self.config, self.styleDir, outputDir, "website_") website.export(package) (self.styleDir/'nav.css').copyfile(outputDir/'nav.css') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(outputDir/'favicon.ico') if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd') (outputDir/'content.data').write_bytes(encodeObject(package)) (outputDir/'contentv3.xml').write_bytes(encodeObjectToXML(package)) # Zip it up! self.filename.safeSave(self.doZip, _('EXPORT FAILED!\nLast succesful export is %s.'), outputDir) # Clean up the temporary dir outputDir.rmtree()
def copyFiles(self, package, outputDir): """ Copy all the files used by the website. """ if os.path.isdir(self.stylesDir): # Copy the style sheet files to the output dir styleFiles = [self.stylesDir/'..'/'base.css'] styleFiles += [self.stylesDir/'..'/'popup_bg.gif'] styleFiles += self.stylesDir.files("*.css") styleFiles += self.stylesDir.files("*.jpg") styleFiles += self.stylesDir.files("*.gif") styleFiles += self.stylesDir.files("*.png") styleFiles += self.stylesDir.files("*.js") styleFiles += self.stylesDir.files("*.html") styleFiles += self.stylesDir.files("*.ico") styleFiles += self.stylesDir.files("*.ttf") styleFiles += self.stylesDir.files("*.eot") styleFiles += self.stylesDir.files("*.otf") styleFiles += self.stylesDir.files("*.woff") self.stylesDir.copylist(styleFiles, outputDir) # copy the package's resource files package.resourceDir.copyfiles(outputDir) # copy script files. my_style = G.application.config.styleStore.getStyle(package.style) # jQuery if my_style.hasValidConfig: if my_style.get_jquery() == True: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') else: jsFile = (self.scriptsDir/'exe_jquery.js') jsFile.copyfile(outputDir/'exe_jquery.js') jsFile = (self.scriptsDir/'common.js') jsFile.copyfile(outputDir/'common.js') #dT = common.getExportDocType() dT=common.getExportDocType(); if dT == "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') # Incluide eXe's icon if the Style doesn't have one themePath = Path(G.application.config.stylesDir/package.style) themeFavicon = themePath.joinpath("favicon.ico") if not themeFavicon.exists(): faviconFile = (self.imagesDir/'favicon.ico') faviconFile.copyfile(outputDir/'favicon.ico') # copy players for media idevices. hasFlowplayer = False hasMagnifier = False hasXspfplayer = False hasGallery = False hasFX = False hasSH = False hasGames = False hasWikipedia = False isBreak = False hasInstructions = False hasMediaelement = False hasTooltips = False for page in self.pages: if isBreak: break for idevice in page.node.idevices: if (hasFlowplayer and hasMagnifier and hasXspfplayer and hasGallery and hasFX and hasSH and hasGames and hasWikipedia and hasInstructions and hasMediaelement and hasTooltips): isBreak = True break if not hasFlowplayer: if 'flowPlayer.swf' in idevice.systemResources: hasFlowplayer = True if not hasMagnifier: if 'mojomagnify.js' in idevice.systemResources: hasMagnifier = True if not hasXspfplayer: if 'xspf_player.swf' in idevice.systemResources: hasXspfplayer = True if not hasGallery: hasGallery = common.ideviceHasGallery(idevice) if not hasFX: hasFX = common.ideviceHasFX(idevice) if not hasSH: hasSH = common.ideviceHasSH(idevice) if not hasGames: hasGames = common.ideviceHasGames(idevice) if not hasWikipedia: if 'WikipediaIdevice' == idevice.klass: hasWikipedia = True if not hasInstructions: if 'TrueFalseIdevice' == idevice.klass or 'MultichoiceIdevice' == idevice.klass or 'VerdaderofalsofpdIdevice' == idevice.klass or 'EleccionmultiplefpdIdevice' == idevice.klass: hasInstructions = True if not hasMediaelement: hasMediaelement = common.ideviceHasMediaelement(idevice) if not hasTooltips: hasTooltips = common.ideviceHasTooltips(idevice) if hasFlowplayer: videofile = (self.templatesDir/'flowPlayer.swf') videofile.copyfile(outputDir/'flowPlayer.swf') controlsfile = (self.templatesDir/'flowplayer.controls.swf') controlsfile.copyfile(outputDir/'flowplayer.controls.swf') if hasMagnifier: videofile = (self.templatesDir/'mojomagnify.js') videofile.copyfile(outputDir/'mojomagnify.js') if hasXspfplayer: videofile = (self.templatesDir/'xspf_player.swf') videofile.copyfile(outputDir/'xspf_player.swf') if hasGallery: exeLightbox = (self.scriptsDir/'exe_lightbox') exeLightbox.copyfiles(outputDir) if hasFX: exeEffects = (self.scriptsDir/'exe_effects') exeEffects.copyfiles(outputDir) if hasSH: exeSH = (self.scriptsDir/'exe_highlighter') exeSH.copyfiles(outputDir) if hasGames: exeGames = (self.scriptsDir/'exe_games') exeGames.copyfiles(outputDir) if hasWikipedia: wikipediaCSS = (self.cssDir/'exe_wikipedia.css') wikipediaCSS.copyfile(outputDir/'exe_wikipedia.css') if hasInstructions: common.copyFileIfNotInStyle('panel-amusements.png', self, outputDir) common.copyFileIfNotInStyle('stock-stop.png', self, outputDir) if hasMediaelement: mediaelement = (self.scriptsDir/'mediaelement') mediaelement.copyfiles(outputDir) dT = common.getExportDocType() if dT != "HTML5": jsFile = (self.scriptsDir/'exe_html5.js') jsFile.copyfile(outputDir/'exe_html5.js') if hasTooltips: exe_tooltips = (self.scriptsDir/'exe_tooltips') exe_tooltips.copyfiles(outputDir) if hasattr(package, 'exportSource') and package.exportSource: (G.application.config.webDir/'templates'/'content.xsd').copyfile(outputDir/'content.xsd') (outputDir/'content.data').write_bytes(encodeObject(package)) (outputDir/'contentv3.xml').write_bytes(encodeObjectToXML(package)) if package.license == "license GFDL": # include a copy of the GNU Free Documentation Licence (self.templatesDir/'fdl.html').copyfile(outputDir/'fdl.html')
def convertToFreeText(self): """ Actually do the Converting of MathsIdevice -> FreeTextIdevice, now that FreeText can hold embeddded images. """ new_content = "" # ensure that an image resource still exists on this ImageWithText, # before trying to add it into the FreeText idevice. # Why? corrupt packages have been seen missing resources... # (usually in with extra package objects as well, probably # from old code doing faulty Extracts, or somesuch nonesense) imageResource_exists = False if not self.content.gifResource is None: if os.path.exists(self.content.gifResource.path) and \ os.path.isfile(self.content.gifResource.path): imageResource_exists = True else: log.warn("Couldn't find Maths image when upgrading "\ + self.content.gifResource.storageName) if imageResource_exists: new_content += "<img src=\"resources/" \ + self.content.gifResource.storageName + "\" " # create the expected math resource url for comparison later, # once we do actually create it: math_resource_url="resources/" \ + self.content.gifResource.storageName + ".tex\" " new_content += "exe_math_latex=\"" + math_resource_url + "\" " new_content += "exe_math_size=\"" + repr(self.content.fontsize) \ + "\" " # no height or width for math images, eh? nope. new_content += "/> \n" elif self.content.gifResource: new_content += "<BR>\n[WARNING: missing image: " \ + self.content.gifResource.storageName + "]\n" replacementIdev = FreeTextIdevice(new_content) ########### # now, copy that content field's content into its _w_resourcePaths, # and properly remove the resource directory via Massage.... # for its _wo_resourcePaths: # note that replacementIdev's content field's content # is automatically set at its constructor (above), # as is the default content_w_resourcePaths (a copy of content) # AND the default content_wo_resourcePaths (a copy of content), # so only need to update the content_wo_resourcePaths: replacementIdev.content.content_wo_resourcePaths = \ replacementIdev.content.MassageContentForRenderView( \ replacementIdev.content.content_w_resourcePaths) # Design note: ahhhhh, the above is a good looking reason to possibly # have the MassageContentForRenderView() method # just assume its content_w_resourcePaths as the input # and write the output to its content_wo_resourcePaths..... ####### # next step, add the new IDevice into the same node as this one self.parentNode.addIdevice(replacementIdev) # in passing GalleryImage into the FieldWithResources, # that content field needs to be sure to have an updated # parentNode, courtesy of its idevice: replacementIdev.content.setParentNode() # and semi-manually add/create the current image # resource into the FreeTextIdevice's TextAreaField, content. # the content text will have already been taken care of above, # including the ideal <img src=...> including resources path, # but still need the actual image resource: if imageResource_exists: # Not sure why this can't be imported up top, but it gives # ImportError: cannot import name GalleryImages, # so here it be: from exe.engine.galleryidevice import GalleryImage full_image_path = self.content.gifResource.path # with empty caption: new_GalleryImage = GalleryImage(replacementIdev.content, \ '', full_image_path, mkThumbnail=False) # and.... write the latex_source out into the preview_math_srcfile # such that it can then be passed into the compile command. # Using the desired name (image.gif.tex), write it into tempWebDir: webDir = Path(G.application.tempWebDir) source_tex_name = self.content.gifResource.storageName+".tex" math_path = webDir.joinpath(source_tex_name) math_filename_str = math_path.abspath().encode('utf-8') log.debug("convertToFreeText: writing LaTeX source into \'" \ + math_filename_str + "\'.") math_file = open(math_filename_str, 'wb') # do we need to append a \n here?: math_file.write(self.content.latex) math_file.flush() math_file.close() # finally, creating a resource for the latex_source as well: new_GalleryLatex = GalleryImage(replacementIdev.content, \ '', math_filename_str, mkThumbnail=False) new_GalleryLatexResource = new_GalleryLatex._imageResource mathsrc_resource_path = new_GalleryLatexResource._storageName # and re-concatenate from the global resources name, # to build the webUrl to the resource: mathsrc_resource_url = new_GalleryLatex.resourcesUrl \ + mathsrc_resource_path # AND compare with the newly built resource_url from above, # to ensure that we've got what we had expected, jah! if (mathsrc_resource_url != math_resource_url): log.warn('The math source was resource-ified differently ' \ + 'than expected, to: ' + mathsrc_resource_url \ + '; the source will need to be recreated.') # right. we COULD go ahead and change the exe_math_latex # attribute to point to the actual mathsrc_resource_url, # EXCEPT that the entire exemath plugin is currently built # with the idea that the source .tex file will always be named # as the mathimage.gif.tex, and this exe_math_latex tag # is really just letting the rest of the world know that # there IS corresponding source expected there. # If exemath is to ever change and use the actual contents # of this exe_math_latex tag (rather than just appended .tex), # then this could be revisited here. else: log.debug('math source was resource-ified properly to: ' \ + mathsrc_resource_url) # and move the new idevice up to the position following this node! while ( self.parentNode.idevices.index(replacementIdev) \ > ( (self.parentNode.idevices.index(self) + 1))): replacementIdev.movePrev() # finally: delete THIS idevice itself, deleting it from the node self.delete()