#!/usr/bin/python # This file is part of Espruino, a JavaScript interpreter for Microcontrollers # # Copyright (C) 2013 Gordon Williams # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # ---------------------------------------------------------------------------------------- # Builds HTML documentation for functions from the JSON included in comments in # jswrap_*.c files # ---------------------------------------------------------------------------------------- import subprocess; import re; import json; import sys; import os; sys.path.append("."); import common import urllib2 # Scans files for comments of the form /*JSON......*/ and then writes out an HTML file describing # all the functions jsondatas = common.get_jsondata(True) classes = [] for jsondata in jsondatas: if "class" in jsondata: if not jsondata["class"] in classes: classes.append(jsondata["class"]) # Load list of 'uses' in EspruinoDocs code_uses = [] referenceFile = "../EspruinoDocs/references.json" if os.path.isfile(referenceFile): print "Found references.json - using this to link to examples" code_uses = json.loads(open(referenceFile, "r").read()) # Load list of MDN URLs (to speed up processing) valid_mdn_urls = { 'valid' : [], 'invalid' : [] }; mdnURLFile = "MDN_URLS.txt" if os.path.isfile(mdnURLFile): valid_mdn_urls = json.loads(open(mdnURLFile, "r").read()) # start writing htmlFile = open('functions.html', 'w') def html(s): htmlFile.write(s+"\n"); def htmlify(d): d = re.sub(r'```([^`]+)```', r'\1', d) # code tags d = re.sub(r'`([^`]+)`', r'\1', d) # code tags d = re.sub(r'\[([^\]]*)\]\(([^\)]*)\)', r'\1', d) # links tags d = re.sub(r'([^">])(http://[^ ]+)', r'\1\2', d) # links tags return d def html_description(d,current): if isinstance(d, list): d = "\n".join(d) for link in links: if link!=current: d = d.replace(" "+link+" ", " "+link+" ") d = d.replace(" "+link+".", " "+link+".") d = d.replace(" "+link+"(", " "+link+"(") html("

" + htmlify(d.replace("\n","

\n

")) + "

") def get_prefixed_name(jsondata): s="" if "class" in jsondata: s=s+jsondata["class"]+"." s=s+jsondata["name"] return s def get_fullname(jsondata): s = common.get_prefix_name(jsondata) if s!="": s = s + " " if jsondata["type"]!="constructor": if "class" in jsondata: s=s+jsondata["class"]+"." s=s+jsondata["name"] return s def get_arguments(jsondata): if common.is_property(jsondata): return "" args = []; if "params" in jsondata: for param in jsondata["params"]: args.append(param[0]); if param[1]=="JsVarArray": args.append("..."); return "("+", ".join(args)+")" def get_surround(jsondata): s = common.get_prefix_name(jsondata) if s!="": s = s + " " if jsondata["type"]!="constructor": if "class" in jsondata: s=s+jsondata["class"]+"." s=s+jsondata["name"] s=s+get_arguments(jsondata) return s def get_code(jsondata): if jsondata["type"]=="event": return jsondata["class"]+".on('"+jsondata["name"]+"', function"+get_arguments(jsondata)+" { ... });"; if jsondata["type"]=="constructor": return "new "+jsondata["name"]+get_arguments(jsondata); return get_surround(jsondata) def get_link(jsondata): s="l_"; if "class" in jsondata: s=s+jsondata["class"]+"_" else: s=s+"_global_" s=s+jsondata["name"] return s # If MDN doesn't 404 then include a link to it def insert_mdn_link(jsondata): if "class" in jsondata and "name" in jsondata: url = "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/"+jsondata["class"] if jsondata["type"]!="constructor": url = url +"/"+jsondata["name"] if url in valid_mdn_urls['valid']: code = 200 elif url in valid_mdn_urls['invalid']: code = 404 else: print "Checking URL "+url try: connection = urllib2.urlopen(url) code = connection.getcode() connection.close() except urllib2.HTTPError, e: code = e.getcode() if code==200: valid_mdn_urls['valid'].append(url) else: valid_mdn_urls['invalid'].append(url) if code==200: html("

