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

Fix HTML output #18292

Closed
vbraun opened this issue Apr 23, 2015 · 110 comments
Closed

Fix HTML output #18292

vbraun opened this issue Apr 23, 2015 · 110 comments

Comments

@vbraun
Copy link
Member

vbraun commented Apr 23, 2015

Html output also suffers from the EMBEDDED_MODE syndrome, it should actually return html expressions (instead of the empty string) and not rely on print()ing HTML to the screen doing anything.

The current behavior is:

sage: n=7
sage: L = map(None,[p for p in prime_range(n+1) if p%4==1],[p for p in prime_range(n+1) if p%4==3])
sage: L = [['',l[1]] if l[0] is None else l for l in L]
sage: T = [['$p\equiv 1\\text{ mod }(4)$','$p\equiv 3\\text{ mod }(4)$']]
sage: output = html(table(T+L,header_row=True))   # print() to stdout???
<html>
<div class="notruncate">
<table  class="table_form">
<tbody>
<tr>
<th><script type="math/tex">p\equiv 1\text{ mod }(4)</script></th>
<th><script type="math/tex">p\equiv 3\text{ mod }(4)</script></th>
</tr>
<tr class ="row-a">
<td><script type="math/tex">5</script></td>
<td><script type="math/tex">3</script></td>
</tr>
<tr class ="row-b">
<td></td>
<td><script type="math/tex">7</script></td>
</tr>
</tbody>
</table>
</div>
</html>
sage: repr(output)     # what?
''
sage: type(output)
<class 'sage.misc.html.HTMLExpr'>

CC: @novoselt @kcrisman @jhpalmieri

Component: notebook

Author: Volker Braun

Branch: 553d2bb

Reviewer: Andrey Novoseltsev

Issue created by migration from https://trac.sagemath.org/ticket/18292

@vbraun vbraun added this to the sage-6.7 milestone Apr 23, 2015
@novoselt
Copy link
Member

comment:2

My thinking was that it should call display manager. Or the idea is that html(x) makes some object and when I do show(html(x)) then display hook will be called with HTML input? So far I've done this: novoselt/sage@8667c1e

And actually, since calling html(x) before from the middle of the code resulted in HTML output, we really should not change it without deprecation, all my interacts will be broken otherwise and probably any others that tried to be pretty...

@vbraun
Copy link
Member Author

vbraun commented Apr 23, 2015

comment:3

Yes, the existing HTMLExpr should have _rich_repr_... I'm working on this.

@vbraun
Copy link
Member Author

vbraun commented Apr 24, 2015

Branch: u/vbraun/fix_html_output

@vbraun
Copy link
Member Author

vbraun commented Apr 24, 2015

Commit: d8d97c8

@vbraun
Copy link
Member Author

vbraun commented Apr 24, 2015

comment:6

What about interacts? Obviously the current @interact doesn't do anything desirable outside of SageNB. We could let html(x) actually do show(html(x)) (*) inside an @interact in SageNB.

(*): Really just show(table(...)) instead of html(table(...)) since a table now defaults to HTML rich output if the backend supports HTML.


New commits:

d8d97c8Reasonable html() implementation

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Apr 24, 2015

Branch pushed to git repo; I updated commit sha1. New commits:

4e2e74ffix doctests
f2d400cmatch table and html.table keyword arguments

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Apr 24, 2015

Changed commit from d8d97c8 to f2d400c

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Apr 24, 2015

Changed commit from f2d400c to e9828f8

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Apr 24, 2015

Branch pushed to git repo; I updated commit sha1. New commits:

a65bbfeuse header_row in the interact library
e9828f8revert to old html behavior inside SageNB interacts

@vbraun
Copy link
Member Author

vbraun commented Apr 24, 2015

Author: Volker Braun

@novoselt
Copy link
Member

comment:10

