mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-03-05 03:40:56 +01:00
Display search result fixes (#1901)
Fix syntax highlighting on non highlighted fields. Fix ellipsis on new lines in code syntax highlighting. Fix ellipsis on content start or end in non code fields. Co-authored-by: Sebastian Sdorra <sebastian.sdorra@cloudogu.com>
This commit is contained in:
committed by
GitHub
parent
5b700dc0c7
commit
bc86ed4474
6
gradle/changelog/search_fixes.yaml
Normal file
6
gradle/changelog/search_fixes.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
- type: fixed
|
||||
description: Syntax highlighting on non highlighted fields ([#1901](https://github.com/scm-manager/scm-manager/pull/1901))
|
||||
- type: fixed
|
||||
description: Ellipsis on new lines in code syntax highlighting ([#1901](https://github.com/scm-manager/scm-manager/pull/1901))
|
||||
- type: fixed
|
||||
description: Ellipsis on content start or end in non code fields ([#1901](https://github.com/scm-manager/scm-manager/pull/1901))
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
import { Hit } from "@scm-manager/ui-types";
|
||||
|
||||
export const javaHit: Hit = {
|
||||
score: 2.5,
|
||||
fields: {
|
||||
content: {
|
||||
highlighted: true,
|
||||
fragments: [
|
||||
"import org.slf4j.LoggerFactory;\n\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Jwt implementation of {@link <|[[--AccessTokenBuilder--]]|>}.\n * \n * @author Sebastian Sdorra\n * @since 2.0.0\n */\npublic final class <|[[--JwtAccessTokenBuilder--]]|> implements <|[[--AccessTokenBuilder--]]|> {\n\n /**\n * the logger for <|[[--JwtAccessTokenBuilder--]]|>\n */\n private static final Logger LOG = LoggerFactory.getLogger(<|[[--JwtAccessTokenBuilder.class--]]|>);\n \n private final KeyGenerator keyGenerator; \n private final SecureKeyResolver keyResolver; \n \n private String subject;\n private String issuer;\n",
|
||||
" private final Map<String,Object> custom = Maps.newHashMap();\n \n <|[[--JwtAccessTokenBuilder--]]|>(KeyGenerator keyGenerator, SecureKeyResolver keyResolver) {\n this.keyGenerator = keyGenerator;\n this.keyResolver = keyResolver;\n }\n\n @Override\n public <|[[--JwtAccessTokenBuilder--]]|> subject(String subject) {\n",
|
||||
' public <|[[--JwtAccessTokenBuilder--]]|> custom(String key, Object value) {\n Preconditions.checkArgument(!Strings.isNullOrEmpty(key), "null or empty value not allowed");\n Preconditions.checkArgument(value != null, "null or empty value not allowed");\n'
|
||||
],
|
||||
matchesContentStart: false,
|
||||
matchesContentEnd: false
|
||||
}
|
||||
},
|
||||
_links: {}
|
||||
};
|
||||
|
||||
export const bashHit: Hit = {
|
||||
score: 2.5,
|
||||
fields: {
|
||||
content: {
|
||||
highlighted: true,
|
||||
fragments: [
|
||||
'# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\n#\n\n<|[[--getent--]]|> group scm >/dev/null || groupadd -r scm\n<|[[--getent--]]|> passwd scm >/dev/null || \\\n useradd -r -g scm -M \\\n -s /sbin/nologin -d /var/lib/scm \\\n -c "user for the scm-server process" scm\nexit 0\n\n'
|
||||
],
|
||||
matchesContentStart: false,
|
||||
matchesContentEnd: true
|
||||
}
|
||||
},
|
||||
_links: {}
|
||||
};
|
||||
|
||||
export const markdownHit: Hit = {
|
||||
score: 2.5,
|
||||
fields: {
|
||||
content: {
|
||||
highlighted: true,
|
||||
fragments: [
|
||||
"---\ntitle: SCM-Manager v2 Test <|[[--Cases--]]|>\n---\n\nDescribes the expected behaviour for SCMM v2 REST Resources using manual tests.\n\nThe following states general test <|[[--cases--]]|> per HTTP Method and en expected return code as well as exemplary curl calls.\nResource-specifics are stated \n\n## Test <|[[--Cases--]]|>\n\n### GET\n\n- Collection Resource (e.g. `/users`)\n - Without parameters -> 200\n - Parameters\n - `?pageSize=1` -> Only one embedded element, pageTotal reflects the correct number of pages, `last` link points to last page.\n - `?pageSize=1&page=1` -> `next` link points to page 0 ; `prev` link points to page 2\n - `?sortBy=admin` -> Sorted by `admin` field of embedded objects\n - `?sortBy=admin&desc=true` -> Invert sorting\n- Individual Resource (e.g. `/users/scmadmin`)\n - Exists -> 200\n",
|
||||
"\n### DELETE\n\n- existing -> 204\n- not existing -> 204\n- without permission -> 401\n\n## Exemplary calls & Resource specific test <|[[--cases--]]|>\n\nIn order to extend those tests to other Resources, have a look at the rest docs. Note that the Content Type is specific to each resource as well.\n"
|
||||
],
|
||||
matchesContentStart: true,
|
||||
matchesContentEnd: false
|
||||
}
|
||||
},
|
||||
_links: {}
|
||||
};
|
||||
97
scm-ui/ui-components/src/__resources__/SearchHit.ts
Normal file
97
scm-ui/ui-components/src/__resources__/SearchHit.ts
Normal file
File diff suppressed because one or more lines are too long
@@ -90255,6 +90255,278 @@ In order to extend those tests to other Resources, have a look at the rest docs.
|
||||
</pre>
|
||||
`;
|
||||
|
||||
exports[`Storyshots TextHitField Non Content Search 1`] = `
|
||||
<pre>
|
||||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>scm-clients</artifactId>
|
||||
<groupId>sonia.scm.clients</groupId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>scm-cli-client</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<name>scm-cli-client</name>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- fix javadoc -->
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>\${servlet.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>jta</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>sonia.scm.clients</groupId>
|
||||
<artifactId>scm-client-impl</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>args4j</groupId>
|
||||
<artifactId>args4j</artifactId>
|
||||
<version>2.0.29</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>\${logback.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
<version>2.3.21</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>com.mycila.maven-license-plugin</groupId>
|
||||
<artifactId>maven-license-plugin</artifactId>
|
||||
<version>1.9.0</version>
|
||||
<configuration>
|
||||
<header>http://download.scm-manager.org/licenses/mvn-license.txt</header>
|
||||
<includes>
|
||||
<include>src/**</include>
|
||||
<include>**/test/**</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>target/**</exclude>
|
||||
<exclude>.hg/**</exclude>
|
||||
<exclude>**/*.ftl</exclude>
|
||||
</excludes>
|
||||
<strictCheck>true</strictCheck>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>sonia.scm.cli.App</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
|
||||
<id>it</id>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>sonia.scm</groupId>
|
||||
<artifactId>scm-webapp</artifactId>
|
||||
<version>\${project.version}</version>
|
||||
<type>war</type>
|
||||
<outputDirectory>\${project.build.directory}/webapp</outputDirectory>
|
||||
<destFileName>scm-webapp.war</destFileName>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.12</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<scm.version>\${project.version}</scm.version>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>integration-test</id>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>verify</id>
|
||||
<goals>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>\${jetty.maven.version}</version>
|
||||
<configuration>
|
||||
<stopPort>8085</stopPort>
|
||||
<stopKey>STOP</stopKey>
|
||||
<systemProperties>
|
||||
<systemProperty>
|
||||
<name>scm.home</name>
|
||||
<value>target/scm-it</value>
|
||||
</systemProperty>
|
||||
<systemProperty>
|
||||
<name>file.encoding</name>
|
||||
<value>UTF-8</value>
|
||||
</systemProperty>
|
||||
</systemProperties>
|
||||
<httpConnector>
|
||||
<port>8081</port>
|
||||
</httpConnector>
|
||||
<webApp>
|
||||
<contextPath>/scm</contextPath>
|
||||
</webApp>
|
||||
<war>\${project.build.directory}/webapp/scm-webapp.war</war>
|
||||
<scanIntervalSeconds>0</scanIntervalSeconds>
|
||||
<daemon>true</daemon>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>start-jetty</id>
|
||||
<phase>pre-integration-test</phase>
|
||||
<goals>
|
||||
<goal>deploy-war</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>stop-jetty</id>
|
||||
<phase>post-integration-test</phase>
|
||||
<goals>
|
||||
<goal>stop</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
|
||||
</pre>
|
||||
`;
|
||||
|
||||
exports[`Storyshots TextHitField Truncate 1`] = `
|
||||
<pre>
|
||||
The Hitchhiker's Guide to the Galaxy (sometimes referred to as **HG2G**, **HHGTTG** or **H2G2**) is a comedy science fiction ser...
|
||||
</pre>
|
||||
`;
|
||||
|
||||
exports[`Storyshots TextHitField Truncate Keep Whole Line 1`] = `
|
||||
<pre>
|
||||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<artifactId>scm-clients</artifactId>
|
||||
<groupId>sonia.scm.clients</groupId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>scm-cli-client</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<name>scm-cli-client</name>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- fix javadoc -->
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>\${servlet.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>jta</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>sonia.scm.clients</groupId>
|
||||
<artifactId>scm-client-impl</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
...
|
||||
</pre>
|
||||
`;
|
||||
|
||||
exports[`Storyshots TextHitField Unknown SyntaxHighlighting 1`] = `
|
||||
<pre>
|
||||
...
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import { bashHit, javaHit, markdownHit } from "../__resources__/ContentSearchHit";
|
||||
import { bashHit, filenameXmlHit, javaHit, markdownHit, pullRequestHit } from "../__resources__/SearchHit";
|
||||
import TextHitField from "./TextHitField";
|
||||
|
||||
storiesOf("TextHitField", module)
|
||||
@@ -51,4 +51,19 @@ storiesOf("TextHitField", module)
|
||||
<pre>
|
||||
<TextHitField hit={bashHit} field={"content"} syntaxHighlightingLanguage="__unknown__" />
|
||||
</pre>
|
||||
))
|
||||
.add("Non Content Search", () => (
|
||||
<pre>
|
||||
<TextHitField hit={filenameXmlHit} field={"content"} syntaxHighlightingLanguage="xml" />
|
||||
</pre>
|
||||
))
|
||||
.add("Truncate", () => (
|
||||
<pre>
|
||||
<TextHitField hit={pullRequestHit} field={"description"} truncateValueAt={128} />
|
||||
</pre>
|
||||
))
|
||||
.add("Truncate Keep Whole Line", () => (
|
||||
<pre>
|
||||
<TextHitField hit={filenameXmlHit} field={"content"} syntaxHighlightingLanguage="xml" truncateValueAt={1024} />
|
||||
</pre>
|
||||
));
|
||||
|
||||
@@ -40,11 +40,7 @@ const HighlightedTextField: FC<HighlightedTextFieldProps> = ({ field, syntaxHigh
|
||||
{field.fragments.map((fragment, i) => (
|
||||
<React.Fragment key={fragment}>
|
||||
{field.matchesContentStart ? null : separator}
|
||||
{syntaxHighlightingLanguage ? (
|
||||
<SyntaxHighlightedFragment value={fragment} language={syntaxHighlightingLanguage} />
|
||||
) : (
|
||||
<HighlightedFragment value={fragment} />
|
||||
)}
|
||||
<FieldFragment fragment={fragment} syntaxHighlightingLanguage={syntaxHighlightingLanguage} />
|
||||
{i + 1 >= field.fragments.length && !field.matchesContentEnd ? separator : null}
|
||||
</React.Fragment>
|
||||
))}
|
||||
@@ -52,6 +48,18 @@ const HighlightedTextField: FC<HighlightedTextFieldProps> = ({ field, syntaxHigh
|
||||
);
|
||||
};
|
||||
|
||||
type FieldFragmentProps = {
|
||||
fragment: string;
|
||||
syntaxHighlightingLanguage?: string;
|
||||
};
|
||||
|
||||
const FieldFragment: FC<FieldFragmentProps> = ({ fragment, syntaxHighlightingLanguage }) => {
|
||||
if (syntaxHighlightingLanguage) {
|
||||
return <SyntaxHighlightedFragment value={fragment} language={syntaxHighlightingLanguage} />;
|
||||
}
|
||||
return <HighlightedFragment value={fragment} />;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
hit: Hit;
|
||||
field: string;
|
||||
@@ -59,6 +67,20 @@ type Props = {
|
||||
syntaxHighlightingLanguage?: string;
|
||||
};
|
||||
|
||||
function truncate(value: string, truncateValueAt: number = 0, syntaxHighlightingLanguage?: string): string {
|
||||
if (truncateValueAt > 0 && value.length > truncateValueAt) {
|
||||
if (syntaxHighlightingLanguage) {
|
||||
let nextLineBreak = value.indexOf("\n", truncateValueAt);
|
||||
if (nextLineBreak >= 0 && nextLineBreak < value.length - 1) {
|
||||
value = value.substring(0, nextLineBreak) + "\n...";
|
||||
}
|
||||
} else {
|
||||
value = value.substring(0, truncateValueAt) + "...";
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
const TextHitField: FC<Props> = ({
|
||||
hit,
|
||||
field: fieldName,
|
||||
@@ -75,8 +97,9 @@ const TextHitField: FC<Props> = ({
|
||||
let value = field.value;
|
||||
if (value === "") {
|
||||
return <>{children}</>;
|
||||
} else if (typeof value === "string" && truncateValueAt > 0 && value.length > truncateValueAt) {
|
||||
value = value.substring(0, truncateValueAt) + "...";
|
||||
} else if (typeof value === "string") {
|
||||
const v = truncate(value, truncateValueAt, syntaxHighlightingLanguage);
|
||||
return <FieldFragment fragment={v} syntaxHighlightingLanguage={syntaxHighlightingLanguage} />;
|
||||
}
|
||||
return <>{value}</>;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public final class LuceneHighlighter {
|
||||
if (fieldAnalyzer == Indexed.Analyzer.CODE) {
|
||||
return keepWholeLine(value, fragments);
|
||||
}
|
||||
return Arrays.stream(fragments).map(ContentFragment::new)
|
||||
return Arrays.stream(fragments).map(f -> createContentFragment(value, f))
|
||||
.toArray(ContentFragment[]::new);
|
||||
}
|
||||
|
||||
@@ -122,4 +122,9 @@ public final class LuceneHighlighter {
|
||||
return new ContentFragment(snippet + content.substring(index + raw.length(), end) + (matchesContentEnd ? "" : "\n"), matchesContentStart, matchesContentEnd);
|
||||
}
|
||||
|
||||
private ContentFragment createContentFragment(String content, String fragment) {
|
||||
String raw = fragment.replace(PRE_TAG, "").replace(POST_TAG, "");
|
||||
return new ContentFragment(fragment, content.startsWith(raw), content.endsWith(raw));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -123,6 +123,24 @@ class LuceneHighlighterTest {
|
||||
assertThat(contentFragments[0].isMatchesContentEnd()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldMatchContentStartWithDefaultAnalyzer() throws InvalidTokenOffsetsException, IOException {
|
||||
ContentFragment[] contentFragments = highlight("GameOfLife.java", "gameoflife");
|
||||
|
||||
assertThat(contentFragments).hasSize(1);
|
||||
assertThat(contentFragments[0].isMatchesContentStart()).isTrue();
|
||||
assertThat(contentFragments[0].isMatchesContentEnd()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldMatchContentEndWithDefaultAnalyzer() throws InvalidTokenOffsetsException, IOException {
|
||||
ContentFragment[] contentFragments = highlight("Button.tsx", "default");
|
||||
|
||||
assertThat(contentFragments).hasSize(1);
|
||||
assertThat(contentFragments[0].isMatchesContentStart()).isFalse();
|
||||
assertThat(contentFragments[0].isMatchesContentEnd()).isTrue();
|
||||
}
|
||||
|
||||
@Nested
|
||||
class IsHighlightableTests {
|
||||
|
||||
@@ -162,6 +180,16 @@ class LuceneHighlighterTest {
|
||||
|
||||
}
|
||||
|
||||
private ContentFragment[] highlight(String resource, String search) throws IOException, InvalidTokenOffsetsException {
|
||||
StandardAnalyzer analyzer = new StandardAnalyzer();
|
||||
Query query = new TermQuery(new Term("content", search));
|
||||
|
||||
String content = content(resource);
|
||||
|
||||
LuceneHighlighter highlighter = new LuceneHighlighter(analyzer, query);
|
||||
return highlighter.highlight("content", Indexed.Analyzer.DEFAULT, content);
|
||||
}
|
||||
|
||||
private ContentFragment[] highlightCode(String resource, String search) throws IOException, InvalidTokenOffsetsException {
|
||||
NonNaturalLanguageAnalyzer analyzer = new NonNaturalLanguageAnalyzer();
|
||||
Query query = new TermQuery(new Term("content", search));
|
||||
|
||||
Reference in New Issue
Block a user