From dd28cdac698c8fad3f3e0d729bfd4227701f02ef Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Sat, 11 May 2024 18:46:36 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=8C=20Streamline=20internal=20CSS=20(#?= =?UTF-8?q?1178)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit restructures the internal CSS used by the extension, with the goal of improving compatibility sphinx theme extensions. - `common.css` is split into multiple files, relating to their purpose. - most hard-coded colors set within the CSS are replaced with CSS variables, that can be set/overridden by themes/users - most per-theme CSS is replaced with simply defining the CSS variable colors (removing a lot of duplication) - Outdated/deprecated handling of CSS/JS in `sphinx_needs/environment.py` is replaced with modern sphinx methods --- docs/configuration.rst | 21 +- pyproject.toml | 2 +- sphinx_needs/config.py | 5 +- sphinx_needs/css/blank/blank.css | 67 ------ sphinx_needs/css/blank/styles.css | 95 -------- sphinx_needs/css/common.css | 162 ------------- sphinx_needs/css/common/need_core.css | 61 +++++ sphinx_needs/css/common/need_links.css | 17 ++ sphinx_needs/css/common/need_style.css | 214 +++++++++++++++++ sphinx_needs/css/common/need_toggle.css | 26 ++ sphinx_needs/css/common/needstable.css | 65 +++++ sphinx_needs/css/dark/dark.css | 151 ------------ sphinx_needs/css/dark/layouts.css | 93 ------- sphinx_needs/css/dark/styles.css | 121 ---------- sphinx_needs/css/grids.css | 1 - sphinx_needs/css/modern/layouts.css | 93 ------- sphinx_needs/css/modern/modern.css | 28 --- sphinx_needs/css/modern/styles.css | 129 ---------- sphinx_needs/css/themes/blank.css | 31 +++ sphinx_needs/css/themes/dark.css | 135 +++++++++++ sphinx_needs/css/themes/modern.css | 31 +++ sphinx_needs/defaults.py | 2 - sphinx_needs/environment.py | 226 +++++------------- sphinx_needs/layout.py | 1 - tests/test_styles/test_style_blank.py | 11 - .../test_style_css_js_registration.py | 12 +- tests/test_styles/test_style_custom.py | 11 - tests/test_styles/test_style_modern.py | 11 - tests/test_styles/test_style_unknown.py | 27 ++- 29 files changed, 665 insertions(+), 1184 deletions(-) delete mode 100644 sphinx_needs/css/blank/blank.css delete mode 100644 sphinx_needs/css/blank/styles.css delete mode 100644 sphinx_needs/css/common.css create mode 100644 sphinx_needs/css/common/need_core.css create mode 100644 sphinx_needs/css/common/need_links.css create mode 100644 sphinx_needs/css/common/need_style.css create mode 100644 sphinx_needs/css/common/need_toggle.css create mode 100644 sphinx_needs/css/common/needstable.css delete mode 100644 sphinx_needs/css/dark/dark.css delete mode 100644 sphinx_needs/css/dark/layouts.css delete mode 100644 sphinx_needs/css/dark/styles.css delete mode 100644 sphinx_needs/css/grids.css delete mode 100644 sphinx_needs/css/modern/layouts.css delete mode 100644 sphinx_needs/css/modern/modern.css delete mode 100644 sphinx_needs/css/modern/styles.css create mode 100644 sphinx_needs/css/themes/blank.css create mode 100644 sphinx_needs/css/themes/dark.css create mode 100644 sphinx_needs/css/themes/modern.css diff --git a/docs/configuration.rst b/docs/configuration.rst index 39a79db72..5c808c9bb 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -1637,28 +1637,9 @@ This may be needed to avoid custom table handling of some specific Sphinx theme needs_table_classes = ['my_custom_class', 'another_class'] -Default: ``['rtd-exclude-wy-table', 'no-sphinx-material-strip']`` - -This classes are not set for needtables using the ``table`` style, which is using the normal Sphinx table layout +These classes are not set for needtables using the ``table`` style, which is using the normal Sphinx table layout and therefore must be handled by themes. -The following themes support the following table classes to deactivate their specific handling: - -.. list-table:: - - - * Theme - * Class - - * ReadTheDocs - * ``rtd-exclude-wy-table`` - - * Sphinx-Material - * ``no-sphinx-material-strip`` - -.. hint:: - - The deactivation of theme specific table handling is quite a new feature in most themes. - Please be sure to use the newest theme version or even the nightly build. - - .. _needs_builder_filter: needs_builder_filter diff --git a/pyproject.toml b/pyproject.toml index f6338c270..dfeaa3eda 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,7 +102,7 @@ markers = [ ] filterwarnings = [ "ignore:.*removed in Python 3.14.*:DeprecationWarning", - # "ignore::sphinx.deprecation.RemovedInSphinx90Warning" + "ignore::PendingDeprecationWarning:sphinx_data_viewer.*", ] diff --git a/sphinx_needs/config.py b/sphinx_needs/config.py index 1a71f6ab8..ed800ba2a 100644 --- a/sphinx_needs/config.py +++ b/sphinx_needs/config.py @@ -6,7 +6,7 @@ from sphinx.application import Sphinx from sphinx.config import Config as _SphinxConfig -from sphinx_needs.defaults import DEFAULT_DIAGRAM_TEMPLATE, NEEDS_TABLES_CLASSES +from sphinx_needs.defaults import DEFAULT_DIAGRAM_TEMPLATE if TYPE_CHECKING: from sphinx.util.logging import SphinxLoggerAdapter @@ -376,8 +376,7 @@ def __setattr__(self, name: str, value: Any) -> None: default="is_external==False", metadata={"rebuild": "html", "types": (str,)} ) table_classes: list[str] = field( - default_factory=lambda: NEEDS_TABLES_CLASSES, - metadata={"rebuild": "html", "types": (list,)}, + default_factory=list, metadata={"rebuild": "html", "types": (list,)} ) """Additional classes to set for needs and needtable.""" string_links: dict[str, dict[str, Any]] = field( diff --git a/sphinx_needs/css/blank/blank.css b/sphinx_needs/css/blank/blank.css deleted file mode 100644 index 2f4278783..000000000 --- a/sphinx_needs/css/blank/blank.css +++ /dev/null @@ -1,67 +0,0 @@ -/* whole NEED container */ -div.need { - -} - -/* -Styles based on need type -************************* -The name depends on the type name. -If a type like "story" was configured in conf.py, -span.needs-story can be used for custom styles for this type. -*/ - -span.needs-specification { - -} - -span.needs-requirement { - -} - -/* -Single elements -*************** -*/ - -/* The type text of a need. The part before the title starts */ -span.needs-type { - -} - -/* The title text of need. Part between need type and need id */ -span.needs-title { - -} - -/* The ID of a need (text behind the need title) */ -span.needs-id { - -} - -/* Tags inside a need*/ -span.needs-tag { - -} - -/* Status of a need */ -span.needs-status { - -} - -/* Outgoing need links. -Applies for outgoing links inside a need and for the role :need_outgoing: */ -em.need_outgoing { - -} - -/* Incoming need links. -Applies for incoming links inside a need and for the role :need_incoming: */ -em.need_incoming { - -} - -/* Linked needs inside text (by using role :need:)*/ -em.need { - -} \ No newline at end of file diff --git a/sphinx_needs/css/blank/styles.css b/sphinx_needs/css/blank/styles.css deleted file mode 100644 index f44e2da4a..000000000 --- a/sphinx_needs/css/blank/styles.css +++ /dev/null @@ -1,95 +0,0 @@ -/*Colors based on https://flatuicolors.com/palette/se*/ - -/* ********************* */ -/* Full need table color */ -/* ********************* */ -table.needs_style_clean, -table.needs_style_clean tr, -table.needs_style_clean td{ - margin-bottom: 10px; - border: none !important; - width: 100%; - background: None !important; - padding: 0; - box-shadow: None; -} - -table.needs_style_green, -table.needs_style_green tr.need, -table.needs_style_green td.need, -table.needs_style_implemented, -table.needs_style_implemented tr.need, -table.needs_style_implemented td.need { - background-color: #05c46b !important; -} - -table.needs_style_red, -table.needs_style_red tr.need, -table.needs_style_red td.need, -table.needs_style_open, -table.needs_style_open tr.need, -table.needs_style_open td.need { - background-color: #ff3f34 !important; -} - -table.needs_style_yellow, -table.needs_style_yellow tr.need, -table.needs_style_yellow td.need, -table.needs_style_in_progress, -table.needs_style_in_progress tr.need, -table.needs_style_in_progress td.need { - background-color: #ffc048 !important; -} - -table.needs_style_blue, -table.needs_style_blue tr.need, -table.needs_style_blue td.need { - background-color: #0fbcf9 !important; -} - -/* **************************** */ -/* Border only need table color */ -/* **************************** */ -table.needs_style_green_border { - border: 5px solid #05c46b !important; -} - -table.needs_style_red_border { - border: 5px solid #ff3f34 !important; -} - -table.needs_style_yellow_border { - border: 5px solid #ffc048 !important; -} - -table.needs_style_blue_border { - border: 5px solid #0fbcf9 !important; -} - -/* ******************************************************* */ -/* Bar on right side that takes 10 % of total table width */ -/* ******************************************************* */ - -table.needs_style_green_bar { - background: linear-gradient(to right, transparent 90%, #05c46b 10%); -} - -table.needs_style_red_bar { - background: linear-gradient(to right, transparent 90%, #ff3f34 10%); -} - -table.needs_style_orange_bar { - background: linear-gradient(to right, transparent 90%, #e67e22 10%); -} - -table.needs_style_yellow_bar { - background: linear-gradient(to right, transparent 90%, #ffc048 10%); -} - -table.needs_style_blue_bar { - background: linear-gradient(to right, transparent 90%, #0fbcf9 10%); -} - -.collapse_is_hidden { - display: none; -} \ No newline at end of file diff --git a/sphinx_needs/css/common.css b/sphinx_needs/css/common.css deleted file mode 100644 index 98b7cc629..000000000 --- a/sphinx_needs/css/common.css +++ /dev/null @@ -1,162 +0,0 @@ -/* This is needed to avoid custom settings for common tables, like the ReadTheDocs theme docs */ -/* It reimplements the normal browser behavior of breaking/wrapping table content if too long.*/ -table.need td { - white-space: normal; -} - -table.NEEDS_TABLE, table.NEEDS_DATATABLES { - display: table; - overflow-x: auto; - white-space: normal; - width: 100%; - /* If this is set, col->width does not work any more*/ - /*max-width: -moz-fit-content;*/ - /*max-width: fit-content;*/ - margin: 0 auto; -} - -div.needstable_wrapper { - width: 100%; - overflow-x: auto; - padding: 0; -} - -/* We need not line-block margin:24 px here, which is coming from sphinx theme */ -table.need td div.needs_side.line-block{ - margin-bottom: 0; -} - -table.need tr.head div.line-block, -table.need tr.meta div.line-block, -table.need tr.footer div.line-block { - display: block; - margin-top: 0; - margin-bottom: 0; -} - -/* START CUSTOM ReadTheDocs theming css START */ -div.dataTables_scrollHeadInner > table.rtd-exclude-wy-table { - margin-bottom: 0px; -} -/* END CUSTOM ReadTheDocs theming css START */ - -.toggle .header { - display: block; - clear: both; -} - -.toggle .header p{ - display: inline; -} - -.toggle .header:after { - content: " ▷"; -} - -.toggle .header.open:after { - content: " ▽"; -} - -div.toggle { - /*border: 2px solid #ddd;*/ - /*padding: 5px;*/ - /*border-radius: 5px;*/ -} - -div.need div.toggle { - /*margin-top: -15px;*/ -} - -div.need div.toggle div.line-block { - margin-top: 0px; - margin-left: 30px; -} - -/* DEAD Links config */ -/* allowed dead links */ -span.needs_dead_link { - opacity: 0.8; -} -/*forbidden dead links */ -span.needs_dead_link.forbidden{ - color: #dc3545; -} - - -/* Style configuration */ - -/* CLEAN */ -table.style_needs_clean { - background: None !important; - border: None !important; - box-shadow: None !important; -} - -table.style_needs_clean td { - padding: 0; -} - - -/* **************** */ -/* DataTable layout */ -/* **************** */ -table.dataTable { - border-collapse: collapse; - border: none; -} - -div.dataTables_length { - margin-bottom: 10px; -} - -div.dataTables_wrapper{ - overflow-x: auto; - padding: 0px 5px; /*Space needed for table borders */ -} - -.dataTables_wrapper .dataTables_paginate .paginate_button { - padding: 0.15em 0.75em; - background: none; -} - -.dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover { - background: none; -} - -div.dataTables_length select { - background: none; -} - -/*DataTables Download Buttons*/ -div.dt-buttons { - margin-left: 10%; -} - -div.dt-buttons button { - padding: 0.1em 1em; - border: 1px solid #999; - border-radius: 2px; - font-size: 0.88em; - line-height: inherit; - color: inherit; - white-space: nowrap; - overflow: hidden; - background-color: inherit; - background-image: none; -} - -/* Cares about setting the final bottom border */ -table.rtd-exclude-wy-table { - border: 1px solid #e1e4e5 !important; -} - -/* Style for external need links*/ -a.external_link:after { - content: "🡽" - /* Same, but with none breaking space (  not supported in content!)*/ - /*content: "\00a0\00a0🡽"*/ -} - -span.needs_collapse > :is(.collapsed, .visible) { - cursor: pointer; -} diff --git a/sphinx_needs/css/common/need_core.css b/sphinx_needs/css/common/need_core.css new file mode 100644 index 000000000..13a520e46 --- /dev/null +++ b/sphinx_needs/css/common/need_core.css @@ -0,0 +1,61 @@ +/* This is the core CSS to style the representation of each need */ + +table.need { + margin-bottom: 10px; + background-color: var(--sn-color-need-bg); + border: 1px solid var(--sn-color-need-border); + width: 100%; +} + +table.need tr.head div.line-block, +table.need tr.meta div.line-block, +table.need tr.footer div.line-block { + display: block; + margin-top: 0; + margin-bottom: 0; +} + +table.need tr.head { + background-color: var(--sn-color-need-bg-head); + border-bottom: 1px solid var(--sn-color-need-border); +} + +table.need tr.meta { + border-bottom: 1px solid var(--sn-color-need-border); + font-size: smaller; +} + +table.need tr.footer { + border-top: 1px solid var(--sn-color-need-border); + font-size: small; +} + +table.need a { + border-bottom: none; +} + +table.need td { + border: none; + /* This is needed to avoid custom settings for common tables, like the ReadTheDocs theme docs */ + /* It reimplements the normal browser behavior of breaking/wrapping table content if too long.*/ + white-space: normal; +} + +/* We need not line-block margin:24 px here, which is coming from sphinx theme */ +table.need td div.needs_side.line-block{ + margin-bottom: 0; +} + + +/* *************** */ +/* collapse button */ +/* *************** */ + +span.needs_collapse> :is(.collapsed, .visible) { + cursor: pointer; +} + +/* this class is added dynamically by sphinx_needs_collapse.js */ +.collapse_is_hidden { + display: none !important; +} diff --git a/sphinx_needs/css/common/need_links.css b/sphinx_needs/css/common/need_links.css new file mode 100644 index 000000000..0b4eed487 --- /dev/null +++ b/sphinx_needs/css/common/need_links.css @@ -0,0 +1,17 @@ +/* DEAD Links config */ +/* allowed dead links */ +span.needs_dead_link { + opacity: 0.8; +} + +/*forbidden dead links */ +span.needs_dead_link.forbidden { + color: var(--sn-color-forbidden-dead-link); +} + +/* Style for external need links*/ +a.external_link:after { + content: "🡽" + /* Same, but with none breaking space (  not supported in content!)*/ + /*content: "\00a0\00a0🡽"*/ +} diff --git a/sphinx_needs/css/common/need_style.css b/sphinx_needs/css/common/need_style.css new file mode 100644 index 000000000..97e8a4182 --- /dev/null +++ b/sphinx_needs/css/common/need_style.css @@ -0,0 +1,214 @@ +/* These classes are added by the sphinx_needs.layout.LayoutHandler class, +to style the representation per need, +based on layout/style keys in the need definition. +*/ + +/* ************ */ +/* layout names */ +/* ************ */ +table.needs_layout_focus_l td.side { + text-orientation: upright; + writing-mode: sideways-lr; + font-size: small; +} + +table.needs_layout_focus_r td.side { + text-orientation: upright; + writing-mode: sideways-rl; + font-size: small; +} + +table.needs_layout_complete td.head_left { + text-align: left; + background-color: var(--sn-color-complete-bg-head); + font-size: smaller; +} + +table.needs_layout_complete td.head_center { + text-align: center; + font-weight: bold; +} + +table.needs_layout_complete td.head_right { + text-align: right; + background-color: var(--sn-color-complete-bg-head); + font-size: smaller; +} + +table.needs_layout_complete tr.footer { + background-color: var(--sn-color-complete-bg-foot); +} + +table.needs_layout_complete td.footer_right { + text-align: right; +} + +table.needs_layout_complete td.footer { + text-align: center; +} + +/* ************* */ +/* layout styles */ +/* ************* */ + +table.needs_style_clean, +table.needs_style_clean tr, +table.needs_style_clean td { + margin-bottom: 10px; + border: none !important; + background: None !important; + padding: 0; + box-shadow: None; +} + +table.needs_style_clean { + width: 100%; +} + +table.needs_style_discreet, +table.needs_style_discreet tr.need, +table.needs_style_discreet td.need { + background-color: var(--sn-color-bg-lightgray) !important; +} + +table.needs_style_gray, +table.needs_style_gray tr.need, +table.needs_style_gray td.need { + background-color: var(--sn-color-bg-gray) !important; +} + +table.needs_style_green, +table.needs_style_green tr.need, +table.needs_style_green td.need, +tr.needs_green, +table.needs_style_implemented, +table.needs_style_implemented tr.need, +table.needs_style_implemented td.need, +tr.needs_implemented { + background-color: var(--sn-color-bg-green) !important; +} + +table.needs_style_red, +table.needs_style_red tr.need, +table.needs_style_red td.need, +tr.needs_red, +table.needs_style_open, +table.needs_style_open tr.need, +table.needs_style_open td.need, +tr.needs_open { + background-color: var(--sn-color-bg-red) !important; +} + +table.needs_style_yellow, +table.needs_style_yellow tr.need, +table.needs_style_yellow td.need, +tr.needs_yellow, +table.needs_style_in_progress, +table.needs_style_in_progress tr.need, +table.needs_style_in_progress td.need tr.needs_in_progress { + background-color: var(--sn-color-bg-yellow) !important; +} + +table.needs_style_blue, +table.needs_style_blue tr.need, +table.needs_style_blue td.need, +tr.needs_blue { + background-color: var(--sn-color-bg-blue) !important; +} + +table.needs_style_green_border { + border: 5px solid var(--sn-color-border-green) !important; +} + +table.needs_style_red_border { + border: 5px solid var(--sn-color-border-red) !important; +} + +table.needs_style_yellow_border { + border: 5px solid var(--sn-color-border-yellow) !important; +} + +table.needs_style_blue_border { + border: 5px solid var(--sn-color-border-blue) !important; +} + +table.needs_style_discreet_border { + border: 5px solid var(--sn-color-border-lightgray) !important; +} + +table.needs_style_green_bar { + background: linear-gradient(to right, transparent 90%, var(--sn-bar-green) 10%); +} + +table.needs_style_red_bar { + background: linear-gradient(to right, transparent 90%, var(--sn-bar-red) 10%); +} + +table.needs_style_orange_bar { + background: linear-gradient(to right, transparent 90%, var(--sn-bar-orange) 10%); +} + +table.needs_style_yellow_bar { + background: linear-gradient(to right, transparent 90%, var(--sn-bar-yellow) 10%); +} + +table.needs_style_blue_bar { + background: linear-gradient(to right, transparent 90%, var(--sn-bar-blue) 10%); +} + +/* ***************** + layout debug view + ***************** + +- debug_on_layout_btn is set when collapsed.startswith("Debug view") +- debug_off_layout_btn is set when visible.startswith("Debug view") +*/ + +.debug_on_layout_btn, +.debug_off_layout_btn { + border: 2px solid #000; + width: fit-content; + padding: 3px 6px; + border-radius: 4px; +} + +.debug_on_layout_btn:before { + content: "Hide debugger"; + color: #f43333; + font-size: large; + font-weight: 400; + margin-top: 3px; + cursor: pointer; + outline: none; +} + +.debug_on_layout_btn:after { + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='25' height='20' viewBox='0 0 24 24' fill='none' stroke='%23f43333' stroke-width='2.0' stroke-linecap='round' stroke-linejoin='round' class='feather feather-eye-off'%3E%3Cpath d='M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24'%3E%3C/path%3E%3Cline x1='1' y1='1' x2='23' y2='23'%3E%3C/line%3E%3C/svg%3E"); + color: #f43333; + font-size: large; + font-weight: 400; + margin-top: 3px; + cursor: pointer; + outline: none; +} + +.debug_off_layout_btn:before { + content: "Show debugger"; + color: #0dd3f5; + font-size: large; + font-weight: 400; + margin-top: 3px; + cursor: pointer; + outline: none; +} + +.debug_off_layout_btn:after { + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='25' height='20' viewBox='0 0 24 24' fill='none' stroke='%230dd3f5' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' class='feather feather-eye'%3E%3Cpath d='M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z'%3E%3C/path%3E%3Ccircle cx='12' cy='12' r='3'%3E%3C/circle%3E%3C/svg%3E"); + ; + color: #0dd3f5; + font-size: large; + font-weight: 400; + margin-top: 3px; + cursor: pointer; + outline: none; +} \ No newline at end of file diff --git a/sphinx_needs/css/common/need_toggle.css b/sphinx_needs/css/common/need_toggle.css new file mode 100644 index 000000000..a1bfbb47f --- /dev/null +++ b/sphinx_needs/css/common/need_toggle.css @@ -0,0 +1,26 @@ +/* +The toggle class appears to be only used in sphinx_needs/directives/needimport_template.rst, +but it is not clear if this is ever actually used, or what JS it is supposed to be used with it. +*/ + +.toggle .header { + display: block; + clear: both; +} + +.toggle .header p { + display: inline; +} + +.toggle .header:after { + content: " ▷"; +} + +.toggle .header.open:after { + content: " ▽"; +} + +div.need div.toggle div.line-block { + margin-top: 0px; + margin-left: 30px; +} diff --git a/sphinx_needs/css/common/needstable.css b/sphinx_needs/css/common/needstable.css new file mode 100644 index 000000000..1ea93cf7c --- /dev/null +++ b/sphinx_needs/css/common/needstable.css @@ -0,0 +1,65 @@ +/* These are used by the needtable directive +to style the table representation of the needs. +*/ + +table.NEEDS_TABLE, +table.NEEDS_DATATABLES { + display: table; + overflow-x: auto; + white-space: normal; + width: 100%; + /* If this is set, col->width does not work any more*/ + /*max-width: -moz-fit-content;*/ + /*max-width: fit-content;*/ + margin: 0 auto; +} + +div.needstable_wrapper { + width: 100%; + overflow-x: auto; + padding: 0; +} + +/* These are "overrides" for CSS added by the bundled https://datatables.net JS package */ + +table.dataTable { + border-collapse: collapse; + border: none; +} + +div.dataTables_length { + margin-bottom: 10px; +} + +div.dataTables_wrapper{ + overflow-x: auto; + padding: 0px 5px; /*Space needed for table borders */ +} + +.dataTables_wrapper .dataTables_paginate .paginate_button { + padding: 0.15em 0.75em; + background: none; +} + +.dataTables_wrapper .dataTables_paginate .paginate_button.current, +.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover { + background: none; +} + +div.dataTables_length select { + background: none; +} + +div.dt-buttons button { + padding: 0.1em 1em; + border: 1px solid #999; + border-radius: 2px; + font-size: 0.88em; + line-height: inherit; + color: inherit; + white-space: nowrap; + overflow: hidden; + background-color: inherit; + background-image: none; +} + diff --git a/sphinx_needs/css/dark/dark.css b/sphinx_needs/css/dark/dark.css deleted file mode 100644 index acd5d3ffd..000000000 --- a/sphinx_needs/css/dark/dark.css +++ /dev/null @@ -1,151 +0,0 @@ -table.need { - margin-bottom: 10px; - background-color: #333; - border: 1px solid #555; - width: 100%; -} - -table.need td { - border: none; -} -table.need tr.head { - background-color: rgba(0,0,0,0.1); - border-bottom: 1px solid #555; -} - -table.need tr.meta { - border-bottom: 1px solid #555; - font-size: smaller; -} - -table.need tr.footer { - border-top: 1px solid #555; - font-size: small; -} - -table.need a { - border-bottom: none; -} - - - - -/* DataTable layout*/ -table.dataTable { - border-collapse: collapse; - border: none; -} - -div.dataTables_length { - margin-bottom: 10px; -} - -.dataTables_wrapper .dataTables_paginate .paginate_button { - padding: 0.15em 0.75em; - background: none; -} - -.dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover { - background: none; - color: inherit !important; -} - -.dataTables_wrapper .dataTables_paginate .paginate_button { - color: inherit !important; - border: none; -} - -.dataTables_wrapper .dataTables_paginate .paginate_button:hover { - border: none; - background: inherit; -} - -div.dataTables_length select { - background: none; -} - -.dataTables_wrapper .dataTables_length, .dataTables_wrapper .dataTables_filter, .dataTables_wrapper .dataTables_info, .dataTables_wrapper .dataTables_processing, .dataTables_wrapper .dataTables_paginate { - color: inherit; -} - -table.dataTable tbody tr { - background-color: inherit; -} - -div.dataTables_length select { - background: none; - color: inherit; - border: none; -} - -div.dataTables_length select option{ - background: #333; - color: inherit; - border: none; -} - -div.dataTables_filter input { - background: inherit; - color: inherit; - border: 1px solid #666; -} - -div.dataTables_filter input:focus { - outline: none; -} - -table.dataTable thead th, table.dataTable thead td { - border-bottom: inherit; -} - -/*DataTables Download Buttons*/ -div.dt-buttons { - margin-left: 10%; -} - -div.dt-buttons button { - padding: 0.1em 1em; - border: 1px solid #999; - border-radius: 2px; - font-size: 0.88em; - line-height: inherit; - color: inherit; - white-space: nowrap; - overflow: hidden; - background-color: inherit; - background-image: none; -} - -button.dt-button:hover:not(.disabled), div.dt-button:hover:not(.disabled), a.dt-button:hover:not(.disabled) { - background-color: inherit; - background-image: none; - border: inherit; -} - -/*DataTables Column visibility Select list*/ -div.dt-button-collection { - background-color: #333; -} - -/* Button active*/ -div.dt-button-collection button.dt-button:active:not(.disabled), div.dt-button-collection button.dt-button.active:not(.disabled), div.dt-button-collection div.dt-button:active:not(.disabled), div.dt-button-collection div.dt-button.active:not(.disabled), div.dt-button-collection a.dt-button:active:not(.disabled), div.dt-button-collection a.dt-button.active:not(.disabled) { - background: #444 none; - box-shadow: none; -} - -/* Button active hover*/ -button.dt-button:hover:not(.disabled), div.dt-button:hover:not(.disabled), a.dt-button:hover:not(.disabled) { - background: #333 none; - box-shadow: none; -} - -/* Button deactivated hover*/ -button.dt-button:active:not(.disabled):hover:not(.disabled), button.dt-button.active:not(.disabled):hover:not(.disabled), div.dt-button:active:not(.disabled):hover:not(.disabled), div.dt-button.active:not(.disabled):hover:not(.disabled), a.dt-button:active:not(.disabled):hover:not(.disabled), a.dt-button.active:not(.disabled):hover:not(.disabled) { - background: #555 none; - box-shadow: none; -} - -/* DataTablesScrollWrapper*/ -div.DTS div.dataTables_scrollBody { - background: inherit; -} diff --git a/sphinx_needs/css/dark/layouts.css b/sphinx_needs/css/dark/layouts.css deleted file mode 100644 index 9867deaba..000000000 --- a/sphinx_needs/css/dark/layouts.css +++ /dev/null @@ -1,93 +0,0 @@ -/* ******************* */ -/* FOCUS based layouts */ -/* ******************* */ -table.needs_layout_focus_l td.side { - text-orientation: upright; - writing-mode: sideways-lr; - font-size: small; -} - -table.needs_layout_focus_r td.side { - text-orientation: upright; - writing-mode: sideways-rl; - font-size: small; -} - -/* ********************** */ -/* COMPLETE based layouts */ -/* ********************** */ -table.needs_layout_complete td.head_left { - text-align: left; - background-color: rgba(0,0,0,0.1); - font-size: smaller; -} - -table.needs_layout_complete td.head_center { - text-align: center; - font-weight: bold; -} - -table.needs_layout_complete td.head_right { - text-align: right; - background-color: rgba(0,0,0,0.1); - font-size: smaller; -} - -table.needs_layout_complete tr.footer { - background-color: rgba(0,0,0,0.1); -} - -table.needs_layout_complete td.footer_right { - text-align: right; -} - -table.needs_layout_complete td.footer { - text-align: center; -} - -.debug_on_layout_btn, .debug_off_layout_btn { - border: 2px solid #000; - width: fit-content; - padding: 3px 6px; - border-radius: 4px; -} - -.debug_on_layout_btn:before{ - content: "Hide debugger"; - color: #f43333; - font-size: large; - font-weight: 400; - margin-top: 3px; - cursor: pointer; - outline: none; -} - -.debug_on_layout_btn:after{ - content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='25' height='20' viewBox='0 0 24 24' fill='none' stroke='%23f43333' stroke-width='2.0' stroke-linecap='round' stroke-linejoin='round' class='feather feather-eye-off'%3E%3Cpath d='M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24'%3E%3C/path%3E%3Cline x1='1' y1='1' x2='23' y2='23'%3E%3C/line%3E%3C/svg%3E"); - color: #f43333; - font-size: large; - font-weight: 400; - margin-top: 3px; - cursor: pointer; - outline: none; -} - -.debug_off_layout_btn:before{ - content: "Show debugger"; - color: #0dd3f5; - font-size: large; - font-weight: 400; - margin-top: 3px; - cursor: pointer; - outline: none; -} - -.debug_off_layout_btn:after{ - content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='25' height='20' viewBox='0 0 24 24' fill='none' stroke='%230dd3f5' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' class='feather feather-eye'%3E%3Cpath d='M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z'%3E%3C/path%3E%3Ccircle cx='12' cy='12' r='3'%3E%3C/circle%3E%3C/svg%3E");; - color: #0dd3f5; - font-size: large; - font-weight: 400; - margin-top: 3px; - cursor: pointer; - outline: none; -} diff --git a/sphinx_needs/css/dark/styles.css b/sphinx_needs/css/dark/styles.css deleted file mode 100644 index 164fa3af6..000000000 --- a/sphinx_needs/css/dark/styles.css +++ /dev/null @@ -1,121 +0,0 @@ -/*Colors based on https://flatuicolors.com/palette/se*/ - -/* ********************* */ -/* Full need table color */ -/* ********************* */ -table.needs_style_gray, -table.needs_style_gray tr, -table.needs_style_gray td { - background-color: #333; -} - -/* CLEAN*/ -table.needs_style_clean, -table.needs_style_clean tr, -table.needs_style_clean td{ - margin-bottom: 10px; - border: none !important; - background: None !important; - padding: 0; - box-shadow: None; -} - -table.needs_style_clean { - width: 100%; -} - -/* DISCREET */ -table.needs_style_discreet, -table.needs_style_discreet tr.need, -table.needs_style_discreet td.need { - background-color: rgba(255,255,255,0.1) !important; -} - - -/* GREEN */ -table.needs_style_green, -table.needs_style_green tr.need, -table.needs_style_green td.need, -table.needs_style_implemented, -table.needs_style_implemented tr.need, -table.needs_style_implemented td.need { - background-color: #04723c !important; -} - -/* RED */ -table.needs_style_red, -table.needs_style_red tr.need, -table.needs_style_red td.need, -table.needs_style_open, -table.needs_style_open tr.need, -table.needs_style_open td.need { - background-color: #81201b !important; -} - -/* YELLOW */ -table.needs_style_yellow, -table.needs_style_yellow tr.need, -table.needs_style_yellow td.need, -table.needs_style_in_progress, -table.needs_style_in_progress tr.need, -table.needs_style_in_progress td.need { - background-color: #a97c32 !important; -} - -/* BLUE*/ -table.needs_style_blue, -table.needs_style_blue tr.need, -table.needs_style_blue td.need { - background-color: #096285 !important; -} - -/* **************************** */ -/* Border only need table color */ -/* **************************** */ -table.needs_style_green_border { - border: 5px solid #04723c !important; -} - -table.needs_style_red_border { - border: 5px solid #81201b !important; -} - -table.needs_style_yellow_border { - border: 5px solid #a97c32 !important; -} - -table.needs_style_blue_border { - border: 5px solid #096285 !important; -} - -table.needs_style_discreet_border { - border: 5px solid rgba(255,255,255,0.2) !important; -} - -/* ******************************************************* */ -/* Bar on right side that takes 10 % of total table width */ -/* ******************************************************* */ - -table.needs_style_green_bar { - background: linear-gradient(to right, transparent 90%, #05c46b 10%); -} - -table.needs_style_red_bar { - background: linear-gradient(to right, transparent 90%, #ff3f34 10%); -} - -table.needs_style_orange_bar { - background: linear-gradient(to right, transparent 90%, #e67e22 10%); -} - -table.needs_style_yellow_bar { - background: linear-gradient(to right, transparent 90%, #ffc048 10%); -} - -table.needs_style_blue_bar { - background: linear-gradient(to right, transparent 90%, #0fbcf9 10%); -} - -.collapse_is_hidden { - display: none; -} \ No newline at end of file diff --git a/sphinx_needs/css/grids.css b/sphinx_needs/css/grids.css deleted file mode 100644 index 8b1378917..000000000 --- a/sphinx_needs/css/grids.css +++ /dev/null @@ -1 +0,0 @@ - diff --git a/sphinx_needs/css/modern/layouts.css b/sphinx_needs/css/modern/layouts.css deleted file mode 100644 index 35b68f670..000000000 --- a/sphinx_needs/css/modern/layouts.css +++ /dev/null @@ -1,93 +0,0 @@ -/* ******************* */ -/* FOCUS based layouts */ -/* ******************* */ -table.needs_layout_focus_l td.side { - text-orientation: upright; - writing-mode: sideways-lr; - font-size: small; -} - -table.needs_layout_focus_r td.side { - text-orientation: upright; - writing-mode: sideways-rl; - font-size: small; -} - -/* ********************** */ -/* COMPLETE based layouts */ -/* ********************** */ -table.needs_layout_complete td.head_left { - text-align: left; - background-color: rgba(0,0,0,0.1); - font-size: smaller; -} - -table.needs_layout_complete td.head_center { - text-align: center; - font-weight: bold; -} - -table.needs_layout_complete td.head_right { - text-align: right; - background-color: rgba(0,0,0,0.1); - font-size: smaller; -} - -table.needs_layout_complete tr.footer { - background-color: rgba(0,0,0,0.1); -} - -table.needs_layout_complete td.footer_right { - text-align: right; -} - -table.needs_layout_complete td.footer { - text-align: center; -} - -.debug_on_layout_btn, .debug_off_layout_btn { - border: 2px solid #000; - width: fit-content; - padding: 3px 6px; - border-radius: 4px; -} - -.debug_on_layout_btn:before{ - content: "Hide debugger"; - color: #f43333; - font-size: large; - font-weight: 400; - margin-top: 3px; - cursor: pointer; - outline:none; - } - -.debug_on_layout_btn:after{ - content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='25' height='20' viewBox='0 0 24 24' fill='none' stroke='%23f43333' stroke-width='2.0' stroke-linecap='round' stroke-linejoin='round' class='feather feather-eye-off'%3E%3Cpath d='M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24'%3E%3C/path%3E%3Cline x1='1' y1='1' x2='23' y2='23'%3E%3C/line%3E%3C/svg%3E"); - color: #f43333; - font-size: large; - font-weight: 400; - margin-top: 3px; - cursor: pointer; - outline:none; -} - -.debug_off_layout_btn:before{ - content: "Show debugger"; - color: #0dd3f5; - font-size: large; - font-weight: 400; - margin-top: 3px; - cursor: pointer; - outline:none; - } - -.debug_off_layout_btn:after{ - content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='25' height='20' viewBox='0 0 24 24' fill='none' stroke='%230dd3f5' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' class='feather feather-eye'%3E%3Cpath d='M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z'%3E%3C/path%3E%3Ccircle cx='12' cy='12' r='3'%3E%3C/circle%3E%3C/svg%3E");; - color: #0dd3f5; - font-size: large; - font-weight: 400; - margin-top: 3px; - cursor: pointer; - outline:none; - } diff --git a/sphinx_needs/css/modern/modern.css b/sphinx_needs/css/modern/modern.css deleted file mode 100644 index 9984ab44d..000000000 --- a/sphinx_needs/css/modern/modern.css +++ /dev/null @@ -1,28 +0,0 @@ -table.need { - margin-bottom: 10px; - background-color: #eee; - border: 1px solid #888; - width: 100%; -} - -table.need td { - border: none; -} -table.need tr.head { - background-color: rgba(0,0,0,0.1); - border-bottom: 1px solid #888; -} - -table.need tr.meta { - border-bottom: 1px solid #888; - font-size: smaller; -} - -table.need tr.footer { - border-top: 1px solid #888; - font-size: small; -} - -table.need a { - border-bottom: none; -} diff --git a/sphinx_needs/css/modern/styles.css b/sphinx_needs/css/modern/styles.css deleted file mode 100644 index 3da446603..000000000 --- a/sphinx_needs/css/modern/styles.css +++ /dev/null @@ -1,129 +0,0 @@ -/*Colors based on https://flatuicolors.com/palette/se*/ - -/* ********************* */ -/* Full need table color */ -/* ********************* */ -table.needs_style_gray, -table.needs_style_gray tr, -table.needs_style_gray td { - background-color: #eee; -} - -table.needs_style_clean, -table.needs_style_clean tr, -table.needs_style_clean td{ - margin-bottom: 10px; - border: none !important; - background: None !important; - padding: 0; - box-shadow: None; -} - -table.needs_style_clean { - width: 100%; -} - -/* DISCREET */ -table.needs_style_discreet, -table.needs_style_discreet tr.need, -table.needs_style_discreet td.need { - background-color: rgba(0,0,0,0.004) !important; - box-shadow: None; -} - - -table.needs_style_green, -table.needs_style_green tr.need, -table.needs_style_green td.need, -table.needs_style_implemented, -table.needs_style_implemented tr.need, -table.needs_style_implemented td.need, -tr.needs_green, -tr.needs_implemented { - background-color: #05c46b !important; -} - -table.needs_style_red, -table.needs_style_red tr.need, -table.needs_style_red td.need, -table.needs_style_open, -table.needs_style_open tr.need, -table.needs_style_open td.need, -tr.needs_red, -tr.needs_open { - background-color: #ff3f34 !important; -} - -table.needs_style_yellow, -table.needs_style_yellow tr.need, -table.needs_style_yellow td.need, -table.needs_style_in_progress, -table.needs_style_in_progress tr.need, -table.needs_style_in_progress td.need -tr.needs_yellow, -tr.needs_in_progress { - background-color: #ffc048 !important; -} - -table.needs_style_blue, -table.needs_style_blue tr.need, -table.needs_style_blue td.need, -tr.needs_blue { - background-color: #0fbcf9 !important; -} - -/* **************************** */ -/* Border only need table color */ -/* **************************** */ -table.needs_style_green_border, -tr.needs_green_border { - border: 5px solid #05c46b !important; -} - -table.needs_style_red_border, -tr.needs_red_border{ - border: 5px solid #ff3f34 !important; -} - -table.needs_style_yellow_border, -tr.needs_yellow_border{ - border: 5px solid #ffc048 !important; -} - -table.needs_style_blue_border, -tr.needs_blue_border { - border: 5px solid #0fbcf9 !important; -} - -table.needs_style_discreet_border, -table.needs_style_discreet_border tr.need, -table.needs_style_discreet_border td.need { - border: 1px solid rgba(0,0,0,0.05) !important; -} - -/* ******************************************************* */ -/* Bar on right side that takes 10 % of total table width */ -/* ******************************************************* */ - -table.needs_style_green_bar { - background: linear-gradient(to right, transparent 90%, #05c46b 10%); -} - -table.needs_style_red_bar { - background: linear-gradient(to right, transparent 90%, #ff3f34 10%); -} - -table.needs_style_orange_bar { - background: linear-gradient(to right, transparent 90%, #e67e22 10%); -} - -table.needs_style_yellow_bar { - background: linear-gradient(to right, transparent 90%, #ffc048 10%); -} - -table.needs_style_blue_bar { - background: linear-gradient(to right, transparent 90%, #0fbcf9 10%); -} -.collapse_is_hidden { - display: none; -} \ No newline at end of file diff --git a/sphinx_needs/css/themes/blank.css b/sphinx_needs/css/themes/blank.css new file mode 100644 index 000000000..5f52ce893 --- /dev/null +++ b/sphinx_needs/css/themes/blank.css @@ -0,0 +1,31 @@ +/* Colors based on https://flatuicolors.com/palette/se */ + +:root { + --sn-color-bg-gray: #333; + --sn-color-bg-lightgray: rgba(255,255,255,0.1); + --sn-color-bg-green: #05c46b; + --sn-color-bg-red: #ff3f34; + --sn-color-bg-yellow: #ffc048; + --sn-color-bg-blue: #0fbcf9; + + --sn-color-border-lightgray: rgba(255,255,255,0.2); + --sn-color-border-green: #05c46b; + --sn-color-border-red: #ff3f34; + --sn-color-border-yellow: #ffc048; + --sn-color-border-blue: #0fbcf9; + + --sn-color-bar-green: #05c46b; + --sn-color-bar-red: #ff3f34; + --sn-color-bar-yellow: #ffc048; + --sn-color-bar-orange: #e67e22; + --sn-color-bar-blue: #0fbcf9; + + --sn-color-need-border: #555; + --sn-color-need-bg: #eee; + --sn-color-need-bg-head: rgba(0,0,0,0.1); + + --sn-color-complete-bg-head: rgba(0,0,0,0.1); + --sn-color-complete-bg-foot: rgba(0,0,0,0.1); + + --sn-color-forbidden-dead-link: #dc3545; +} diff --git a/sphinx_needs/css/themes/dark.css b/sphinx_needs/css/themes/dark.css new file mode 100644 index 000000000..de6d6247b --- /dev/null +++ b/sphinx_needs/css/themes/dark.css @@ -0,0 +1,135 @@ +/* Colors based on https://flatuicolors.com/palette/se*/ + +:root { + --sn-color-bg-gray: #333; + --sn-color-bg-lightgray: rgba(255,255,255,0.1); + --sn-color-bg-green: #04723c; + --sn-color-bg-red: #81201b; + --sn-color-bg-yellow: #a97c32; + --sn-color-bg-blue: #096285; + + --sn-color-border-lightgray: rgba(255,255,255,0.2); + --sn-color-border-green: #04723c; + --sn-color-border-red: #81201b; + --sn-color-border-yellow: #a97c32; + --sn-color-border-blue: #096285; + + --sn-color-bar-green: #05c46b; + --sn-color-bar-red: #ff3f34; + --sn-color-bar-yellow: #ffc048; + --sn-color-bar-orange: #e67e22; + --sn-color-bar-blue: #0fbcf9; + + --sn-color-need-border: #888; + --sn-color-need-bg: #333; + --sn-color-need-bg-head: rgba(0,0,0,0.1); + + --sn-color-complete-bg-head: rgba(0,0,0,0.1); + --sn-color-complete-bg-foot: rgba(0,0,0,0.1); + + --sn-color-forbidden-dead-link: #dc3545; +} + + +/* DataTable layout*/ +/* TODO this should not be part of the theme */ +.dataTables_wrapper .dataTables_paginate .paginate_button.current, +.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover { + color: inherit !important; +} + +.dataTables_wrapper .dataTables_paginate .paginate_button { + color: inherit !important; +} + +.dataTables_wrapper .dataTables_paginate .paginate_button:hover { + border: none; + background: inherit; +} + +.dataTables_wrapper .dataTables_length, +.dataTables_wrapper .dataTables_filter, +.dataTables_wrapper .dataTables_info, +.dataTables_wrapper .dataTables_processing, +.dataTables_wrapper .dataTables_paginate { + color: inherit; +} + +table.dataTable tbody tr { + background-color: inherit; +} + +div.dataTables_length select { + color: inherit; + border: none; +} + +div.dataTables_length select option { + background: #333; + color: inherit; + border: none; +} + +div.dataTables_filter input { + background: inherit; + color: inherit; + border: 1px solid #666; +} + +div.dataTables_filter input:focus { + outline: none; +} + +table.dataTable thead th, table.dataTable thead td { + border-bottom: inherit; +} + +/*DataTables Download Buttons*/ + +button.dt-button:hover:not(.disabled), +div.dt-button:hover:not(.disabled), +a.dt-button:hover:not(.disabled) { + background-color: inherit; + background-image: none; + border: inherit; +} + +/*DataTables Column visibility Select list*/ +div.dt-button-collection { + background-color: #333; +} + +/* Button active*/ +div.dt-button-collection button.dt-button:active:not(.disabled), +div.dt-button-collection button.dt-button.active:not(.disabled), +div.dt-button-collection div.dt-button:active:not(.disabled), +div.dt-button-collection div.dt-button.active:not(.disabled), +div.dt-button-collection a.dt-button:active:not(.disabled), +div.dt-button-collection a.dt-button.active:not(.disabled) { + background: #444 none; + box-shadow: none; +} + +/* Button active hover*/ +button.dt-button:hover:not(.disabled), +div.dt-button:hover:not(.disabled), +a.dt-button:hover:not(.disabled) { + background: #333 none; + box-shadow: none; +} + +/* Button deactivated hover*/ +button.dt-button:active:not(.disabled):hover:not(.disabled), +button.dt-button.active:not(.disabled):hover:not(.disabled), +div.dt-button:active:not(.disabled):hover:not(.disabled), +div.dt-button.active:not(.disabled):hover:not(.disabled), +a.dt-button:active:not(.disabled):hover:not(.disabled), +a.dt-button.active:not(.disabled):hover:not(.disabled) { + background: #555 none; + box-shadow: none; +} + +/* DataTablesScrollWrapper*/ +div.DTS div.dataTables_scrollBody { + background: inherit; +} diff --git a/sphinx_needs/css/themes/modern.css b/sphinx_needs/css/themes/modern.css new file mode 100644 index 000000000..22ab31884 --- /dev/null +++ b/sphinx_needs/css/themes/modern.css @@ -0,0 +1,31 @@ +/* Colors based on https://flatuicolors.com/palette/se */ + +:root { + --sn-color-bg-gray: #eee; + --sn-color-bg-lightgray: rgba(0,0,0,0.004); + --sn-color-bg-green: #05c46b; + --sn-color-bg-red: #ff3f34; + --sn-color-bg-yellow: #ffc048; + --sn-color-bg-blue: #0fbcf9; + + --sn-color-border-lightgray: rgba(0,0,0,0.05); + --sn-color-border-green: #05c46b; + --sn-color-border-red: #ff3f34; + --sn-color-border-yellow: #ffc048; + --sn-color-border-blue: #0fbcf9; + + --sn-color-bar-green: #05c46b; + --sn-color-bar-red: #ff3f34; + --sn-color-bar-yellow: #ffc048; + --sn-color-bar-orange: #e67e22; + --sn-color-bar-blue: #0fbcf9; + + --sn-color-need-border: #555; + --sn-color-need-bg: #eee; + --sn-color-need-bg-head: rgba(0,0,0,0.1); + + --sn-color-complete-bg-head: rgba(0,0,0,0.1); + --sn-color-complete-bg-foot: rgba(0,0,0,0.1); + + --sn-color-forbidden-dead-link: #dc3545; +} diff --git a/sphinx_needs/defaults.py b/sphinx_needs/defaults.py index 5df8eddb4..a051b1dc7 100644 --- a/sphinx_needs/defaults.py +++ b/sphinx_needs/defaults.py @@ -227,5 +227,3 @@ NEEDEXTEND_NOT_ALLOWED_OPTIONS = ["id"] NEEDS_PROFILING = [x.upper() for x in os.environ.get("NEEDS_PROFILING", "").split(",")] - -NEEDS_TABLES_CLASSES = ["rtd-exclude-wy-table", "no-sphinx-material-strip"] diff --git a/sphinx_needs/environment.py b/sphinx_needs/environment.py index 786ea2666..5724c385e 100644 --- a/sphinx_needs/environment.py +++ b/sphinx_needs/environment.py @@ -1,179 +1,79 @@ from __future__ import annotations -from pathlib import Path, PurePosixPath -from typing import Iterable +from pathlib import Path from jinja2 import Environment, PackageLoader, select_autoescape +from sphinx import version_info as sphinx_version from sphinx.application import Sphinx from sphinx.environment import BuildEnvironment -from sphinx.util.console import brown # type: ignore[attr-defined] -from sphinx.util.osutil import copyfile +from sphinx.util.fileutil import copy_asset, copy_asset_file from sphinx_needs.config import NeedsSphinxConfig from sphinx_needs.utils import logger -try: - from sphinx.util.display import status_iterator -except ImportError: - # will be removed in Sphinx 8.0 - from sphinx.util import status_iterator # type: ignore +_STATIC_DIR_NAME = "_static" -IMAGE_DIR_NAME = "_static" - -def safe_add_file(filename: Path, app: Sphinx) -> None: - """ - Adds files to builder resources only, if the given filename was not already - registered. - - Needed mainly for tests to avoid multiple registration of the same file and - therefore also multiple execution of e.g. a javascript file during page load. - - :param filename: filename to remove - :param app: app object - :return: None - """ - builder = app.builder - # Use PurePosixPath, so that the path can be used as "web"-path - pure_path = PurePosixPath(filename) - static_data_file = PurePosixPath("_static") / pure_path - - if pure_path.suffix == ".js": - # Make sure the calculated (posix)-path is not already registered as "web"-path - if ( - hasattr(builder, "script_files") - and str(static_data_file) not in builder.script_files - ): - app.add_js_file(str(pure_path)) - elif pure_path.suffix == ".css": - if ( - hasattr(builder, "css_files") - and str(static_data_file) not in builder.css_files - ): - app.add_css_file(str(pure_path)) - else: - raise NotImplementedError( - f"File type {pure_path.suffix} not support by save_add_file" - ) - - -def safe_remove_file(filename: Path, app: Sphinx) -> None: - """ - Removes a given resource file from builder resources. - - Needed mostly during test, if multiple sphinx-build are started. During these tests - js/cass-files are not cleaned, so a css_file from run A is still registered in run - B. - - :param filename: filename to remove - :param app: app object - :return: None - """ - static_data_file = PurePosixPath(Path("_static") / filename) - - def _remove_file(file: PurePosixPath, attribute: str) -> None: - files = getattr(app.builder, attribute, []) - if str(file) in files: - files.remove(str(file)) - - attributes = { - ".js": "script_files", - ".css": "css_files", - } - - attribute = attributes.get(filename.suffix) - if attribute: - _remove_file(static_data_file, attribute) - - -# Base implementation from sphinxcontrib-images -# https://github.com/spinus/sphinxcontrib-images/blob/master/sphinxcontrib/images.py#L203 -def install_styles_static_files(app: Sphinx, env: BuildEnvironment) -> None: - builder = app.builder - # Do not copy static_files for our "needs" builder - if builder.name == "needs": +def _add_css_file(app: Sphinx, rel_path: Path) -> None: + # note this deduplication is already done in Sphinx v7.2.1+ + # https://github.com/sphinx-doc/sphinx/commit/0c22d9c9ff4a0a6b3ce2f0aa6bc591b4525b4163 + rel_str = rel_path.as_posix() + if sphinx_version < (7, 2) and f"_static/{rel_str}" in getattr( + app.builder, "css_files", [] + ): return + app.add_css_file(rel_str) - statics_dir = Path(builder.outdir) / IMAGE_DIR_NAME - css_root = Path(__file__).parent / "css" - dest_dir = statics_dir / "sphinx-needs" - def _find_css_files() -> Iterable[Path]: - needs_css = NeedsSphinxConfig(app.config).css - for theme in ["modern", "dark", "blank"]: - if needs_css == f"{theme}.css": - css_dir = css_root / theme - return [f for f in css_dir.glob("**/*") if f.is_file()] - return [Path(needs_css)] - - files_to_copy = [Path("common.css")] - files_to_copy.extend(_find_css_files()) - - # Be sure no "old" css layout is already set - for theme in ["common", "modern", "dark", "blank"]: - path = Path("sphinx-needs") / f"{theme}.css" - safe_remove_file(path, app) - - for source_file_path in status_iterator( - files_to_copy, - "Copying static files for sphinx-needs custom style support...", - brown, - length=len(files_to_copy), - stringify_func=lambda x: x.name, +def _add_js_file(app: Sphinx, rel_path: Path) -> None: + # note this deduplication is already done in Sphinx v7.2.1+ + # https://github.com/sphinx-doc/sphinx/commit/0c22d9c9ff4a0a6b3ce2f0aa6bc591b4525b4163 + rel_str = rel_path.as_posix() + if sphinx_version < (7, 2) and f"_static/{rel_str}" in getattr( + app.builder, "script_files", [] ): - source_file_path = Path(source_file_path) - - if not source_file_path.is_absolute(): - source_file_path = css_root / source_file_path - - if not source_file_path.exists(): - source_file_path = css_root / "blank" / "blank.css" - logger.warning( - f"{source_file_path} not found. Copying sphinx-internal blank.css [needs]", - type="needs", - ) - - dest_file = dest_dir / source_file_path.name - dest_dir.mkdir(exist_ok=True) - - copyfile(str(source_file_path), str(dest_file)) - - relative_path = Path(dest_file).relative_to(statics_dir) - safe_add_file(relative_path, app) + return + app.add_js_file(rel_str) -def install_static_files( - app: Sphinx, - source_dir: Path, - destination_dir: Path, - files_to_copy: list[Path], - message: str, -) -> None: +def install_styles_static_files(app: Sphinx, env: BuildEnvironment) -> None: builder = app.builder # Do not copy static_files for our "needs" builder if builder.name == "needs": return - for source_file_path in status_iterator( - files_to_copy, - message, - brown, - length=len(files_to_copy), - stringify_func=lambda x: Path(x).name, - ): - source_file = Path(source_file_path) - - if not source_file.is_absolute(): - raise OSError(f"Path must be absolute. Got: {source_file}") + logger.info("Copying static style files for sphinx-needs") - if not source_file.exists(): - raise OSError(f"File not found: {source_file}") + config = NeedsSphinxConfig(app.config) - relative_path = source_file.relative_to(source_dir) - destination_file = destination_dir / relative_path - destination_file.parent.mkdir(parents=True, exist_ok=True) + statics_dir = Path(builder.outdir) / _STATIC_DIR_NAME + dest_dir = statics_dir / "sphinx-needs" + css_root = Path(__file__).parent / "css" - copyfile(str(source_file), str(destination_file)) + # Add common css files + copy_asset( + str(css_root.joinpath("common")), + str(dest_dir.joinpath("common_css")), + lambda path: not path.endswith(".css"), + ) + for common_path in dest_dir.joinpath("common_css").glob("*.css"): + _add_css_file(app, common_path.relative_to(statics_dir)) + + # Add theme css file + if config.css in [f.name for f in css_root.joinpath("themes").glob("*.css")]: + copy_asset_file(str(css_root.joinpath("themes", config.css)), str(dest_dir)) + _add_css_file(app, dest_dir.joinpath(config.css).relative_to(statics_dir)) + elif Path(config.css).is_file(): + copy_asset_file(config.css, str(dest_dir)) + _add_css_file( + app, dest_dir.joinpath(Path(config.css).name).relative_to(statics_dir) + ) + else: + logger.warning( + f"needs_css not an existing file: {config.css} [needs.config]", + type="needs", + subtype="config", + ) def install_lib_static_files(app: Sphinx, env: BuildEnvironment) -> None: @@ -188,29 +88,21 @@ def install_lib_static_files(app: Sphinx, env: BuildEnvironment) -> None: if builder.name == "needs": return - statics_dir = Path(builder.outdir) / IMAGE_DIR_NAME + logger.info("Copying static files for sphinx-needs datatables support") + + statics_dir = Path(builder.outdir) / _STATIC_DIR_NAME source_dir = Path(__file__).parent / "libs" / "html" destination_dir = statics_dir / "sphinx-needs" / "libs" / "html" - files_to_copy = [f for f in source_dir.glob("**/*") if f.is_file()] - - install_static_files( - app, - source_dir, - destination_dir, - files_to_copy, - "Copying static files for sphinx-needs datatables support...", - ) + # "Copying static files for sphinx-needs datatables support..." + copy_asset(str(source_dir), str(destination_dir)) # Add the needed datatables js and css file lib_path = Path("sphinx-needs") / "libs" / "html" - for f in [ - "datatables.min.js", - "datatables_loader.js", - "datatables.min.css", - "sphinx_needs_collapse.js", - ]: - safe_add_file(lib_path / f, app) + _add_js_file(app, lib_path.joinpath("datatables.min.js")) + _add_js_file(app, lib_path.joinpath("datatables_loader.js")) + _add_css_file(app, lib_path.joinpath("datatables.min.css")) + _add_js_file(app, lib_path.joinpath("sphinx_needs_collapse.js")) def install_permalink_file(app: Sphinx, env: BuildEnvironment) -> None: diff --git a/sphinx_needs/layout.py b/sphinx_needs/layout.py index ad2a49b48..5ca9e12d3 100644 --- a/sphinx_needs/layout.py +++ b/sphinx_needs/layout.py @@ -235,7 +235,6 @@ def __init__( else: self.fromdocname = fromdocname - # For ReadTheDocs Theme we need to add 'rtd-exclude-wy-table'. classes = [ "need", "needs_grid_" + self.layout["grid"], diff --git a/tests/test_styles/test_style_blank.py b/tests/test_styles/test_style_blank.py index f4934b42b..2ae847e9e 100644 --- a/tests/test_styles/test_style_blank.py +++ b/tests/test_styles/test_style_blank.py @@ -1,8 +1,6 @@ from pathlib import Path import pytest -from sphinx import version_info -from sphinx.builders.html import StandaloneHTMLBuilder @pytest.mark.parametrize( @@ -11,15 +9,6 @@ indirect=True, ) def test_doc_style_blank(test_app): - # css_files is not cleared between test runs so css files get - # progressively added. This forces it to clear before re-building - if version_info >= (7, 2): - # TODO changed in sphinx 7.2 - if hasattr(StandaloneHTMLBuilder, "_css_files"): - del StandaloneHTMLBuilder._css_files[:] - elif hasattr(StandaloneHTMLBuilder, "css_files"): - del StandaloneHTMLBuilder.css_files[:] - app = test_app app.build() html = Path(app.outdir, "index.html").read_text() diff --git a/tests/test_styles/test_style_css_js_registration.py b/tests/test_styles/test_style_css_js_registration.py index fbbb73aa5..b774ad4af 100644 --- a/tests/test_styles/test_style_css_js_registration.py +++ b/tests/test_styles/test_style_css_js_registration.py @@ -33,12 +33,14 @@ def test_file_registration(tmp_path: Path, make_app: type[SphinxTestApp]): # Only check Sphinx-Needs files css_files = [ - x for x in sphinx_app.builder.css_files if x.startswith("_static/sphinx-needs") + x + for x in sphinx_app.builder.css_files + if x.filename.startswith("_static/sphinx-needs") ] script_files = [ x for x in sphinx_app.builder.script_files - if x.startswith("_static/sphinx-needs") + if x.filename.startswith("_static/sphinx-needs") ] css_run_1 = len(css_files) script_run_1 = len(script_files) @@ -54,12 +56,14 @@ def test_file_registration(tmp_path: Path, make_app: type[SphinxTestApp]): # Only check Sphinx-Needs files css_files = [ - x for x in sphinx_app.builder.css_files if x.startswith("_static/sphinx-needs") + x + for x in sphinx_app.builder.css_files + if x.filename.startswith("_static/sphinx-needs") ] script_files = [ x for x in sphinx_app.builder.script_files - if x.startswith("_static/sphinx-needs") + if x.filename.startswith("_static/sphinx-needs") ] css_run_2 = len(css_files) script_run_2 = len(script_files) diff --git a/tests/test_styles/test_style_custom.py b/tests/test_styles/test_style_custom.py index e2f392fd0..259fd793e 100644 --- a/tests/test_styles/test_style_custom.py +++ b/tests/test_styles/test_style_custom.py @@ -1,8 +1,6 @@ from pathlib import Path import pytest -from sphinx import version_info -from sphinx.builders.html import StandaloneHTMLBuilder @pytest.mark.parametrize( @@ -11,15 +9,6 @@ indirect=True, ) def test_doc_style_custom(test_app): - # css_files is not cleared between test runs so css files get - # progressively added. This forces it to clear before re-building - if version_info >= (7, 2): - # TODO changed in sphinx 7.2 - if hasattr(StandaloneHTMLBuilder, "_css_files"): - del StandaloneHTMLBuilder._css_files[:] - elif hasattr(StandaloneHTMLBuilder, "css_files"): - del StandaloneHTMLBuilder.css_files[:] - app = test_app app.build() html = Path(app.outdir, "index.html").read_text() diff --git a/tests/test_styles/test_style_modern.py b/tests/test_styles/test_style_modern.py index 6c9956216..79983eb8a 100644 --- a/tests/test_styles/test_style_modern.py +++ b/tests/test_styles/test_style_modern.py @@ -1,8 +1,6 @@ from pathlib import Path import pytest -from sphinx import version_info -from sphinx.builders.html import StandaloneHTMLBuilder @pytest.mark.parametrize( @@ -11,15 +9,6 @@ indirect=True, ) def test_doc_style_modern(test_app): - # css_files is not cleared between test runs so css files get - # progressively added. This forces it to clear before re-building - if version_info >= (7, 2): - # TODO changed in sphinx 7.2 - if hasattr(StandaloneHTMLBuilder, "_css_files"): - del StandaloneHTMLBuilder._css_files[:] - elif hasattr(StandaloneHTMLBuilder, "css_files"): - del StandaloneHTMLBuilder.css_files[:] - app = test_app app.build() html = Path(app.outdir, "index.html").read_text() diff --git a/tests/test_styles/test_style_unknown.py b/tests/test_styles/test_style_unknown.py index c934525a0..1cef8a7c4 100644 --- a/tests/test_styles/test_style_unknown.py +++ b/tests/test_styles/test_style_unknown.py @@ -1,28 +1,29 @@ from pathlib import Path import pytest -from sphinx import version_info -from sphinx.builders.html import StandaloneHTMLBuilder +from sphinx.util.console import strip_colors @pytest.mark.parametrize( "test_app", - [{"buildername": "html", "srcdir": "doc_test/doc_style_unknown"}], + [ + { + "buildername": "html", + "srcdir": "doc_test/doc_style_unknown", + "no_plantuml": True, + } + ], indirect=True, ) def test_doc_style_unknown(test_app): - # css_files is not cleared between test runs so css files get - # progressively added. This forces it to clear before re-building - if version_info >= (7, 2): - # TODO changed in sphinx 7.2 - if hasattr(StandaloneHTMLBuilder, "_css_files"): - del StandaloneHTMLBuilder._css_files[:] - elif hasattr(StandaloneHTMLBuilder, "css_files"): - del StandaloneHTMLBuilder.css_files[:] - app = test_app app.build() + + warnings = strip_colors(app._warning.getvalue()).splitlines() + assert warnings == [ + "WARNING: needs_css not an existing file: UNKNOWN.css [needs.config]" + ] + html = Path(app.outdir, "index.html").read_text() - assert "blank.css" in html assert "modern.css" not in html assert "UNKNOWN.css" not in html