diff --git a/text_extensions_for_pandas/jupyter.py b/text_extensions_for_pandas/jupyter.py index dc6d6e25..b870c438 100644 --- a/text_extensions_for_pandas/jupyter.py +++ b/text_extensions_for_pandas/jupyter.py @@ -120,27 +120,25 @@ def pretty_print_html(column: Union["SpanArray", "TokenSpanArray"], style_text = "" script_text = "" - if _spanarray_instance_counter == 1: - style_text = importlib.resources.read_text(resources, "span_array.css") - script_text = importlib.resources.read_text(resources, "span_array.js") + style_text = importlib.resources.read_text(resources, "span_array.css") + script_text = importlib.resources.read_text(resources, "span_array.js") return textwrap.dedent(f"""
If you're reading this message, your notebook viewer does not support Javascript execution. Try pasting the URL into a service like nbviewer.
""") diff --git a/text_extensions_for_pandas/resources/span_array.css b/text_extensions_for_pandas/resources/span_array.css index b94aab40..8821ad50 100644 --- a/text_extensions_for_pandas/resources/span_array.css +++ b/text_extensions_for_pandas/resources/span_array.css @@ -1,11 +1,12 @@ .span-array { - --thead-background-color: #0d2025; - --thead-text-color: whitesmoke; - --tbody-background-color-1: inherit; - --tbody-background-color-2: inherit; - --tbody-background-color-hover: inherit; - --tbody-background-color-disabled: inherit; - --tbody-text-color: inherit; + --thead-background-color: var(--jp-layout-color4, inherit); + --thead-text-color: var(--jp-ui-font-color4); + --tbody-background-color-1: var(--jp-layout-color2, inherit); + --tbody-background-color-2: var(--jp-layout-color1, inherit); + --tbody-background-color-hover: var(--jp-layout-color3, inherit); + --tbody-background-color-disabled: var(--jp-layout-color4, inherit); + --tbody-text-color: var(--jp-ui-font-color0, inherit); + --table-font-family: var(--jp-content-font-family, var(--fallback-font-family, inherit)); --root-highlight: #a0c4ff; --nested-highlight: #ffadad; @@ -14,6 +15,8 @@ --inverted-background-color: #0B525B; --inverted-text-color: rgb(243, 243, 243); --paragraph-border-color: transparent; + + --fallback-font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif } body[data-jp-theme-light="false"] .span-array { @@ -45,7 +48,7 @@ body[data-jp-theme-light="true"] .span-array { overflow: hidden; width: 100%; border-collapse: collapse; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + font-family: var(--table-font-family); } .span-array>table thead { @@ -85,9 +88,9 @@ body[data-jp-theme-light="true"] .span-array { border:1px solid var(--paragraph-border-color); border-radius: 0.2em; padding: 1em; - line-height: 2.5; + line-height: calc(var(--jp-content-line-height, 1.6) * 1.6); box-sizing: border-box; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif; + font-family: var(--jp-content-font-family, var(--fallback-font-family, inherit)); } body[data-jp-theme-light="false"].span-array>p { diff --git a/text_extensions_for_pandas/resources/span_array.js b/text_extensions_for_pandas/resources/span_array.js index b0524335..696bf9b4 100644 --- a/text_extensions_for_pandas/resources/span_array.js +++ b/text_extensions_for_pandas/resources/span_array.js @@ -1,5 +1,5 @@ // Increment the version to invalidate the cached script -const VERSION = 0.41 +const VERSION = 0.48 if(!window.SpanArray || window.SpanArray.VERSION < VERSION) { @@ -27,11 +27,29 @@ if(!window.SpanArray || window.SpanArray.VERSION < VERSION) { class Entry { - static updateSets(entries) { + // Creates an ordered list of entries from a list of spans with struct [begin, end] + static fromSpanArray(spanArray) { + let entries = [] + let id = 0 + + spanArray.sort((a, b) => { + if(a[0] < b[0]) { + return a + } else if(a[0] == b[0] && a[1] >= b[1]) { + return a + } else { + return b + } + }) + .forEach(span => { + entries.push(new Entry(id, span[0], span[1])) + id += 1 + }) + + let set; for(let i = 0; i < entries.length; i++) { for(let j = i+1; j < entries.length; j++) { if(entries[j].begin < entries[i].end) { - let set; if(entries[j].end <= entries[i].end) { set = {type: TYPE_NESTED, entry: entries[j]} } else { @@ -41,17 +59,8 @@ if(!window.SpanArray || window.SpanArray.VERSION < VERSION) { } } } - } - static fromSpanArray(spanArray, start_id) { - let set = [] - if(start_id == undefined) start_id = 0 - let id = start_id - spanArray.forEach(span => { - set.push(new Entry(id, span[0], span[1])) - id += 1 - }) - return set + return entries } constructor(id, begin, end) { @@ -62,25 +71,24 @@ if(!window.SpanArray || window.SpanArray.VERSION < VERSION) { this.visible = true } - get length() { - return this.end - this.begin - } - + // Returns only visible sets get valid_sets() { let valid_sets = [] + this.sets.forEach(set => { if(set.entry.visible) valid_sets.push(set) }) + return valid_sets } + // Returns true if mark should render as a compound set of spans isComplex() { - for(let i = 0; i < this.valid_sets.length; i++) - { + for(let i = 0; i < this.valid_sets.length; i++) { let otherMember = this.valid_sets[i].entry; - if(this.valid_sets[i].type == TYPE_OVERLAP && otherMember.visible) return true; - else - { + if(this.valid_sets[i].type == TYPE_OVERLAP && otherMember.visible) { + return true; + } else { if(otherMember.valid_sets.length > 0 && otherMember.visible) { return true; } @@ -89,34 +97,37 @@ if(!window.SpanArray || window.SpanArray.VERSION < VERSION) { return false; } - + // Gets the combined span of all connected elements getSetSpan() { let begin = this.begin let end = this.end let highest_id = this.id + this.valid_sets.forEach(set => { let other = set.entry.getSetSpan() if(other.begin < begin) begin = other.begin if(other.end > end) end = other.end if(other.highest_id > highest_id) highest_id = other.highest_id }) + return {begin: begin, end: end, highest_id: highest_id} } } window.SpanArray.Entry = Entry + // Render DOM function render(doc_text, entries, instance_id, show_offsets) { let frag = document.createDocumentFragment() + // Render Table if(show_offsets) { let table = document.createElement("table") table.innerHTML = ` - id begin end context @@ -132,8 +143,7 @@ if(!window.SpanArray || window.SpanArray.VERSION < VERSION) { } row.innerHTML += ` - - ${entry.id.toString()} + ${entry.id.toString()} ${entry.begin} ${entry.end} ${doc_text.substring(entry.begin, entry.end)}` @@ -144,6 +154,7 @@ if(!window.SpanArray || window.SpanArray.VERSION < VERSION) { frag.appendChild(table) } + // Render Text let highlight_regions = [] for(let i = 0; i < entries.length; i++) { @@ -170,10 +181,10 @@ if(!window.SpanArray || window.SpanArray.VERSION < VERSION) { let begin = 0 highlight_regions.forEach(region => { paragraph.innerHTML += sanitize(doc_text.substring(begin, region.begin)) + let mark = document.createElement("mark") mark.setAttribute("data-ids", ""); - if (region.type != TYPE_NESTED) - { + if (region.type != TYPE_NESTED) { region.ids.forEach(id => { mark.setAttribute("data-ids", mark.getAttribute("data-ids") + `${id},`) }) @@ -209,15 +220,13 @@ if(!window.SpanArray || window.SpanArray.VERSION < VERSION) { frag.appendChild(paragraph) + // Attach fragments to all copies of the instance let containers = document.querySelectorAll(`.span-array[data-instance='${instance_id}']`) - containers.forEach(container => { let cloned_frag = frag.cloneNode(true) - // attach events container.innerHTML = "" container.appendChild(cloned_frag) }) - } window.SpanArray.render = render diff --git a/text_extensions_for_pandas/test_jupyter.py b/text_extensions_for_pandas/test_jupyter.py index 4da879f3..4eebf78d 100644 --- a/text_extensions_for_pandas/test_jupyter.py +++ b/text_extensions_for_pandas/test_jupyter.py @@ -36,41 +36,37 @@ class JupyterTest(TestBase): def test_pretty_print_html(self): self.maxDiff = None html = pretty_print_html(_TEST_TOKS["span"].values, True) - suffix = html[-1571:] + suffix = html[-380:] # print(f"[[[{suffix}]]]") self.assertEqual( suffix, """\ - - -
- -
-

- Item's for < $100 & change -

-
- -
- +ndow.SpanArray.render = render +} + const Entry = window.SpanArray.Entry + const render = window.SpanArray.render + const spanArray = [[0,4],[4,6],[7,10],[11,12],[13,14],[14,17],[18,19],[20,26]] + const entries = Entry.fromSpanArray(spanArray) + const doc_text = `Item's for < $100 & change` + render(doc_text, entries, 1, true) + } + """) html = pretty_print_html(_TEST_TOKS["span"].values, False) - suffix = html[-1599:] + suffix = html[-380:] # print(f"[[[{suffix}]]]") self.assertEqual( suffix, """\ - -
- -
-

- Item's for < $100 & change -

-
- -
+dow.SpanArray.render = render +} + const Entry = window.SpanArray.Entry + const render = window.SpanArray.render + const spanArray = [[0,4],[4,6],[7,10],[11,12],[13,14],[14,17],[18,19],[20,26]] + const entries = Entry.fromSpanArray(spanArray) + const doc_text = `Item's for < $100 & change` + render(doc_text, entries, 2, false) + } + """)