docfx
docfx copied to clipboard
Support for nested namespaces
I believe a very useful feature for DocFX is to support nested namespaces, I realize that this in itself can be quite a challenge, but having the option to turn this feature on would help to generate less confusing and a more compact TOC, especially in much larger projects.
:+1: Yes, please! And proper tree view control for nested namespaces (it could be an option or special template).
On the screenshot the font size for entries was custom selected (I've modified the template), so AtomicTorch.CBND.GameAPI.
matches exactly the width of the column, otherwise it wraps really weird:
I hope it will be addressed soon...
Regards!
Is there any news on this?
Looks like this only relates to TOC structure. A quick work around for this is to re-format TOC.yml before docfx build
, using a custom script.
I work on a big project and would appreciate to have it out of the box. Still not progress yet?
Looks like this only relates to TOC structure. A quick work around for this is to re-format TOC.yml before
docfx build
, using a custom script.
try this:
var fs = require('fs');
var yaml = require('js-yaml');
var toc = yaml.safeLoad(fs.readFileSync('./api/toc.yml'));
var namespaces = {};
for(var i=0; i<toc.length; i++) {
var fullnamespace = toc[i].uid;
var splitnamespace = fullnamespace.split('.');
var parent = namespaces;
for(var j = 0; j < splitnamespace.length; j++) {
var partialnamespace = splitnamespace[j];
if(parent[partialnamespace] == undefined) {
parent[partialnamespace] = {};
}
parent = parent[partialnamespace];
}
if(parent.items == undefined) {
parent.items = toc[i].items;
}
else {
parent.items.push(toc[i]);
}
}
var newToc = [];
function recurse(obj, path="") {
var items = [];
Object.keys(obj).forEach((e, i)=>{
if(e!="items") {
var newPath;
if(path=="") {
newPath = e;
}
else {
newPath = path + '.' + e;
}
var newObj = {uid: newPath, name: newPath, items: obj[e].items || []}
newObj.items.push(...recurse(obj[e], newPath));
items.push(newObj);
}
});
return items;
}
var items = recurse(namespaces);
fs.writeFileSync('./api/toc.yml', yaml.safeDump(items));
Hello BernsteinA, thanks a lot for this script... really a pity not to have nested namespaces... Maybe you can help me to quickly find where this script is hooked into DocFx. I'm a little confused by the different hook/plugin options DocFx offers. Can you tell me which DocFx howto is the right one for this??
Greetings and thanks for your script again!
@Onnno I'm not using any of the docfx hooks. There probably is a way to do it automatically, but I just run that script manually after docfx metadata
(and before docfx build
)
Ok, thanks :-).
This would be an enabler feature for me. Currently the TOC is useless as our namespaces are just too long. This in turn makes the output difficult for user to use.
Raise cost of use mean acceptance never gained.
I scripted the whole thing and it finally works :-). If you push me again I'll try to find some time to publish it. It is a little hacky approach - however, it was the only way I could do it and it works fine. I had to modify docFx code slightly due to a bug and a small missing feature. I also had to add scripts in some places. I could push the project online if I clean it from stuff proprietary to the company I work for. Vote for it if you like so it will push me to do so soon.
A quick publish should be possible.
LOL
If you push me again I'll try to find some time to publish it.
Push!
Go @Onnno, go @Onnno! PUSH!
Ok, I talked to my boss and got the go :-) I'll have to cleanup/prepare it for you before publish. I think I'll get it done within this or next week. I'll link to it from here... You may consider it as a christmas present though I cannot prevent you from unpacking it before christmas :-P
was this ever finished? @Onnno did you ever get to push this?
I use @BernsteinA script with a very small modification, in the name
I pass e
instead of newPath
and now it really short. My first 3 levels in the namespace have no code (my root namespace is along the lines of MyCompany.Modules.MyModule ) so it really made it look nice now:
I scripted the whole thing and it finally works :-). If you push me again I'll try to find some time to publish it. It is a little hacky approach - however, it was the only way I could do it and it works fine. I had to modify docFx code slightly due to a bug and a small missing feature. I also had to add scripts in some places. I could push the project online if I clean it from stuff proprietary to the company I work for. Vote for it if you like so it will push me to do so soon.
A quick publish should be possible.
Has this been published anywhere?
Past, I worked on the solution via a custom template script: WIP: https://gist.github.com/wcoder/1ffaae564978d048357c32652e3f84c7
Looks like this only relates to TOC structure. A quick work around for this is to re-format TOC.yml before
docfx build
, using a custom script.try this:
var fs = require('fs'); var yaml = require('js-yaml'); var toc = yaml.safeLoad(fs.readFileSync('./api/toc.yml')); var namespaces = {}; for(var i=0; i<toc.length; i++) { var fullnamespace = toc[i].uid; var splitnamespace = fullnamespace.split('.'); var parent = namespaces; for(var j = 0; j < splitnamespace.length; j++) { var partialnamespace = splitnamespace[j]; if(parent[partialnamespace] == undefined) { parent[partialnamespace] = {}; } parent = parent[partialnamespace]; } if(parent.items == undefined) { parent.items = toc[i].items; } else { parent.items.push(toc[i]); } } var newToc = []; function recurse(obj, path="") { var items = []; Object.keys(obj).forEach((e, i)=>{ if(e!="items") { var newPath; if(path=="") { newPath = e; } else { newPath = path + '.' + e; } var newObj = {uid: newPath, name: newPath, items: obj[e].items || []} newObj.items.push(...recurse(obj[e], newPath)); items.push(newObj); } }); return items; } var items = recurse(namespaces); fs.writeFileSync('./api/toc.yml', yaml.safeDump(items));
How to use this script before build?
Workaround:
- Install NodeJS
- Create a .js file with this content in the same folder of docfx.json
- Run
docfx metadata
- Run
node your_file.js
- Run
docfx build --serve
- Profit
@gumbarros
How to use this script before build?
I run that script manually after docfx metadata
(and before docfx build
)
PowerShell Script
unflatten-namespaces.ps1 I've taken the liberty to port @BernsteinA's NodeJS script to PowerShell. No NodeJS dependencies, cross platform, and copy-paste for Azure DevOps pipelines.
Works like a charm. I'll probably update it with some nice-to-haves, like putting folders at the top instead of the bottom and hiding the root namespace when there's only one item.
I made an extension for toc.js, it can be used in a template, but it is raw and bugs are possible.
https://github.com/deriglazoff/documentation/blob/main/templates/darkfx/toc.extension.js
=>
I have the same problem ... what can i use ?
I have the same problem ... what can i use ?
You can use like us
nested_namespaces.js implementation https://github.com/JJConsulting/JJMasterData/blob/main/doc/JJMasterData.Documentation/server.bat
Result https://portal.jjconsulting.tech/jjdoc/
I's work ! Thanks :)
I've created a pull request that will add an option for this in the docfx.json.
How do we use it now? I went through the PR code and it adds the option "tocNamespaceStyle" to the docfx.json. However, when trying to use it, nothing happens. As for the values that can be used, I assume it is "Flattened" and "Nested", as per definition in the enum. There is no error / warning message that anything is wrong, so I don't know what I am doing wrong.
@MiTschMR use namespaceLayout
in metadata section of your docfx.json:
{
"metadata": [
{
...
"namespaceLayout": "nested"
}
]
}
Thanks a lot, the nesting doesn't yet work, but at least it shows it in the log that it is in experimental state. Most likely I am doing something wrong, or it may be my filter config, will have to check.
A working example with a screenshot would be very much appreciated nonetheless 😄
v2.62.2 fixes the bug with the nesting not shown, no config change (except adding the "namespaceLayout" key) required.
Thanks again @wcoder for the help with getting it to run!