Well, @interact does something extremely desirable in SageMathCell (to the point that I would have little use for it if there were no interacts), but the implementation is different and I have no clue about it yet. Personally I was using stuff like html("Something in a prettier font than print command") and html("Layout code for interact")

@kcrisman
Copy link
Member

comment:11

Well, @interact does something extremely desirable in SageMathCell (to the point that I would have little use for it if there were no interacts),

Agreed.

but the implementation is different and I have no clue about it yet. Personally I was using stuff like html("Something in a prettier font than print command") and html("Layout code for interact")

Yes, exactly, and especially to get LaTeX of things that might vary in an interact. I am pretty sure we are not the only ones using it for this, either.

@vbraun
Copy link
Member Author

vbraun commented Apr 24, 2015

comment:12

Is there a hook for checking whether we are running in the sage cell server? There is no sage.plot.plot.EMBEDDED_MODE...

What might be worth a thought is to have every top-level statement in an @interact-function show its rich output, e.g.

@interact
def f():
    plot(sin)         # shows plot
    plt = plot(sin)   # does not show

though better not on this ticket...

@novoselt
Copy link
Member

comment:13

There used to be a special version of EMBEDDED_MODE which is still in the deployed version, corresponding to https://github.com/novoselt/sage/tree/sagecell however I switched to the new display backend in https://github.com/novoselt/sage/tree/celldev which has minimal changes from Sage-6.6 + new show. I will switch to this branch (currently running on http://sagecell.sagedev.org/ ) next week while switching hosting, so any investigation/fixing should be based on that.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Apr 25, 2015

Changed commit from e9828f8 to 1f75112

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Apr 25, 2015

Branch pushed to git repo; I updated commit sha1. New commits:

1f75112also support arguments that are not literal

@novoselt
Copy link
Member

comment:15

Karl-Dieter - any plans to adjust !SageNB to use new display framework "properly"? Once it is done, we can get rid of EMBEDDED_MODE shrubbery completely, I think.

@kcrisman
Copy link
Member

comment:16

I accept pull requests but don't understand this new framework at all and don't have time to learn it for some time yet.

@vbraun
Copy link
Member Author

vbraun commented Apr 27, 2015

comment:17

IMHO there isn't really any need to change SageNB, backend_sagenb.py can just keep translating output into whatever SageNB expects. To get rid of the EMBEDDING_MODE global we need to tie up a couple of loose ends on the Sage side first, e.g. pager...

@novoselt
Copy link
Member

comment:18

What is the motivation for replacing header with header_row?

@novoselt
Copy link
Member

Reviewer: Andrey Novoseltsev

@novoselt
Copy link
Member

comment:19

Otherwise looks good to me and should be merged for widespread testing!

@vbraun
Copy link
Member Author

vbraun commented Apr 29, 2015

comment:20

table() uses header_row, so I'm thinking that html.table() should match that. We could change table to use header instead, which is shorter. The only downside is that probably more people use table than html.table... I would be fine with either way, though.

@kcrisman
Copy link
Member

comment:21

table() uses header_row, so I'm thinking that html.table() should match that. We could change table to use header instead, which is shorter. The only downside is that probably more people use table than html.table... I would be fine with either way, though.

I think that the decision was made at the time John et al. made table() to just leave html.table() alone, so that there was no need for deprecation... the intent would be for people to eventually all switch to table(). Which I was hoping to do for my NT text this time around, but unfortunately the cell server doesn't support it (yet) so I am sticking with html.table(). Anyway, could be worth briefly asking about that, or saving it for another ticket.

(Also, there is no header column option in html.table() which there is in table(), I believe, so there isn't the need to change it that way either.)

@vbraun
Copy link
Member Author

vbraun commented Apr 29, 2015

comment:22

With this ticket + updating the cell server to the new display backend just table() should work and display a html table. Should I just deprecate html.table altogether?

@kcrisman
Copy link
Member

comment:79

it would be easier to make an html table by firing up Sage and having it output the correct html for a complicated table of function values

Sage is not a HTML authoring tool. Any attempts at making Sage a HTML authoring tool will be to the detriment of users that want to use Sage for math. And you can always have your web browser display the source if you really are curious how its done.

Heehee, that's what I thought you'd say - hence the smiley face. But there are always unauthorized uses for any computation :)

