sphinx-filter-tabs 1.2.2__py3-none-any.whl → 1.2.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- filter_tabs/renderer.py +30 -43
- filter_tabs/static/filter_tabs.css +27 -1
- filter_tabs/static/filter_tabs.js +28 -87
- {sphinx_filter_tabs-1.2.2.dist-info → sphinx_filter_tabs-1.2.5.dist-info}/METADATA +1 -1
- sphinx_filter_tabs-1.2.5.dist-info/RECORD +11 -0
- sphinx_filter_tabs-1.2.2.dist-info/RECORD +0 -11
- {sphinx_filter_tabs-1.2.2.dist-info → sphinx_filter_tabs-1.2.5.dist-info}/WHEEL +0 -0
- {sphinx_filter_tabs-1.2.2.dist-info → sphinx_filter_tabs-1.2.5.dist-info}/entry_points.txt +0 -0
- {sphinx_filter_tabs-1.2.2.dist-info → sphinx_filter_tabs-1.2.5.dist-info}/licenses/LICENSE +0 -0
- {sphinx_filter_tabs-1.2.2.dist-info → sphinx_filter_tabs-1.2.5.dist-info}/top_level.txt +0 -0
filter_tabs/renderer.py
CHANGED
|
@@ -46,31 +46,31 @@ class ContentTypeInferrer:
|
|
|
46
46
|
(['development', 'staging', 'production', 'test', 'local'], 'environment'),
|
|
47
47
|
(['source', 'binary', 'docker', 'manual', 'automatic'], 'installation method'),
|
|
48
48
|
]
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
@classmethod
|
|
51
51
|
def infer_type(cls, tab_names: List[str]) -> str:
|
|
52
52
|
"""
|
|
53
53
|
Infer content type from a list of tab names.
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
Args:
|
|
56
56
|
tab_names: List of tab names to analyze
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
Returns:
|
|
59
59
|
Inferred content type string (e.g., 'programming language', 'operating system')
|
|
60
60
|
"""
|
|
61
61
|
lower_names = [name.lower() for name in tab_names]
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
# First pass: exact matches
|
|
64
64
|
for keywords, content_type in cls.PATTERNS:
|
|
65
65
|
if any(name in keywords for name in lower_names):
|
|
66
66
|
return content_type
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
# Second pass: substring matches
|
|
69
69
|
for keywords, content_type in cls.PATTERNS:
|
|
70
70
|
for name in lower_names:
|
|
71
71
|
if any(keyword in name for keyword in keywords):
|
|
72
72
|
return content_type
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
# Default fallback
|
|
75
75
|
return 'option'
|
|
76
76
|
|
|
@@ -92,53 +92,52 @@ class FilterTabsRenderer:
|
|
|
92
92
|
self.tab_data = tab_data
|
|
93
93
|
self.general_content = general_content
|
|
94
94
|
self.custom_legend = custom_legend
|
|
95
|
-
|
|
95
|
+
|
|
96
96
|
# 1. Load configuration first
|
|
97
97
|
self.config = FilterTabsConfig.from_sphinx_config(self.app.config)
|
|
98
|
-
|
|
98
|
+
|
|
99
99
|
# 2. Safely initialize the counter on the environment if it doesn't exist
|
|
100
100
|
if not hasattr(self.env, 'filter_tabs_counter'):
|
|
101
101
|
self.env.filter_tabs_counter = 0
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
# 3. Increment the counter for this new tab group
|
|
104
104
|
self.env.filter_tabs_counter += 1
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
# 4. Generate the unique group ID and the ID generator instance
|
|
107
107
|
self.group_id = f"filter-group-{self.env.filter_tabs_counter}"
|
|
108
108
|
self.id_gen = IDGenerator(self.group_id)
|
|
109
|
-
|
|
109
|
+
|
|
110
110
|
# 5. Perform debug logging now that config and group_id are set
|
|
111
111
|
if self.config.debug_mode:
|
|
112
112
|
logger.info(f"Initialized new tab group with id: '{self.group_id}'")
|
|
113
113
|
|
|
114
114
|
def render_html(self) -> List[nodes.Node]:
|
|
115
|
-
"""Render HTML with
|
|
115
|
+
"""Render HTML with CSS-only approach (no inline styles)."""
|
|
116
116
|
if self.config.debug_mode:
|
|
117
117
|
logger.info(f"Rendering filter-tabs group {self.group_id}")
|
|
118
118
|
|
|
119
|
-
css_node = self._generate_compatible_css()
|
|
120
|
-
|
|
121
119
|
container_attrs = self._get_container_attributes()
|
|
122
120
|
container = ContainerNode(**container_attrs)
|
|
123
121
|
|
|
124
122
|
fieldset = self._create_fieldset()
|
|
125
123
|
container.children = [fieldset]
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
|
|
125
|
+
# FIXED: No more inline CSS generation
|
|
126
|
+
return [container]
|
|
128
127
|
|
|
129
128
|
def render_fallback(self) -> List[nodes.Node]:
|
|
130
129
|
"""Render for non-HTML builders (e.g., LaTeX)."""
|
|
131
130
|
output_nodes: List[nodes.Node] = []
|
|
132
|
-
|
|
131
|
+
|
|
133
132
|
if self.general_content:
|
|
134
133
|
output_nodes.extend(copy.deepcopy(self.general_content))
|
|
135
|
-
|
|
134
|
+
|
|
136
135
|
for tab in self.tab_data:
|
|
137
136
|
admonition = nodes.admonition()
|
|
138
137
|
admonition += nodes.title(text=tab.name)
|
|
139
138
|
admonition.extend(copy.deepcopy(tab.content))
|
|
140
139
|
output_nodes.append(admonition)
|
|
141
|
-
|
|
140
|
+
|
|
142
141
|
return output_nodes
|
|
143
142
|
|
|
144
143
|
def _get_container_attributes(self) -> Dict[str, Any]:
|
|
@@ -150,42 +149,31 @@ class FilterTabsRenderer:
|
|
|
150
149
|
'style': self.config.to_css_properties()
|
|
151
150
|
}
|
|
152
151
|
|
|
153
|
-
|
|
154
|
-
"""Generate CSS using sibling selectors to show/hide panels."""
|
|
155
|
-
css_rules = []
|
|
156
|
-
for i, tab in enumerate(self.tab_data):
|
|
157
|
-
radio_id = self.id_gen.radio_id(i)
|
|
158
|
-
panel_id = self.id_gen.panel_id(i)
|
|
159
|
-
css_rules.append(
|
|
160
|
-
f"#{radio_id}:checked ~ .{SFT_CONTENT} #{panel_id} {{ display: block; }}"
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
css_content = "\n".join(css_rules)
|
|
164
|
-
return nodes.raw(text=f"<style>\n{css_content}\n</style>", format='html')
|
|
152
|
+
# REMOVED: _generate_compatible_css method - no longer needed!
|
|
165
153
|
|
|
166
154
|
def _create_fieldset(self) -> FieldsetNode:
|
|
167
155
|
"""Create the main fieldset containing the legend, radio buttons, and panels."""
|
|
168
156
|
fieldset = FieldsetNode(role="radiogroup")
|
|
169
|
-
|
|
157
|
+
|
|
170
158
|
fieldset += self._create_legend()
|
|
171
|
-
|
|
159
|
+
|
|
172
160
|
radio_group = ContainerNode(classes=[SFT_RADIO_GROUP])
|
|
173
161
|
self._populate_radio_group(radio_group)
|
|
174
|
-
|
|
162
|
+
|
|
175
163
|
content_area = ContainerNode(classes=[SFT_CONTENT])
|
|
176
164
|
self._populate_content_area(content_area)
|
|
177
|
-
|
|
165
|
+
|
|
178
166
|
# This is the fix: place the content_area inside the radio_group.
|
|
179
167
|
radio_group += content_area
|
|
180
|
-
|
|
168
|
+
|
|
181
169
|
fieldset += radio_group
|
|
182
|
-
|
|
170
|
+
|
|
183
171
|
return fieldset
|
|
184
172
|
|
|
185
173
|
def _create_legend(self) -> LegendNode:
|
|
186
174
|
"""Create a meaningful, visible legend for the tab group."""
|
|
187
175
|
legend = LegendNode(classes=[SFT_LEGEND], ids=[self.id_gen.legend_id()])
|
|
188
|
-
|
|
176
|
+
|
|
189
177
|
# Use the custom legend if it exists
|
|
190
178
|
if self.custom_legend:
|
|
191
179
|
legend_text = self.custom_legend
|
|
@@ -194,14 +182,14 @@ class FilterTabsRenderer:
|
|
|
194
182
|
tab_names = [tab.name for tab in self.tab_data]
|
|
195
183
|
content_type = ContentTypeInferrer.infer_type(tab_names)
|
|
196
184
|
legend_text = f"Choose {content_type}: {', '.join(tab_names)}"
|
|
197
|
-
|
|
185
|
+
|
|
198
186
|
legend += nodes.Text(legend_text)
|
|
199
187
|
return legend
|
|
200
188
|
|
|
201
189
|
def _populate_radio_group(self, radio_group: ContainerNode) -> None:
|
|
202
190
|
"""Create and add all radio buttons and labels to the radio group container."""
|
|
203
191
|
default_index = next((i for i, tab in enumerate(self.tab_data) if tab.is_default), 0)
|
|
204
|
-
|
|
192
|
+
|
|
205
193
|
for i, tab in enumerate(self.tab_data):
|
|
206
194
|
radio_group += self._create_radio_button(i, tab, is_checked=(i == default_index))
|
|
207
195
|
radio_group += self._create_label(i, tab)
|
|
@@ -241,7 +229,7 @@ class FilterTabsRenderer:
|
|
|
241
229
|
general_panel = PanelNode(classes=[SFT_PANEL], **{'data-filter': 'General'})
|
|
242
230
|
general_panel.extend(copy.deepcopy(self.general_content))
|
|
243
231
|
content_area += general_panel
|
|
244
|
-
|
|
232
|
+
|
|
245
233
|
for i, tab in enumerate(self.tab_data):
|
|
246
234
|
content_area += self._create_tab_panel(i, tab)
|
|
247
235
|
|
|
@@ -250,7 +238,7 @@ class FilterTabsRenderer:
|
|
|
250
238
|
panel_attrs = {
|
|
251
239
|
'classes': [SFT_PANEL],
|
|
252
240
|
'ids': [self.id_gen.panel_id(index)],
|
|
253
|
-
'role': '
|
|
241
|
+
'role': 'tabpanel',
|
|
254
242
|
'aria-labelledby': self.id_gen.radio_id(index),
|
|
255
243
|
'tabindex': '0',
|
|
256
244
|
'data-tab': tab.name.lower().replace(' ', '-')
|
|
@@ -258,4 +246,3 @@ class FilterTabsRenderer:
|
|
|
258
246
|
panel = PanelNode(**panel_attrs)
|
|
259
247
|
panel.extend(copy.deepcopy(tab.content))
|
|
260
248
|
return panel
|
|
261
|
-
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
/* Content area */
|
|
87
87
|
.sft-content {
|
|
88
88
|
padding: 20px;
|
|
89
|
-
flex-basis: 100%;
|
|
89
|
+
flex-basis: 100%;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
/* Panels - hidden by default */
|
|
@@ -110,6 +110,32 @@
|
|
|
110
110
|
border-bottom: 1px solid #eee;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/*
|
|
114
|
+
* FIXED: Panel visibility using CSS without inline styles
|
|
115
|
+
* This uses a general approach with nth-child selectors
|
|
116
|
+
* No more inline <style> elements needed!
|
|
117
|
+
*/
|
|
118
|
+
|
|
119
|
+
/* Show panels when corresponding radio is checked */
|
|
120
|
+
.sft-radio-group input[type="radio"]:nth-child(1):checked ~ .sft-content .sft-panel:nth-of-type(1),
|
|
121
|
+
.sft-radio-group input[type="radio"]:nth-child(3):checked ~ .sft-content .sft-panel:nth-of-type(2),
|
|
122
|
+
.sft-radio-group input[type="radio"]:nth-child(5):checked ~ .sft-content .sft-panel:nth-of-type(3),
|
|
123
|
+
.sft-radio-group input[type="radio"]:nth-child(7):checked ~ .sft-content .sft-panel:nth-of-type(4),
|
|
124
|
+
.sft-radio-group input[type="radio"]:nth-child(9):checked ~ .sft-content .sft-panel:nth-of-type(5),
|
|
125
|
+
.sft-radio-group input[type="radio"]:nth-child(11):checked ~ .sft-content .sft-panel:nth-of-type(6),
|
|
126
|
+
.sft-radio-group input[type="radio"]:nth-child(13):checked ~ .sft-content .sft-panel:nth-of-type(7),
|
|
127
|
+
.sft-radio-group input[type="radio"]:nth-child(15):checked ~ .sft-content .sft-panel:nth-of-type(8),
|
|
128
|
+
.sft-radio-group input[type="radio"]:nth-child(17):checked ~ .sft-content .sft-panel:nth-of-type(9),
|
|
129
|
+
.sft-radio-group input[type="radio"]:nth-child(19):checked ~ .sft-content .sft-panel:nth-of-type(10) {
|
|
130
|
+
display: block;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* Alternative approach using CSS custom properties (more elegant) */
|
|
134
|
+
/*
|
|
135
|
+
* If you prefer a more modern approach, you could use CSS custom properties
|
|
136
|
+
* and update the renderer to set --active-tab instead of generating CSS rules
|
|
137
|
+
*/
|
|
138
|
+
|
|
113
139
|
/* Screen reader only content */
|
|
114
140
|
.sr-only {
|
|
115
141
|
position: absolute;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
// Progressive enhancement for
|
|
2
|
-
// This file
|
|
3
|
-
// while maintaining a CSS-only fallback.
|
|
1
|
+
// Progressive enhancement for focus management and accessibility announcements.
|
|
2
|
+
// This file provides enhancements while maintaining native radio button keyboard behavior.
|
|
4
3
|
|
|
5
4
|
(function() {
|
|
6
5
|
'use strict';
|
|
7
|
-
|
|
6
|
+
|
|
8
7
|
// Only enhance if the extension's HTML is present on the page.
|
|
9
8
|
if (!document.querySelector('.sft-container')) return;
|
|
10
|
-
|
|
9
|
+
|
|
11
10
|
/**
|
|
12
11
|
* Moves focus to the content panel associated with a given radio button.
|
|
13
12
|
* This improves accessibility by directing screen reader users to the new content.
|
|
@@ -15,12 +14,12 @@
|
|
|
15
14
|
*/
|
|
16
15
|
function focusOnPanel(radio) {
|
|
17
16
|
if (!radio.checked) return;
|
|
18
|
-
|
|
17
|
+
|
|
19
18
|
// Derive the panel's ID from the radio button's ID.
|
|
20
19
|
// e.g., 'filter-group-1-radio-0' becomes 'filter-group-1-panel-0'
|
|
21
20
|
const panelId = radio.id.replace('-radio-', '-panel-');
|
|
22
21
|
const panel = document.getElementById(panelId);
|
|
23
|
-
|
|
22
|
+
|
|
24
23
|
if (panel) {
|
|
25
24
|
panel.focus();
|
|
26
25
|
}
|
|
@@ -47,10 +46,10 @@
|
|
|
47
46
|
liveRegion.style.overflow = 'hidden';
|
|
48
47
|
document.body.appendChild(liveRegion);
|
|
49
48
|
}
|
|
50
|
-
|
|
49
|
+
|
|
51
50
|
// Update the announcement text.
|
|
52
51
|
liveRegion.textContent = `${tabName} tab selected`;
|
|
53
|
-
|
|
52
|
+
|
|
54
53
|
// Clear the announcement after a short delay to prevent clutter.
|
|
55
54
|
setTimeout(() => {
|
|
56
55
|
liveRegion.textContent = '';
|
|
@@ -58,103 +57,45 @@
|
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
/**
|
|
61
|
-
* Initializes
|
|
60
|
+
* Initializes progressive enhancements for all filter-tab components.
|
|
61
|
+
* REMOVED: Custom keyboard navigation (now uses native radio button behavior)
|
|
62
|
+
* KEPT: Focus management and screen reader announcements
|
|
62
63
|
*/
|
|
63
|
-
function
|
|
64
|
+
function initTabEnhancements() {
|
|
64
65
|
const containers = document.querySelectorAll('.sft-container');
|
|
65
|
-
|
|
66
|
+
|
|
66
67
|
containers.forEach(container => {
|
|
67
68
|
const tabBar = container.querySelector('.sft-radio-group');
|
|
68
69
|
if (!tabBar) return;
|
|
69
|
-
|
|
70
|
+
|
|
70
71
|
const radios = tabBar.querySelectorAll('input[type="radio"]');
|
|
71
72
|
const labels = tabBar.querySelectorAll('label');
|
|
72
|
-
|
|
73
|
+
|
|
73
74
|
if (radios.length === 0 || labels.length === 0) return;
|
|
74
|
-
|
|
75
|
-
// Make labels focusable to act as keyboard navigation targets.
|
|
76
|
-
labels.forEach(label => {
|
|
77
|
-
if (!label.hasAttribute('tabindex')) {
|
|
78
|
-
label.setAttribute('tabindex', '0');
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
75
|
|
|
82
|
-
//
|
|
83
|
-
labels.forEach((label, index) => {
|
|
84
|
-
label.addEventListener('keydown', (event) => {
|
|
85
|
-
let targetIndex = index;
|
|
86
|
-
let handled = false;
|
|
87
|
-
|
|
88
|
-
switch (event.key) {
|
|
89
|
-
case 'ArrowRight':
|
|
90
|
-
event.preventDefault();
|
|
91
|
-
targetIndex = (index + 1) % labels.length;
|
|
92
|
-
handled = true;
|
|
93
|
-
break;
|
|
94
|
-
|
|
95
|
-
case 'ArrowLeft':
|
|
96
|
-
event.preventDefault();
|
|
97
|
-
targetIndex = (index - 1 + labels.length) % labels.length;
|
|
98
|
-
handled = true;
|
|
99
|
-
break;
|
|
100
|
-
|
|
101
|
-
case 'Home':
|
|
102
|
-
event.preventDefault();
|
|
103
|
-
targetIndex = 0;
|
|
104
|
-
handled = true;
|
|
105
|
-
break;
|
|
106
|
-
|
|
107
|
-
case 'End':
|
|
108
|
-
event.preventDefault();
|
|
109
|
-
targetIndex = labels.length - 1;
|
|
110
|
-
handled = true;
|
|
111
|
-
break;
|
|
112
|
-
|
|
113
|
-
case 'Enter':
|
|
114
|
-
case ' ':
|
|
115
|
-
// Activate the associated radio button on Enter/Space.
|
|
116
|
-
event.preventDefault();
|
|
117
|
-
if (radios[index]) {
|
|
118
|
-
radios[index].checked = true;
|
|
119
|
-
radios[index].dispatchEvent(new Event('change', { bubbles: true }));
|
|
120
|
-
}
|
|
121
|
-
return;
|
|
122
|
-
|
|
123
|
-
default:
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (handled) {
|
|
128
|
-
// Move focus to the target label and activate its radio button.
|
|
129
|
-
labels[targetIndex].focus();
|
|
130
|
-
if (radios[targetIndex]) {
|
|
131
|
-
radios[targetIndex].checked = true;
|
|
132
|
-
radios[targetIndex].dispatchEvent(new Event('change', { bubbles: true }));
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// Add listeners for announcements and focus management.
|
|
76
|
+
// Add change listeners for announcements and focus management
|
|
139
77
|
radios.forEach((radio, index) => {
|
|
140
78
|
radio.addEventListener('change', () => {
|
|
141
79
|
if (radio.checked) {
|
|
142
|
-
//
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
//
|
|
80
|
+
// Get the tab name from the associated label
|
|
81
|
+
const label = labels[index];
|
|
82
|
+
const tabName = label ? label.textContent.trim() : 'Unknown';
|
|
83
|
+
|
|
84
|
+
// Announce the change to screen readers
|
|
85
|
+
announceTabChange(tabName);
|
|
86
|
+
|
|
87
|
+
// Move focus to the newly visible panel
|
|
147
88
|
focusOnPanel(radio);
|
|
148
89
|
}
|
|
149
90
|
});
|
|
150
91
|
});
|
|
151
92
|
});
|
|
152
93
|
}
|
|
153
|
-
|
|
154
|
-
// Initialize the
|
|
94
|
+
|
|
95
|
+
// Initialize the enhancements once the DOM is ready
|
|
155
96
|
if (document.readyState === 'loading') {
|
|
156
|
-
document.addEventListener('DOMContentLoaded',
|
|
97
|
+
document.addEventListener('DOMContentLoaded', initTabEnhancements);
|
|
157
98
|
} else {
|
|
158
|
-
|
|
99
|
+
initTabEnhancements();
|
|
159
100
|
}
|
|
160
101
|
})();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sphinx-filter-tabs
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.5
|
|
4
4
|
Summary: A Sphinx extension for accessible, CSS-first filterable content tabs.
|
|
5
5
|
Author-email: Aputsiak Niels Janussen <aputtu+sphinx@gmail.com>
|
|
6
6
|
License: GNU General Public License v3.0
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
filter_tabs/__init__.py,sha256=VPpIhj4HaLeMX7ai7dZFkUm81ii2ePPGjCd9hsMjsN4,397
|
|
2
|
+
filter_tabs/extension.py,sha256=Dspt9r8TVoYChHFvGsncuV01GEga7BOOsPaMwYdMQcg,18014
|
|
3
|
+
filter_tabs/renderer.py,sha256=m0_sD5ujtT4rmhYlhm6vMgSn0W1WAJPJWaTjh6zXezY,9730
|
|
4
|
+
filter_tabs/static/filter_tabs.css,sha256=EbsG5zdEv8g3rdV7y76CXSwEMiBaBTX01qFYDiXeJt0,5379
|
|
5
|
+
filter_tabs/static/filter_tabs.js,sha256=URduEo1P8y_-TaT485U6APGXsdQg6rFBpib3yaNc-9g,3989
|
|
6
|
+
sphinx_filter_tabs-1.2.5.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
7
|
+
sphinx_filter_tabs-1.2.5.dist-info/METADATA,sha256=nH86wxyNL4OAwRnPL0W8k4vJcj0mxKpoc_bk_2b2cv0,3483
|
|
8
|
+
sphinx_filter_tabs-1.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
+
sphinx_filter_tabs-1.2.5.dist-info/entry_points.txt,sha256=za_bQcueY8AHyq7XnnjkW9X3C-LsZjeERVQ_ds7jV1A,62
|
|
10
|
+
sphinx_filter_tabs-1.2.5.dist-info/top_level.txt,sha256=K0Iy-6EsYYdvlyXdsJT0SQg-BLDBgT5-Y8ZKy5SNAfc,12
|
|
11
|
+
sphinx_filter_tabs-1.2.5.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
filter_tabs/__init__.py,sha256=VPpIhj4HaLeMX7ai7dZFkUm81ii2ePPGjCd9hsMjsN4,397
|
|
2
|
-
filter_tabs/extension.py,sha256=Dspt9r8TVoYChHFvGsncuV01GEga7BOOsPaMwYdMQcg,18014
|
|
3
|
-
filter_tabs/renderer.py,sha256=e_nUV67ojDHfEXWB7jFkclzy4fOLotluKBg573fGng8,10436
|
|
4
|
-
filter_tabs/static/filter_tabs.css,sha256=V7y8BCp0UTQ1KXZNeIYtfz0Zt6b-uJPKYeXcx4PHz4A,3913
|
|
5
|
-
filter_tabs/static/filter_tabs.js,sha256=-d_TJREyNxu9TtQNDLvQ0G5qCVWR2TxwrWmApGs2CBo,6559
|
|
6
|
-
sphinx_filter_tabs-1.2.2.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
7
|
-
sphinx_filter_tabs-1.2.2.dist-info/METADATA,sha256=qX7ycCD1JfwXgju5W5pnlhoN1p09cnR_U9yUQZrFpBk,3483
|
|
8
|
-
sphinx_filter_tabs-1.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
-
sphinx_filter_tabs-1.2.2.dist-info/entry_points.txt,sha256=za_bQcueY8AHyq7XnnjkW9X3C-LsZjeERVQ_ds7jV1A,62
|
|
10
|
-
sphinx_filter_tabs-1.2.2.dist-info/top_level.txt,sha256=K0Iy-6EsYYdvlyXdsJT0SQg-BLDBgT5-Y8ZKy5SNAfc,12
|
|
11
|
-
sphinx_filter_tabs-1.2.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|