Repository: holoviz/holoviews

Issue:
hv.Labels does not expose all style opts with Bokeh backend
#### ALL software version info
Holoviews 1.18.3
Bokeh 3.4.1

#### Description of expected behavior and the observed behavior
Since Bokeh 3, the `Text` glyph offers a string of customisation options that were not available in Bokeh 2 (see [here](https://docs.bokeh.org/en/2.4.3/docs/reference/models/glyphs/text.html) and [here](https://docs.bokeh.org/en/3.4.0/docs/reference/models/glyphs/text.html) to compare). However, these are not exposed in Holoviews.

The options involved are everything `border_*` and `background_*`.

I thought options were discovered dynamically to check whether they exist in the underlying Bokeh model but rather they are specified explicitly. In this case they have to be added to `style_opts` (and maybe `_batched_style_opts`) in `LabelsPlot`. They are a variety of ways to add them in the `styles.py` module but we need to avoid adding unexisting options to other elements.

#### Complete, minimal, self-contained example code that reproduces the issue

```python
import holoviews as hv
import numpy as np

hv.extension('bokeh')

np.random.seed(9)
data = np.random.rand(10, 2)
labels = hv.Labels({('x', 'y'): data, 'text': [chr(65+i) for i in range(10)]}, ['x', 'y'], 'text').opts(background_fill_color='#FF46F7')
labels
```

#### Stack traceback and/or browser JavaScript console output
```
ValueError: Unexpected option 'background_fill_color' for Labels type across all extensions. No similar options found.
```

- [x] I may be interested in making a pull request to address this



Discussion:
You are correct. You are welcome to go ahead and expose the style options. 

Resolving patch:
diff --git a/holoviews/plotting/bokeh/annotation.py b/holoviews/plotting/bokeh/annotation.py
--- a/holoviews/plotting/bokeh/annotation.py
+++ b/holoviews/plotting/bokeh/annotation.py
@@ -15,7 +15,14 @@
 from .element import AnnotationPlot, ColorbarPlot, CompositeElementPlot, ElementPlot
 from .plot import BokehPlot
 from .selection import BokehOverlaySelectionDisplay
-from .styles import base_properties, fill_properties, line_properties, text_properties
+from .styles import (
+    background_properties,
+    base_properties,
+    border_properties,
+    fill_properties,
+    line_properties,
+    text_properties,
+)
 from .util import bokeh32, date_to_integer
 
 arrow_start = {'<->': NormalHead, '<|-|>': NormalHead}
@@ -104,7 +111,8 @@ class VSpansAnnotationPlot(_SyntheticAnnotationPlot):
 
 class TextPlot(ElementPlot, AnnotationPlot):
 
-    style_opts = text_properties+['color', 'angle', 'visible']
+    style_opts = (text_properties + background_properties
+                  + border_properties + ['color', 'angle', 'visible'])
     _plot_methods = dict(single='text', batched='text')
 
     selection_display = None
@@ -167,12 +175,13 @@ class LabelsPlot(ColorbarPlot, AnnotationPlot):
 
     selection_display = BokehOverlaySelectionDisplay()
 
-    style_opts = base_properties + text_properties + ['cmap', 'angle']
+    style_opts = (base_properties + text_properties
+                  + background_properties + border_properties + ['cmap', 'angle'])
 
     _nonvectorized_styles = base_properties + ['cmap']
 
     _plot_methods = dict(single='text', batched='text')
-    _batched_style_opts = text_properties
+    _batched_style_opts = text_properties + background_properties + border_properties
 
     def get_data(self, element, ranges, style):
         style = self.style[self.cyclic_index]
diff --git a/holoviews/plotting/bokeh/styles.py b/holoviews/plotting/bokeh/styles.py
--- a/holoviews/plotting/bokeh/styles.py
+++ b/holoviews/plotting/bokeh/styles.py
@@ -29,14 +29,22 @@
 
 base_properties = ['visible', 'muted']
 
-line_properties = ['line_color', 'line_alpha', 'color', 'alpha', 'line_width',
-                   'line_join', 'line_cap', 'line_dash']
-line_properties += [f'{prefix}_{prop}' for prop in line_properties
-                    for prefix in property_prefixes]
-
-fill_properties = ['fill_color', 'fill_alpha']
-fill_properties += [f'{prefix}_{prop}' for prop in fill_properties
-                    for prefix in property_prefixes]
+line_base_properties = ['line_color', 'line_alpha', 'color', 'alpha', 'line_width',
+                        'line_join', 'line_cap', 'line_dash', 'line_dash_offset']
+line_properties = line_base_properties + [f'{prefix}_{prop}'
+                                          for prop in line_base_properties
+                                          for prefix in property_prefixes]
+
+fill_base_properties = ['fill_color', 'fill_alpha']
+fill_properties = fill_base_properties + [f'{prefix}_{prop}'
+                                          for prop in fill_base_properties
+                                          for prefix in property_prefixes]
+
+border_properties = ['border_' + prop for prop in line_base_properties + ['radius']]
+
+hatch_properties = ['hatch_color', 'hatch_scale', 'hatch_weight',
+                    'hatch_extra', 'hatch_pattern', 'hatch_alpha']
+background_properties = ['background_' + prop for prop in fill_base_properties + hatch_properties]
 
 text_properties = ['text_font', 'text_font_size', 'text_font_style', 'text_color',
                    'text_alpha', 'text_align', 'text_baseline']


Test patch: