#/** # * # * Licensed under the Apache License, Version 2.0 (the "License"); # * you may not use this file except in compliance with the License. # * You may obtain a copy of the License at # * # * http://www.apache.org/licenses/LICENSE-2.0 # * # * Unless required by applicable law or agreed to in writing, software # * distributed under the License is distributed on an "AS IS" BASIS, # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # * See the License for the specific language governing permissions and # * limitations under the License. # * # */ import logging import time from xml.dom import minidom from WikiTextConverter import WikiTextConverter class WikiPageCreator: logger = logging.getLogger(__name__) classesWithSubclasses = [ 'gadgets.io', 'gadgets.skins', 'gadgets.views', 'opensocial.DataRequest', 'opensocial.Enum', 'opensocial.Environment', 'opensocial.IdSpec', 'opensocial.MediaItem', 'opensocial.NavigationParameters', 'opensocial.ResponseItem', ] classesToRename = { 'Single Request Objects': 'osapi.Request', 'Batch Request Objects': 'osapi.BatchRequest', 'JavaScript Internationalization (i18n)': 'gadgets.i18n', } classesWithFields = [ 'JavaScript Internationalization (i18n)', 'opensocial.CreateActivityPriority', ] def __init__(self, osSpecFile, gadgetSpecFile): # Create a DOM self.osSpec = minidom.parse(osSpecFile) self.gSpec = minidom.parse(gadgetSpecFile) # Get the version number of the spec self.specVersion = self.__getSpecVersion() self.API_ALPHA_LIST = "\n\n{{ JsApiAlphaList_%s }}\n\n" % (self.specVersion) self.ALPHA_LIST_HEADER = """
""" % self.specVersion self.ALPHA_LIST_FOOTER = '
'''OpenSocial %s'''
' # Instantiate an object to hold the wikified output self.wiki = None # Instantiate the converter self.converter = WikiTextConverter(self.specVersion) # Parses the spec version from the element in the <front> section # Returns the spec version. For example: (v0.9) def __getSpecVersion(self): front = self.osSpec.getElementsByTagName("front")[0] title = front.getElementsByTagName("title")[0].firstChild.data return "(%s)" % title[25:] # Converts the spec to WikiMedia import/export format and prints the result def run(self): # Parse self.osSpec DOM (populates self.wiki) self._parseOpenSocialSpec() # Parse self.gSpec DOM (populates self.wiki) self._parseGadgetSpec() # Create the JsApiAlphaList page and the new API Reference homepage for this version self._createApiReferencePages() # Write the wiki DOM to stdout print self.wiki.toxml(encoding="utf-8") # Finds the part of the OpenSocial spec that contains the API reference and transforms it # so it can be imported in to MediaWiki. # def _parseOpenSocialSpec(self): # Create a document for the wikified API Reference doc = minidom.parseString(""" <mediawiki xmlns="http://www.mediawiki.org/xml/export-0.3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.3/ http://www.mediawiki.org/xml/export-0.3.xsd" version="0.3" xml:lang="en"></mediawiki>""") self.wiki = doc.firstChild # Find <section title="API Class Reference"> for node in self.osSpec.getElementsByTagName("section"): title = node.getAttribute("title") if (title == "API Class Reference"): specApiRef = node break self._parseApiReference(specApiRef) # Find <section title="Service Requests"> for node in self.osSpec.getElementsByTagName("section"): title = node.getAttribute("title") if (title == "Service Requests"): osapiApiRef = node break self._parseApiReference(osapiApiRef) # Find <section title="Service Objects"> for node in self.osSpec.getElementsByTagName("section"): title = node.getAttribute("title") if (title == "Service Objects"): osapiApiRef = node break self._parseApiReference(osapiApiRef) # Finds the part of the Gadget spec that contains the API reference and transforms it # so it can be imported in to MediaWiki. # def _parseGadgetSpec(self): # Find <section title="Core JavaScript API"> and parse it for node in self.gSpec.getElementsByTagName("section"): title = node.getAttribute("title") if (title == "Core JavaScript API"): coreApiRef = node break self._parseApiReference(coreApiRef) # Find <section title="Highly Recommended Features"> and parse it for node in self.gSpec.getElementsByTagName("section"): title = node.getAttribute("title") if (title == "Highly Recommended Features"): featuresApiRef = node break self._parseApiReference(featuresApiRef) # Creates the main page for this version of the API Reference and the JsApiAlphaList template # that gets inserted into the main page and each class page def _createApiReferencePages(self): title = "Template:JsApiAlphaList_%s" % self.specVersion text = self.ALPHA_LIST_HEADER + '<td style="vertical-align:top">' pages = self.wiki.getElementsByTagName('page') linksPerColumn = (len(pages) / 4) + 1 count = 0 for node in pages: count += 1 pageTitle = node.getElementsByTagName('title')[0].firstChild.data linkText = pageTitle[:-len(self.specVersion)] # drop the spec version from the link text text += '[[%s | %s]]\n\n' % (pageTitle, linkText) if count % linksPerColumn == 0: text += '</td><td style="vertical-align:top">\n' text += "</td>" + self.ALPHA_LIST_FOOTER alphaListPage = self._createPageElement(title, text) self.wiki.appendChild(alphaListPage) mainPageTitle = "JavaScript_API_Reference_%s" % self.specVersion mainPageText = "{{ JsApiAlphaList_%s }}" % self.specVersion mainPage = self._createPageElement(mainPageTitle, mainPageText) self.wiki.appendChild(mainPage) # Processes a part of the spec that contains API Reference # # @param specApiRef - a xml.dom.minidom.Node containing the API Reference section def _parseApiReference(self, specApiRef): for node in specApiRef.getElementsByTagName("section"): if node.parentNode.isSameNode(specApiRef): # Check for .Field classes and append them to the parent object's page if node.getAttribute("title").endswith(".Field"): pageTitle = node.getAttribute("title")[:-6] # drop the 6 chars in '<class>.Field' page = self._getPage("%s %s" % (pageTitle, self.specVersion)) self._addFields(page, node) continue # Check for classes with subclasses and append them to the existing parent object's page found = False for className in self.classesWithSubclasses: if node.getAttribute("title").find("%s." % className) != -1: self.logger.info("node title: %s className: %s" % (node.getAttribute("title"), className)) page = self._getPage("%s %s" % (className, self.specVersion)) self._addFields(page, node) found = True if found: continue # Otherwise create a new page for this class if node.getAttribute("title") in self.classesToRename.keys(): title = "%s %s" % (self.classesToRename[node.getAttribute("title")], self.specVersion) else: title = "%s %s" % (node.getAttribute("title"), self.specVersion) text = self.converter.convertClass(node) text += self.API_ALPHA_LIST newPage = self._createPageElement(title, text) # Special case for gadgets i18n if node.getAttribute("title") in self.classesWithFields: self._addFields(newPage, node) self.wiki.appendChild(newPage) # Returns the wikified page corresponding to the given title # # param wiki A minidom.Document containing the wikified info # param pageTitle A string with the title to search for # returns A minidom.Node for the page with the given title def _getPage(self, pageTitle): for node in self.wiki.getElementsByTagName("page"): nodeTitle = node.getElementsByTagName("title")[0].firstChild.data if nodeTitle == pageTitle: return node # Creates a new element for a wiki page with the given title and populates it with the # given text. # # param title a String containing the title of the page # param text a String containing the wiki text for the page # returns a minidom.Node representing a wiki page def _createPageElement(self, title, text): self.logger.info("Creating page for %s" % title) # create the <page> page = minidom.Element("page") # add the <title> to the <page> titleNode = minidom.Element("title") page.appendChild(titleNode) titleText = minidom.Text() titleText.data = title titleNode.appendChild(titleText) # add the <revision> to the <page> revision = minidom.Element("revision") page.appendChild(revision) # add a <timestamp> to the <revision> timestamp = minidom.Element("timestamp") timestampText = minidom.Text() timestampText.data = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) timestamp.appendChild(timestampText) revision.appendChild(timestamp) # add the <text> to the <revision> textNode = minidom.Element("text") textNode.setAttribute("xml:space", "preserve") textText = minidom.Text() textText.data = text textNode.appendChild(textText) revision.appendChild(textNode) return page # Appends the fields from the spec to the given wikified page # # param page A minidom.Node with wikified info for an OpenSocial class # param specFields A minidom.Node with fields in spec format def _addFields(self, page, specFields): pageTitle = page.getElementsByTagName("title")[0] self.logger.info("Adding fields to page for %s" % pageTitle.firstChild.data) text = page.getElementsByTagName("text")[0].firstChild # Remove the Alphalist after the class text.data = text.data[:-len(self.API_ALPHA_LIST)] # Add the wiki text for the fields text.data = text.data + self.converter.convertFields(specFields) # Re-add the Alphalist after the fields text.data += self.API_ALPHA_LIST