-
Notifications
You must be signed in to change notification settings - Fork 191
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #846 from ONLYOFFICE/feature/documentation
Added documentation generation scripts
- Loading branch information
Showing
10 changed files
with
610 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
|
||
# Documentation Generation Guide | ||
|
||
This guide explains how to generate documentation for Onlyoffice API using the provided Python scripts, `generate_docs_json.py` and `generate_docs_md.py`. These scripts are used to create JSON and Markdown documentation for the `apiBuilder.js` files from the word, cell, and slide editors. | ||
|
||
## Prerequisites | ||
|
||
1. **Node.js and npm**: Ensure you have Node.js and npm installed on your machine. You can download them from [Node.js official website](https://nodejs.org/). | ||
|
||
2. **jsdoc**: The scripts use `jsdoc` to generate documentation. Install it using npm: | ||
```bash | ||
npm install | ||
``` | ||
|
||
## Scripts Overview | ||
|
||
### `generate_docs_json.py` | ||
|
||
This script generates JSON documentation based on the `apiBuilder.js` files. | ||
|
||
- **Usage**: | ||
```bash | ||
python generate_docs_json.py output_path | ||
``` | ||
|
||
- **Parameters**: | ||
- `output_path` (optional): The directory where the JSON documentation will be saved. If not specified, the default path is `Onlyoffice/sdkjs/deploy/api_builder/json`. | ||
|
||
### `generate_docs_md.py` | ||
|
||
This script generates Markdown documentation from the `apiBuilder.js` files. | ||
|
||
- **Usage**: | ||
```bash | ||
python generate_docs_md.py output_path | ||
``` | ||
|
||
- **Parameters**: | ||
- `output_path` (optional): The directory where the Markdown documentation will be saved. If not specified, the default path is `Onlyoffice/office-js-api`. | ||
|
||
## Example | ||
|
||
To generate JSON documentation with the default output path: | ||
```bash | ||
python generate_docs_json.py /path/to/save/json | ||
``` | ||
|
||
To generate Markdown documentation and specify a custom output path: | ||
```bash | ||
python generate_docs_md.py /path/to/save/markdown | ||
``` | ||
|
||
## Notes | ||
|
||
- Make sure to have all necessary permissions to run these scripts and write to the specified directories. | ||
- The output directories will be created if they do not exist. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"source": { | ||
"include": ["../../../../sdkjs/word/apiBuilder.js", "../../../../sdkjs/slide/apiBuilder.js", "../../../../sdkjs/cell/apiBuilder.js"] | ||
}, | ||
"plugins": ["./correct_doclets.js"], | ||
"opts": { | ||
"destination": "./out", | ||
"recurse": true | ||
}, | ||
"templates": { | ||
"json": { | ||
"pretty": true | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
exports.handlers = { | ||
processingComplete: function(e) { | ||
// Инициализация массива для сохранения отфильтрованных doclets | ||
const filteredDoclets = []; | ||
|
||
const cleanName = name => name ? name.replace('<anonymous>~', '').replaceAll('"', '') : name; | ||
|
||
// Итерация по doclets и фильтрация | ||
for (let i = 0; i < e.doclets.length; i++) { | ||
const doclet = e.doclets[i]; | ||
const isMethod = doclet.kind === 'function' || doclet.kind === 'method'; | ||
const hasTypeofEditorsTag = isMethod && doclet.tags && doclet.tags.some(tag => tag.title === 'typeofeditors' && tag.value.includes(process.env.EDITOR)); | ||
|
||
const shouldAddMethod = | ||
doclet.kind !== 'member' && | ||
(!doclet.longname || doclet.longname.search('private') === -1) && | ||
doclet.scope !== 'inner' && | ||
(!isMethod || hasTypeofEditorsTag); | ||
|
||
if (shouldAddMethod) { | ||
// Оставляем только нужные поля | ||
doclet.memberof = cleanName(doclet.memberof); | ||
doclet.longname = cleanName(doclet.longname); | ||
doclet.name = cleanName(doclet.name); | ||
|
||
const filteredDoclet = { | ||
comment: doclet.comment, | ||
description: doclet.description, | ||
memberof: cleanName(doclet.memberof), | ||
|
||
params: doclet.params ? doclet.params.map(param => ({ | ||
type: param.type ? { | ||
names: param.type.names, | ||
parsedType: param.type.parsedType | ||
} : param.type, | ||
|
||
name: param.name, | ||
description: param.description, | ||
optional: param.optional, | ||
defaultvalue: param.defaultvalue | ||
})) : doclet.params, | ||
|
||
returns: doclet.returns ? doclet.returns.map(returnObj => ({ | ||
type: { | ||
names: returnObj.type.names, | ||
parsedType: returnObj.type.parsedType | ||
} | ||
})) : doclet.returns, | ||
|
||
name: doclet.name, | ||
longname: cleanName(doclet.longname), | ||
kind: doclet.kind, | ||
scope: doclet.scope, | ||
|
||
type: doclet.type ? { | ||
names: doclet.type.names, | ||
parsedType: doclet.type.parsedType | ||
} : doclet.type, | ||
|
||
properties: doclet.properties ? doclet.properties.map(property => ({ | ||
type: property.type ? { | ||
names: property.type.names, | ||
parsedType: property.type.parsedType | ||
} : property.type, | ||
|
||
name: property.name, | ||
description: property.description, | ||
optional: property.optional, | ||
defaultvalue: property.defaultvalue | ||
})) : doclet.properties, | ||
|
||
meta: doclet.meta ? { | ||
lineno: doclet.meta.lineno, | ||
columnno: doclet.meta.columnno | ||
} : doclet.meta, | ||
|
||
see: doclet.see | ||
}; | ||
|
||
if (!doclet.see) { | ||
delete doclet.see; | ||
} | ||
|
||
// Добавляем отфильтрованный doclet в массив | ||
filteredDoclets.push(filteredDoclet); | ||
} | ||
else if (doclet.kind == 'class') { | ||
const filteredDoclet = { | ||
comment: doclet.comment, | ||
description: doclet.description, | ||
name: cleanName(doclet.name), | ||
longname: cleanName(doclet.longname), | ||
kind: doclet.kind, | ||
scope: "global", | ||
augments: doclet.augments || undefined, | ||
meta: doclet.meta ? { | ||
lineno: doclet.meta.lineno, | ||
columnno: doclet.meta.columnno | ||
} : doclet.meta, | ||
see: doclet.see || undefined | ||
}; | ||
|
||
filteredDoclets.push(filteredDoclet); | ||
} | ||
} | ||
|
||
// Заменяем doclets на отфильтрованный массив | ||
e.doclets.splice(0, e.doclets.length, ...filteredDoclets); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"source": { | ||
"include": ["../../../../sdkjs-forms/apiBuilder.js"] | ||
}, | ||
"plugins": ["./correct_doclets.js"], | ||
"opts": { | ||
"destination": "./out", | ||
"recurse": true, | ||
"encoding": "utf8" | ||
}, | ||
"templates": { | ||
"json": { | ||
"pretty": true | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"source": { | ||
"include": ["../../../../sdkjs/word/apiBuilder.js", "../../../../sdkjs/slide/apiBuilder.js"] | ||
}, | ||
"plugins": ["./correct_doclets.js"], | ||
"opts": { | ||
"destination": "./out", | ||
"recurse": true | ||
}, | ||
"templates": { | ||
"json": { | ||
"pretty": true | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"source": { | ||
"include": ["../../../../sdkjs/word/apiBuilder.js"] | ||
}, | ||
"plugins": ["./correct_doclets.js"], | ||
"opts": { | ||
"destination": "./out", | ||
"recurse": true, | ||
"encoding": "utf8" | ||
}, | ||
"templates": { | ||
"json": { | ||
"pretty": true | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import os | ||
import subprocess | ||
import json | ||
import argparse | ||
|
||
# Конфигурационные файлы | ||
configs = [ | ||
"./config/word.json", | ||
"./config/cell.json", | ||
"./config/slide.json", | ||
"./config/forms.json" | ||
] | ||
|
||
editors_maps = { | ||
"word": "CDE", | ||
"cell": "CSE", | ||
"slide": "CPE", | ||
"forms": "CFE" | ||
} | ||
|
||
def generate(output_dir): | ||
missing_examples_file = f'{output_dir}/missing_examples.txt' | ||
|
||
if not os.path.exists(output_dir): | ||
os.makedirs(output_dir) | ||
|
||
# Пересоздание файла missing_examples.txt | ||
with open(missing_examples_file, 'w', encoding='utf-8') as f: | ||
f.write('') | ||
|
||
# Генерация json документации | ||
for config in configs: | ||
editor_name = config.split('/')[-1].replace('.json', '') | ||
output_file = os.path.join(output_dir, editor_name + ".json") | ||
command = f"set EDITOR={editors_maps[editor_name]} && npx jsdoc -c {config} -X > {output_file}" | ||
print(f"Generating {editor_name}.json: {command}") | ||
subprocess.run(command, shell=True) | ||
|
||
# дозапись примеров в json документацию | ||
for config in configs: | ||
editor_name = config.split('/')[-1].replace('.json', '') | ||
output_file = os.path.join(output_dir, editor_name + ".json") | ||
|
||
# Чтение JSON файла | ||
with open(output_file, 'r', encoding='utf-8') as f: | ||
data = json.load(f) | ||
|
||
# Модификация JSON данных | ||
for doclet in data: | ||
if 'see' in doclet: | ||
if doclet['see'] is not None: | ||
file_path = 'C:\\Users\\khrom\\Desktop\\Onlyoffice\\' + doclet['see'][0] | ||
if os.path.exists(file_path): | ||
with open(file_path, 'r', encoding='utf-8') as see_file: | ||
example_content = see_file.read() | ||
|
||
# Извлечение первой строки как комментария, если она существует | ||
lines = example_content.split('\n') | ||
if lines[0].startswith('//'): | ||
comment = lines[0] + '\n' | ||
code_content = '\n'.join(lines[1:]) | ||
else: | ||
comment = '' | ||
code_content = example_content | ||
|
||
# Форматирование содержимого для doclet['example'] | ||
doclet['example'] = comment + "```js\n" + code_content + "\n```" | ||
del doclet['see'] | ||
else: | ||
# Запись пропущенного примера в файл missing_examples.txt | ||
with open(missing_examples_file, 'a', encoding='utf-8') as missing_file: | ||
missing_file.write(f"{file_path}\n") | ||
|
||
# Запись измененного JSON файла обратно | ||
with open(output_file, 'w', encoding='utf-8') as f: | ||
json.dump(data, f, ensure_ascii=False, indent=4) | ||
|
||
print("Documentation generation completed.") | ||
|
||
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="../../../../document-builder-declarations/document-builder" # Default value | ||
) | ||
args = parser.parse_args() | ||
|
||
generate(args.destination) |
Oops, something went wrong.