psdi-data-conversion 0.0.23__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.
Files changed (81) hide show
  1. psdi_data_conversion/__init__.py +11 -0
  2. psdi_data_conversion/app.py +242 -0
  3. psdi_data_conversion/bin/linux/atomsk +0 -0
  4. psdi_data_conversion/bin/linux/c2x +0 -0
  5. psdi_data_conversion/bin/mac/atomsk +0 -0
  6. psdi_data_conversion/bin/mac/c2x +0 -0
  7. psdi_data_conversion/constants.py +185 -0
  8. psdi_data_conversion/converter.py +459 -0
  9. psdi_data_conversion/converters/__init__.py +6 -0
  10. psdi_data_conversion/converters/atomsk.py +32 -0
  11. psdi_data_conversion/converters/base.py +702 -0
  12. psdi_data_conversion/converters/c2x.py +32 -0
  13. psdi_data_conversion/converters/openbabel.py +239 -0
  14. psdi_data_conversion/database.py +1064 -0
  15. psdi_data_conversion/dist.py +87 -0
  16. psdi_data_conversion/file_io.py +216 -0
  17. psdi_data_conversion/log_utility.py +241 -0
  18. psdi_data_conversion/main.py +776 -0
  19. psdi_data_conversion/scripts/atomsk.sh +32 -0
  20. psdi_data_conversion/scripts/c2x.sh +26 -0
  21. psdi_data_conversion/security.py +38 -0
  22. psdi_data_conversion/static/content/accessibility.htm +254 -0
  23. psdi_data_conversion/static/content/convert.htm +121 -0
  24. psdi_data_conversion/static/content/convertato.htm +65 -0
  25. psdi_data_conversion/static/content/convertc2x.htm +65 -0
  26. psdi_data_conversion/static/content/documentation.htm +94 -0
  27. psdi_data_conversion/static/content/feedback.htm +53 -0
  28. psdi_data_conversion/static/content/header-links.html +8 -0
  29. psdi_data_conversion/static/content/index-versions/header-links.html +8 -0
  30. psdi_data_conversion/static/content/index-versions/psdi-common-footer.html +99 -0
  31. psdi_data_conversion/static/content/index-versions/psdi-common-header.html +28 -0
  32. psdi_data_conversion/static/content/psdi-common-footer.html +99 -0
  33. psdi_data_conversion/static/content/psdi-common-header.html +28 -0
  34. psdi_data_conversion/static/content/report.htm +103 -0
  35. psdi_data_conversion/static/data/data.json +143940 -0
  36. psdi_data_conversion/static/img/colormode-toggle-dm.svg +3 -0
  37. psdi_data_conversion/static/img/colormode-toggle-lm.svg +3 -0
  38. psdi_data_conversion/static/img/psdi-icon-dark.svg +136 -0
  39. psdi_data_conversion/static/img/psdi-icon-light.svg +208 -0
  40. psdi_data_conversion/static/img/psdi-logo-darktext.png +0 -0
  41. psdi_data_conversion/static/img/psdi-logo-lighttext.png +0 -0
  42. psdi_data_conversion/static/img/social-logo-bluesky-black.svg +4 -0
  43. psdi_data_conversion/static/img/social-logo-bluesky-white.svg +4 -0
  44. psdi_data_conversion/static/img/social-logo-instagram-black.svg +1 -0
  45. psdi_data_conversion/static/img/social-logo-instagram-white.svg +1 -0
  46. psdi_data_conversion/static/img/social-logo-linkedin-black.png +0 -0
  47. psdi_data_conversion/static/img/social-logo-linkedin-white.png +0 -0
  48. psdi_data_conversion/static/img/social-logo-mastodon-black.svg +4 -0
  49. psdi_data_conversion/static/img/social-logo-mastodon-white.svg +4 -0
  50. psdi_data_conversion/static/img/social-logo-x-black.svg +3 -0
  51. psdi_data_conversion/static/img/social-logo-x-white.svg +3 -0
  52. psdi_data_conversion/static/img/social-logo-youtube-black.png +0 -0
  53. psdi_data_conversion/static/img/social-logo-youtube-white.png +0 -0
  54. psdi_data_conversion/static/img/ukri-epsr-logo-darktext.png +0 -0
  55. psdi_data_conversion/static/img/ukri-epsr-logo-lighttext.png +0 -0
  56. psdi_data_conversion/static/img/ukri-logo-darktext.png +0 -0
  57. psdi_data_conversion/static/img/ukri-logo-lighttext.png +0 -0
  58. psdi_data_conversion/static/javascript/accessibility.js +196 -0
  59. psdi_data_conversion/static/javascript/common.js +42 -0
  60. psdi_data_conversion/static/javascript/convert.js +296 -0
  61. psdi_data_conversion/static/javascript/convert_common.js +252 -0
  62. psdi_data_conversion/static/javascript/convertato.js +107 -0
  63. psdi_data_conversion/static/javascript/convertc2x.js +107 -0
  64. psdi_data_conversion/static/javascript/data.js +176 -0
  65. psdi_data_conversion/static/javascript/format.js +611 -0
  66. psdi_data_conversion/static/javascript/load_accessibility.js +89 -0
  67. psdi_data_conversion/static/javascript/psdi-common.js +177 -0
  68. psdi_data_conversion/static/javascript/report.js +381 -0
  69. psdi_data_conversion/static/styles/format.css +147 -0
  70. psdi_data_conversion/static/styles/psdi-common.css +705 -0
  71. psdi_data_conversion/templates/index.htm +114 -0
  72. psdi_data_conversion/testing/__init__.py +5 -0
  73. psdi_data_conversion/testing/constants.py +12 -0
  74. psdi_data_conversion/testing/conversion_callbacks.py +394 -0
  75. psdi_data_conversion/testing/conversion_test_specs.py +208 -0
  76. psdi_data_conversion/testing/utils.py +522 -0
  77. psdi_data_conversion-0.0.23.dist-info/METADATA +663 -0
  78. psdi_data_conversion-0.0.23.dist-info/RECORD +81 -0
  79. psdi_data_conversion-0.0.23.dist-info/WHEEL +4 -0
  80. psdi_data_conversion-0.0.23.dist-info/entry_points.txt +2 -0
  81. psdi_data_conversion-0.0.23.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,177 @@