Once the deprecation period is over and html() actually returns a HtmlFragment you can use it like a string (combine, convert, save, print, ...) to work with the HTML source, but I still wouldn't want to advertise Sage as a HTML authoring tool.

No, of course not.

As a different question, what happens with iframe in this new behavior?

Nothing, works like before (i.e. doesn't work for sites that prevent iframing like google.com)

Great, thanks - I think Andrey implied this as well.

@vbraun
Copy link
Member Author

vbraun commented Aug 27, 2015

comment:80

Replying to @novoselt:

Regarding interacts, which are also supported by SMCs (SageMathCell and SageMathCloud ;-)) - what is "the right way" to adjust sage.interacts.decorator.interact to other UIs?

Perhaps the best solution would be to add a hook to the rich output backend, what do you think? It is very much related to the UI frontend. Though ideally do this on a separate ticket.

Do we need math_parse?

I potentially agree but don't want to change it on this ticket. I haven't tried whether your suggestion will work.

Why do we need this test:

+        OutputHtml = display_manager.types.OutputHtml
+        if OutputHtml in display_manager.supported_output():
+            return OutputHtml(self._html_())

isn't the point of all this display framework to make these decisions WITHOUT object's interference?

The commandline can't display HTML output, so that tests is false. Not returning anything from _rich_repr_ means that the ordinary _repr_ is used, which here means ascii art table.

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 27, 2015

Changed commit from 11ebe8a to 553d2bb

@sagetrac-git
Copy link
Mannequin

sagetrac-git mannequin commented Aug 27, 2015

Branch pushed to git repo; I updated commit sha1. New commits:

553d2bbfix the remaining doctests

@kcrisman
Copy link
Member

comment:82

Lest this all seem of academic importance, see this SO question.

@vbraun
Copy link
Member Author

vbraun commented Aug 27, 2015

comment:83

Replying to @kcrisman:

Lest this all seem of academic importance, see this SO question.

And that poor soul just wants a good-looking table. But table doesn't produce decent tables in browsers and html.table is too married to SageNB to be of any use. Whereas with this ticket + SMC integration he'd just call table and get a nice-looking table.

@kcrisman
Copy link
Member

comment:84

Correct, that was my point.

@novoselt
Copy link
Member

novoselt commented Sep 2, 2015

comment:85

Loose ends:

  • some hook for interact implementations
  • get rid of math_parse, I'll open a ticket and do it

@vbraun
Copy link
Member Author

vbraun commented Sep 2, 2015

Changed branch from u/vbraun/fix_html_output to 553d2bb

@kcrisman
Copy link
Member

Changed commit from 553d2bb to none

@kcrisman
Copy link
Member

comment:87

Hah! I was right about all this silly stuff like "pretty_print". Real-life users don't get all these conventions.

http://ask.sagemath.org/question/29450/is-there-a-way-to-fix-my-html-lines/

I love "about 8 weeks of my work were gobbled up". Even if this is really a "bug" in the cell server, I don't think anyone was crying out for html to suddenly return a string.

(And note that even if there is a regex that can solve all this user's woes, that is not really the correct solution, any more than the fact that my library's recent decision to completely change their web hierarchy has as a solution "email so-and-so for the new URL for that page". We can't be handing out regex commands like candy all day long.)

@novoselt
Copy link
Member

comment:88

I am crying for a) consistency and b) being able to construct HTML representations of objects.

When you call latex(x), you do NOT get x displayed, instead you get LaTeX code for x which you can use to cook up LaTeX representation of a more complicated object. I want to have the same for html(x).

@kcrisman
Copy link
Member

comment:89

And I didn't push back too hard here because the sagenb continues to allow

html("hi there $x^2$")

to correctly render, without a deprecation, or so the above discussion (and my testing just now) suggests. But now the Sage cell apparently doesn't? Though I don't see the deprecation warning... so why is it showing up in the embedded version for this user? (We can open a new ticket or discuss at the ask.sagemath question, if need be.)

@novoselt
Copy link
Member

comment:90

html here returns something and that something is automatically displayed as the last thing in the cell. Try putting some stuff after html in the same cell - you should get deprecation. Same with the cell server: html by itself has no warning (and will work like that forever), but if it is followed by something there is a warning and it has to be addressed in a year or so.

@kcrisman
Copy link
Member

comment:91

If html() returns html, I thought that the legendary "display hook" would make that html display as well. Why does it matter if something is after the stuff in html? I could very easily imagine someone with zero examples that trigger deprecation warning in that case suddenly being surprised!

@vbraun
Copy link
Member Author

vbraun commented Sep 16, 2015

comment:92

The displayhook displays the result of the last expression:

  • A cell containing

    1/3  # <-- first expression
    2/3  # <-- second (=last) expression
    

    outputs 2/3

  • A cell containing

    latex(1/3)
    latex(2/3)
    

    outputs \frac{2}{3}

  • A cell containing

    html(1/3)
    html(2/3)
    

    should output mathjax for 2/3.

@kcrisman
Copy link
Member

comment:93

Thank you, that is SUPER helpful and it's a wonder that I never saw that clear of an explanation before.

So at least one workaround that should work into the future is, as Andrey says, just putting html(stuff) in the last expression always. Maybe this could be in the documentation for html()? Or would that be considered gauche?

@novoselt
Copy link
Member

comment:94

That's not at all a workaround if you have code that tries to display multiple HTML bits in different places. And there is (or rather there will be) nothing special about html(x): it returns HTML code similar to latex(x) returning a LaTeX expression, plot(x) returning a graphical object, and, for that matter, str(x) returning a string. All of them just return, but not display by themselves in case you have different plans (e.g. constructing a more complicated object from pieces or saving to a file). If you want to see any, call print or pretty_print. This also helps with the issue of what pretty_print(x) should mean when x can be typeset/plotted/etc - it will do some default, but if you prefer something specific do pretty_print(plot(x)) or pretty_print(html(x)) depending on your needs.

@novoselt
Copy link
Member

comment:95

Follow up: #19230

@kcrisman
Copy link
Member

comment:96

Something's still up, at least in cell server -

from sage.misc.html import HtmlFragment
pretty_print(HtmlFragment((interacts.calculus.riemann_sum())))

doesn't work. Nor does anything else I tried with the interact library. Also, I'm not sure we need to ask people to import HtmlFragment but I suppose that battle's already lost. Any ideas?

@novoselt
Copy link
Member

comment:97

Note that cell server is running 6.9.beta6 (unless you are experimenting with the test one I've set up recently). I am fine with putting HtmlFragment into global space ;-)

@kcrisman
Copy link
Member

comment:98

I guess the point being that I can't figure out a way to use things like interacts.calculus.riemann_sum(). Given that it is the only way to now put HTML in notebooks (I guess?) I think HtmlFragment in global namespace is good but I don't know how others would feel about that.

@vbraun
Copy link
Member Author

vbraun commented Apr 21, 2016

comment:99

You are supposed to build HtmlFragments with the html() function, it should definitely not be in the global namespace:

sage: sage.misc.html._old_and_deprecated_behavior = False
sage: html('test')
test
sage: type(_)
<class 'sage.misc.html.HtmlFragment'>

@kcrisman
Copy link
Member

comment:100

That's fine. I don't actually care about HtmlFragment per se, but I do want the interact library to work in the cell server - but maybe there's no workaround other than building a new display hook there?

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

No branches or pull requests

4 participants