@turnipxenon/pineapple 2.4.53 → 2.4.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.idea/workspace.xml +37 -27
- package/.svelte-kit/__package__/index.d.ts +1 -0
- package/.svelte-kit/__package__/index.js +1 -0
- package/.svelte-kit/__package__/template/seaweed/CreateUrlForm.svelte +54 -0
- package/.svelte-kit/__package__/template/seaweed/CreateUrlForm.svelte.d.ts +16 -0
- package/.svelte-kit/__package__/template/seaweed/ParseQueryTerms.d.ts +1 -0
- package/.svelte-kit/__package__/template/seaweed/ParseQueryTerms.js +23 -0
- package/.svelte-kit/__package__/template/seaweed/SeaweedTemplate.svelte +10 -25
- package/.svelte-kit/__package__/template/seaweed/SeaweedTemplate.svelte.d.ts +0 -2
- package/.svelte-kit/__package__/types/api/CreateUrl.d.ts +15 -0
- package/.svelte-kit/__package__/types/api/CreateUrl.js +19 -0
- package/.svelte-kit/__package__/types/api/index.d.ts +1 -0
- package/.svelte-kit/__package__/types/api/index.js +2 -0
- package/.svelte-kit/ambient.d.ts +2 -4
- package/.svelte-kit/generated/server/internal.js +1 -1
- package/.svelte-kit/types/route_meta_data.json +3 -0
- package/.svelte-kit/types/src/routes/api/create-url/$types.d.ts +10 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/template/seaweed/CreateUrlForm.svelte +54 -0
- package/dist/template/seaweed/CreateUrlForm.svelte.d.ts +16 -0
- package/dist/template/seaweed/ParseQueryTerms.d.ts +1 -0
- package/dist/template/seaweed/ParseQueryTerms.js +23 -0
- package/dist/template/seaweed/SeaweedTemplate.svelte +10 -25
- package/dist/template/seaweed/SeaweedTemplate.svelte.d.ts +0 -2
- package/dist/types/api/CreateUrl.d.ts +15 -0
- package/dist/types/api/CreateUrl.js +19 -0
- package/dist/types/api/index.d.ts +1 -0
- package/dist/types/api/index.js +2 -0
- package/package.json +1 -1
- package/src/lib/index.ts +1 -0
- package/src/lib/template/seaweed/CreateUrlForm.svelte +58 -0
- package/src/lib/template/seaweed/ParseQueryTerms.ts +26 -0
- package/src/lib/template/seaweed/SeaweedTemplate.svelte +10 -37
- package/src/lib/types/api/CreateUrl.ts +30 -0
- package/src/lib/types/api/index.ts +3 -0
- package/src/routes/(seaweed)/+layout.svelte +2 -1
- package/src/routes/(seaweed)/portfolio/actual/+page.svelte +1 -1
- package/src/routes/api/create-url/+server.ts +24 -0
package/.idea/workspace.xml
CHANGED
|
@@ -4,8 +4,14 @@
|
|
|
4
4
|
<option name="autoReloadType" value="SELECTIVE" />
|
|
5
5
|
</component>
|
|
6
6
|
<component name="ChangeListManager">
|
|
7
|
-
<list default="true" id="accb6ba2-c343-4f84-ad30-6e2d71eceee5" name="Changes" comment="Add
|
|
7
|
+
<list default="true" id="accb6ba2-c343-4f84-ad30-6e2d71eceee5" name="Changes" comment="Add dynamic url adder UI">
|
|
8
|
+
<change afterPath="$PROJECT_DIR$/src/lib/template/seaweed/UrlShortenerForm.svelte" afterDir="false" />
|
|
9
|
+
<change afterPath="$PROJECT_DIR$/src/lib/types/api/CreateUrl.ts" afterDir="false" />
|
|
10
|
+
<change afterPath="$PROJECT_DIR$/src/lib/types/api/index.ts" afterDir="false" />
|
|
11
|
+
<change afterPath="$PROJECT_DIR$/src/routes/api/create-url/+server.ts" afterDir="false" />
|
|
12
|
+
<change beforePath="$PROJECT_DIR$/src/lib/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/index.ts" afterDir="false" />
|
|
8
13
|
<change beforePath="$PROJECT_DIR$/src/lib/template/seaweed/SeaweedTemplate.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/template/seaweed/SeaweedTemplate.svelte" afterDir="false" />
|
|
14
|
+
<change beforePath="$PROJECT_DIR$/src/routes/(seaweed)/+layout.svelte" beforeDir="false" afterPath="$PROJECT_DIR$/src/routes/(seaweed)/+layout.svelte" afterDir="false" />
|
|
9
15
|
</list>
|
|
10
16
|
<option name="SHOW_DIALOG" value="false" />
|
|
11
17
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
|
@@ -48,11 +54,12 @@
|
|
|
48
54
|
<option value="Soulwork" />
|
|
49
55
|
<option value="ItchPromo" />
|
|
50
56
|
<option value="EntryOrderConfig" />
|
|
51
|
-
<option value="TypeScript File" />
|
|
52
57
|
<option value="ComboBox" />
|
|
53
58
|
<option value="ComboBoxWithButton" />
|
|
54
59
|
<option value="CSS File" />
|
|
55
60
|
<option value="RandomComponent" />
|
|
61
|
+
<option value="UrlShortenerForm" />
|
|
62
|
+
<option value="TypeScript File" />
|
|
56
63
|
</list>
|
|
57
64
|
</option>
|
|
58
65
|
</component>
|
|
@@ -115,7 +122,7 @@
|
|
|
115
122
|
"WebServerToolWindowFactoryState": "false",
|
|
116
123
|
"git-widget-placeholder": "turnip/customizable2",
|
|
117
124
|
"ignore.virus.scanning.warn.message": "true",
|
|
118
|
-
"last_opened_file_path": "C:/Users/Pumpkin/Projects/Web/pineapple/
|
|
125
|
+
"last_opened_file_path": "C:/Users/Pumpkin/Projects/Web/pineapple/src/routes/api/create-url",
|
|
119
126
|
"list.type.of.created.stylesheet": "CSS",
|
|
120
127
|
"node.js.detected.package.eslint": "true",
|
|
121
128
|
"node.js.detected.package.tslint": "true",
|
|
@@ -137,11 +144,11 @@
|
|
|
137
144
|
}</component>
|
|
138
145
|
<component name="RecentsManager">
|
|
139
146
|
<key name="CopyFile.RECENT_KEYS">
|
|
147
|
+
<recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\routes\api\create-url" />
|
|
148
|
+
<recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\lib\template\seaweed" />
|
|
140
149
|
<recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\lib\template\seaweed\entries" />
|
|
141
150
|
<recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\routes\(pineapple)\pineapple\(extra-pages)\page3\page7\(test_layout)\page8" />
|
|
142
151
|
<recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\routes\(pineapple)\pineapple\(extra-pages)\page3\page5" />
|
|
143
|
-
<recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\routes\(pineapple)\pineapple\(extra-pages)\page2" />
|
|
144
|
-
<recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\lib\components\navigation_component" />
|
|
145
152
|
</key>
|
|
146
153
|
<key name="MoveFile.RECENT_KEYS">
|
|
147
154
|
<recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\lib\components\combo_box" />
|
|
@@ -329,23 +336,10 @@
|
|
|
329
336
|
<workItem from="1712534451700" duration="490000" />
|
|
330
337
|
<workItem from="1712535021202" duration="299000" />
|
|
331
338
|
<workItem from="1712535434722" duration="522000" />
|
|
332
|
-
<workItem from="1712536086680" duration="
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
<
|
|
336
|
-
<created>1711683031188</created>
|
|
337
|
-
<option name="number" value="00118" />
|
|
338
|
-
<option name="presentableId" value="LOCAL-00118" />
|
|
339
|
-
<option name="project" value="LOCAL" />
|
|
340
|
-
<updated>1711683031188</updated>
|
|
341
|
-
</task>
|
|
342
|
-
<task id="LOCAL-00119" summary="Change media to containre">
|
|
343
|
-
<option name="closed" value="true" />
|
|
344
|
-
<created>1711685062499</created>
|
|
345
|
-
<option name="number" value="00119" />
|
|
346
|
-
<option name="presentableId" value="LOCAL-00119" />
|
|
347
|
-
<option name="project" value="LOCAL" />
|
|
348
|
-
<updated>1711685062499</updated>
|
|
339
|
+
<workItem from="1712536086680" duration="3657000" />
|
|
340
|
+
<workItem from="1712557998479" duration="1152000" />
|
|
341
|
+
<workItem from="1712560061741" duration="265000" />
|
|
342
|
+
<workItem from="1712560426380" duration="2683000" />
|
|
349
343
|
</task>
|
|
350
344
|
<task id="LOCAL-00120" summary="Change media to container">
|
|
351
345
|
<option name="closed" value="true" />
|
|
@@ -723,7 +717,23 @@
|
|
|
723
717
|
<option name="project" value="LOCAL" />
|
|
724
718
|
<updated>1712535169690</updated>
|
|
725
719
|
</task>
|
|
726
|
-
<
|
|
720
|
+
<task id="LOCAL-00167" summary="Move parseQtTerm on afterUpdate">
|
|
721
|
+
<option name="closed" value="true" />
|
|
722
|
+
<created>1712537061829</created>
|
|
723
|
+
<option name="number" value="00167" />
|
|
724
|
+
<option name="presentableId" value="LOCAL-00167" />
|
|
725
|
+
<option name="project" value="LOCAL" />
|
|
726
|
+
<updated>1712537061829</updated>
|
|
727
|
+
</task>
|
|
728
|
+
<task id="LOCAL-00168" summary="Change parseQueryTerm to parse during runtime on the DOM instead of on the raw svelte text">
|
|
729
|
+
<option name="closed" value="true" />
|
|
730
|
+
<created>1712543711416</created>
|
|
731
|
+
<option name="number" value="00168" />
|
|
732
|
+
<option name="presentableId" value="LOCAL-00168" />
|
|
733
|
+
<option name="project" value="LOCAL" />
|
|
734
|
+
<updated>1712543711416</updated>
|
|
735
|
+
</task>
|
|
736
|
+
<option name="localTasksCounter" value="169" />
|
|
727
737
|
<servers />
|
|
728
738
|
</component>
|
|
729
739
|
<component name="TypeScriptGeneratedFilesManager">
|
|
@@ -781,9 +791,6 @@
|
|
|
781
791
|
</option>
|
|
782
792
|
</component>
|
|
783
793
|
<component name="VcsManagerConfiguration">
|
|
784
|
-
<MESSAGE value="Add cdktf" />
|
|
785
|
-
<MESSAGE value="Implement cdktf for empty AppService" />
|
|
786
|
-
<MESSAGE value="WIP: cdktf" />
|
|
787
794
|
<MESSAGE value="Revert "Correct app_build_command in Azure SWA GithubActions" Revert b34caf17" />
|
|
788
795
|
<MESSAGE value="Temporarily delete workflow to let Azure auto-generate secrets" />
|
|
789
796
|
<MESSAGE value="Change npm to yarn in GithubActions" />
|
|
@@ -806,6 +813,9 @@
|
|
|
806
813
|
<MESSAGE value="Put parseQTTerms in afterUpdate instead of onMount" />
|
|
807
814
|
<MESSAGE value="Add logs to observe queryTermMap in downstream package" />
|
|
808
815
|
<MESSAGE value="Add logs to observe parseQtTerms in downstream package" />
|
|
809
|
-
<
|
|
816
|
+
<MESSAGE value="Move parseQtTerm on afterUpdate" />
|
|
817
|
+
<MESSAGE value="Change parseQueryTerm to parse during runtime on the DOM instead of on the raw svelte text" />
|
|
818
|
+
<MESSAGE value="Add dynamic url adder UI" />
|
|
819
|
+
<option name="LAST_COMMIT_MESSAGE" value="Add dynamic url adder UI" />
|
|
810
820
|
</component>
|
|
811
821
|
</project>
|
|
@@ -5,6 +5,7 @@ export { default as Card } from "./components/Card.svelte";
|
|
|
5
5
|
export { default as SocialSection } from "./components/SocialSection.svelte";
|
|
6
6
|
export * from "./components/overrideable_meta/index";
|
|
7
7
|
export * from "./components/navigation_component/index";
|
|
8
|
+
export * from "./types/api/index";
|
|
8
9
|
export * from "./components/dialog_manager/DialogManagerStore";
|
|
9
10
|
export * from "./components/dialog_manager/DialogManager";
|
|
10
11
|
export * from "./components/dialog_manager/DialogUtils";
|
|
@@ -6,6 +6,7 @@ export { default as Card } from "./components/Card.svelte";
|
|
|
6
6
|
export { default as SocialSection } from "./components/SocialSection.svelte";
|
|
7
7
|
export * from "./components/overrideable_meta/index";
|
|
8
8
|
export * from "./components/navigation_component/index";
|
|
9
|
+
export * from "./types/api/index";
|
|
9
10
|
export * from "./components/dialog_manager/DialogManagerStore";
|
|
10
11
|
export * from "./components/dialog_manager/DialogManager";
|
|
11
12
|
export * from "./components/dialog_manager/DialogUtils";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script>import { CreateUrlResult, jsonToCreateUrlResponse } from "../../types/api/CreateUrl";
|
|
2
|
+
import { getToastStore } from "@skeletonlabs/skeleton";
|
|
3
|
+
export let queryParams = "";
|
|
4
|
+
const toastStore = getToastStore();
|
|
5
|
+
let request = {
|
|
6
|
+
queryParams: "",
|
|
7
|
+
shortUrl: "",
|
|
8
|
+
password: ""
|
|
9
|
+
};
|
|
10
|
+
$:
|
|
11
|
+
request.queryParams = queryParams;
|
|
12
|
+
const failToast = {
|
|
13
|
+
message: "Adding new url failed"
|
|
14
|
+
};
|
|
15
|
+
const toastMap = /* @__PURE__ */ new Map([
|
|
16
|
+
[CreateUrlResult.Success, {
|
|
17
|
+
message: "Successfully added new url"
|
|
18
|
+
}],
|
|
19
|
+
[CreateUrlResult.Duplicate, {
|
|
20
|
+
message: "Short url already used; try again with another url"
|
|
21
|
+
}],
|
|
22
|
+
[CreateUrlResult.Fail, failToast]
|
|
23
|
+
]);
|
|
24
|
+
const post = () => {
|
|
25
|
+
fetch("/api/create-url", {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers: {
|
|
28
|
+
"Content-Type": "application/json"
|
|
29
|
+
},
|
|
30
|
+
body: JSON.stringify(request)
|
|
31
|
+
}).then(
|
|
32
|
+
(resp) => resp.json()
|
|
33
|
+
).then((json) => {
|
|
34
|
+
const properResp = jsonToCreateUrlResponse(json);
|
|
35
|
+
toastStore.trigger(toastMap.get(properResp.result) ?? failToast);
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<div>
|
|
41
|
+
<label for="short-url">Short URL for url shortener</label>
|
|
42
|
+
<input bind:value={request.shortUrl}
|
|
43
|
+
name="short-url"
|
|
44
|
+
class="input"
|
|
45
|
+
type="text"
|
|
46
|
+
placeholder="short-url" />
|
|
47
|
+
<label for="password">Password</label>
|
|
48
|
+
<input bind:value={request.password}
|
|
49
|
+
name="password"
|
|
50
|
+
class="input"
|
|
51
|
+
type="password"
|
|
52
|
+
placeholder="Input" />
|
|
53
|
+
<button class="btn variant-filled" on:click={post}>Send link</button>
|
|
54
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
queryParams?: string | undefined;
|
|
5
|
+
};
|
|
6
|
+
events: {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
};
|
|
9
|
+
slots: {};
|
|
10
|
+
};
|
|
11
|
+
export type CreateUrlFormProps = typeof __propDef.props;
|
|
12
|
+
export type CreateUrlFormEvents = typeof __propDef.events;
|
|
13
|
+
export type CreateUrlFormSlots = typeof __propDef.slots;
|
|
14
|
+
export default class CreateUrlForm extends SvelteComponent<CreateUrlFormProps, CreateUrlFormEvents, CreateUrlFormSlots> {
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const parseQueryTerms: (node: Element, querySet: Set<string>) => void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const parseQueryTerms = (node, querySet) => {
|
|
2
|
+
// change all text content to gibberish
|
|
3
|
+
for (const child of Array.from(node.children)) {
|
|
4
|
+
if (child.nodeType === Node.ELEMENT_NODE) {
|
|
5
|
+
parseQueryTerms(child, querySet);
|
|
6
|
+
// todo: if it's a span and it wraps a word, and qt class then we count that as query
|
|
7
|
+
// for (const childOfChild of child.childNodes) {
|
|
8
|
+
// if (childOfChild.nodeType === Node.TEXT_NODE && childOfChild.textContent?.trim()) {
|
|
9
|
+
// // todo analyze textcontent
|
|
10
|
+
// }
|
|
11
|
+
// }
|
|
12
|
+
// Warning: below is not redundant and is a catch-all
|
|
13
|
+
// Long-term solution: figure out the correct typing
|
|
14
|
+
if ((typeof child.className === "string") && child.className?.includes("qt-")) {
|
|
15
|
+
child.className.split(" ").forEach(c => {
|
|
16
|
+
if (c.startsWith("qt-")) {
|
|
17
|
+
querySet.add(c);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script>import {
|
|
1
|
+
<script>import { afterUpdate, onMount } from "svelte";
|
|
2
2
|
import EntryOrderConfig from "./entry_order_config/EntryOrderConfig.svelte";
|
|
3
3
|
import { runChaos } from "./RunChaos";
|
|
4
4
|
import SocialSection from "../../components/SocialSection.svelte";
|
|
@@ -8,24 +8,23 @@ import { Accordion, AccordionItem, CodeBlock, SlideToggle } from "@skeletonlabs/
|
|
|
8
8
|
import { page } from "$app/stores";
|
|
9
9
|
import Card from "../../components/Card.svelte";
|
|
10
10
|
import ElementVisbilityDetector from "../../components/ElementVisbilityDetector.svelte";
|
|
11
|
-
import selfContent from "./SeaweedTemplate.svelte?raw";
|
|
12
11
|
import {
|
|
13
12
|
AllGroupedEntriesProjectFirst,
|
|
14
13
|
GetEntryFromGlobal,
|
|
15
14
|
seaweedTemplateData,
|
|
16
15
|
TurnGroupEntriesMutable
|
|
17
16
|
} from "./SeaweedTemplateData";
|
|
17
|
+
import { parseQueryTerms } from "./ParseQueryTerms";
|
|
18
|
+
import UrlShortenerForm from "./CreateUrlForm.svelte";
|
|
18
19
|
export let letChaos = true;
|
|
19
20
|
export let name = "Turnip";
|
|
20
21
|
export let email = "turnipxenon@gmail.com";
|
|
21
22
|
export let linkedinSlug = "turnip-xenon";
|
|
22
23
|
export let domain = "http://localhost:5173/portfolio/actual/";
|
|
23
24
|
export let serverSideQueryParams = "";
|
|
24
|
-
export let extraComponent = void 0;
|
|
25
25
|
const entryProps = {
|
|
26
26
|
email
|
|
27
27
|
};
|
|
28
|
-
const entryList = import.meta.glob("./entries/*.svelte", { query: "?raw", eager: true });
|
|
29
28
|
const paramQTSet = /* @__PURE__ */ new Set();
|
|
30
29
|
let isVisible = true;
|
|
31
30
|
let isAdvanceSettingOn = false;
|
|
@@ -46,25 +45,9 @@ const syncQT = () => {
|
|
|
46
45
|
});
|
|
47
46
|
seaweedTemplateData.queryTermMap = seaweedTemplateData.queryTermMap;
|
|
48
47
|
};
|
|
49
|
-
const
|
|
50
|
-
console.log("parsing", seaweedTemplateData.queryTermMap.size);
|
|
48
|
+
const parseQueryTermsLocal = async () => {
|
|
51
49
|
const qtSet = /* @__PURE__ */ new Set();
|
|
52
|
-
|
|
53
|
-
[...Object.values(entryList).map((e) => e.default), selfContent].forEach((body) => {
|
|
54
|
-
console.log("parsing", body);
|
|
55
|
-
rawTermList.push(
|
|
56
|
-
...body.split('"').filter((s) => s.startsWith("qt-"))
|
|
57
|
-
// step 2: filter out texts that does not begin with "qt-"
|
|
58
|
-
);
|
|
59
|
-
});
|
|
60
|
-
rawTermList.forEach((t) => {
|
|
61
|
-
t.split(" ").forEach((nt) => {
|
|
62
|
-
if (["qt-1", "qt-2", "qt-*", "qt-"].includes(nt)) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
qtSet.add(nt);
|
|
66
|
-
});
|
|
67
|
-
});
|
|
50
|
+
parseQueryTerms(document.body, qtSet);
|
|
68
51
|
qtSet.forEach((t) => seaweedTemplateData.queryTermMap.set(t, true));
|
|
69
52
|
seaweedTemplateData.queryTermMap = seaweedTemplateData.queryTermMap;
|
|
70
53
|
syncQT();
|
|
@@ -132,7 +115,7 @@ let isParsed = false;
|
|
|
132
115
|
afterUpdate(async () => {
|
|
133
116
|
if (!letChaos && !isParsed) {
|
|
134
117
|
isParsed = true;
|
|
135
|
-
await
|
|
118
|
+
await parseQueryTermsLocal();
|
|
136
119
|
}
|
|
137
120
|
});
|
|
138
121
|
const toggleTerm = (term) => {
|
|
@@ -141,6 +124,7 @@ const toggleTerm = (term) => {
|
|
|
141
124
|
};
|
|
142
125
|
let orderUrl = "";
|
|
143
126
|
let advancedUrl = domain;
|
|
127
|
+
let advancedQuery = "";
|
|
144
128
|
const updateUrl = (seaweedTemplateData2) => {
|
|
145
129
|
const queryParams = [];
|
|
146
130
|
if (orderUrl) {
|
|
@@ -164,7 +148,8 @@ const updateUrl = (seaweedTemplateData2) => {
|
|
|
164
148
|
queryParams.push("game-section-first=false");
|
|
165
149
|
}
|
|
166
150
|
if (queryParams.length > 0) {
|
|
167
|
-
|
|
151
|
+
advancedQuery = queryParams.join("&");
|
|
152
|
+
advancedUrl = `${domain}?${advancedQuery}`;
|
|
168
153
|
} else {
|
|
169
154
|
advancedUrl = domain;
|
|
170
155
|
}
|
|
@@ -375,7 +360,7 @@ $:
|
|
|
375
360
|
<p>Copy the url below and open a new page with it</p>
|
|
376
361
|
<CodeBlock language="url" code={advancedUrl}></CodeBlock>
|
|
377
362
|
|
|
378
|
-
<
|
|
363
|
+
<UrlShortenerForm queryParams={advancedQuery}></UrlShortenerForm>
|
|
379
364
|
{/if}
|
|
380
365
|
</div>
|
|
381
366
|
</Card>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
|
-
import { type ComponentType } from "svelte";
|
|
3
2
|
import "./seaweed.postcss";
|
|
4
3
|
declare const __propDef: {
|
|
5
4
|
props: {
|
|
@@ -9,7 +8,6 @@ declare const __propDef: {
|
|
|
9
8
|
linkedinSlug?: string | undefined;
|
|
10
9
|
domain?: string | undefined;
|
|
11
10
|
serverSideQueryParams?: string | undefined;
|
|
12
|
-
extraComponent?: ComponentType | undefined;
|
|
13
11
|
};
|
|
14
12
|
events: {
|
|
15
13
|
[evt: string]: CustomEvent<any>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface CreateUrlRequest {
|
|
2
|
+
queryParams: string;
|
|
3
|
+
shortUrl: string;
|
|
4
|
+
password: string;
|
|
5
|
+
}
|
|
6
|
+
export declare enum CreateUrlResult {
|
|
7
|
+
Fail = 0,
|
|
8
|
+
Success = 1,
|
|
9
|
+
Duplicate = 2
|
|
10
|
+
}
|
|
11
|
+
export interface CreateUrlResponse {
|
|
12
|
+
result: CreateUrlResult;
|
|
13
|
+
}
|
|
14
|
+
export declare const jsonToCreateUrlRequest: (json: Record<string, never>) => CreateUrlRequest;
|
|
15
|
+
export declare const jsonToCreateUrlResponse: (json: Record<string, never>) => CreateUrlResponse;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export var CreateUrlResult;
|
|
2
|
+
(function (CreateUrlResult) {
|
|
3
|
+
CreateUrlResult[CreateUrlResult["Fail"] = 0] = "Fail";
|
|
4
|
+
CreateUrlResult[CreateUrlResult["Success"] = 1] = "Success";
|
|
5
|
+
CreateUrlResult[CreateUrlResult["Duplicate"] = 2] = "Duplicate";
|
|
6
|
+
})(CreateUrlResult || (CreateUrlResult = {}));
|
|
7
|
+
export const jsonToCreateUrlRequest = (json) => {
|
|
8
|
+
return {
|
|
9
|
+
queryParams: json["queryParams"] ?? "",
|
|
10
|
+
shortUrl: json["shortUrl"] ?? "",
|
|
11
|
+
password: json["password"] ?? ""
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export const jsonToCreateUrlResponse = (json) => {
|
|
15
|
+
const enumIndex = json["result"];
|
|
16
|
+
return {
|
|
17
|
+
result: CreateUrlResult[enumIndex] ? enumIndex : CreateUrlResult.Fail
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./CreateUrl";
|
package/.svelte-kit/ambient.d.ts
CHANGED
|
@@ -37,8 +37,6 @@ declare module '$env/static/private' {
|
|
|
37
37
|
export const COMSPEC: string;
|
|
38
38
|
export const DriverData: string;
|
|
39
39
|
export const EXEPATH: string;
|
|
40
|
-
export const FPS_BROWSER_APP_PROFILE_STRING: string;
|
|
41
|
-
export const FPS_BROWSER_USER_PROFILE_STRING: string;
|
|
42
40
|
export const GIT_XL_PATH: string;
|
|
43
41
|
export const GoLand: string;
|
|
44
42
|
export const GOPATH: string;
|
|
@@ -165,6 +163,7 @@ declare module '$env/static/private' {
|
|
|
165
163
|
export const PUBLIC: string;
|
|
166
164
|
export const PWD: string;
|
|
167
165
|
export const PyCharm: string;
|
|
166
|
+
export const SESSIONNAME: string;
|
|
168
167
|
export const SHLVL: string;
|
|
169
168
|
export const SYSTEMDRIVE: string;
|
|
170
169
|
export const SYSTEMROOT: string;
|
|
@@ -229,8 +228,6 @@ declare module '$env/dynamic/private' {
|
|
|
229
228
|
COMSPEC: string;
|
|
230
229
|
DriverData: string;
|
|
231
230
|
EXEPATH: string;
|
|
232
|
-
FPS_BROWSER_APP_PROFILE_STRING: string;
|
|
233
|
-
FPS_BROWSER_USER_PROFILE_STRING: string;
|
|
234
231
|
GIT_XL_PATH: string;
|
|
235
232
|
GoLand: string;
|
|
236
233
|
GOPATH: string;
|
|
@@ -357,6 +354,7 @@ declare module '$env/dynamic/private' {
|
|
|
357
354
|
PUBLIC: string;
|
|
358
355
|
PWD: string;
|
|
359
356
|
PyCharm: string;
|
|
357
|
+
SESSIONNAME: string;
|
|
360
358
|
SHLVL: string;
|
|
361
359
|
SYSTEMDRIVE: string;
|
|
362
360
|
SYSTEMROOT: string;
|
|
@@ -21,7 +21,7 @@ export const options = {
|
|
|
21
21
|
app: ({ head, body, assets, nonce, env }) => "<!DOCTYPE html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<link rel=\"icon\" href=\"" + assets + "/favicon.png\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width\" />\n\t\t" + head + "\n\t</head>\n\n\t<body data-sveltekit-preload-data=\"hover\" data-theme=\"crimson\">\n\t\t<div style=\"display: contents\" class=\"h-full overflow-hidden\">" + body + "</div>\n\t</body>\n</html>\n",
|
|
22
22
|
error: ({ status, message }) => "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<title>" + message + "</title>\n\n\t\t<style>\n\t\t\tbody {\n\t\t\t\t--bg: white;\n\t\t\t\t--fg: #222;\n\t\t\t\t--divider: #ccc;\n\t\t\t\tbackground: var(--bg);\n\t\t\t\tcolor: var(--fg);\n\t\t\t\tfont-family:\n\t\t\t\t\tsystem-ui,\n\t\t\t\t\t-apple-system,\n\t\t\t\t\tBlinkMacSystemFont,\n\t\t\t\t\t'Segoe UI',\n\t\t\t\t\tRoboto,\n\t\t\t\t\tOxygen,\n\t\t\t\t\tUbuntu,\n\t\t\t\t\tCantarell,\n\t\t\t\t\t'Open Sans',\n\t\t\t\t\t'Helvetica Neue',\n\t\t\t\t\tsans-serif;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: center;\n\t\t\t\theight: 100vh;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t.error {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tmax-width: 32rem;\n\t\t\t\tmargin: 0 1rem;\n\t\t\t}\n\n\t\t\t.status {\n\t\t\t\tfont-weight: 200;\n\t\t\t\tfont-size: 3rem;\n\t\t\t\tline-height: 1;\n\t\t\t\tposition: relative;\n\t\t\t\ttop: -0.05rem;\n\t\t\t}\n\n\t\t\t.message {\n\t\t\t\tborder-left: 1px solid var(--divider);\n\t\t\t\tpadding: 0 0 0 1rem;\n\t\t\t\tmargin: 0 0 0 1rem;\n\t\t\t\tmin-height: 2.5rem;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t}\n\n\t\t\t.message h1 {\n\t\t\t\tfont-weight: 400;\n\t\t\t\tfont-size: 1em;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t@media (prefers-color-scheme: dark) {\n\t\t\t\tbody {\n\t\t\t\t\t--bg: #222;\n\t\t\t\t\t--fg: #ddd;\n\t\t\t\t\t--divider: #666;\n\t\t\t\t}\n\t\t\t}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<div class=\"error\">\n\t\t\t<span class=\"status\">" + status + "</span>\n\t\t\t<div class=\"message\">\n\t\t\t\t<h1>" + message + "</h1>\n\t\t\t</div>\n\t\t</div>\n\t</body>\n</html>\n"
|
|
23
23
|
},
|
|
24
|
-
version_hash: "
|
|
24
|
+
version_hash: "shyqvz"
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
export async function get_hooks() {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type * as Kit from '@sveltejs/kit';
|
|
2
|
+
|
|
3
|
+
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
type MatcherParam<M> = M extends (param : string) => param is infer U ? U extends string ? U : string : string;
|
|
6
|
+
type RouteParams = { };
|
|
7
|
+
type RouteId = '/api/create-url';
|
|
8
|
+
|
|
9
|
+
export type RequestHandler = Kit.RequestHandler<RouteParams, RouteId>;
|
|
10
|
+
export type RequestEvent = Kit.RequestEvent<RouteParams, RouteId>;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { default as Card } from "./components/Card.svelte";
|
|
|
5
5
|
export { default as SocialSection } from "./components/SocialSection.svelte";
|
|
6
6
|
export * from "./components/overrideable_meta/index";
|
|
7
7
|
export * from "./components/navigation_component/index";
|
|
8
|
+
export * from "./types/api/index";
|
|
8
9
|
export * from "./components/dialog_manager/DialogManagerStore";
|
|
9
10
|
export * from "./components/dialog_manager/DialogManager";
|
|
10
11
|
export * from "./components/dialog_manager/DialogUtils";
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ export { default as Card } from "./components/Card.svelte";
|
|
|
6
6
|
export { default as SocialSection } from "./components/SocialSection.svelte";
|
|
7
7
|
export * from "./components/overrideable_meta/index";
|
|
8
8
|
export * from "./components/navigation_component/index";
|
|
9
|
+
export * from "./types/api/index";
|
|
9
10
|
export * from "./components/dialog_manager/DialogManagerStore";
|
|
10
11
|
export * from "./components/dialog_manager/DialogManager";
|
|
11
12
|
export * from "./components/dialog_manager/DialogUtils";
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<script>import { CreateUrlResult, jsonToCreateUrlResponse } from "../../types/api/CreateUrl";
|
|
2
|
+
import { getToastStore } from "@skeletonlabs/skeleton";
|
|
3
|
+
export let queryParams = "";
|
|
4
|
+
const toastStore = getToastStore();
|
|
5
|
+
let request = {
|
|
6
|
+
queryParams: "",
|
|
7
|
+
shortUrl: "",
|
|
8
|
+
password: ""
|
|
9
|
+
};
|
|
10
|
+
$:
|
|
11
|
+
request.queryParams = queryParams;
|
|
12
|
+
const failToast = {
|
|
13
|
+
message: "Adding new url failed"
|
|
14
|
+
};
|
|
15
|
+
const toastMap = /* @__PURE__ */ new Map([
|
|
16
|
+
[CreateUrlResult.Success, {
|
|
17
|
+
message: "Successfully added new url"
|
|
18
|
+
}],
|
|
19
|
+
[CreateUrlResult.Duplicate, {
|
|
20
|
+
message: "Short url already used; try again with another url"
|
|
21
|
+
}],
|
|
22
|
+
[CreateUrlResult.Fail, failToast]
|
|
23
|
+
]);
|
|
24
|
+
const post = () => {
|
|
25
|
+
fetch("/api/create-url", {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers: {
|
|
28
|
+
"Content-Type": "application/json"
|
|
29
|
+
},
|
|
30
|
+
body: JSON.stringify(request)
|
|
31
|
+
}).then(
|
|
32
|
+
(resp) => resp.json()
|
|
33
|
+
).then((json) => {
|
|
34
|
+
const properResp = jsonToCreateUrlResponse(json);
|
|
35
|
+
toastStore.trigger(toastMap.get(properResp.result) ?? failToast);
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<div>
|
|
41
|
+
<label for="short-url">Short URL for url shortener</label>
|
|
42
|
+
<input bind:value={request.shortUrl}
|
|
43
|
+
name="short-url"
|
|
44
|
+
class="input"
|
|
45
|
+
type="text"
|
|
46
|
+
placeholder="short-url" />
|
|
47
|
+
<label for="password">Password</label>
|
|
48
|
+
<input bind:value={request.password}
|
|
49
|
+
name="password"
|
|
50
|
+
class="input"
|
|
51
|
+
type="password"
|
|
52
|
+
placeholder="Input" />
|
|
53
|
+
<button class="btn variant-filled" on:click={post}>Send link</button>
|
|
54
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
queryParams?: string | undefined;
|
|
5
|
+
};
|
|
6
|
+
events: {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
};
|
|
9
|
+
slots: {};
|
|
10
|
+
};
|
|
11
|
+
export type CreateUrlFormProps = typeof __propDef.props;
|
|
12
|
+
export type CreateUrlFormEvents = typeof __propDef.events;
|
|
13
|
+
export type CreateUrlFormSlots = typeof __propDef.slots;
|
|
14
|
+
export default class CreateUrlForm extends SvelteComponent<CreateUrlFormProps, CreateUrlFormEvents, CreateUrlFormSlots> {
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const parseQueryTerms: (node: Element, querySet: Set<string>) => void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const parseQueryTerms = (node, querySet) => {
|
|
2
|
+
// change all text content to gibberish
|
|
3
|
+
for (const child of Array.from(node.children)) {
|
|
4
|
+
if (child.nodeType === Node.ELEMENT_NODE) {
|
|
5
|
+
parseQueryTerms(child, querySet);
|
|
6
|
+
// todo: if it's a span and it wraps a word, and qt class then we count that as query
|
|
7
|
+
// for (const childOfChild of child.childNodes) {
|
|
8
|
+
// if (childOfChild.nodeType === Node.TEXT_NODE && childOfChild.textContent?.trim()) {
|
|
9
|
+
// // todo analyze textcontent
|
|
10
|
+
// }
|
|
11
|
+
// }
|
|
12
|
+
// Warning: below is not redundant and is a catch-all
|
|
13
|
+
// Long-term solution: figure out the correct typing
|
|
14
|
+
if ((typeof child.className === "string") && child.className?.includes("qt-")) {
|
|
15
|
+
child.className.split(" ").forEach(c => {
|
|
16
|
+
if (c.startsWith("qt-")) {
|
|
17
|
+
querySet.add(c);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script>import {
|
|
1
|
+
<script>import { afterUpdate, onMount } from "svelte";
|
|
2
2
|
import EntryOrderConfig from "./entry_order_config/EntryOrderConfig.svelte";
|
|
3
3
|
import { runChaos } from "./RunChaos";
|
|
4
4
|
import SocialSection from "../../components/SocialSection.svelte";
|
|
@@ -8,24 +8,23 @@ import { Accordion, AccordionItem, CodeBlock, SlideToggle } from "@skeletonlabs/
|
|
|
8
8
|
import { page } from "$app/stores";
|
|
9
9
|
import Card from "../../components/Card.svelte";
|
|
10
10
|
import ElementVisbilityDetector from "../../components/ElementVisbilityDetector.svelte";
|
|
11
|
-
import selfContent from "./SeaweedTemplate.svelte?raw";
|
|
12
11
|
import {
|
|
13
12
|
AllGroupedEntriesProjectFirst,
|
|
14
13
|
GetEntryFromGlobal,
|
|
15
14
|
seaweedTemplateData,
|
|
16
15
|
TurnGroupEntriesMutable
|
|
17
16
|
} from "./SeaweedTemplateData";
|
|
17
|
+
import { parseQueryTerms } from "./ParseQueryTerms";
|
|
18
|
+
import UrlShortenerForm from "./CreateUrlForm.svelte";
|
|
18
19
|
export let letChaos = true;
|
|
19
20
|
export let name = "Turnip";
|
|
20
21
|
export let email = "turnipxenon@gmail.com";
|
|
21
22
|
export let linkedinSlug = "turnip-xenon";
|
|
22
23
|
export let domain = "http://localhost:5173/portfolio/actual/";
|
|
23
24
|
export let serverSideQueryParams = "";
|
|
24
|
-
export let extraComponent = void 0;
|
|
25
25
|
const entryProps = {
|
|
26
26
|
email
|
|
27
27
|
};
|
|
28
|
-
const entryList = import.meta.glob("./entries/*.svelte", { query: "?raw", eager: true });
|
|
29
28
|
const paramQTSet = /* @__PURE__ */ new Set();
|
|
30
29
|
let isVisible = true;
|
|
31
30
|
let isAdvanceSettingOn = false;
|
|
@@ -46,25 +45,9 @@ const syncQT = () => {
|
|
|
46
45
|
});
|
|
47
46
|
seaweedTemplateData.queryTermMap = seaweedTemplateData.queryTermMap;
|
|
48
47
|
};
|
|
49
|
-
const
|
|
50
|
-
console.log("parsing", seaweedTemplateData.queryTermMap.size);
|
|
48
|
+
const parseQueryTermsLocal = async () => {
|
|
51
49
|
const qtSet = /* @__PURE__ */ new Set();
|
|
52
|
-
|
|
53
|
-
[...Object.values(entryList).map((e) => e.default), selfContent].forEach((body) => {
|
|
54
|
-
console.log("parsing", body);
|
|
55
|
-
rawTermList.push(
|
|
56
|
-
...body.split('"').filter((s) => s.startsWith("qt-"))
|
|
57
|
-
// step 2: filter out texts that does not begin with "qt-"
|
|
58
|
-
);
|
|
59
|
-
});
|
|
60
|
-
rawTermList.forEach((t) => {
|
|
61
|
-
t.split(" ").forEach((nt) => {
|
|
62
|
-
if (["qt-1", "qt-2", "qt-*", "qt-"].includes(nt)) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
qtSet.add(nt);
|
|
66
|
-
});
|
|
67
|
-
});
|
|
50
|
+
parseQueryTerms(document.body, qtSet);
|
|
68
51
|
qtSet.forEach((t) => seaweedTemplateData.queryTermMap.set(t, true));
|
|
69
52
|
seaweedTemplateData.queryTermMap = seaweedTemplateData.queryTermMap;
|
|
70
53
|
syncQT();
|
|
@@ -132,7 +115,7 @@ let isParsed = false;
|
|
|
132
115
|
afterUpdate(async () => {
|
|
133
116
|
if (!letChaos && !isParsed) {
|
|
134
117
|
isParsed = true;
|
|
135
|
-
await
|
|
118
|
+
await parseQueryTermsLocal();
|
|
136
119
|
}
|
|
137
120
|
});
|
|
138
121
|
const toggleTerm = (term) => {
|
|
@@ -141,6 +124,7 @@ const toggleTerm = (term) => {
|
|
|
141
124
|
};
|
|
142
125
|
let orderUrl = "";
|
|
143
126
|
let advancedUrl = domain;
|
|
127
|
+
let advancedQuery = "";
|
|
144
128
|
const updateUrl = (seaweedTemplateData2) => {
|
|
145
129
|
const queryParams = [];
|
|
146
130
|
if (orderUrl) {
|
|
@@ -164,7 +148,8 @@ const updateUrl = (seaweedTemplateData2) => {
|
|
|
164
148
|
queryParams.push("game-section-first=false");
|
|
165
149
|
}
|
|
166
150
|
if (queryParams.length > 0) {
|
|
167
|
-
|
|
151
|
+
advancedQuery = queryParams.join("&");
|
|
152
|
+
advancedUrl = `${domain}?${advancedQuery}`;
|
|
168
153
|
} else {
|
|
169
154
|
advancedUrl = domain;
|
|
170
155
|
}
|
|
@@ -375,7 +360,7 @@ $:
|
|
|
375
360
|
<p>Copy the url below and open a new page with it</p>
|
|
376
361
|
<CodeBlock language="url" code={advancedUrl}></CodeBlock>
|
|
377
362
|
|
|
378
|
-
<
|
|
363
|
+
<UrlShortenerForm queryParams={advancedQuery}></UrlShortenerForm>
|
|
379
364
|
{/if}
|
|
380
365
|
</div>
|
|
381
366
|
</Card>
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
|
-
import { type ComponentType } from "svelte";
|
|
3
2
|
import "./seaweed.postcss";
|
|
4
3
|
declare const __propDef: {
|
|
5
4
|
props: {
|
|
@@ -9,7 +8,6 @@ declare const __propDef: {
|
|
|
9
8
|
linkedinSlug?: string | undefined;
|
|
10
9
|
domain?: string | undefined;
|
|
11
10
|
serverSideQueryParams?: string | undefined;
|
|
12
|
-
extraComponent?: ComponentType | undefined;
|
|
13
11
|
};
|
|
14
12
|
events: {
|
|
15
13
|
[evt: string]: CustomEvent<any>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface CreateUrlRequest {
|
|
2
|
+
queryParams: string;
|
|
3
|
+
shortUrl: string;
|
|
4
|
+
password: string;
|
|
5
|
+
}
|
|
6
|
+
export declare enum CreateUrlResult {
|
|
7
|
+
Fail = 0,
|
|
8
|
+
Success = 1,
|
|
9
|
+
Duplicate = 2
|
|
10
|
+
}
|
|
11
|
+
export interface CreateUrlResponse {
|
|
12
|
+
result: CreateUrlResult;
|
|
13
|
+
}
|
|
14
|
+
export declare const jsonToCreateUrlRequest: (json: Record<string, never>) => CreateUrlRequest;
|
|
15
|
+
export declare const jsonToCreateUrlResponse: (json: Record<string, never>) => CreateUrlResponse;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export var CreateUrlResult;
|
|
2
|
+
(function (CreateUrlResult) {
|
|
3
|
+
CreateUrlResult[CreateUrlResult["Fail"] = 0] = "Fail";
|
|
4
|
+
CreateUrlResult[CreateUrlResult["Success"] = 1] = "Success";
|
|
5
|
+
CreateUrlResult[CreateUrlResult["Duplicate"] = 2] = "Duplicate";
|
|
6
|
+
})(CreateUrlResult || (CreateUrlResult = {}));
|
|
7
|
+
export const jsonToCreateUrlRequest = (json) => {
|
|
8
|
+
return {
|
|
9
|
+
queryParams: json["queryParams"] ?? "",
|
|
10
|
+
shortUrl: json["shortUrl"] ?? "",
|
|
11
|
+
password: json["password"] ?? ""
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export const jsonToCreateUrlResponse = (json) => {
|
|
15
|
+
const enumIndex = json["result"];
|
|
16
|
+
return {
|
|
17
|
+
result: CreateUrlResult[enumIndex] ? enumIndex : CreateUrlResult.Fail
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./CreateUrl";
|
package/package.json
CHANGED
package/src/lib/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export { default as SocialSection } from "./components/SocialSection.svelte";
|
|
|
8
8
|
|
|
9
9
|
export * from "$pkg/components/overrideable_meta/index";
|
|
10
10
|
export * from "$pkg/components/navigation_component/index";
|
|
11
|
+
export * from "$pkg/types/api/index";
|
|
11
12
|
export * from "./components/dialog_manager/DialogManagerStore";
|
|
12
13
|
export * from "./components/dialog_manager/DialogManager";
|
|
13
14
|
export * from "./components/dialog_manager/DialogUtils";
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { type CreateUrlRequest, CreateUrlResult, jsonToCreateUrlResponse } from "$pkg/types/api/CreateUrl";
|
|
3
|
+
import { getToastStore, type ToastSettings } from "@skeletonlabs/skeleton";
|
|
4
|
+
|
|
5
|
+
export let queryParams = "";
|
|
6
|
+
|
|
7
|
+
const toastStore = getToastStore();
|
|
8
|
+
|
|
9
|
+
let request: CreateUrlRequest = {
|
|
10
|
+
queryParams: "",
|
|
11
|
+
shortUrl: "",
|
|
12
|
+
password: ""
|
|
13
|
+
};
|
|
14
|
+
$: request.queryParams = queryParams;
|
|
15
|
+
|
|
16
|
+
const failToast: ToastSettings = {
|
|
17
|
+
message: "Adding new url failed"
|
|
18
|
+
};
|
|
19
|
+
const toastMap = new Map<CreateUrlResult, ToastSettings>([
|
|
20
|
+
[CreateUrlResult.Success, {
|
|
21
|
+
message: "Successfully added new url"
|
|
22
|
+
}],
|
|
23
|
+
[CreateUrlResult.Duplicate, {
|
|
24
|
+
message: "Short url already used; try again with another url"
|
|
25
|
+
}],
|
|
26
|
+
[CreateUrlResult.Fail, failToast]
|
|
27
|
+
]);
|
|
28
|
+
const post = () => {
|
|
29
|
+
fetch("/api/create-url", {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: {
|
|
32
|
+
"Content-Type": "application/json"
|
|
33
|
+
},
|
|
34
|
+
body: JSON.stringify(request)
|
|
35
|
+
}).then(resp =>
|
|
36
|
+
resp.json()
|
|
37
|
+
).then(json => {
|
|
38
|
+
const properResp = jsonToCreateUrlResponse(json);
|
|
39
|
+
toastStore.trigger(toastMap.get(properResp.result) ?? failToast);
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<div>
|
|
45
|
+
<label for="short-url">Short URL for url shortener</label>
|
|
46
|
+
<input bind:value={request.shortUrl}
|
|
47
|
+
name="short-url"
|
|
48
|
+
class="input"
|
|
49
|
+
type="text"
|
|
50
|
+
placeholder="short-url" />
|
|
51
|
+
<label for="password">Password</label>
|
|
52
|
+
<input bind:value={request.password}
|
|
53
|
+
name="password"
|
|
54
|
+
class="input"
|
|
55
|
+
type="password"
|
|
56
|
+
placeholder="Input" />
|
|
57
|
+
<button class="btn variant-filled" on:click={post}>Send link</button>
|
|
58
|
+
</div>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const parseQueryTerms = (node: Element, querySet: Set<string>) => {
|
|
2
|
+
// change all text content to gibberish
|
|
3
|
+
for (const child of Array.from(node.children)) {
|
|
4
|
+
if (child.nodeType === Node.ELEMENT_NODE) {
|
|
5
|
+
parseQueryTerms(child, querySet);
|
|
6
|
+
// todo: if it's a span and it wraps a word, and qt class then we count that as query
|
|
7
|
+
// for (const childOfChild of child.childNodes) {
|
|
8
|
+
// if (childOfChild.nodeType === Node.TEXT_NODE && childOfChild.textContent?.trim()) {
|
|
9
|
+
// // todo analyze textcontent
|
|
10
|
+
// }
|
|
11
|
+
// }
|
|
12
|
+
|
|
13
|
+
// Warning: below is not redundant and is a catch-all
|
|
14
|
+
// Long-term solution: figure out the correct typing
|
|
15
|
+
if ((typeof child.className === "string") && child.className?.includes("qt-")) {
|
|
16
|
+
child.className.split(" ").forEach(c => {
|
|
17
|
+
|
|
18
|
+
if (c.startsWith("qt-")) {
|
|
19
|
+
querySet.add(c);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { type ComponentType, onMount
|
|
2
|
+
import { afterUpdate, type ComponentType, onMount } from "svelte";
|
|
3
3
|
import EntryOrderConfig from "$pkg/template/seaweed/entry_order_config/EntryOrderConfig.svelte";
|
|
4
4
|
import { runChaos } from "$pkg/template/seaweed/RunChaos";
|
|
5
5
|
import SocialSection from "$pkg/components/SocialSection.svelte";
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
import { page } from "$app/stores";
|
|
10
10
|
import Card from "$pkg/components/Card.svelte";
|
|
11
11
|
import ElementVisbilityDetector from "$pkg/components/ElementVisbilityDetector.svelte";
|
|
12
|
-
import selfContent from "./SeaweedTemplate.svelte?raw";
|
|
13
12
|
import {
|
|
14
13
|
AllGroupedEntriesProjectFirst,
|
|
15
14
|
type EntryGroup,
|
|
@@ -19,7 +18,8 @@
|
|
|
19
18
|
TurnGroupEntriesMutable
|
|
20
19
|
} from "./SeaweedTemplateData";
|
|
21
20
|
import type { EntryProps } from "$pkg/template/seaweed/entries/EntryProps";
|
|
22
|
-
import
|
|
21
|
+
import { parseQueryTerms } from "$pkg/template/seaweed/ParseQueryTerms";
|
|
22
|
+
import UrlShortenerForm from "$pkg/template/seaweed/CreateUrlForm.svelte";
|
|
23
23
|
|
|
24
24
|
export let letChaos = true;
|
|
25
25
|
export let name = "Turnip";
|
|
@@ -27,14 +27,12 @@
|
|
|
27
27
|
export let linkedinSlug = "turnip-xenon";
|
|
28
28
|
export let domain = "http://localhost:5173/portfolio/actual/";
|
|
29
29
|
export let serverSideQueryParams = "";
|
|
30
|
-
export let extraComponent: ComponentType | undefined = undefined;
|
|
31
30
|
|
|
32
31
|
// region query params
|
|
33
32
|
const entryProps: EntryProps = {
|
|
34
33
|
email
|
|
35
34
|
};
|
|
36
35
|
|
|
37
|
-
const entryList = import.meta.glob("./entries/*.svelte", { query: "?raw", eager: true });
|
|
38
36
|
const paramQTSet = new Set<string>();
|
|
39
37
|
|
|
40
38
|
let isVisible = true;
|
|
@@ -61,36 +59,9 @@
|
|
|
61
59
|
seaweedTemplateData.queryTermMap = seaweedTemplateData.queryTermMap;
|
|
62
60
|
};
|
|
63
61
|
|
|
64
|
-
const
|
|
65
|
-
console.log("parsing", seaweedTemplateData.queryTermMap.size);
|
|
62
|
+
const parseQueryTermsLocal = async () => {
|
|
66
63
|
const qtSet = new Set<string>();
|
|
67
|
-
|
|
68
|
-
[...Object.values(entryList).map(e => (e as RawGlob).default), selfContent].forEach(body => {
|
|
69
|
-
// parse the qt-* term which exists within elements like:
|
|
70
|
-
// <span class="qt-*">TERM</span>
|
|
71
|
-
console.log("parsing", body);
|
|
72
|
-
rawTermList.push(
|
|
73
|
-
...body // step 3: destructure the array
|
|
74
|
-
.split("\"") // step 1: split the text as double quotations (") as the delimiter
|
|
75
|
-
.filter(s => s.startsWith("qt-")) // step 2: filter out texts that does not begin with "qt-"
|
|
76
|
-
);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// step 4: some spans contain multiple classes, split them up
|
|
80
|
-
// then add them to qtTerms
|
|
81
|
-
// e.g. <span class="qt-1 qt-2">TERM</span>
|
|
82
|
-
rawTermList.forEach(t => {
|
|
83
|
-
t.split(" ").forEach(nt => {
|
|
84
|
-
// filter out some of this meta terms
|
|
85
|
-
if (["qt-1", "qt-2", "qt-*", "qt-"].includes(nt)) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
// adding to set ensures the entry is unique
|
|
90
|
-
qtSet.add(nt);
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
64
|
+
parseQueryTerms(document.body, qtSet);
|
|
94
65
|
qtSet.forEach(t => seaweedTemplateData.queryTermMap.set(t, true));
|
|
95
66
|
// force svelte update
|
|
96
67
|
seaweedTemplateData.queryTermMap = seaweedTemplateData.queryTermMap;
|
|
@@ -194,7 +165,7 @@
|
|
|
194
165
|
afterUpdate(async () => {
|
|
195
166
|
if (!letChaos && !isParsed) {
|
|
196
167
|
isParsed = true;
|
|
197
|
-
await
|
|
168
|
+
await parseQueryTermsLocal();
|
|
198
169
|
}
|
|
199
170
|
});
|
|
200
171
|
|
|
@@ -206,6 +177,7 @@
|
|
|
206
177
|
// when either gameSectionFirst or the queryTerms are updated, update advancedUrl
|
|
207
178
|
let orderUrl = "";
|
|
208
179
|
let advancedUrl = domain;
|
|
180
|
+
let advancedQuery = "";
|
|
209
181
|
const updateUrl = (seaweedTemplateData: SeaweedTemplateData) => {
|
|
210
182
|
const queryParams: string[] = [];
|
|
211
183
|
|
|
@@ -237,7 +209,8 @@
|
|
|
237
209
|
}
|
|
238
210
|
|
|
239
211
|
if (queryParams.length > 0) {
|
|
240
|
-
|
|
212
|
+
advancedQuery = queryParams.join("&");
|
|
213
|
+
advancedUrl = `${domain}?${advancedQuery}`;
|
|
241
214
|
} else {
|
|
242
215
|
advancedUrl = domain;
|
|
243
216
|
}
|
|
@@ -448,7 +421,7 @@
|
|
|
448
421
|
<p>Copy the url below and open a new page with it</p>
|
|
449
422
|
<CodeBlock language="url" code={advancedUrl}></CodeBlock>
|
|
450
423
|
|
|
451
|
-
<
|
|
424
|
+
<UrlShortenerForm queryParams={advancedQuery}></UrlShortenerForm>
|
|
452
425
|
{/if}
|
|
453
426
|
</div>
|
|
454
427
|
</Card>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface CreateUrlRequest {
|
|
2
|
+
queryParams: string;
|
|
3
|
+
shortUrl: string;
|
|
4
|
+
password: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export enum CreateUrlResult {
|
|
8
|
+
Fail = 0,
|
|
9
|
+
Success = 1,
|
|
10
|
+
Duplicate = 2
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface CreateUrlResponse {
|
|
14
|
+
result: CreateUrlResult;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const jsonToCreateUrlRequest = (json: Record<string, never>): CreateUrlRequest => {
|
|
18
|
+
return {
|
|
19
|
+
queryParams: json["queryParams"] ?? "",
|
|
20
|
+
shortUrl: json["shortUrl"] ?? "",
|
|
21
|
+
password: json["password"] ?? ""
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const jsonToCreateUrlResponse = (json: Record<string, never>): CreateUrlResponse => {
|
|
26
|
+
const enumIndex = json["result"] as number;
|
|
27
|
+
return {
|
|
28
|
+
result: CreateUrlResult[enumIndex] ? enumIndex : CreateUrlResult.Fail
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { initializeStores } from "@skeletonlabs/skeleton";
|
|
2
|
+
import { initializeStores, Toast } from "@skeletonlabs/skeleton";
|
|
3
3
|
import { Modal } from "@skeletonlabs/skeleton";
|
|
4
4
|
|
|
5
5
|
initializeStores();
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<Modal />
|
|
9
|
+
<Toast />
|
|
9
10
|
|
|
10
11
|
<slot />
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
email="allanmanuba@gmail.com"
|
|
9
9
|
linkedinSlug="allan-manuba"
|
|
10
10
|
serverSideQueryParams="order=Games:Hepcat|ChefWings|Soulwork|ItchPromo:games-section,Projects:MigranteAlberta|DecentralizedSocialMedia|CustomizedYarnspinner|FullStackC|Workset|ThisWebpage|MockUberApp:projects-section,Relevant projects:MigranteAlberta:games-section&game-section-first=false"
|
|
11
|
-
|
|
11
|
+
>
|
|
12
12
|
|
|
13
13
|
</SeaweedTemplate>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { RequestHandler } from "./$types";
|
|
2
|
+
import { type CreateUrlResponse, CreateUrlResult, jsonToCreateUrlRequest } from "$pkg/types/api/CreateUrl";
|
|
3
|
+
|
|
4
|
+
export const POST: RequestHandler = async ({ request }) => {
|
|
5
|
+
const response: CreateUrlResponse = {
|
|
6
|
+
result: CreateUrlResult.Fail
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
console.log("This is a fake API. The real API is somewhere else.");
|
|
10
|
+
const data = jsonToCreateUrlRequest(await request.json());
|
|
11
|
+
console.log(data);
|
|
12
|
+
|
|
13
|
+
if (data.password !== "FakePassword") {
|
|
14
|
+
return new Response(JSON.stringify(response));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (data.shortUrl === "already-used") {
|
|
18
|
+
response.result = CreateUrlResult.Duplicate;
|
|
19
|
+
return new Response(JSON.stringify(response));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
response.result = CreateUrlResult.Success;
|
|
23
|
+
return new Response(JSON.stringify(response));
|
|
24
|
+
};
|