-
Notifications
You must be signed in to change notification settings - Fork 133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Automatically convert GitHub-based projects into MarkBind websites #698
Conversation
31fa32c
to
dafe7a4
Compare
|
That sounds about right. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR @amad-person. I've left some comments and potential improvements. Overall, I think the process is sound and I've tested it on some wikis. I think the thing that bugs me the most is including the header in every addressable page. Not sure if layouts/front matter can help us here.
Do remember to write the documentation and tests! When you're done remember to remove the [WIP] tag in the PR title. Once again thanks for the effort!
If you try
We should either parse the wiki pages to "escape" problematic syntax, or at least document that |
I think in general, when we fail a conversion, we should just retain the original For edge cases in general, we can try to apply fixes wherever possible, a good rule of thumb is that if the fix is not too complicated in code, and the fix is not "controversial" in nature, then we can consider handling the edge case. Otherwise we shouldn't worry about them too much. For this edge case though, while I think escaping could be a good try, the problem is that there is no known consistent way of escaping Nunjucks stuff (this is a known bug btw, we have always been abusing |
Currently, the conversion process doesn't parse the Any ideas for getting these build errors? Maybe I can parse the files before starting the conversion and log the errors - so users can fix them and start again? |
Personally I feel that if we handle nunjucks error well, the author would be able to identify the problem and adjust accordingly? Perhaps this isn't in the scope of this feature? @yamgent Do you agree? |
I agree that this PR shouldn't be going inside the nunjucks code and modify stuff for this current edge case, the fixing of the errors should be done manually by the author. Printing a user-friendly message will make that experience better, so I agree that this isn't the scope of the current PR. |
So, would adding the following in this PR be okay?
|
I don't think this message would be very useful, such messages are generally not paid attention to, because it works, the error message is redundant, and if it doesn't, users will see the error churned out by nunjucks and may not make the connections between the error and this message. The documentation is fine and we should definitely include it. |
cf4de8a
to
258ad1e
Compare
Updates after discussion -
|
020c49d
to
faeab48
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes @amad-person. I've left some brief comments on the things we went through during the meeting.
I also think that you have a misunderstanding on how some of the js features work. I've left some comments wrt to one code snippet. Please let me know if it was unclear.
Also do remember to write tests and remove [WIP] in your PR title when you are ready for review.
src/Site.js
Outdated
const updatedAddressablePageContent = includeTopNavCode + addressablePageContent; | ||
return fs.outputFileAsync(addressablePagePath, updatedAddressablePageContent); | ||
} | ||
return Promise.all(outputFilesPromises); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume what you are trying to do is to create an array of promises called outputFilesPromises
, after which calling Promise.all(outputFilesPromises
so that when all pages have been written, it will continue down the promise chain.
I think there are 2 main problems with this code.
- forEach (line 598)
- outputFilesPromises will be undefined because forEach would return
undefined
- you should use
map
instead
- outputFilesPromises will be undefined because forEach would return
- Promise.all (line 607)
- Promise.all takes in an array (iterable) of promises. Only when all the promises are resolved would it resolve and continue down the promise chain.
- returning this in the for loop does not do any assignment
- does not pass this promise down the chain. As such, the next
.then
will execute before all the files have been output.
i believe the code that should be written is
const outputFilesPromises = this.addressablePages
.filter(addressablePage => !addressablePage.src.startsWith('_'))
.map((page) => {
const addressablePagePath = path.join(this.rootPath, page.src);
const topNavRelativePath = path.relative(this.rootPath, topNavDefaultPath);
if (topNavRelativePath.length > 0) {
const includeTopNavCode = `<include src="${topNavRelativePath}" />\n\n`;
const addressablePageContent = fs.readFileSync(addressablePagePath, 'utf8');
const updatedAddressablePageContent = includeTopNavCode + addressablePageContent;
return fs.outputFileAsync(addressablePagePath, updatedAddressablePageContent);
}
return Promise.resolve();
});
return Promise.all(outputFilesPromises);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition, some statements can be moved out of map
.
const topNavRelativePath = path.relative(this.rootPath, topNavDefaultPath);
if (topNavRelativePath.length == 0) {
return Promise.resolve();
}
const includeTopNavCode = `<include src="${topNavRelativePath}" />\n\n`;
const outputFilesPromises = this.addressablePages
.filter(addressablePage => !addressablePage.src.startsWith('_'))
.map((page) => {
const addressablePagePath = path.join(this.rootPath, page.src);
const addressablePageContent = fs.readFileSync(addressablePagePath, 'utf8');
const updatedAddressablePageContent = includeTopNavCode + addressablePageContent;
return fs.outputFileAsync(addressablePagePath, updatedAddressablePageContent);
});
return Promise.all(outputFilesPromises);
This function modifies the source files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function inserts a top nav to every addressable page. I dont think there's a clean way to insert a top nav without modifying the original wiki site in some way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, this is specific to conversion. If not entirely possible to abstract this out of Site
, then shall we at least put this in a different file (e.g. Site.convert.js)? We can expect the caller to require
that file after Site.js.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@amad-person could you update the feature based on #698 (comment) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@acjh @yamgent how should we handle the constants in Site.js
used in the conversion feature. It seems like defining constants in that manner is not good for modularity.
Should we:
- Make the used constants static variables of
Site
- Copy the constants in
Site.convert.js
and refactor in the future - Keep the feature in
Site
and refactor everything in one shot
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Copy the constants in
Site.convert.js
and refactor in the future
This seems like a pretty good option
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Projects usually have file(s) for constants, e.g. https://github.com/vuejs/vue/blob/dev/src/shared/constants.js
Let's start with src/constants.js
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the input @acjh @yamgent. From discussion today, we already have an issue tracking this #597. Perhaps the change is out of scope of the pull request? Perhaps we shall do all the refactoring in one shot and when there is less on going development at the moment.
So to be clear what i mean is that the conversion logic will be be in Site.js
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am cool with it.
7910455
to
22707f0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes and sorry for late review. I noted that if my test fails, the removal of unwanted directories is not done. Additionally I've left some comments.
As for the styling of the side nav and footer I agree that it can be done in another PR and is also a candidate for good first issue.
expect(fs.existsSync(path.resolve('inner/_markbind/layouts/default/footer.md'))).toEqual(true); | ||
|
||
// site navigation | ||
expect(fs.existsSync(path.resolve('inner/_markbind/layouts/default/navigation.md'))).toEqual(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this addressed else where?
If no I was thinking of doing a check on the content of the navigation file here. The file is generated by the conversion and the results should be predictable.
* Add section in Project Workflow page * Add link to section in CLI Commands page
* Minor changes to documentation Co-Authored-By: amad-person <aadyaa@u.nus.edu>
b4b602a
to
93cb7e4
Compare
@amad-person thanks for the PR. Could you write a a Proposed Commit message for the PR (to be updated in the PR description)? |
@nicholaschuayunzhi @yamgent updated PR description with the proposed commit message. |
What is the purpose of this pull request? (put "X" next to an item, remove the rest)
• [X] New feature
Fixes #675. Part of #660.
What is the rationale for this request?
Provides a way to convert an existing Github wiki or a docs folder into a MarkBind website. It will be easier to integrate MarkBind into the workflow for Github-based project.
What changes did you make? (Give an overview)
--convert
/-c
. Users can runmarkbind init -c
in the desired directory to convert it into a MarkBind project.markbind init
.README.md
(orHome.md
) toindex.md
about.md
page if not present.navigation.md
in the default layout. As mentioned in Automatically convert GitHub Wikis to MarkBind sites #675, if_Sidebar.md
is present in the root directory, this will be used for the site navigation menu. Otherwise a menu will be generated.footer.md
in the default layout. As mentioned in Automatically convert GitHub Wikis to MarkBind sites #675, if_Footer.md
is present in the root directory, this will be used for the site navigation menu. Otherwise the default footer generated bymarkbind init
will be used.header.md
in the default layout.Is there anything you'd like reviewers to focus on?
test.bat
file.Testing instructions:
Run
markbind init -c
in a folder of your choice and build the site. Runnpm run test(win)
to run the UTs and FT.Proposed Commit Message: