diff --git a/NEWS.cs.md b/NEWS.cs.md index 6ffba211..54aeeb94 100644 --- a/NEWS.cs.md +++ b/NEWS.cs.md @@ -1,3 +1,9 @@ +#### Verze 3.3.0 + +- Přidána možnost stáhnout anotovaný soubor bez nepotvrzených výskytů. +- Upraveno fulltextové vyhledávání - nově se zobrazuje informace o atributu, ve kterém byla shoda nalezena. +- Do fasetového vyhledávání přidána možnost filtrovat dle příkladů (`skos:example`). + #### Verze 3.2.0 - Přidána podpora pro import slovníků z MS Excel. diff --git a/NEWS.en.md b/NEWS.en.md index 4462c108..d48dc975 100644 --- a/NEWS.en.md +++ b/NEWS.en.md @@ -1,3 +1,9 @@ +#### Version 3.3.0 + +- Added the possibility to download annotated file without unconfirmed occurrences. +- Enhanced fulltext search - now it shows information about the attribute in which a match was found. +- Added support for filtering by example (`skos:example`) in the faceted search. + #### Version 3.2.0 - Added support for importing a vocabulary from MS Excel. diff --git a/package-lock.json b/package-lock.json index 03856ff2..61c6e863 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "termit-ui", - "version": "3.2.0", + "version": "3.3.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "termit-ui", - "version": "3.2.0", + "version": "3.3.1", "license": "GPL-3.0-only", "dependencies": { "@formatjs/intl-pluralrules": "^5.3.1", @@ -73,7 +73,7 @@ "@redux-devtools/extension": "^3.2.5", "@types/enzyme": "^3.10.13", "@types/jest": "^27.4.1", - "@types/js-cookie": "^3.0.3", + "@types/js-cookie": "^3.0.6", "@types/lodash": "^4.17.10", "@types/luxon": "^3.4.2", "@types/node": "^18.11.17", @@ -3764,9 +3764,9 @@ } }, "node_modules/@types/js-cookie": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.3.tgz", - "integrity": "sha512-Xe7IImK09HP1sv2M/aI+48a20VX+TdRJucfq4vfRVy6nWN8PYPOEnlMRSgxJAgYQIXJVL8dZ4/ilAM7dWNaOww==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", "dev": true }, "node_modules/@types/json-schema": { @@ -20661,9 +20661,9 @@ } }, "@types/js-cookie": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.3.tgz", - "integrity": "sha512-Xe7IImK09HP1sv2M/aI+48a20VX+TdRJucfq4vfRVy6nWN8PYPOEnlMRSgxJAgYQIXJVL8dZ4/ilAM7dWNaOww==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", "dev": true }, "@types/json-schema": { diff --git a/package.json b/package.json index 34949c0b..955faa45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "termit-ui", - "version": "3.2.0", + "version": "3.3.1", "private": true, "homepage": ".", "license": "GPL-3.0-only", @@ -83,7 +83,7 @@ "@redux-devtools/extension": "^3.2.5", "@types/enzyme": "^3.10.13", "@types/jest": "^27.4.1", - "@types/js-cookie": "^3.0.3", + "@types/js-cookie": "^3.0.6", "@types/lodash": "^4.17.10", "@types/luxon": "^3.4.2", "@types/node": "^18.11.17", diff --git a/src/component/annotator/AnnotatorContent.tsx b/src/component/annotator/AnnotatorContent.tsx index 1ec43025..f54a6bbc 100644 --- a/src/component/annotator/AnnotatorContent.tsx +++ b/src/component/annotator/AnnotatorContent.tsx @@ -35,8 +35,16 @@ const PREPROCESSING_INSTRUCTIONS = [ shouldPreprocessNode: (node: any): boolean => node.name && node.name === "a", preprocessNode: (node: any) => { - node.attribs["data-href"] = node.attribs.href; - delete node.attribs.href; + // Remove href from relative links, absolute links will open in blank tab + if (!Utils.isLink(node.attribs.href)) { + node.attribs["data-href"] = node.attribs.href; + delete node.attribs.href; + } else { + node.attribs["data-target"] = node.attribs.target; + node.attribs["target"] = "_blank"; + node.attribs["data-rel"] = node.attribs.rel; + node.attribs["rel"] = "noopener noreferrer"; + } }, }, ]; diff --git a/src/component/annotator/HtmlParserUtils.ts b/src/component/annotator/HtmlParserUtils.ts index e0e20842..469d91ef 100644 --- a/src/component/annotator/HtmlParserUtils.ts +++ b/src/component/annotator/HtmlParserUtils.ts @@ -4,12 +4,33 @@ import render from "dom-serializer"; const RDF_ATTRIBUTE_NAMES = ["about", "property", "resource", "typeof"]; +function removeAddedAttributes(elem: Element) { + // Restore links to their original state - see AnnotatorContent.PREPROCESSING_INSTRUCTIONS + if (elem.tagName === "a") { + if (elem.attribs["data-href"]) { + elem.attribs.href = elem.attribs["data-href"]; + delete elem.attribs["data-href"]; + } + delete elem.attribs["target"]; + delete elem.attribs["rel"]; + if (elem.attribs["data-rel"]) { + elem.attribs.rel = elem.attribs["data-rel"]; + delete elem.attribs["data-rel"]; + } + if (elem.attribs["data-target"]) { + elem.attribs.target = elem.attribs["data-target"]; + delete elem.attribs["data-target"]; + } + } +} + const HtmlParserUtils = { html2dom(html: string): Node[] { // Do not decode HTML entities (e.g., <) when parsing content for object representation, it caused issues // with rendering const options = { decodeEntities: false }; - const handler = new DomHandler(); + // @ts-ignore + const handler = new DomHandler(null, null, removeAddedAttributes); const parser = new HtmlParser(handler, options); parser.parseComplete(html); return handler.dom as Node[]; diff --git a/src/component/annotator/__tests__/Annotator.test.tsx b/src/component/annotator/__tests__/Annotator.test.tsx index 31af1e03..99226224 100644 --- a/src/component/annotator/__tests__/Annotator.test.tsx +++ b/src/component/annotator/__tests__/Annotator.test.tsx @@ -118,7 +118,7 @@ describe("Annotator", () => { expect(wrapper.html().includes(sampleContent)).toBe(true); }); - it("renders body of provided html content with replaced anchor hrefs", () => { + it("preserves absolute URL href anchors", () => { const htmlContent = surroundWithHtml( 'This is a link' ); @@ -138,7 +138,28 @@ describe("Annotator", () => { ) ); const sampleOutput = - 'This is a link'; + 'This is a link'; + expect(wrapper.html().includes(sampleOutput)).toBe(true); + }); + + it("renders body of provided html content with replaced relative anchor hrefs", () => { + const htmlContent = surroundWithHtml('This is a link'); + + const wrapper = mountWithIntl( + withWebSocket( + + + + ) + ); + const sampleOutput = 'This is a link'; expect(wrapper.html().includes(sampleOutput)).toBe(true); }); diff --git a/src/component/annotator/__tests__/HtmlParserUtils.test.ts b/src/component/annotator/__tests__/HtmlParserUtils.test.ts new file mode 100644 index 00000000..620db37f --- /dev/null +++ b/src/component/annotator/__tests__/HtmlParserUtils.test.ts @@ -0,0 +1,22 @@ +import { Element } from "domhandler"; +import HtmlParserUtils from "../HtmlParserUtils"; + +describe("HtmlParserUtils", () => { + describe("html2dom", () => { + it("remove target and rel attributes added when rendering HTML", () => { + const html = + 'Example'; + const nodes = HtmlParserUtils.html2dom(html); + expect((nodes[0] as Element).attribs.href).toEqual("http://example.com"); + expect((nodes[0] as Element).attribs.target).not.toBeDefined(); + expect((nodes[0] as Element).attribs.rel).not.toBeDefined(); + }); + + it("set href attribute to data-href attribute created when rendering HTML", () => { + const html = 'Example'; + const nodes = HtmlParserUtils.html2dom(html); + expect((nodes[0] as Element).attribs.href).toEqual("./about.html"); + expect((nodes[0] as Element).attribs["data-href"]).not.toBeDefined(); + }); + }); +}); diff --git a/src/util/Utils.ts b/src/util/Utils.ts index 45b54beb..b4fd2cb9 100644 --- a/src/util/Utils.ts +++ b/src/util/Utils.ts @@ -51,10 +51,11 @@ const Utils = { */ isLink(str: string): boolean { return ( - str.startsWith("http://") || - str.startsWith("https://") || - str.startsWith("ftp://") || - str.startsWith("sftp://") + str !== undefined && + (str.startsWith("http://") || + str.startsWith("https://") || + str.startsWith("ftp://") || + str.startsWith("sftp://")) ); },