View MDN documentation

") html("") html(" ") html(" Espruino Reference") html(" ") html(" ") html(" ") html("

Espruino Software Reference

") html("

Version "+common.get_version()+"

") html("

Contents

") html("

Globals

") html(" ") html("

"+className+"

") html(" ") html("

Detail

") lastClass = "XXX" for jsondata in detail: className = "" niceName = "" linkName = "" if "class" in jsondata: className=jsondata["class"] niceName=className+" Class" linkName=className else: className="" niceName="Global Functions" linkName="_global" if className!=lastClass: lastClass=className html("

"+niceName+"

") html("

(top)

") for j in jsondatas: if (j["type"]=="class" or j["type"]=="library") and j["class"]==className and "description" in j: ds = html_description(j["description"], className) instances = [] for j in jsondatas: if "instanceof" in j and j["instanceof"]==className: instances.append(j) if len(instances)>0: html("

Instances

") html(" ") html("

Methods and Fields

") html(" ") html("

"+get_fullname(jsondata)+"

") insert_mdn_link(jsondata); html("

(top)

") html("

Call type:

") html("

"+get_code(jsondata)+"

") if "description" in jsondata: html("

Description

") desc = jsondata["description"] if not isinstance(desc, list): desc = [ desc ] if ("ifdef" in jsondata) or ("ifndef" in jsondata): conds = "" if "ifdef" in jsondata: conds = common.get_ifdef_description(jsondata["ifdef"]) if "ifndef" in jsondata: if conds!="": conds += " and " conds = "not "+common.get_ifdef_description(jsondata["ifndef"]) desc.append("Note: This is only available in some devices: "+conds); html_description(desc, jsondata["name"]) html("

Parameters

") if "params" in jsondata: for param in jsondata["params"]: desc = "" if len(param)>2: desc=param[2] if isinstance(desc, list): desc = '
'.join(desc) extra = "" if param[1]=="JsVarArray": extra = ", ..."; html("

"+param[0]+extra+" "+htmlify(desc)+"

") else: html("

No parameters

") html("

Returns

") if "return" in jsondata: desc = "" if len(jsondata["return"])>1: desc=jsondata["return"][1] if desc=="": desc="See description above" html("

"+htmlify(desc)+"

") else: html("

No return value (undefined)

") url = "http://www.espruino.com/Reference#"+get_link(jsondata) if url in code_uses: uses = code_uses[url] html("

Examples

") html("

This function is used in the following places in Espruino's documentation

") html(" ") html(" ") html("") # -------------------------------------------------------------------------- # Write/create keywords # -------------------------------------------------------------------------- keywords = {} for j in jsondatas: if ("name" in j): item = { "title" : get_surround(j), "path": "/Reference#"+get_link(j) }; jkeywords = [ j["name"] ] if get_prefixed_name(j)!=j["name"]: jkeywords.append(get_prefixed_name(j)) if "class" in j: jkeywords.append(j["class"]) for k in jkeywords: k = k.lower() if not k in keywords: keywords[k] = [ item ] else: keywords[k].append(item) #print(json.dumps(keywords, sort_keys=True, indent=2)) keywordFile = open('function_keywords.js', 'w') keywordFile.write(json.dumps(keywords, sort_keys=True, indent=2)); # ---------------------------- Just random helper stuff builtins = [] for jsondata in jsondatas: if jsondata["type"]=="staticmethod" or jsondata["type"]=="staticproperty" or jsondata["type"]=="class": if not jsondata["class"] in builtins: builtins.append(jsondata["class"]) elif jsondata["type"]=="function" or jsondata["type"]=="variable" or jsondata["type"]=="class": if not jsondata["name"] in builtins: builtins.append(jsondata["name"]) print "------------------------------------------------------" print('Global classes and functions: '+' '.join(builtins)); print "------------------------------------------------------" # Writing MDN URL file open(mdnURLFile, "w").write(json.dumps(valid_mdn_urls, sort_keys=True, indent=2))