Files
2025-06-30 18:33:47 +07:00

232 lines
8.0 KiB
Python

#!/usr/bin/env python
import os
import shutil
import re
import argparse
def readFile(path):
with open(path, "r", errors='replace') as file:
filedata = file.read()
return filedata
def writeFile(path, content):
if (os.path.isfile(path)):
os.remove(path)
with open(path, "w", encoding='utf-8') as file:
file.write(content)
return
class EditorApi(object):
def __init__(self):
self.records = []
self.init = False
self.folder = "word"
self.type = "CDE"
self.numfile = 0
self.files = []
return
def initFiles(self, type, files):
self.folder = type
if "word" == self.folder:
self.type = "CDE"
elif "slide" == self.folder:
self.type = "CPE"
else:
self.type = "CSE"
self.files = files
return
def getReturnValue(self, description):
paramStart = description.find("@returns {")
if -1 == paramStart:
return "{}"
paramEnd = description.find("}", paramStart)
retParam = description[paramStart + 10:paramEnd]
isArray = False
if -1 != retParam.find("[]"):
isArray = True
retParam = retParam.replace("[]", "")
retType = retParam.replace("|", " ").replace(".", " ").split(" ")[0]
retTypeLower = retType.lower()
retValue = ""
if -1 != retType.find("\""):
retValue = "\"\""
elif "boolean" == retTypeLower or "bool" == retTypeLower:
retValue = "true"
elif "string" == retTypeLower:
retValue = "\"\""
elif "number" == retTypeLower:
retValue = "0"
elif "undefined" == retTypeLower:
retValue = "undefined"
elif "null" == retTypeLower:
retValue = "null"
elif "array" == retTypeLower:
retValue = "[]"
elif "base64img" == retTypeLower:
retValue = "base64img"
elif "error" == retTypeLower:
retValue = "undefined"
else:
retValue = "new " + retType + "()"
if isArray:
retValue = "[" + retValue + "]"
return "{ return " + retValue + "; }"
def check_record(self, recordData):
rec = recordData
rec = rec.replace("\t", "")
rec = rec.replace('\n ', '\n')
indexEndDecoration = rec.find("*/")
indexOfStartPropName = rec.find('Object.defineProperty(')
if indexOfStartPropName != -1:
propName = re.search(r'"([^\"]*)"', rec[indexOfStartPropName:])[0]
else:
propName = None
decoration = "/**" + rec[0:indexEndDecoration + 2]
decoration = decoration.replace("Api\n", "ApiInterface\n")
decoration = decoration.replace("Api ", "ApiInterface ")
decoration = decoration.replace("{Api}", "{ApiInterface}")
decoration = decoration.replace("@return ", "@returns ")
decoration = decoration.replace("@returns {?", "@returns {")
decoration = decoration.replace("?}", "}")
if -1 != decoration.find("@name ApiInterface"):
self.append_record(decoration, "var ApiInterface = function() {};\nvar Api = new ApiInterface();\n", True)
return
code = rec[indexEndDecoration + 2:]
code = code.replace("=\n", "= ").strip("\t\n\r ")
lines = code.split("\n")
codeCorrect = ""
sMethodName = re.search(r'.prototype.(.*)=', code)
is_found_function = False
addon_for_func = "{}"
if -1 != decoration.find("@return"):
addon_for_func = "{ return null; }"
for line in lines:
line = line.strip("\t\n\r ")
line = line.replace("{", "")
line = line.replace("}", "")
lineWithoutSpaces = line.replace(" ", "")
if not is_found_function and 0 == line.find("function "):
if -1 == decoration.find("@constructor"):
return
codeCorrect += (line + addon_for_func + "\n")
is_found_function = True
if not is_found_function and -1 != line.find(".prototype."):
codeCorrect += (line + self.getReturnValue(decoration) + ";\n")
is_found_function = True
if -1 != lineWithoutSpaces.find(".prototype="):
codeCorrect += (line + "\n")
if -1 != line.find(".prototype.constructor"):
codeCorrect += (line + "\n")
codeCorrect = codeCorrect.replace("Api.prototype", "ApiInterface.prototype")
self.append_record(decoration, codeCorrect)
className = codeCorrect[0:codeCorrect.find('.')]
# если свойство определено сразу под методом (без декорации)
if propName is not None and sMethodName is not None:
prop_define = f'{className}.prototype.{propName[1:-1]} = {className}.prototype.{sMethodName.group(1)}();\n'
self.append_record(decoration, prop_define)
#иначе
elif propName is not None:
className = re.search(r'.defineProperty\((.*).prototype', code).group(1).strip()
returnValue = 'undefined' if decoration.find('@return') == -1 else self.getReturnValue(decoration)
if (returnValue != 'undefined'):
returnValue = re.search(r'{ return (.*); }', returnValue).group(1).strip()
prop_define = f'{className}.prototype.{propName[1:-1]} = {returnValue};\n'
self.append_record(decoration, prop_define)
return
def append_record(self, decoration, code, init=False):
if init:
if not self.init:
self.init = True
self.records.append(decoration + "\n" + code + "\n\n")
return
# check on private
if -1 != code.find(".prototype.private_"):
return
# add records only for current editor
index_type_editors = decoration.find("@typeofeditors")
if -1 != index_type_editors:
index_type_editors_end = decoration.find("]", index_type_editors)
if -1 != index_type_editors_end:
editors_support = decoration[index_type_editors:index_type_editors_end]
if -1 == editors_support.find(self.type):
return
decoration = "\n".join(
line for line in decoration.splitlines()
if "@typeofeditors" not in line and "@see" not in line
)
# optimizations for first file
if 0 == self.numfile:
self.records.append(decoration + "\n" + code + "\n")
return
# check override js classes
if 0 == code.find("function "):
index_end_name = code.find("(")
function_name = code[9:index_end_name].strip(" ")
for rec in range(len(self.records)):
if -1 != self.records[rec].find("function " + function_name + "("):
self.records[rec] = ""
elif -1 != self.records[rec].find("function " + function_name + " ("):
self.records[rec] = ""
elif -1 != self.records[rec].find("\n" + function_name + ".prototype."):
self.records[rec] = ""
self.records.append(decoration + "\n" + code + "\n")
return
def generate(self):
for file in self.files:
file_content = readFile(f'{sdkjs_dir}/{file}')
arrRecords = file_content.split("/**")
arrRecords = arrRecords[1:-1]
for record in arrRecords:
self.check_record(record)
self.numfile += 1
correctContent = ''.join(self.records)
correctContent += "\n"
os.mkdir(args.destination + self.folder)
writeFile(args.destination + self.folder + "/api.js", correctContent)
return
def convert_to_interface(arrFiles, sEditorType):
editor = EditorApi()
editor.initFiles(sEditorType, arrFiles)
editor.generate()
return
sdkjs_dir = "../../../sdkjs"
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Generate documentation")
parser.add_argument(
"destination",
type=str,
help="Destination directory for the generated documentation",
nargs='?', # Indicates the argument is optional
default="../../../web-apps/vendor/monaco/libs/" # Default value
)
args = parser.parse_args()
old_cur = os.getcwd()
if True == os.path.isdir(args.destination):
shutil.rmtree(args.destination, ignore_errors=True)
os.mkdir(args.destination)
convert_to_interface(["word/apiBuilder.js", "../sdkjs-forms/apiBuilder.js"], "word")
convert_to_interface(["word/apiBuilder.js", "slide/apiBuilder.js"], "slide")
convert_to_interface(["word/apiBuilder.js", "slide/apiBuilder.js", "cell/apiBuilder.js"], "cell")
os.chdir(old_cur)