Skip to content
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

Support exporting markdown cells to notebook file #1498

Merged
merged 11 commits into from
Jan 7, 2019

Conversation

kylebarron
Copy link
Contributor

@kylebarron kylebarron commented Dec 25, 2018

This adds support for Markdown cells in the export-notebook command (closes #1296).

  • This requires the substring md or markdown to be present on the cell marker line, i.e. any of the following would work correctly:

     # %% md
     # %% markdown
     # %% [md]
     # %% [markdown]
     # In[1] md
     # In[1] markdown
     # In[1] [md]
     # In[1] [markdown]
     # <codecell> md
     # <codecell> markdown
     # <codecell> [md]
     # <codecell> [markdown]

    Right now, # <md> and # <markdown> are not supported. It wouldn't be hard to support them; I'd just have to change this regex list:

    const regexString = `${escapedCommentStartString}(%%| %%| <codecell>| In\[[0-9 ]*\]:?)`;

  • If there's a comment symbol as the first characters on a line, it and any left whitespace will be removed.

  • There's always a cell created before the first # %% marker, even if it's on the first line. To me that's a bug, but that should be solved in another PR.

Any comments/code improvement suggestions are welcome. Hopefully this JS is a little more idiomatic than my last PR.

# %%
print('hello world')

# %% markdown
# # Headline1
# - bullet point
# **bold text**

# %%
print('bye world')

In Jupyter Notebook:
image

cc: @mwouts, @Madhu94

@kylebarron
Copy link
Contributor Author

Should I make md and markdown case insensitive, so that the following would also be caught?

# %% Md
# %% Markdown

@mwouts
Copy link

mwouts commented Dec 26, 2018

Hello @kylebarron , thanks for the developement, this feature was wanted for a long time!

Is it correct that %% [markdown] cells from jupytext will also be recognized as markdown? Like in this example? As a quick reminder: we have choosen square brackets and not just the work markdown in order to support cell titles from Spyder, cf this thread.

@kylebarron
Copy link
Contributor Author

# %% [markdown] would be supported fine. As long as the substring markdown (or md) exists somewhere after # %%, it'll be caught. I think that's better than us imposing another format.

I'm also working on a PR to import Notebook files into Hydrogen, and hopefully it'll be possible to import, modify, and export without any data loss. I'd love to explore a run all cells and export notebook command that adds cell output to the created notebook file.

@mwouts
Copy link

mwouts commented Dec 26, 2018

# %% [markdown] would be supported fine. As long as the substring markdown (or md) exists somewhere after # %%, it'll be caught. I think that's better than us imposing another format.

Very nice!

I'm also working on a PR to import Notebook files into Hydrogen, and hopefully it'll be possible to import, modify, and export without any data loss. I'd love to explore a run all cells and export notebook command that adds cell output to the created notebook file.

That sounds great! That will make Hydrogen the first text editor where users can act on the ipynb file without having to run the notebook in full a second time.

@kylebarron
Copy link
Contributor Author

That sounds great! That will make Hydrogen the first text editor where users can act on the ipynb file without having to run the notebook in full a second time.

Well, not necessarily, at least not at first. I'm working on a simple PR to import just the source text. That's quite straightforward. In the short run, no outputs will be saved in import or export.

I don't know enough about Hydrogen internals yet to work with output in import or export.

Copy link
Member

@lgeiger lgeiger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kylebarron this looks, good. I'm happy to add this functionality to Hydrogen.

Could you add some documentation in the readme?

return "code";
}
var rowText = getRow(editor, start.row - 1);
if (_.includes(rowText, "md") || _.includes(rowText, "markdown")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's OK for now.

_.forEach(lines, line => {
if (line.startsWith(commentStartString)) {
// Remove comment from start of line
editedLines.push(line.slice(commentStartString.length).trimLeft());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this still allow for indentation in the markdown cell?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I don't think it does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just removing .trimLeft() isn't my favorite solution because then if a markdown cell looks like

# %% markdown
# # Header
# **bold**
# - list
#     - indented list

then the text in the markdown cell in the Jupyter notebook would still have a leading space in each row, i.e.:

 # Header
 **bold**
 - list
     - indented list

I think writing with a space after the # is clearer in the .py file, while having a leading space on every line in the exported markdown cell is annoying.

I added code to dedent common leading whitespace for Markdown blocks, so that the above cell would be converted to

# Header
**bold**
- list
    - indented list

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discovered the tiny dependency https://github.com/sindresorhus/strip-indent, which probably has better code than mine. I added that and removed my custom code.

lib/store/index.js Show resolved Hide resolved
@@ -307,13 +307,15 @@ describe("Store", () => {
expect(store.notebook).toEqual(commutable.toJS(nb));
});

xit("should return a fully-fledged notebook when the file isn't empty", () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously the test had used xit(), so I think the test was never run, especially because it would have failed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was marked as expect fail intentionally because the error didn't make sense and we didn't want to hold up ci.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh that makes sense. Is the updated test ok now?

@@ -307,13 +307,15 @@ describe("Store", () => {
expect(store.notebook).toEqual(commutable.toJS(nb));
});

xit("should return a fully-fledged notebook when the file isn't empty", () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test still doesn't pass, but I'm not sure why because it seems to produce the correct output when I paste the test commands into the dev console.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You seem to have discovered why it was failing and made it pass, though It looks like we are testing that there is an empty cell at the top now, which seems like a bug. I know you pointed this out before, is it something to fix?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kylebarron
Copy link
Contributor Author

kylebarron commented Jan 3, 2019

@lgeiger It took a while but I figured out why the test wasn't passing. I think I had to activate language-python. I borrowed waitAsync from code-manager-spec.js. If you want me to create a separate file instead of duplicating the waitAsync wrapper, I can do that.

I also added one simple test for testing that code under %% markdown should be exported to a Markdown cell. Is that ok by itself?

Maybe tomorrow I'll add some documentation.

@BenRussert
Copy link
Member

Maybe tomorrow I'll add some documentation.

I'll add the WIP tag for now, but remove it when you are ready and we can merge.

@kylebarron
Copy link
Contributor Author

@BenRussert I added a new page in the documentation for exporting a file to a notebook. Hopefully in the future that page will also be updated for notebook import #1501

@kylebarron
Copy link
Contributor Author

I also updated the breakpoints grammar so that markdown cell markers also get highlighted, at least if not using tree-sitter (#1134 (comment))

@kylebarron
Copy link
Contributor Author

@BenRussert @lgeiger
If I have an approving review and some tests and they pass, is it ok for me to merge my own pull requests? I don't know what the acceptable norms are around that, and I don't want to commit any changes that aren't accepted.

@BenRussert BenRussert merged commit 2814771 into nteract:master Jan 7, 2019
@BenRussert
Copy link
Member

Thanks @kylebarron!

@BenRussert
Copy link
Member

BenRussert commented Jan 14, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Export Notebook - markdown cells not correctly exported to ipynb
4 participants