|
@@ -24,6 +24,252 @@ fn header(title: &str, css_path: &str) -> String {
|
|
|
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0,user-scalable=0' />
|
|
|
<link rel='icon' href='data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📧</text></svg>'>
|
|
|
<meta name="description" content="{title}"/>
|
|
|
+ <script>
|
|
|
+ let numberingVisible = true;
|
|
|
+ let blankLinesVisible = false;
|
|
|
+
|
|
|
+ function applyNumberingVisibility() {{
|
|
|
+ const purplenumbers = document.querySelectorAll('.purplenumber');
|
|
|
+ purplenumbers.forEach(element => {{
|
|
|
+ element.classList.toggle('transparent', !numberingVisible);
|
|
|
+ }});
|
|
|
+ }}
|
|
|
+
|
|
|
+ function applyBlankLinesVisibility() {{
|
|
|
+ const content = document.getElementById('content');
|
|
|
+
|
|
|
+ if (blankLinesVisible) {{
|
|
|
+ if (window.originalBrElements) {{
|
|
|
+ window.originalBrElements.forEach(br => {{
|
|
|
+ const parent = br.parent;
|
|
|
+ if (parent) {{
|
|
|
+ parent.insertBefore(br.element, parent.children[br.index]);
|
|
|
+ }}
|
|
|
+ }});
|
|
|
+ window.originalBrElements = [];
|
|
|
+ }}
|
|
|
+
|
|
|
+ if (window.originalStyles) {{
|
|
|
+ window.originalStyles.forEach(item => {{
|
|
|
+ item.element.style.marginTop = item.styles.marginTop;
|
|
|
+ item.element.style.marginBottom = item.styles.marginBottom;
|
|
|
+ }});
|
|
|
+ window.originalStyles = [];
|
|
|
+ }}
|
|
|
+ }} else {{
|
|
|
+ const brElements = content.querySelectorAll('br');
|
|
|
+ window.originalBrElements = [];
|
|
|
+ brElements.forEach(br => {{
|
|
|
+ const parent = br.parentNode;
|
|
|
+ const index = Array.prototype.indexOf.call(parent.children, br);
|
|
|
+ window.originalBrElements.push({{element: br, parent, index}});
|
|
|
+ parent.removeChild(br);
|
|
|
+ }});
|
|
|
+
|
|
|
+ const allElements = document.querySelectorAll('*');
|
|
|
+ window.originalStyles = [];
|
|
|
+ allElements.forEach(element => {{
|
|
|
+ window.originalStyles.push({{
|
|
|
+ element: element,
|
|
|
+ styles: {{
|
|
|
+ marginTop: element.style.marginTop,
|
|
|
+ marginBottom: element.style.marginBottom
|
|
|
+ }}
|
|
|
+ }});
|
|
|
+ element.style.marginTop = '0';
|
|
|
+ element.style.marginBottom = '0';
|
|
|
+ }});
|
|
|
+ }}
|
|
|
+ }}
|
|
|
+
|
|
|
+ function showElement(body_id, summary_id) {{
|
|
|
+ const summaries = document.querySelectorAll('.message-meta');
|
|
|
+ const innerElements = document.querySelectorAll('.email-body');
|
|
|
+ const zoom_ins = document.querySelectorAll('.zoom_in');
|
|
|
+ const zoom_outs = document.querySelectorAll('.zoom_out');
|
|
|
+
|
|
|
+ summaries.forEach(summary => {{
|
|
|
+ summary.style.display = 'none';
|
|
|
+ }});
|
|
|
+ innerElements.forEach(element => {{
|
|
|
+ element.style.display = 'none';
|
|
|
+ }});
|
|
|
+
|
|
|
+ zoom_ins.forEach(element => {{
|
|
|
+ element.style.display = 'none';
|
|
|
+ }});
|
|
|
+
|
|
|
+ zoom_outs.forEach(element => {{
|
|
|
+ element.style.display = 'block';
|
|
|
+ }});
|
|
|
+
|
|
|
+ document.getElementById(body_id).style.display = 'block';
|
|
|
+ document.getElementById(summary_id).style.display = 'block';
|
|
|
+
|
|
|
+ window.scrollTo(0, 0);
|
|
|
+ }}
|
|
|
+
|
|
|
+ function showSummaries() {{
|
|
|
+ const summaries = document.querySelectorAll('.message-meta');
|
|
|
+ const innerElements = document.querySelectorAll('.email-body');
|
|
|
+ const zoom_ins = document.querySelectorAll('.zoom_in');
|
|
|
+ const zoom_outs = document.querySelectorAll('.zoom_out');
|
|
|
+
|
|
|
+ summaries.forEach(summary => {{
|
|
|
+ summary.style.display = 'block';
|
|
|
+ }});
|
|
|
+
|
|
|
+ innerElements.forEach(element => {{
|
|
|
+ element.style.display = 'none';
|
|
|
+ }});
|
|
|
+
|
|
|
+ zoom_ins.forEach(element => {{
|
|
|
+ element.style.display = 'block';
|
|
|
+ }});
|
|
|
+
|
|
|
+ zoom_outs.forEach(element => {{
|
|
|
+ element.style.display = 'none';
|
|
|
+ }});
|
|
|
+
|
|
|
+ window.scrollTo(0, 0);
|
|
|
+ }}
|
|
|
+
|
|
|
+ function jumpToItem() {{
|
|
|
+ const id = document.getElementById('textfield').value;
|
|
|
+ if (id) {{
|
|
|
+ window.location.href = '#' + id;
|
|
|
+ }}
|
|
|
+ }}
|
|
|
+
|
|
|
+ function refreshPage() {{
|
|
|
+ localStorage.setItem('scrollPosition', window.scrollY);
|
|
|
+ localStorage.setItem('blankLinesVisible', blankLinesVisible);
|
|
|
+ localStorage.setItem('numberingVisible', numberingVisible);
|
|
|
+ location.reload();
|
|
|
+ }}
|
|
|
+
|
|
|
+ function openNewWindow() {{
|
|
|
+ const newWindow = window.open('', '', 'width=400,height=300');
|
|
|
+ const popupContent = `
|
|
|
+ <html>
|
|
|
+ <head>
|
|
|
+ <title>Viewspecs</title>
|
|
|
+ <style>
|
|
|
+ .popup-content {{
|
|
|
+ font-family: Arial, sans-serif;
|
|
|
+ font-size: 14px;
|
|
|
+ margin: 20px;
|
|
|
+ }}
|
|
|
+ .popup-content fieldset {{
|
|
|
+ border: 1px solid #000;
|
|
|
+ padding: 10px;
|
|
|
+ }}
|
|
|
+ .popup-content legend {{
|
|
|
+ padding: 0 10px;
|
|
|
+ font-weight: bold;
|
|
|
+ }}
|
|
|
+ .popup-content label {{
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ }}
|
|
|
+ .popup-content input {{
|
|
|
+ margin-right: 5px;
|
|
|
+ }}
|
|
|
+ .accept-button {{
|
|
|
+ margin-top: 10px;
|
|
|
+ padding: 5px 10px;
|
|
|
+ font-size: 14px;
|
|
|
+ cursor: pointer;
|
|
|
+ }}
|
|
|
+ </style>
|
|
|
+ </head>
|
|
|
+ <body>
|
|
|
+ <div class="popup-content">
|
|
|
+ <fieldset>
|
|
|
+ <legend>Show</legend>
|
|
|
+ <label><input type="checkbox" id="blankLines"> Blank lines (y/z)</label>
|
|
|
+ <label><input type="checkbox" id="numbering" checked> Numbering (m/n)</label>
|
|
|
+ </fieldset>
|
|
|
+ <button class="accept-button" onclick="window.close()">Accept</button>
|
|
|
+ </div>
|
|
|
+ <script>
|
|
|
+ const mainWindow = window.opener;
|
|
|
+ document.getElementById('blankLines').checked = mainWindow.blankLinesVisible;
|
|
|
+ document.getElementById('numbering').checked = mainWindow.numberingVisible;
|
|
|
+
|
|
|
+ document.getElementById('blankLines').addEventListener('change', function() {{
|
|
|
+ mainWindow.blankLinesVisible = this.checked;
|
|
|
+ mainWindow.applyBlankLinesVisibility();
|
|
|
+ }});
|
|
|
+
|
|
|
+ document.getElementById('numbering').addEventListener('change', function() {{
|
|
|
+ mainWindow.numberingVisible = this.checked;
|
|
|
+ mainWindow.applyNumberingVisibility();
|
|
|
+ }});
|
|
|
+
|
|
|
+ </body>
|
|
|
+ </html>
|
|
|
+ `;
|
|
|
+ newWindow.document.open();
|
|
|
+ newWindow.document.write(popupContent);
|
|
|
+ newWindow.document.close();
|
|
|
+ }}
|
|
|
+
|
|
|
+ document.addEventListener('DOMContentLoaded', function() {{
|
|
|
+ const textfield = document.getElementById('textfield');
|
|
|
+ textfield.addEventListener('keydown', function(event) {{
|
|
|
+ if (event.key === 'Enter') {{
|
|
|
+ jumpToItem();
|
|
|
+ }}
|
|
|
+ }});
|
|
|
+
|
|
|
+ const jumpButton = document.querySelector('input[type="button"][value="Jump Item:"]');
|
|
|
+ jumpButton.addEventListener('click', jumpToItem);
|
|
|
+
|
|
|
+ // Apply stored states on load
|
|
|
+ blankLinesVisible = JSON.parse(localStorage.getItem('blankLinesVisible') || 'false');
|
|
|
+ numberingVisible = JSON.parse(localStorage.getItem('numberingVisible') || 'true');
|
|
|
+ applyBlankLinesVisibility();
|
|
|
+ applyNumberingVisibility();
|
|
|
+
|
|
|
+ document.getElementById('numbering').addEventListener('change', function() {{
|
|
|
+ numberingVisible = this.checked;
|
|
|
+ applyNumberingVisibility();
|
|
|
+ }});
|
|
|
+
|
|
|
+ document.getElementById('blankLines').addEventListener('change', function() {{
|
|
|
+ blankLinesVisible = this.checked;
|
|
|
+ applyBlankLinesVisibility();
|
|
|
+ }});
|
|
|
+ }});
|
|
|
+
|
|
|
+ // Keyboard shortcuts
|
|
|
+ document.addEventListener('keydown', function(event) {{
|
|
|
+ const numberingCheckbox = document.getElementById('numbering');
|
|
|
+ const blankLinesCheckbox = document.getElementById('blankLines');
|
|
|
+
|
|
|
+ if (event.key === 'm') {{
|
|
|
+ numberingVisible = true;
|
|
|
+ if (numberingCheckbox) numberingCheckbox.checked = true;
|
|
|
+ applyNumberingVisibility();
|
|
|
+ }}
|
|
|
+ if (event.key === 'n') {{
|
|
|
+ numberingVisible = false;
|
|
|
+ if (numberingCheckbox) numberingCheckbox.checked = false;
|
|
|
+ applyNumberingVisibility();
|
|
|
+ }}
|
|
|
+ if (event.key === 'y') {{
|
|
|
+ blankLinesVisible = true;
|
|
|
+ if (blankLinesCheckbox) blankLinesCheckbox.checked = true;
|
|
|
+ applyBlankLinesVisibility();
|
|
|
+ }}
|
|
|
+ if (event.key === 'z') {{
|
|
|
+ blankLinesVisible = false;
|
|
|
+ if (blankLinesCheckbox) blankLinesCheckbox.checked = false;
|
|
|
+ applyBlankLinesVisibility();
|
|
|
+ }}
|
|
|
+ }});
|
|
|
+ </script>
|
|
|
</head>
|
|
|
<body>
|
|
|
<div id="button-container">
|
|
@@ -59,253 +305,6 @@ const FOOTER: &str = r#"
|
|
|
</html>
|
|
|
"#;
|
|
|
|
|
|
-fn generate_popup_js() -> String {
|
|
|
- r#"
|
|
|
- function toggleNumbering() {
|
|
|
- const numberingCheckbox = document.getElementById('numbering');
|
|
|
- const purplenumbers = window.opener.document.querySelectorAll('.purplenumber');
|
|
|
- purplenumbers.forEach(element => {
|
|
|
- element.classList.toggle('transparent', !numberingCheckbox.checked);
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- document.addEventListener('DOMContentLoaded', function() {
|
|
|
- const numberingCheckbox = document.getElementById('numbering');
|
|
|
- numberingCheckbox.addEventListener('change', toggleNumbering);
|
|
|
- });
|
|
|
- "#.to_string()
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-const JS_SCRIPT_VIEWSPECS: &str = r##"
|
|
|
-<script>
|
|
|
- function showElement(body_id, summary_id){
|
|
|
- const summaries = document.querySelectorAll('.message-meta');
|
|
|
- const innerElements = document.querySelectorAll('.email-body');
|
|
|
- const zoom_ins = document.querySelectorAll('.zoom_in');
|
|
|
- const zoom_outs = document.querySelectorAll('.zoom_out');
|
|
|
-
|
|
|
- summaries.forEach(summary => {
|
|
|
- summary.style.display = 'none';
|
|
|
- });
|
|
|
- innerElements.forEach(element => {
|
|
|
- element.style.display = 'none';
|
|
|
- });
|
|
|
-
|
|
|
- zoom_ins.forEach(element => {
|
|
|
- element.style.display = 'none';
|
|
|
- });
|
|
|
-
|
|
|
- zoom_outs.forEach(element => {
|
|
|
- element.style.display = 'block';
|
|
|
- });
|
|
|
-
|
|
|
- document.getElementById(body_id).style.display = 'block';
|
|
|
- document.getElementById(summary_id).style.display = 'block';
|
|
|
-
|
|
|
- window.scrollTo(0, 0);
|
|
|
- }
|
|
|
-
|
|
|
- function showSummaries() {
|
|
|
- const summaries = document.querySelectorAll('.message-meta');
|
|
|
- const innerElements = document.querySelectorAll('.email-body');
|
|
|
- const zoom_ins = document.querySelectorAll('.zoom_in');
|
|
|
- const zoom_outs = document.querySelectorAll('.zoom_out');
|
|
|
-
|
|
|
- summaries.forEach(summary => {
|
|
|
- summary.style.display = 'block';
|
|
|
- });
|
|
|
-
|
|
|
- innerElements.forEach(element => {
|
|
|
- element.style.display = 'none';
|
|
|
- });
|
|
|
-
|
|
|
- zoom_ins.forEach(element => {
|
|
|
- element.style.display = 'block';
|
|
|
- });
|
|
|
-
|
|
|
- zoom_outs.forEach(element => {
|
|
|
- element.style.display = 'none';
|
|
|
- });
|
|
|
-
|
|
|
- window.scrollTo(0, 0);
|
|
|
- }
|
|
|
-
|
|
|
- function jumpToItem() {
|
|
|
- const id = document.getElementById('textfield').value;
|
|
|
- if (id) {
|
|
|
- window.location.href = `#${id}`;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- document.addEventListener('DOMContentLoaded', function() {
|
|
|
- const textfield = document.getElementById('textfield');
|
|
|
- textfield.addEventListener('keydown', function(event) {
|
|
|
- if (event.key === 'Enter') {
|
|
|
- jumpToItem();
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- const jumpButton = document.querySelector('input[type="button"][value="Jump Item:"]');
|
|
|
- jumpButton.addEventListener('click', jumpToItem);
|
|
|
- });
|
|
|
- function refreshPage() {
|
|
|
- // Save the current scroll position and checkbox states to localStorage
|
|
|
- localStorage.setItem('scrollPosition', window.scrollY);
|
|
|
- localStorage.setItem('blankLinesChecked', blankLinesChecked);
|
|
|
- localStorage.setItem('numberingChecked', numberingChecked);
|
|
|
- location.reload();
|
|
|
- }
|
|
|
-
|
|
|
- function openNewWindow() {
|
|
|
- const popupJs = `
|
|
|
- function toggleNumbering() {
|
|
|
- const numberingCheckbox = document.getElementById('numbering');
|
|
|
- const purplenumbers = window.opener.document.querySelectorAll('.purplenumber');
|
|
|
- purplenumbers.forEach(element => {
|
|
|
- element.classList.toggle('transparent', !numberingCheckbox.checked);
|
|
|
- });
|
|
|
- }
|
|
|
- function toggleBlankLines() {
|
|
|
- const blankLinesCheckbox = document.getElementById('blankLines');
|
|
|
- const content = window.opener.document.getElementById('content');
|
|
|
-
|
|
|
- if (blankLinesCheckbox.checked) {
|
|
|
-
|
|
|
- if (window.opener.originalBrElements) {
|
|
|
- window.opener.originalBrElements.forEach(br => {
|
|
|
- const parent = br.parent; // Use the correct parent reference
|
|
|
-
|
|
|
- if (parent) { // Ensure parent is defined
|
|
|
- parent.insertBefore(br.element, parent.children[br.index]);
|
|
|
- }
|
|
|
- });
|
|
|
- window.opener.originalBrElements = []; // Clear the array after restoration
|
|
|
- }
|
|
|
-
|
|
|
- if (window.opener.originalStyles) {
|
|
|
- window.opener.originalStyles.forEach(item => {
|
|
|
-
|
|
|
- item.element.style.marginTop = item.styles.marginTop;
|
|
|
- item.element.style.marginBottom = item.styles.marginBottom;
|
|
|
- });
|
|
|
- window.opener.originalStyles = []; // Clear the array after restoration
|
|
|
- }
|
|
|
- } else {
|
|
|
- // Remove all <br> elements
|
|
|
- const brElements = content.querySelectorAll('br');
|
|
|
- window.opener.originalBrElements = [];
|
|
|
- brElements.forEach(br => {
|
|
|
- const parent = br.parentNode;
|
|
|
- const index = Array.prototype.indexOf.call(parent.children, br);
|
|
|
- window.opener.originalBrElements.push({element: br, parent, index});
|
|
|
- parent.removeChild(br);
|
|
|
- });
|
|
|
-
|
|
|
- // Set margins to 0 and store original styles
|
|
|
- const allElements = window.opener.document.querySelectorAll('*');
|
|
|
- window.opener.originalStyles = [];
|
|
|
- allElements.forEach(element => {
|
|
|
- window.opener.originalStyles.push({
|
|
|
- element: element,
|
|
|
- styles: {
|
|
|
- marginTop: element.style.marginTop,
|
|
|
- marginBottom: element.style.marginBottom
|
|
|
- }
|
|
|
- });
|
|
|
- element.style.marginTop = '0';
|
|
|
- element.style.marginBottom = '0';
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- // Update the main page state
|
|
|
- window.opener.blankLinesChecked = blankLinesCheckbox.checked;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- function saveStateAndClose() {
|
|
|
- // Save the state of checkboxes to localStorage
|
|
|
- localStorage.setItem('blankLinesChecked', document.getElementById('blankLines').checked);
|
|
|
- localStorage.setItem('numberingChecked', document.getElementById('numbering').checked);
|
|
|
-
|
|
|
- window.opener.refreshPage();
|
|
|
- }
|
|
|
-
|
|
|
- document.addEventListener('DOMContentLoaded', function() {
|
|
|
- const numberingCheckbox = document.getElementById('numbering');
|
|
|
- numberingCheckbox.addEventListener('change', toggleNumbering);
|
|
|
-
|
|
|
- const blankLinesCheckbox = document.getElementById('blankLines');
|
|
|
- blankLinesCheckbox.addEventListener('change', toggleBlankLines);
|
|
|
-
|
|
|
- //esure the checkbox is iniatially ticked
|
|
|
- blankLinesCheckbox.checked = true;
|
|
|
- });
|
|
|
- `;
|
|
|
-
|
|
|
- const newWindow = window.open('', '', 'width=400,height=300');
|
|
|
- newWindow.document.write(`
|
|
|
- <html>
|
|
|
- <head>
|
|
|
- <title>Viewspecs</title>
|
|
|
- <style>
|
|
|
- .popup-content {
|
|
|
- font-family: Arial, sans-serif;
|
|
|
- font-size: 14px;
|
|
|
- margin: 20px;
|
|
|
- }
|
|
|
- .popup-content fieldset {
|
|
|
- border: 1px solid #000;
|
|
|
- padding: 10px;
|
|
|
- }
|
|
|
- .popup-content legend {
|
|
|
- padding: 0 10px;
|
|
|
- font-weight: bold;
|
|
|
- }
|
|
|
- .popup-content label {
|
|
|
- display: block;
|
|
|
- margin-bottom: 5px;
|
|
|
- }
|
|
|
- .popup-content input {
|
|
|
- margin-right: 5px;
|
|
|
- }
|
|
|
- .accept-button {
|
|
|
- margin-top: 10px;
|
|
|
- padding: 5px 10px;
|
|
|
- font-size: 14px;
|
|
|
- cursor: pointer;
|
|
|
- }
|
|
|
- .transparent {
|
|
|
- color: transparent !important;
|
|
|
- }
|
|
|
- .compress-blank-lines * {
|
|
|
- padding: 0;
|
|
|
- margin: 0;
|
|
|
- }
|
|
|
- </style>
|
|
|
- </head>
|
|
|
- <body>
|
|
|
- <div class="popup-content">
|
|
|
- <fieldset>
|
|
|
- <legend>Show</legend>
|
|
|
- <label><input type="checkbox" id="blankLines"> y z Blank lines</label>
|
|
|
- <label><input type="checkbox" id="numbering" checked> m n Numbering</label>
|
|
|
- <label><input type="checkbox" id="statementSignatures"> K L Statement signatures</label>
|
|
|
- </fieldset>
|
|
|
- <button class="accept-button" onclick="window.close()">Accept</button>
|
|
|
- </div>
|
|
|
- <script>${popupJs}<\/script>
|
|
|
- </body>
|
|
|
- </html>
|
|
|
- `);
|
|
|
- newWindow.document.close();
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-</script>
|
|
|
-"##;
|
|
|
|
|
|
impl Lists {
|
|
|
pub fn to_html(&self) -> String {
|
|
@@ -680,8 +679,7 @@ impl Thread {
|
|
|
message_id_css += 1;
|
|
|
}
|
|
|
|
|
|
- body.push_str(&*format!(r#"</div><hr>{}</body></html>"#, JS_SCRIPT_VIEWSPECS));
|
|
|
- remove_inline_styles_from_body(&body)
|
|
|
+ remove_inline_styles_from_body(&body)
|
|
|
}
|
|
|
}
|
|
|
|