summaryrefslogtreecommitdiff
path: root/src/SMAPI.Web/Views/LogParser/Index.cshtml
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2017-10-27 19:38:13 -0400
committerJesse Plamondon-Willard <github@jplamondonw.com>2017-10-27 19:38:13 -0400
commit9f5af37391ac196fe183122f57496846843335cd (patch)
tree32980a41fffa414a6be982aeaff4a188b2dbcf5e /src/SMAPI.Web/Views/LogParser/Index.cshtml
parent6cbe43a233eccbc6c8d1cfdd9c80e391463eb7c8 (diff)
downloadSMAPI-9f5af37391ac196fe183122f57496846843335cd.tar.gz
SMAPI-9f5af37391ac196fe183122f57496846843335cd.tar.bz2
SMAPI-9f5af37391ac196fe183122f57496846843335cd.zip
move log parser CSS/JS out of HTML (#358)
Diffstat (limited to 'src/SMAPI.Web/Views/LogParser/Index.cshtml')
-rw-r--r--src/SMAPI.Web/Views/LogParser/Index.cshtml674
1 files changed, 6 insertions, 668 deletions
diff --git a/src/SMAPI.Web/Views/LogParser/Index.cshtml b/src/SMAPI.Web/Views/LogParser/Index.cshtml
index 417fe428..021293b6 100644
--- a/src/SMAPI.Web/Views/LogParser/Index.cshtml
+++ b/src/SMAPI.Web/Views/LogParser/Index.cshtml
@@ -1,6 +1,12 @@
@{
ViewData["Title"] = "SMAPI log parser";
}
+@section Head {
+ <link rel="stylesheet" href="~/Content/css/log-parser.css" />
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" crossorigin="anonymous"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/lz-string/1.4.4/lz-string.min.js" crossorigin="anonymous"></script>
+ <script src="~/Content/js/log-parser.js"></script>
+}
<h2>How to share a SMAPI log</h2>
<ol>
@@ -14,387 +20,10 @@
<em>TODO</em>
-
<!DOCTYPE html>
<html>
<head>
<title>SMAPI log parser</title>
- <style type="text/css">
- body {
- font-size: 10pt;
- background: #fff;
- }
-
- .mod-repeat {
- font-size: 8pt;
- }
-
- input[type="button"] {
- cursor: pointer;
- }
-
- .template {
- display: none;
- }
-
- .popup, #uploader {
- position: fixed;
- top: 0px;
- left: 0px;
- right: 0px;
- bottom: 0;
- background-color: rgba(0, 0, 0, .33);
- z-index: 2;
- display: none;
- padding: 5px;
- }
-
- #uploader:after {
- content: attr(data-text);
- display: block;
- width: 100px;
- height: 24px;
- line-height: 25px;
- border: 1px solid #000;
- background: #fff;
- position: absolute;
- top: 50%;
- left: 50%;
- margin: -12px -50px 0 0;
- font-size: 18px;
- font-weight: bold;
- text-align: center;
- border-radius: 5px;
- }
-
- .popup h1 {
- position: absolute;
- top: 10%;
- left: 50%;
- margin-left: -150px;
- text-align: center;
- width: 300px;
- border: 1px solid #008;
- border-radius: 5px;
- background: #fff;
- font-family: sans-serif;
- font-size: 40px;
- margin-top: -25px;
- }
-
- .frame {
- margin: auto;
- margin-top: 25px;
- position: absolute;
- top: 10%;
- left: 10%;
- right: 10%;
- bottom: 10%;
- padding-bottom: 30px;
- }
-
- .buttons {
- position: absolute;
- display: inline-block;
- bottom: -10px;
- right: 0px;
- padding: 5px;
- border: 1px solid #008;
- border-radius: 5px;
- background: #fff;
- }
-
- #cancel, #closeraw {
- font-size: 20px;
- border-radius: 5px;
- border: 1px solid #880000;
- background-color: #fcc;
- outline: none;
- box-shadow: inset 0px 0px 1px 1px rgba(0, 0, 0, .2);
- }
-
- #cancel:hover, #closeraw:hover {
- background-color: #fee;
- }
-
- #submit {
- font-size: 20px;
- border-radius: 5px;
- border: 1px solid #008800;
- background-color: #cfc;
- outline: none;
- box-shadow: inset 0px 0px 1px 1px rgba(0, 0, 0, .2);
- }
-
- #submit:hover {
- background-color: #efe;
- }
-
- #input, #dataraw {
- width: 100%;
- height: 100%;
- max-width: 100%;
- max-height: 100%;
- margin: auto;
- box-sizing: border-box;
- border-radius: 5px;
- border: 1px solid #000088;
- outline: none;
- box-shadow: inset 0px 0px 1px 1px rgba(0, 0, 192, .2);
- }
-
- .color-red {
- color: red;
- }
-
- .color-green {
- color: green;
- }
-
- #tabs {
- top: 0px;
- left: 0px;
- right: 0px;
- border-bottom: 0;
- display: block;
- position: fixed;
- margin: 0;
- padding: 0;
- background: linear-gradient(to bottom, rgba(255, 255, 255, 1) 0%, rgba(210, 235, 249, 1) 100%);
- }
-
- #tabs li {
- margin: 5px 1px 0 0;
- height: 25px;
- float: left;
- display: inline-block;
- width: 75px;
- border: 1px solid #000000;
- border-bottom: 0;
- border-radius: 5px 5px 0 0;
- text-align: center;
- font-family: monospace;
- font-size: 18px;
- cursor: pointer;
- font-weight: bold;
- color: #000;
- text-shadow: 0px 0px 2px #fff;
- border-color: #880000;
- background-color: #fcc;
- box-shadow: inset 0px 0px 1px 1px rgba(0, 0, 0, .2);
- }
-
- #tabs li:hover {
- background-color: #fee;
- }
-
- #tabs li:first-child {
- margin-left: 5px;
- }
-
- #tabs li.active {
- background: #cfc;
- border-color: #008800;
- }
-
- #tabs li.active:hover {
- background: #efe;
- }
-
- #tabs li.upload {
- float: right;
- background: #ccf;
- border-color: #000088;
- margin-right: 5px;
- }
-
- #tabs li.upload:hover {
- background: #eef;
- }
-
- #tabs li.notice {
- color: #000000;
- background: transparent;
- border: 0;
- padding-top: 1px;
- font-size: 13px;
- font-weight: normal;
- width: auto;
- margin-left: 5px;
- cursor: default;
- box-shadow: none;
- font-style: italic;
- }
-
- #output {
- border-top: 1px solid #888;
- position: fixed;
- top: 30px;
- left: 0px;
- right: 0px;
- bottom: 0px;
- padding: 10px;
- overflow: auto;
- font-family: monospace;
- }
-
- #output > * {
- display: block;
- }
-
- #output.trace .trace,
- #output.debug .debug,
- #output.info .info,
- #output.alert .alert,
- #output.warn .warn,
- #output.error .error {
- display: none;
- }
-
- #output .trace {
- color: #999;
- }
-
- #output .debug {
- color: #595959;
- }
-
- #output .info {
- color: #000
- }
-
- #output .alert {
- color: #b0b;
- }
-
- #output .warn {
- color: #f80
- }
-
- #output .error {
- color: #f00
- }
-
- #output .always {
- font-weight: bold;
- border-bottom: 1px dashed #888888;
- padding-bottom: 10px;
- margin-bottom: 5px;
- }
-
- caption {
- text-align: left;
- padding-top: 2px;
- }
-
- #log {
- border-spacing: 0;
- }
-
- #log tr {
- background: #fff;
- }
-
- #log td {
- padding: 0 1px;
- background: inherit;
- border-bottom: 1px dotted #ccc;
- border-top: 2px solid #fff;
- vertical-align: top;
- }
-
- #log td:not(:last-child) {
- max-width: 175px;
- padding: 0 4px;
- overflow: hidden;
- white-space: nowrap;
- }
-
- #log td[data-title]:hover {
- font-size: 1px;
- overflow: inherit;
- position: relative;
- }
-
- #log td:nth-child(3):hover:after {
- content: attr(data-title);
- display: block;
- position: absolute;
- border-radius: 4px;
- box-shadow: 1px 1px 2px #ccc;
- background: inherit;
- border: 1px solid #ccc;
- background: #efefef;
- padding: 1px 1px 0 1px;
- font-size: 10pt;
- top: -2px;
- left: 2px;
- color: #000;
- }
-
- #log td:last-child {
- width: 100%;
- }
-
- table#gameinfo,
- table#modslist {
- border: 1px solid #000000;
- background: #ffffff;
- border-radius: 5px;
- border-spacing: 1px;
- overflow: hidden;
- cursor: default;
- box-shadow: 1px 1px 1px 1px #dddddd;
- }
-
- #modslist {
- min-width: 400px;
- }
-
- #gameinfo td:first-child {
- padding-right: 5px;
- }
-
- #gameinfo tr,
- #modslist tr {
- background: #eee
- }
-
- #gameinfo tr:nth-child(even),
- #modslist tr:nth-child(even) {
- background: #fff
- }
-
- #modslist tr {
- cursor: pointer;
- }
-
- span.notice {
- font-weight: normal;
- font-size: 11px;
- position: relative;
- top: -1px;
- display: none;
- }
-
- span.notice.btn {
- cursor: pointer;
- border: 1px solid #000;
- border-radius: 5px;
- position: relative;
- top: -1px;
- padding: 0 2px;
- background: #eee;
- }
-
- #output:not(.modfilter) span.notice.txt {
- display: inline-block;
- }
-
- #output.modfilter span.notice.btn {
- display: inline-block;
- }
- </style>
<style type="text/css" id="modflags"></style>
</head>
<body>
@@ -486,296 +115,5 @@
</div>
</div>
<div id="uploader"></div>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js" crossorigin="anonymous"></script>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/lz-string/1.4.4/lz-string.min.js" crossorigin="anonymous"></script>
- <script>
- $(function() {
- function modClicked(evt) {
- var id = $(evt.currentTarget).attr("id").split('-')[1],
- cls = "mod-" + id;;
- if (output.hasClass(cls))
- filters--;
- else
- filters++;
- output.toggleClass(cls);
- if (filters == 0) {
- output.removeClass("modfilter");
- } else {
- output.addClass("modfilter");
- }
- }
-
- function removeFilter() {
- for (var c = 0; c < modInfo.length; c++) {
- output.removeClass("mod-" + c);
- }
- filters = 0;
- output.removeClass("modfilter");
- }
-
- function selectAll() {
- for (var c = 0; c < modInfo.length; c++) {
- output.addClass("mod-" + c);
- }
- filters = modInfo.length;
- output.addClass("modfilter");
- }
-
- function parseData() {
- Stage = "parseData.pre";
- var data = $("#input").val();
- if (!data) {
- Stage = "parseData.checkNullData";
- throw new Error("Field `data` is null");
-
- }
- var dataInfo = regexInfo.exec(data) || regexInfo.exec(data) || regexInfo.exec(data),
- dataMods = regexMods.exec(data) || regexMods.exec(data) || regexMods.exec(data),
- dataDate = regexDate.exec(data) || regexDate.exec(data) || regexDate.exec(data),
- dataPath = regexPath.exec(data) || regexPath.exec(data) || regexPath.exec(data),
- match;
- console.log("dataInfo:", dataInfo);
- console.log("dataMods:", dataMods);
- console.log("dataDate:", dataDate);
- console.log("dataPath:", dataPath);
- Stage = "parseData.doNullCheck";
- if (!dataInfo)
- throw new Error("Field `dataInfo` is null");
- if (!dataMods)
- throw new Error("Field `dataMods` is null");
- if (!dataPath)
- throw new Error("Field `dataPath` is null");
- dataMods = dataMods[0];
- Stage = "parseData.setupDefaults";
- modMap = {
- "SMAPI": 0
- };
- modErrors = {
- "SMAPI": 0,
- "Console.Out": 0
- };
- logInfo = [];
- modInfo = [
- ["SMAPI", dataInfo[1], "Zoryn, CLxS & Pathoschild"]
- ];
- Stage = "parseData.parseInfo";
- if (dataDate)
- var date = new Date(dataDate[1] + "Z");
- versionInfo = [dataInfo[1], dataInfo[2], dataInfo[3], dataDate ? date.getFullYear() + "-" + ("0" + date.getMonth().toString()).substr(-2) + "-" + ("0" + date.getDay().toString()).substr(-2) + " at " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds() + " " + date.toLocaleTimeString('en-us', { timeZoneName: 'short' }).split(' ')[2] : "No timestamp found", dataPath[1]];
- Stage = "parseData.parseMods";
- while (match = regexMod.exec(dataMods)) {
- modErrors[match[1]] = 0;
- modMap[match[1]] = modInfo.length;
- modInfo.push([match[1], match[2], match[3] ? ("by " + match[3]) : "Unknown author"]);
- }
- Stage = "parseData.parseLog";
- while (match = regexLog.exec(data)) {
- if (match[2] == "ERROR")
- modErrors[match[3]]++;
- logInfo.push([match[1], match[2], match[3], match[4]]);
- }
- Stage = "parseData.post";
- modMap["Console.Out"] = modInfo.length;
- modInfo.push(["Console.Out", "", ""]);
- }
-
- function renderData() {
- Stage = "renderData.pre";
- output.html(prepare(templateBody, versionInfo));
- var modslist = $("#modslist"), log = $("#log"), modCache = [], y = 0
- for (; y < modInfo.length; y++) {
- var errors = modErrors[modInfo[y][0]],
- err, cls = "color-red";
- if (errors == 0) {
- err = "No Errors";
- cls = "color-green";
- } else if (errors == 1)
- err = "1 Error";
- else
- err = errors + " Errors";
- modCache.push(prepare(templateModentry, [y, modInfo[y][0], modInfo[y][1], modInfo[y][2], cls, err]));
- }
- modslist.append(modCache.join(""));
- for (var z = 0; z < modInfo.length; z++)
- $("#modlink-" + z).on("click", modClicked);
- var flagCache = [];
- for (var c = 0; c < modInfo.length; c++)
- flagCache.push(prepare(templateCss, [c]));
- flags.html(flagCache.join(""));
- var logCache = [], dupeCount = 0, dupeMemory = "|||";
- for (var x = 0; x < logInfo.length; x++) {
- var dm = logInfo[x][1] + "|" + logInfo[x][2] + "|" + logInfo[x][3];
- if (dupeMemory != dm) {
- if (dupeCount > 0)
- logCache.push(prepare(templateLognotice, [logInfo[x - 1][1].toLowerCase(), modMap[logInfo[x - 1][2]], dupeCount]));
- dupeCount = 0;
- dupeMemory = dm;
- logCache.push(prepare(templateLogentry, [logInfo[x][1].toLowerCase(), modMap[logInfo[x][2]], logInfo[x][0], logInfo[x][1], logInfo[x][2], logInfo[x][3].split(" ").join("&nbsp ").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\n/g, "<br />")]));
- }
- else
- dupeCount++;
- }
- log.append(logCache.join(""));
- $("#modlink-r").on("click", removeFilter);
- $("#modlink-a").on("click", selectAll);
- }
-
- function prepare(str, arr) {
- var regex = /\{(\d)\}/g,
- match;
- while (match = regex.exec(str))
- str = str.replace(match[0], arr[match[1]]);
- return str;
- }
- function loadData() {
- try {
- Stage = "loadData.Pre";
- var start = performance.now();
- parseData();
- renderData();
- var end = performance.now();
- $(".always").prepend('<div>Log processed in: ' + (Math.round((end - start) * 100) / 100) + ' ms (<a id="viewraw" href="#">View raw</a>)</div><br />');
- $("#viewraw").on("click", function() {
- $("#dataraw").val($("#input").val());
- $("#popup-raw").fadeIn();
- })
- Stage = "loadData.Post";
- }
- catch (err) {
- $("#output").html('<div id="log" class="color-red"><h1>Parsing failed!</h1>Parsing of the log failed, details follow.<br />&nbsp;<p>Stage: ' + Stage + '</p>' + err + '<hr /><div id="rawlog"></div></div>');
- $("#rawlog").text($("#input").val());
- }
- }
- function getData() {
- $("#uploader").attr("data-text", "Loading...");
- $("#uploader").fadeIn();
- $.get("https://cors-anywhere.herokuapp.com/pastebin.com/raw/" + location.search.substring(1) + "/?nocache=" + Math.random(), function(data, state, xhr) {
- if (data.substring(0, 9) == "<!DOCTYPE") {
- $("#output").html('<div id="log" class="color-red"><h1>Captcha required!</h1>The pastebin server is asking for a captcha, but their API doesnt let us show it to you directly.<br />Instead, to finish saving the log, you need to <a href="https://pastebin.com/' + location.search.substring(1) + '" target="_blank">solve the captcha in a new tab</a>, once you have done so, reload this page.</div>');
- }
- else {
- $("#input").val(LZString.decompressFromUTF16(data) || data);
- loadData();
- }
- $("#uploader").fadeOut();
- });
- }
- var Stage,
- flags = $("#modflags"),
- output = $("#output"),
- filters = 0,
- memory = "",
- versionInfo,
- modInfo,
- modMap,
- modErrors,
- logInfo,
- templateBody = $("#template-body").text(),
- templateModentry = $("#template-modentry").text(),
- templateCss = $("#template-css").text(),
- templateLogentry = $("#template-logentry").text(),
- templateLognotice = $("#template-lognotice").text(),
- regexInfo = /\[[\d\:]+ INFO SMAPI] SMAPI (.*?) with Stardew Valley (.*?) on (.*?)\n/g,
- regexMods = /\[[^\]]+\] Loaded \d+ mods:(?:\n\[[^\]]+\] .+)+/g,
- regexLog = /\[([\d\:]+) (TRACE|DEBUG|INFO|WARN|ALERT|ERROR) ? ([^\]]+)\] ?((?:\n|.)*?)(?=(?:\[\d\d:|$))/g,
- regexMod = /\[(?:.*?)\] *(.*?) (\d+\.?(?:.*?))(?: by (.*?))? \|(?:.*?)$/gm,
- regexDate = /\[\d{2}:\d{2}:\d{2} TRACE SMAPI\] Log started at (.*?) UTC/g,
- regexPath = /\[\d{2}:\d{2}:\d{2} DEBUG SMAPI\] Mods go here: (.*?)(?:\n|$)/g
- ;
- $("#tabs li:not(.notice)").on("click", function(evt) {
- var t = $(evt.currentTarget)
- t.toggleClass("active");
- $("#output").toggleClass(t.text().toLowerCase());
- })
- $("#upload").on("click", function() {
- memory = $("#input").val() || "";
- $("#input").val("");
- $("#popup-upload").fadeIn();
- })
- var proxies = [
- "https://cors-anywhere.herokuapp.com/",
- "https://galvanize-cors-proxy.herokuapp.com/"
- ];
- $('#popup-upload').on({
- 'dragover dragenter': function(e) {
- e.preventDefault();
- e.stopPropagation();
- },
- 'drop': function(e) {
- $("#uploader").attr("data-text", "Reading...")
- $("#uploader").show();
- var dataTransfer = e.originalEvent.dataTransfer;
- if (dataTransfer && dataTransfer.files.length) {
- e.preventDefault();
- e.stopPropagation();
- var file = dataTransfer.files[0];
- var reader = new FileReader();
- reader.onload = $.proxy(function(file, $input, event) {
- $input.val(event.target.result);
- $("#uploader").fadeOut();
- $("#submit").click();
- }, this, file, $("#input"));
- reader.readAsText(file);
- }
- }
- });
- function logSize(id, str) {
- console.log(id + ":", str.length * 2, "bytes", Math.round(str.length / 5.12) / 100, "kb");
- }
- $("#submit").on("click", function() {
- $("#popup-upload").fadeOut();
- if ($("#input").val()) {
- memory = "";
- var raw = $("#input").val();
- var paste = LZString.compressToUTF16(raw);
- logSize("Raw", raw);
- logSize("Compressed", paste);
- if (paste.length * 2 > 524288) {
- $("#output").html('<div id="log" class="color-red"><h1>Unable to save!</h1>This log cannot be saved due to its size.<hr />' + $("#input").val() + '</div>');
- return;
- }
- console.log("paste:", paste);
- var packet = {
- api_dev_key: "b8219d942109d1e60ebb14fbb45f06f9",
- api_option: "paste",
- api_paste_private: 1,
- api_paste_code: paste,
- api_paste_expire_date: "1W"
- };
- $("#uploader").attr("data-text", "Saving...");
- $("#uploader").fadeIn();
- var uri = proxies[Math.floor(Math.random() * proxies.length)] + "pastebin.com/api/api_post.php";
- console.log(packet, uri);
- $.post(uri, packet, function(data, state, xhr) {
- $("#uploader").fadeOut();
- console.log("Result: ", data);
- if (data.substring(0, 15) == "Bad API request")
- $("#output").html('<div id="log" class="color-red"><h1>Parsing failed!</h1>Parsing of the log failed, details follow.<br />&nbsp;<p>Stage: Upload</p>Error: ' + data + '<hr />' + $("#input").val() + '</div>');
- else if (data)
- location.href = "?" + data.split('/').pop();
- else
- $("#output").html('<div id="log" class="color-red"><h1>Parsing failed!</h1>Parsing of the log failed, details follow.<br />&nbsp;<p>Stage: Upload</p>Error: Received null response<hr />' + $("#input").val() + '</div>');
- })
- } else {
- alert("Unable to parse log, the input is empty!");
- $("#uploader").fadeOut();
- }
- })
- $("#cancel").on("click", function() {
- $("#popup-upload").fadeOut(400, function() {
- $("#input").val(memory);
- memory = "";
- });
- });
- $("#closeraw").on("click", function() {
- $("#popup-raw").fadeOut(400);
- })
- if (location.search) {
- getData();
- }
- else
- $("#popup-upload").fadeIn();
- })
- </script>
</body>
</html>