1
+ // This file provides common functions related to the PSDI common assets. Most of these are run automatically as
2
+ // appropriate, except the first batch of functions exported below. These are exposed to the user so that they can
3
+ // customise aspects of the common HTML header
4
+
5
+ const ORIG_TITLE = "$REPLACEME_SITE_TITLE"
6
+ const ORIG_TITLE_LINK = "./"
7
+
8
+ const DEFAULT_TITLE = "";
9
+ const DEFAULT_TITLE_LINK_TARGET = "./";
10
+ const DEFAULT_HEADER_LINKS_SOURCE = "./header-links.html";
11
+ const DEFAULT_HEADER_SOURCE = "./psdi-common-header.html";
12
+ const DEFAULT_FOOTER_SOURCE = "./psdi-common-footer.html";
13
+
14
+ let title = DEFAULT_TITLE;
15
+ let useDefaultTitle = true;
16
+ let titleLinkTarget = DEFAULT_TITLE_LINK_TARGET;
17
+ let useDefaultTitleLink = true;
18
+ let headerLinksSource = DEFAULT_HEADER_LINKS_SOURCE;
19
+ let headerSource = DEFAULT_HEADER_SOURCE
20
+ let footerSource = DEFAULT_FOOTER_SOURCE
21
+
22
+ export function setTitle(s) {
23
+ // Public function for the user to set the site title that will appear in the header, to the right of the PSDI logo
24
+ title = s;
25
+ useDefaultTitle = false;
26
+ }
27
+
28
+ export function setTitleLinkTarget(s) {
29
+ // Public function for the user to set the target that clicking on the site title should link to
30
+ titleLinkTarget = s;
31
+ useDefaultTitleLink = false;
32
+ }
33
+
34
+ // Alias for previous name of `setTitleLinkTarget` to maintain backwards compatibility
35
+ export const setBrandLinkTarget = setTitleLinkTarget;
36
+
37
+ export function setHeaderLinksSource(s) {
38
+ // Public function to set the name of an HTML file containing the links to appear on the right side of the header
39
+ // for a given page
40
+ headerLinksSource = s;
41
+ }
42
+
43
+ export function setHeaderSource(s) {
44
+ // Public function to set the name of the header HTML file to be loaded
45
+ headerSource = s;
46
+ }
47
+
48
+ export function setFooterSource(s) {
49
+ // Public function to set the name of the footer HTML file to be loaded
50
+ footerSource = s;
51
+ }
52
+
53
+ const LIGHT_MODE = "light";
54
+ const DARK_MODE = "dark";
55
+
56
+ // Load color mode from session storage and apply it
57
+ let mode = sessionStorage.getItem("mode");
58
+ if (!mode) {
59
+ mode = LIGHT_MODE;
60
+ }
61
+ document.documentElement.setAttribute("data-theme", mode);
62
+
63
+ function toggleMode() {
64
+ let currentMode = document.documentElement.getAttribute("data-theme");
65
+ let new_mode;
66
+
67
+ if (currentMode == DARK_MODE) {
68
+ new_mode = LIGHT_MODE;
69
+ } else {
70
+ new_mode = DARK_MODE;
71
+ }
72
+
73
+ document.documentElement.setAttribute("data-theme", new_mode);
74
+ sessionStorage.setItem("mode", new_mode);
75
+ }
76
+
77
+ export function connectModeToggleButton() {
78
+ // Connect the mode toggle function to the button
79
+ const lModeToggleButton = document.querySelectorAll(".color-mode-toggle");
80
+ lModeToggleButton.forEach(function (modeToggleButton) {
81
+ modeToggleButton.addEventListener("click", toggleMode);
82
+ });
83
+ }
84
+
85
+ // Counter for elements that need to be loaded - each we request loading will increment this by 1
86
+ let loadSteps = 0;
87
+
88
+ function finalizeLoad() {
89
+ // Decrement the load steps and check if all steps are finished. If so, remove the cover
90
+ --loadSteps;
91
+ if (loadSteps <= 0) {
92
+ $("#cover").hide();
93
+ }
94
+ }
95
+
96
+ export function addHeaderLinks() {
97
+ // We want to load in the links, but preserve the existing mode toggle button alongside them, so this function
98
+ // handles saving it and re-adding it
99
+
100
+ let headerLinksParent = $("#psdi-header .navbar__items--right");
101
+ let modeToggle = $("#psdi-header .color-mode-toggle");
102
+
103
+ headerLinksParent.load(headerLinksSource,
104
+ function (_response, status, _xhr) {
105
+ if (status == "error") {
106
+ headerLinksParent[0].textContent = "ERROR: Could not load header links";
107
+ }
108
+ headerLinksParent[0].appendChild(modeToggle[0]);
109
+ connectModeToggleButton();
110
+ finalizeLoad();
111
+ });
112
+ }
113
+
114
+ $(document).ready(function () {
115
+
116
+ // Start fading out the cover over one second as a failsafe in case something goes wrong and it never gets removed
117
+ $("#cover").fadeOut(1000);
118
+
119
+ // Count the elements we'll need to load first, to avoid prematurely removing the cover
120
+ // We load an element only if it's a pure stub with no children; otherwise we assume it is intended to be used
121
+ // as-is and not overwritten by a load. If it's intended to be used as a fallback for if we can't load, it can be
122
+ // assigned the "fallback" class to load if possible despite something existing
123
+
124
+ const headerStub = $("#psdi-header");
125
+ let loadHeader = false;
126
+ if (headerStub.length > 0 && (headerStub[0].childNodes.length == 0 || headerStub[0].classList.contains("fallback"))) {
127
+ loadHeader = true;
128
+ ++loadSteps;
129
+ }
130
+
131
+ const footerStub = $("#psdi-footer");
132
+ let loadFooter = false;
133
+ if (footerStub.length > 0 && (footerStub[0].childNodes.length == 0 || footerStub[0].classList.contains("fallback"))) {
134
+ loadFooter = true;
135
+ ++loadSteps;
136
+ }
137
+
138
+ // Load only if the header stub has no children
139
+ if (loadHeader) {
140
+ $("#psdi-header").load(headerSource,
141
+ function (_response, status, _xhr) {
142
+ if (status != "error") {
143
+ // Check if we should replace the title link by if a value is set, or if the value in the header matches
144
+ // the original value in the source
145
+ let titleLinkElement = $("#psdi-header a.navbar__title")[0];
146
+ if (!useDefaultTitleLink || String(titleLinkElement.href) == ORIG_TITLE_LINK)
147
+ titleLinkElement.href = titleLinkTarget;
148
+
149
+ // Check if we should replace the title by if a value is set, or if the value in the header matches
150
+ // the original value in the source
151
+ let titleElement = $("#psdi-header .navbar__title h5")[0];
152
+ if (!useDefaultTitle || String(titleElement.textContent) == ORIG_TITLE)
153
+ titleElement.textContent = title;
154
+ addHeaderLinks();
155
+ } else {
156
+ $("#psdi-header")[0].textContent = "ERROR: Could not load page header";
157
+ connectModeToggleButton();
158
+ finalizeLoad();
159
+ }
160
+ });
161
+ }
162
+
163
+ // Load only if the footer stub has no children
164
+ if (loadFooter) {
165
+ $("#psdi-footer").load(footerSource,
166
+ function (_response, status, _xhr) {
167
+ if (status == "error") {
168
+ $("#psdi-footer")[0].textContent = "ERROR: Could not load page footer";
169
+ }
170
+ finalizeLoad();
171
+ });
172
+ }
173
+
174
+ if (loadSteps == 0)
175
+ finalizeLoad();
176
+
177
+ });
@@ -0,0 +1,381 @@
1
+ /*
2
+ report.js
3
+ Version 1.0, 26th June 2024
4
+
5
+ This is the JavaScript which makes the report.htm gui work.
6
+ */
7
+
8
+ import { getAllFormats, getConverters } from "./data.js";
9
+ import { loadServiceMode } from "./common.js";
10
+
11
+ var token = "",
12
+ fromList = new Array(),
13
+ toList = new Array(),
14
+ formatList = new Array();
15
+
16
+ const pageURL = new URL(window.location.toLocaleString());
17
+
18
+ // If coming to this page from a local version of the app, warn if the user clicks a link in the header, which will
19
+ // take them to another page on the public app
20
+ const originUrlParam = pageURL.searchParams.get('origin');
21
+ const localOrigin = (originUrlParam != null && originUrlParam.toLowerCase() == "local") ? true : false;
22
+ let originAlertDisplayed = false;
23
+
24
+ if (localOrigin) {
25
+ $("#psdi-header").click(function (e) {
26
+ if (originAlertDisplayed) return;
27
+ alert("WARNING: This is the online, public version of the app, which you arrived at from the local " +
28
+ "app. Press the back button on your browser to return to the local version, or click \"OK\" on this " +
29
+ "alert to continue to the public app.");
30
+ originAlertDisplayed = true;
31
+ });
32
+ }
33
+
34
+ // Set the service mode variable for this page so that only appropriate elements are shown
35
+ loadServiceMode();
36
+
37
+ $(document).ready(function () {
38
+
39
+ token = sessionStorage.getItem("token");
40
+
41
+ $("#success").css({ display: "none" });
42
+
43
+ // Populates the "Convert from" and "Convert to" selection lists
44
+ getAllFormats().then((allFormats) => {
45
+ populateList(allFormats, "from");
46
+ populateList(allFormats, "to");
47
+ populateList(allFormats, "format");
48
+ });
49
+
50
+ $("#reason").change(display);
51
+ $("#fromList").click(populateConversionSuccess);
52
+ $("#toList").click(populateConversionSuccess);
53
+ $("#formatList").click(populateConversionSuccess);
54
+ $("#searchTo").keyup(filterOptions);
55
+ $("#searchFrom").keyup(filterOptions);
56
+ $("#searchFormats").keyup(filterOptions);
57
+ $("#resetButton").click(resetAll);
58
+ $("#resetButton2").click(resetAll);
59
+ $("#reportButton").click(submitUserInput);
60
+ });
61
+
62
+ // Included in this file for convenience. When the 'Report' button is clicked, a user's missing conversion report
63
+ // is only sent if the undisplayed conversion success box is empty (i.e., the conversion really is missing)
64
+ function populateConversionSuccess(event) {
65
+ const selectedText = getSelectedText(this);
66
+
67
+ if (this.id == "fromList") {
68
+ $("#searchFrom").val(selectedText);
69
+ }
70
+ else if (this.id == "toList") {
71
+ $("#searchTo").val(selectedText);
72
+ }
73
+ else {
74
+ $("#searchFormats").val(selectedText);
75
+ }
76
+
77
+ const from_text = $("#searchFrom").val();
78
+ const to_text = $("#searchTo").val();
79
+
80
+ sessionStorage.setItem("in_str", from_text);
81
+ sessionStorage.setItem("out_str", to_text);
82
+
83
+ this.selectionStart = -1;
84
+ this.selectionEnd = -1;
85
+ this.blur();
86
+ emptySuccess();
87
+ hideConverterDetails();
88
+ hideOffer();
89
+
90
+ try {
91
+ const in_str = $("#searchFrom").val(), // e.g. "ins: ShelX"
92
+ in_str_array = in_str.split(": "),
93
+ in_ext = in_str_array[0], // e.g. "ins"
94
+ in_note = in_str_array[1]; // e.g. "ShelX"
95
+
96
+ const out_str = $("#searchTo").val(),
97
+ out_str_array = out_str.split(": "),
98
+ out_ext = out_str_array[0],
99
+ out_note = out_str_array[1];
100
+
101
+ getConverters(in_ext, in_note, out_ext, out_note).then((converters) => {
102
+ populateList(converters, "success");
103
+ });
104
+ }
105
+ catch (e) {
106
+ // Can do without an error message if the 'Conversion options' box remains empty;
107
+ // however, consider a greyed-out message inside the box (using some of the commented out code below).
108
+
109
+ // const ID_a = getFormat($("#searchFrom").val()),
110
+ // ID_b = getFormat($("#searchTo").val());
111
+
112
+ // if (ID_a.toString() != ID_b.toString() && ID_a != "" && ID_b != "") {
113
+ // conversionSuccessEmpty();
114
+ //}
115
+ }
116
+ }
117
+
118
+ // Retrieve selected text from the "Conversion success" textarea
119
+ function getSelectedText(el) {
120
+ const text = el.value;
121
+ const before = text.substring(0, el.selectionStart);
122
+ const after = text.substring(el.selectionEnd, text.length);
123
+
124
+ el.selectionStart = before.lastIndexOf("\n") >= 0 ? before.lastIndexOf("\n") + 1 : 0;
125
+ el.selectionEnd = after.indexOf("\n") >= 0 ? el.selectionEnd + after.indexOf("\n") : text.length;
126
+
127
+ return el.value.substring(el.selectionStart, el.selectionEnd);
128
+ }
129
+
130
+ // Hides converter details
131
+ function hideConverterDetails() {
132
+ $("#converter").css({ display: "none" });
133
+ $("h3").css({ display: "none" });
134
+ }
135
+
136
+ // Submits user input
137
+ function submitUserInput() {
138
+ const from = $("#searchFrom").val(),
139
+ to = $("#searchTo").val();
140
+
141
+ var reason = $("#in").val(),
142
+ missing = $("#missingFormat").val()
143
+
144
+ if (reason.length > 9 && reason.length < 501) {
145
+ if ($("#reason").val() == "format") {
146
+ if (missing.length > 1 && missing.length < 101) {
147
+ submitFeedback({
148
+ type: "missingFormat",
149
+ missing: missing,
150
+ reason: reason
151
+ });
152
+ }
153
+ else {
154
+ alert("Please enter the missing format (2 to 100 characters).");
155
+ }
156
+ }
157
+ else {
158
+ if (from != "" && to != "") {
159
+ if ($("#success option").length == 0) {
160
+ submitFeedback({
161
+ type: "missingConversion",
162
+ from: from,
163
+ to: to,
164
+ reason: reason
165
+ });
166
+ }
167
+ else {
168
+ alert("At least one converter is capable of carrying out this conversion, therefore your report has not been sent. If you wish to send feedback about this conversion, please click on 'Contact' in the navigation bar.");
169
+ }
170
+ }
171
+ else if (to != "") {
172
+ alert("Please select 'from' format.");
173
+ }
174
+ else if (from != "") {
175
+ alert("Please select 'to' format.");
176
+ }
177
+ else {
178
+ alert("Please select 'to' and 'from' formats.");
179
+ }
180
+ }
181
+ }
182
+ else {
183
+ alert("Please enter a reason, etc. (10 to 500 characters).");
184
+ }
185
+ }
186
+
187
+ // Hide Open Babel conversion offer (not required to do anything on this page)
188
+ function hideOffer() { }
189
+
190
+ // Writes user input to a server-side file
191
+ // $$$$$$$$$$ Retain for now in case logging to file is required for some other purpose $$$$$$$$$$
192
+ //function writeLog(message) {
193
+ // var jqXHR = $.get(`/data/`, {
194
+ // 'token': token,
195
+ // 'data': message
196
+ //})
197
+ // .done(response => {
198
+ // alert("Report received!");
199
+ // })
200
+ // .fail(function(e) {
201
+ // alert("Reporting failed. Please provide feedback by clicking on 'Contact' in the navigation bar.");
202
+
203
+ // // For debugging
204
+ //console.log("Error writing to log");
205
+ // console.log(e.status);
206
+ // console.log(e.responseText);
207
+ // })
208
+ //}
209
+
210
+ // Submit feedback
211
+ function submitFeedback(data) {
212
+ $.post(`/feedback/`, {
213
+ 'token': token,
214
+ 'data': JSON.stringify(data)
215
+ })
216
+ .done(() => {
217
+ alert("Report received!");
218
+ })
219
+ .fail(function (e) {
220
+ alert("Reporting failed. Please provide feedback by clicking on 'Contact' in the navigation bar.");
221
+
222
+ // For debugging
223
+ console.error("Error submitting feedback", e.status, e.responseText);
224
+ });
225
+ }
226
+
227
+ // Only options having user filter input as a substring (case insensitive) are included in the selection list
228
+ function filterOptions(event) {
229
+ const str = this.value.toLowerCase();
230
+ var box, list,
231
+ count = 0,
232
+ text = "";
233
+
234
+ if (this.id == "searchFrom") {
235
+ box = $("#fromList");
236
+ list = fromList;
237
+ }
238
+ else if (this.id == "searchTo") {
239
+ box = $("#toList");
240
+ list = toList;
241
+ }
242
+ else {
243
+ box = $("#formatList");
244
+ list = formatList;
245
+ }
246
+
247
+ box.children().remove();
248
+
249
+ for (var i = 0; i < list.length; i++) {
250
+ if (list[i].toLowerCase().includes(str)) {
251
+ box.append($('<option>', { text: list[i] }));
252
+ count += 1;
253
+ }
254
+ }
255
+
256
+ if (this.id == "searchFrom") {
257
+ $("#fromLabel").html("Select format to convert from (" + count + "):");
258
+ }
259
+ else if (this.id == "searchTo") {
260
+ $("#toLabel").html("Select format to convert to (" + count + "):");
261
+ }
262
+ else {
263
+ $("#formatLabel").html("Check that the format is not present in the list. If it is, consider reporting a missing conversion. (" + count + ")");
264
+ }
265
+
266
+ $("#success").prop({ disabled: true });
267
+ emptySuccess();
268
+ hideConverterDetails();
269
+ hideOffer();
270
+ }
271
+
272
+ // Empties the "Conversion success" textarea
273
+ function emptySuccess() {
274
+ $("#success").html("");
275
+ }
276
+
277
+ // Populates a selection list
278
+ function populateList(entries, sel) {
279
+
280
+ let rows = [];
281
+
282
+ if ((sel === "from") || (sel === "to") || (sel === "format")) {
283
+
284
+ rows = entries.map(entry => `${entry.extension}: ${entry.note}`);
285
+
286
+ } else if (sel === "success") {
287
+
288
+ rows = entries.map(entry => `${entry.name}: ${entry.degree_of_success}`);
289
+ }
290
+
291
+ rows.sort(function (a, b) {
292
+ return a.toLowerCase().localeCompare(b.toLowerCase());
293
+ });
294
+
295
+ $("#success").prop({ disabled: true });
296
+
297
+ for (var i = 0; i < rows.length; i++) {
298
+ const support = rows[i].substring(0, 10) == "Open Babel" ? " (supported)" : " (unsupported)";
299
+
300
+ if (sel == "success") {
301
+ if (rows.length > 0) {
302
+ $("#success").prop({ disabled: false });
303
+ }
304
+
305
+ $("#success").append($('<option>', { text: "" + rows[i] + support }));
306
+ }
307
+
308
+ if (sel == "from") {
309
+ $("#fromList").append($('<option>', { text: rows[i] }));
310
+ fromList[i] = rows[i] + "\n";
311
+ }
312
+ else if (sel == "to") {
313
+ $("#toList").append($('<option>', { text: rows[i] }));
314
+ toList[i] = rows[i] + "\n";
315
+ }
316
+ else if (sel == "format") {
317
+ $("#formatList").append($('<option>', { text: rows[i] }));
318
+ formatList[i] = rows[i] + "\n";
319
+ }
320
+ }
321
+
322
+ if (sel != "success") {
323
+ $("#fromLabel").html("Select format to convert from (" + fromList.length + "):");
324
+ $("#toLabel").html("Select format to convert to (" + toList.length + "):");
325
+ $("#formatLabel").html("Check that the format is not present in the list. If it is, consider reporting a missing conversion. (" + toList.length + ")");
326
+ }
327
+ }
328
+
329
+ // Resets the filtering and format list boxes
330
+ function resetAll() {
331
+ $("#searchFrom").val("");
332
+ $("#searchFrom").keyup();
333
+
334
+ $("#searchTo").val("");
335
+ $("#searchTo").keyup();
336
+
337
+ $("#searchFormats").val("");
338
+ $("#searchFormats").keyup();
339
+ }
340
+
341
+ // Displays format or conversion related content as appropriate
342
+ function display(event) {
343
+ const selectedText = getSelectedText(this);
344
+
345
+ $("#in").val("");
346
+ $("#missingFormat").val("");
347
+
348
+ if (selectedText == "conversion") {
349
+ $("#in_out_formats").css({ display: "block" });
350
+ $("#message").css({ display: "inline" });
351
+
352
+ $("#userInput").css({ display: "block" });
353
+
354
+ $("#formats").css({ display: "none" });
355
+ $("#missing").css({ display: "none" });
356
+
357
+ $("#message").html("Explain why the conversion is required and provide a link to appropriate documentation if possible [max 500 characters].");
358
+ $("#message1").html("The displayed 'from' and 'to' formats will be automatically submitted with your message.");
359
+ }
360
+ else if (selectedText == "format") {
361
+ $("#formats").css({ display: "block" });
362
+ $("#missing").css({ display: "block" });
363
+
364
+ $("#userInput").css({ display: "block" });
365
+
366
+ $("#in_out_formats").css({ display: "none" });
367
+ $("#message").css({ display: "none" });
368
+
369
+ $("#message1").html("Enter details of the file conversions expected for this format and provide a link to appropriate documentation if possible [max 500 characters].");
370
+ }
371
+ else {
372
+ $("#in_out_formats").css({ display: "none" });
373
+ $("#message").css({ display: "none" });
374
+
375
+ $("#formats").css({ display: "none" });
376
+ $("#missing").css({ display: "none" });
377
+
378
+ $("#userInput").css({ display: "none" });
379
+ }
380
+ }
381
+
@@ -0,0 +1,147 @@
1
+ /*
2
+ format.css
3
+ Version 1.0, 11th October 2024
4
+ */
5
+
6
+ @import url("./psdi-common.css");
7
+
8
+ /* Forms inherit style from normal content, and make sure content is well away from the edges */
9
+ form {
10
+ width : 95%;
11
+ min-width : 320px;
12
+ padding-top: 1rem;
13
+ align-self : center;
14
+ }
15
+
16
+ /* Padding for link to converter website. */
17
+ #visit {
18
+ padding-left: 0.125rem;
19
+ }
20
+
21
+ /* Width management for select boxes and forms */
22
+
23
+ .med-width {
24
+ width: 25rem;
25
+ }
26
+
27
+ @media (max-width: 25rem) {
28
+ .med-width {
29
+ width: 100%
30
+ }
31
+ }
32
+
33
+ .large-width {
34
+ width: 50rem;
35
+ }
36
+
37
+ @media (max-width: 50rem) {
38
+ .large-width {
39
+ width: 100%
40
+ }
41
+
42
+ input.large-width {
43
+ width: calc(100% - 0.5rem)
44
+ }
45
+ }
46
+
47
+ /* Converter details, user input and file conversion initially not displayed. */
48
+ .init-hidden {
49
+ display: none
50
+ }
51
+
52
+ /* Buttons that are initially disabled */
53
+ input.button.init-disabled {
54
+ background-color: var(--psdi-bg-color-secondary);
55
+ color : gray
56
+ }
57
+
58
+ /* Small vertical space. */
59
+ .smallGap {
60
+ padding: 0.125rem;
61
+ }
62
+
63
+ /* Medium vertical space. */
64
+ .medGap {
65
+ padding: 1rem;
66
+ }
67
+
68
+ /* Large vertical space. */
69
+ .largeGap {
70
+ padding: 8rem;
71
+ }
72
+
73
+ /* Grid for textarea label/elements. */
74
+ .access-options {
75
+ display : grid;
76
+ grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
77
+ column-gap : 2rem;
78
+ }
79
+
80
+ .access-option-container {
81
+ padding-left : 0 1rem 0 1rem;
82
+ display : flex;
83
+ flex-direction : column;
84
+ justify-content: flex-end;
85
+ }
86
+
87
+ [data-theme="dark"] .access-option-container.lm-only {
88
+ display: none;
89
+ }
90
+
91
+ /* Select boxes for accessibility options */
92
+ .access-option-container select {
93
+ min-width: 5rem;
94
+ width : 100%;
95
+ }
96
+
97
+ select#light-colour,
98
+ select#dark-background {
99
+ background-color: var(--ifm-color-primary);
100
+ color : var(--psdi-light-text-color-body);
101
+ }
102
+
103
+ select#size option {
104
+ font-family: var(--psdi-default-font);
105
+ }
106
+
107
+ select#font option {
108
+ font-size: var(--psdi-default-font-size);
109
+ }
110
+
111
+ select#dark-colour option {
112
+ color: var(--psdi-default-dark-text-color-body);
113
+ }
114
+
115
+ select#light-colour option {
116
+ background-color: var(--ifm-color-primary);
117
+ color : var(--psdi-default-light-text-color-body);
118
+ }
119
+
120
+ select#light-background option {
121
+ background-color: var(--psdi-default-background-color);
122
+ }
123
+
124
+ select#dark-background option {
125
+ background-color: var(--psdi-default-color-primary);
126
+ color : var(--psdi-light-text-color-body);
127
+ }
128
+
129
+ /* We use the service-mode variable to control whether elements with the "service-only" or "local-only" class are shown
130
+ */
131
+ [service-mode=True] .local-only {
132
+ display: none;
133
+ }
134
+
135
+ [service-mode=False] .service-only {
136
+ display: none;
137
+ }
138
+
139
+ /* We use the production-mode variable to control whether elements with the "prod-only" or "dev-only" class are shown
140
+ */
141
+ [production-mode=True] .prod-only {
142
+ display: none;
143
+ }
144
+
145
+ [production-mode=False] .dev-only {
146
+ display: none;
147
+ }