commit 684a2f1fa09426273ee3a63d0811240bd740e5b3
parent a7f087ac11ef94b693293dcfa34c7ec8e717ba26
Author: MTRNord <mtrnord1@gmail.com>
Date: Thu, 20 Jun 2024 11:09:02 +0200
Beautify the output and renderer
Diffstat:
4 files changed, 100 insertions(+), 12 deletions(-)
diff --git a/package.json b/package.json
@@ -15,6 +15,7 @@
"@eslint/js": "^9.4.0",
"@types/eslint__js": "^8.42.3",
"@types/node": "^20.14.2",
+ "@types/prompts": "^2.4.9",
"@types/react": "^18.3.3",
"eslint": "^9.4.0",
"eslint-plugin-tsdoc": "^0.3.0",
@@ -27,6 +28,7 @@
"@sinclair/typebox": "^0.32.31",
"got": "^14.4.1",
"meilisearch": "^0.40.0",
+ "prompts": "^2.4.2",
"react": "^18.3.1",
"yaml": "^2.4.5"
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
@@ -23,6 +23,9 @@ importers:
meilisearch:
specifier: ^0.40.0
version: 0.40.0
+ prompts:
+ specifier: ^2.4.2
+ version: 2.4.2
react:
specifier: ^18.3.1
version: 18.3.1
@@ -39,6 +42,9 @@ importers:
'@types/node':
specifier: ^20.14.2
version: 20.14.2
+ '@types/prompts':
+ specifier: ^2.4.9
+ version: 2.4.9
'@types/react':
specifier: ^18.3.3
version: 18.3.3
@@ -193,6 +199,9 @@ packages:
'@types/node@20.14.2':
resolution: {integrity: sha512-xyu6WAMVwv6AKFLB+e/7ySZVr/0zLCzOa7rSpq6jNwpqOrUbcACDWC+53d4n2QHOnDou0fbIsg8wZu/sxrnI4Q==}
+ '@types/prompts@2.4.9':
+ resolution: {integrity: sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==}
+
'@types/prop-types@15.7.12':
resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==}
@@ -623,6 +632,10 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+ kleur@3.0.3:
+ resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==}
+ engines: {node: '>=6'}
+
levn@0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
@@ -757,6 +770,10 @@ packages:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
+ prompts@2.4.2:
+ resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
+ engines: {node: '>= 6'}
+
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
@@ -835,6 +852,9 @@ packages:
simple-swizzle@0.2.2:
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
+ sisteransi@1.0.5:
+ resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
+
slash@3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
@@ -1168,6 +1188,11 @@ snapshots:
dependencies:
undici-types: 5.26.5
+ '@types/prompts@2.4.9':
+ dependencies:
+ '@types/node': 20.14.2
+ kleur: 3.0.3
+
'@types/prop-types@15.7.12': {}
'@types/react@18.3.3':
@@ -1650,6 +1675,8 @@ snapshots:
dependencies:
json-buffer: 3.0.1
+ kleur@3.0.3: {}
+
levn@0.4.1:
dependencies:
prelude-ls: 1.2.1
@@ -1755,6 +1782,11 @@ snapshots:
prelude-ls@1.2.1: {}
+ prompts@2.4.2:
+ dependencies:
+ kleur: 3.0.3
+ sisteransi: 1.0.5
+
prop-types@15.8.1:
dependencies:
loose-envify: 1.4.0
@@ -1822,6 +1854,8 @@ snapshots:
dependencies:
is-arrayish: 0.3.2
+ sisteransi@1.0.5: {}
+
slash@3.0.0: {}
string_decoder@1.3.0:
diff --git a/src/renderer.tsx b/src/renderer.tsx
@@ -1,7 +1,8 @@
import React, { PropsWithChildren } from 'react';
-import ReactPDF, { Font, Page, Text, View, Document, StyleSheet } from '@react-pdf/renderer';
+import ReactPDF, { Font, Page, Text, View, Document, StyleSheet, Link } from '@react-pdf/renderer';
import Indexer from './indexer.js';
import { Hits } from 'meilisearch';
+import prompts, { PromptObject } from 'prompts';
Font.registerEmojiSource({
format: 'png',
@@ -25,7 +26,7 @@ const indexer = new Indexer();
const borderRadius = 5;
// A pdf renderer
-const MessageDocument = ({ query, queryResults }: PropsWithChildren<{ query: string, queryResults: { hits: Hits<Record<string, any>>; estimatedTotalHits: number; } }>) => {
+const MessageDocument = ({ query, room_id, sender, queryResults }: PropsWithChildren<{ query: string, room_id?: string, sender?: string, queryResults: { hits: Hits<Record<string, any>>; estimatedTotalHits: number; } }>) => {
return (
<Document
title={`Search results for: "${query}"`}
@@ -33,17 +34,36 @@ const MessageDocument = ({ query, queryResults }: PropsWithChildren<{ query: str
keywords='matrix'
>
<Page size="A4" style={styles.page}>
+ {/* Title page which is centered */}
+ <View style={{ flexDirection: "row", alignItems: "center", justifyContent: "center", height: "100%" }}>
+ <View style={{ flexDirection: "column", justifyContent: "center", alignItems: "center" }}>
+ <Text style={{ fontSize: 24, textAlign: 'center' }}>Matrix Search Engine</Text>
+ <Text style={{ fontSize: 12, textAlign: 'center', marginTop: 5 }}>Search results for: "{query}"</Text>
+ {/* Optionally display the other values of room_id and sender*/}
+ {room_id !== undefined && <Text style={{ fontSize: 12, textAlign: 'center' }}>Room ID: {room_id}</Text>}
+ {sender !== undefined && <Text style={{ fontSize: 12, textAlign: 'center' }}>Sender: {sender}</Text>}
+ {/* Number of results */}
+ <Text style={{ fontSize: 10, textAlign: 'center', marginTop: 10 }}>Number of Results: {queryResults.estimatedTotalHits}</Text>
+ {/* Date of creation */}
+ <Text style={{ fontSize: 10, textAlign: 'center', marginTop: 10 }}>Created at: {new Date().toLocaleString()}</Text>
+ </View>
+ </View>
+ </Page>
+ <Page size="A4" style={styles.page}>
<View>
<View style={{ fontSize: 10 }}>
- <Text>Search results for: {query}</Text>
- <Text>Results: {queryResults.estimatedTotalHits}</Text>
+ <Text>Search results for: "{query}"</Text>
+ <Text>Number of Results: {queryResults.estimatedTotalHits}</Text>
</View>
<View>
{queryResults.hits.map((result, index) => (
- <View key={index} style={{ flexDirection: 'column', margin: 10, padding: 5, backgroundColor: '#e6e6e6', gap: 25, borderTopLeftRadius: borderRadius, borderTopRightRadius: borderRadius, borderBottomLeftRadius: borderRadius, borderBottomRightRadius: borderRadius, borderStyle: 'solid', borderWidth: 1, borderColor: '#00000' }}>
+ <View wrap={false} key={index} style={{ flexDirection: 'column', margin: 10, padding: 5, backgroundColor: '#e6e6e6', gap: 25, borderTopLeftRadius: borderRadius, borderTopRightRadius: borderRadius, borderBottomLeftRadius: borderRadius, borderBottomRightRadius: borderRadius, borderStyle: 'solid', borderWidth: 1, borderColor: '#00000' }}>
<View style={{ flexDirection: 'row', justifyContent: 'space-between', fontSize: 10 }} >
<Text>{result.room_name ?? result.room_id}</Text>
- <Text>{result.sender}</Text>
+ <View style={{ flexDirection: 'row' }}>
+ <Text>{result.sender}</Text>
+ <Link style={{ marginLeft: 5 }} src={`https://matrix.to/#/${result.room_id}/${result.id}`}>Link</Link>
+ </View>
</View>
<Text>{result.content.body}</Text>
</View>
@@ -64,10 +84,42 @@ const MessageDocument = ({ query, queryResults }: PropsWithChildren<{ query: str
}
export async function renderPDFToDisk(query: string, room_id?: string, sender?: string) {
- const queryResults = await indexer.search(query, room_id, sender);
+ let cleanedRoomId = room_id?.trim();
+ let cleanedSender = sender?.trim();
+ if (cleanedRoomId === "") {
+ cleanedRoomId = undefined;
+ }
+ if (cleanedSender === "") {
+ cleanedSender = undefined;
+ }
+ const queryResults = await indexer.search(query, cleanedRoomId, cleanedSender);
//console.log(`Search results:`, queryResults);
- await ReactPDF.renderToFile(<MessageDocument query={query} queryResults={queryResults} />, `output.pdf`);
+ await ReactPDF.renderToFile(<MessageDocument query={query} room_id={cleanedRoomId} sender={cleanedSender} queryResults={queryResults} />, `output.pdf`);
}
-await renderPDFToDisk("woah", undefined, "@thibaultmartin:matrix.org");
+
+const questions: PromptObject<string>[] = [
+ {
+ type: 'text',
+ name: 'query',
+ initial: "",
+ message: 'Enter your search query:',
+ },
+ {
+ type: 'text',
+ name: 'room_id',
+ initial: undefined,
+ message: 'Enter the Room ID:',
+ },
+ {
+ type: 'text',
+ name: 'sender',
+ initial: undefined,
+ message: 'Enter the sender:',
+ }
+]
+
+const response = await prompts(questions);
+
+await renderPDFToDisk(response.query as string, response.room_id as string | undefined, response.sender as string | undefined);
console.log("PDF rendered to disk");
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
@@ -85,11 +85,11 @@
"noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
"alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
- // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
- // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
+ "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
+ "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
- // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
+ "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */