Repository: bokeh/bokeh

Issue:
Text doesn't respect new lines
The code below does not render the `\n` as a new line. Replacing it with `<br/>` doesn't help either.

```
import bokeh.plotting as plt

plt.output_file("test.html")
plt.text(x=[1,2,3], y = [0,0,0], text=['hello\nworld!', 'hello\nworld!', 'hello\nworld!'], angle = 0)
plt.show()
```



Discussion:
Not natively supported by html canvas but we can probably put something together. This might be useful

http://stackoverflow.com/questions/4478742/html5-canvas-can-i-somehow-use-linefeeds-in-filltext

> On Aug 12, 2014, at 13:27, "Andy R. Terrel" notifications@github.com wrote:
> 
> The code below does not render the \n as a new line. Replacing it with <br/> doesn't help either.
> 
> import bokeh.plotting as plt
> 
> plt.output_file("test.html")
> plt.text(x=[1,2,3], y = [0,0,0], text=['hello\nworld!', 'hello\nworld!', 'hello\nworld!'], angle)
> plt.show()
> —
> Reply to this email directly or view it on GitHub.

More possibly useful info: https://www.npmjs.org/package/canvas-text-wrapper


Resolving patch:
diff --git a/bokeh/core/property_mixins.py b/bokeh/core/property_mixins.py
--- a/bokeh/core/property_mixins.py
+++ b/bokeh/core/property_mixins.py
@@ -43,7 +43,7 @@ class SomeGlyph(Glyph):
 
 from .enums import LineJoin, LineCap, FontStyle, TextAlign, TextBaseline
 from .has_props import HasProps
-from .properties import ColorSpec, DashPattern, Enum, FontSizeSpec, Int, NumberSpec, String, value
+from .properties import ColorSpec, DashPattern, Enum, FontSizeSpec, Int, Float, NumberSpec, String, value
 
 class FillProps(HasProps):
     ''' Properties relevant to rendering fill regions.
@@ -228,3 +228,10 @@ class TextProps(HasProps):
     - ``'ideographic'``
 
     """)
+
+    text_line_height = Float(default=1.2, help="""
+    In multi-line text, how much additional space should be allocated for
+    each line. The value is provided as a number, but should be treated as
+    a percentage of font size. The default is 120%. Setting it to 1.0, so
+    100%, means no additional space will be used.
+    """)
diff --git a/examples/plotting/file/text.py b/examples/plotting/file/text.py
new file mode 100644
--- /dev/null
+++ b/examples/plotting/file/text.py
@@ -0,0 +1,63 @@
+from bokeh.layouts import column
+from bokeh.models import CustomJS, Slider
+from bokeh.plotting import figure, show, output_file
+
+aligns    = ["left", "center", "right"]
+baselines = ["bottom", "middle", "top" ]
+
+p = figure(x_range=aligns, y_range=baselines, plot_width=800, plot_height=600,
+           title="Variations of multi-line text", toolbar_location=None)
+
+p.background_fill_color = "lightgrey"
+p.xaxis.axis_label = "align"
+p.yaxis.axis_label = "baseline"
+p.axis.major_label_text_font_size = "18px"
+p.axis.major_label_text_font_style = "bold"
+
+p.xgrid.grid_line_color = None
+p.ygrid.grid_line_color = None
+
+texts = [
+
+'''one''',
+
+'''two
+lines''',
+
+'''lines
+here:
+3''',
+
+'''here
+are
+4
+lines'''
+
+]
+
+def xs(cat):
+    return [(cat, -0.3), (cat, -0.1), (cat, 0.1), (cat, 0.3)]
+
+def ys(cat):
+    return [cat] * 4
+
+renderers = {}
+i = 0
+
+for a in aligns:
+    for b in baselines:
+        r = p.text(xs(a), ys(b), texts, text_align=a, text_baseline=b,
+                   text_font_size="14px", text_line_height=1.2)
+        renderers["r" + str(i)] = r
+        i += 1
+
+slider = Slider(title="Text Angle", start=0, end=45, step=1, value=0)
+slider.js_on_change('value', CustomJS(args=renderers, code="""
+    rs = [r0, r1, r2 , r3, r4, r5, r6, r7, r8];
+    for (i=0; i<9; i++) {
+        rs[i].glyph.angle = {value: cb_obj.value, units: "deg"}
+    }
+"""))
+
+output_file("text.html")
+show(column(p, slider))


Test patch:
diff --git a/bokeh/models/tests/utils/property_utils.py b/bokeh/models/tests/utils/property_utils.py
--- a/bokeh/models/tests/utils/property_utils.py
+++ b/bokeh/models/tests/utils/property_utils.py
@@ -5,7 +5,7 @@
 # enums
 FILL = ["fill_color", "fill_alpha"]
 LINE = ["line_color", "line_width", "line_alpha", "line_join", "line_cap", "line_dash", "line_dash_offset"]
-TEXT = ["text_font", "text_font_size", "text_font_style", "text_color", "text_alpha", "text_align", "text_baseline"]
+TEXT = ["text_font", "text_font_size", "text_font_style", "text_color", "text_alpha", "text_align", "text_baseline", "text_line_height"]
 
 ANGLE = ["angle", "angle_units"]