From c3523d020774443b42b5d110e839f7c7de6b8f36 Mon Sep 17 00:00:00 2001 From: Lennard Sprong Date: Sun, 8 Sep 2024 13:25:15 +0200 Subject: [PATCH] parser: Allow importing URLs in Duplicate URL format --- src/puzzle/FileData.js | 5 ++++ src/pzpr/parser.js | 44 +++++++++++++++++++++++++--------- test/.eslintrc.json | 1 + test/pzpr/parser_test.js | 51 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 89 insertions(+), 12 deletions(-) diff --git a/src/puzzle/FileData.js b/src/puzzle/FileData.js index 784c00b23..a2b24b166 100644 --- a/src/puzzle/FileData.js +++ b/src/puzzle/FileData.js @@ -29,6 +29,11 @@ bd.initBoardSize(pzl.cols, pzl.rows); + if (pzl.variant !== null) { + puzzle.setConfig("variant", true); + puzzle.setConfig("variantid", pzl.variant); + } + this.filever = pzl.filever; if (filetype !== pzl.FILE_PBOX_XML) { this.lineseek = 0; diff --git a/src/pzpr/parser.js b/src/pzpr/parser.js index 2ef7ecf19..ac2ab4ba1 100644 --- a/src/pzpr/parser.js +++ b/src/pzpr/parser.js @@ -158,24 +158,40 @@ } // ぱずぷれv3の場合 else { - if (url.startsWith("v:/")) { - url = url.substring(3); - this.variant = true; - } - var qs = url.indexOf("/", url.indexOf("?")); + var start = url.indexOf("?"); + var qs = url.indexOf("/", start); var first = ""; if (qs > -1) { - first = url.substring(url.indexOf("?") + 1, qs); + first = url.substring(start + 1, qs); + + while (first.match(/^(\w+)\=(\w+)\&/)) { + if (RegExp.$1 === "type") { + this.mode = RegExp.$2; + } + + start = url.indexOf("&", start + 1); + first = url.substring(start + 1, qs); + } } else { - first = url.substr(url.indexOf("?") + 1); + first = url.substring(start + 1); + } + + if (first.startsWith("v:")) { + var newstart = start + first.length + 2; + var next = url.indexOf("/", newstart); + first = url.substring(newstart, next); } + if (first.match(/^pzprv[0-9.]*$/)) { + if (start > -1 && start < qs) { + // Remove other querystring parameters + url = url.substring(start + 1); + } + // encoded file; extract pid url = decodeURIComponent(url); - var parts = url.split("/"); - if (parts.length >= 2) { - this.pid = parts[1]; - } + var parts = url.split("/", 4); + this.pid = parts[0].startsWith("v:") ? parts[2] : parts[1]; this.qdata = url; this.type = URL_PZPRFILE; } else { @@ -437,6 +453,7 @@ pzpr.parser.FileData.prototype = { pid: "", type: FILE_AUTO /* == 0 */, + variant: null, filever: 0, fstr: "", qdata: "", @@ -477,6 +494,11 @@ delete this.fstr; /* ヘッダからパズルの種類・ファイルの種類を判定する */ + if (firstline.match(/^v:(.*)/)) { + this.variant = RegExp.$1; + firstline = lines.shift(); + } + if (firstline.match(/^pzprv3/)) { this.type = FILE_PZPR; if (firstline.match(/pzprv3\.(\d+)/)) { diff --git a/test/.eslintrc.json b/test/.eslintrc.json index 32ea65e99..07c434eb7 100644 --- a/test/.eslintrc.json +++ b/test/.eslintrc.json @@ -7,6 +7,7 @@ "ecmaVersion": 6 }, "globals": { + "beforeEach": "readonly", "describe": "readonly", "it": "readonly" }, diff --git a/test/pzpr/parser_test.js b/test/pzpr/parser_test.js index 79408024c..651278a0e 100644 --- a/test/pzpr/parser_test.js +++ b/test/pzpr/parser_test.js @@ -4,7 +4,56 @@ var assert = require("assert"); var pzpr = require("../../"); -var puzzle = new pzpr.Puzzle(); +var puzzle; +beforeEach(function() { + puzzle = new pzpr.Puzzle(); +}); + +describe("URLData", function() { + it("parses files", function() { + var url = "pzprv3/nurikabe/3/3/# # . /1 # 3 /# # . /"; + var pzl = pzpr.parser.parseURL(url); + + assert.equal("nurikabe", pzl.pid); + + puzzle.open(pzl); + assert.equal("nurikabe", puzzle.pid); + + assert.equal(puzzle.board.getc(3, 3).qans, 1); + }); + + it("parses variant files", function() { + var url = "v:/pzprv3/nurikabe/3/3/# # . /1 # 3 /# # . /"; + var pzl = pzpr.parser(url); + assert.equal("nurikabe", pzl.pid); + puzzle.open(pzl); + assert.equal("nurikabe", puzzle.pid); + assert.equal(true, puzzle.getConfig("variant")); + }); + + it("parses variant urls", function() { + var url = + "https://puzz.link/p?type=editor&v:/pzprv3/nurikabe/3/3/%23%20%23%20.%20/1%20%23%203%20/%23%20%23%20.%20//"; + var pzl = pzpr.parser(url); + assert.equal("nurikabe", pzl.pid); + puzzle.open(pzl); + assert.equal("nurikabe", puzzle.pid); + assert.equal(true, puzzle.getConfig("variant")); + }); + + it("parses duplicated urls", function() { + var url = + "https://puzz.link/p?type=editor&pzprv3/nurikabe/3/3/%23%20%23%20.%20/1%20%23%203%20/%23%20%23%20.%20//"; + var pzl = pzpr.parser(url); + + assert.equal("nurikabe", pzl.pid); + + puzzle.open(pzl); + assert.equal("nurikabe", puzzle.pid); + + assert.equal(puzzle.board.getc(3, 3).qans, 1); + }); +}); describe("changeProperPid:URL", function() { it("Check bonsan", function() {