Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export default defineConfig({
command: "npm run build && npm run preview",
port: 4173,
},
fullyParallel: true,
testDir: "src/tests/e2e",
});
2 changes: 1 addition & 1 deletion src/lib/components/modals/CustomSourceModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@
<Combobox
items={defaultAtlases}
type="single"
inputProps={{ placeholder: "Type an alias or use a default..." }}
inputProps={{ placeholder: "Defaults to minecraft:blocks" }}
bind:value={customValues.object.atlas} />
<p class="mt-2">Sprite</p>
<input
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/modals/ExportModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import Modal from "$lib/components/Modal.svelte";
import { outputVersion } from "$lib/stores";
import { translateMOTD } from "$lib/text/motd";
import { convert } from "$lib/text/nbt/nbt_or_json";
import { convert } from "$lib/text/nbt/export";
import IconCopy from "~icons/tabler/copy";
import CheckBox from "../CheckBox.svelte";
let {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/text/MiniEditor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
import IconColor from "~icons/tabler/palette";
import IconSquare from "~icons/tabler/square-filled";
import IconHollow from "~icons/tabler/square-x";
import { convertToTextOrEmpty, snbtToDocument } from "../../text/nbt/nbt";
import { convertToTextOrEmpty, snbtToDocument } from "../../text/nbt/import";

import {
colorMap,
defaultColorLUT,
trueMarkOrUndefined,
} from "$lib/text/utils";
import { addTypeSpecificValues } from "$lib/text/nbt/nbt_or_json";
import { addTypeSpecificValues } from "$lib/text/nbt/export";
import {
FontsExtension,
Obfuscation,
Expand Down
38 changes: 38 additions & 0 deletions src/lib/components/text/ShadowColorButton.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script lang="ts">
import { tooltip } from "$lib/tooltip";
import IconShadow from "~icons/tabler/shadow";

interface Props {
/** DOM element of the label wrapper */
labelElement: HTMLLabelElement | undefined;
/** hex color */
hex: string | null;
/** input label */
label: string;
/** input name, useful in a native form */
name?: string | undefined;
/** directionality left to right, or right to left*/
dir: "ltr" | "rtl";
small?: boolean;
}

let {
labelElement = $bindable(),
hex,
label,
name = undefined,
dir,
small,
}: Props = $props();
</script>

<button
aria-label="Shadow Color"
{@attach tooltip}
class="p-1 {small
? 'text-sm'
: 'text-lg'} rounded-md font-medium hover:bg-white/3">
<label bind:this={labelElement} {dir}>
<IconShadow />
</label>
</button>
61 changes: 29 additions & 32 deletions src/lib/components/text/TextStyleButtons.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { colorMap, defaultColorLUT } from "$lib/text/utils";
import { colorMap } from "$lib/text/utils";
import { tooltip } from "$lib/tooltip";
import type { Editor } from "@tiptap/core";
import ColorPicker from "svelte-awesome-color-picker";
Expand All @@ -9,10 +9,13 @@
import IconShadow from "~icons/tabler/shadow";
import IconStrikethrough from "~icons/tabler/strikethrough";
import IconUnderline from "~icons/tabler/underline";
import ShadowColorButton from "./ShadowColorButton.svelte";

const { editor, small = false }: { editor: Editor; small?: boolean } =
$props();
let shadowColorValue = $state("#ffffff");
let shouldIgnoreInitInput = true;
let isColorPickerOpen = $state(false);
</script>

<button
Expand Down Expand Up @@ -80,42 +83,36 @@
: ''}">
<IconObfuscate />
</button>
<div class="mx-2 h-5 w-px bg-zinc-600"></div>
{#if editor.isActive("shadowColor")}
<button
aria-label="Shadow Color"
name="shadow_color"
{@attach tooltip}
class="p-1 {small
? 'text-sm'
: 'text-lg'} rounded-md bg-zinc-800 font-medium hover:bg-white/3"
onclick={() => editor.chain().focus().unsetShadowColor().run()}>
<IconShadow />
</button>

{#if !editor.isActive("shadowColor") || isColorPickerOpen}
<ColorPicker
isAlpha={false}
bind:hex={shadowColorValue}
bind:isOpen={isColorPickerOpen}
--cp-bg-color="#18181b"
--cp-text-color="white"
--cp-input-color="#0C0C0E"
--cp-button-hover-color="#18181b"
textInputModes={["hex"]}
onInput={(c) => {
if (isColorPickerOpen) {
c.hex && editor.chain().focus().setShadowColor(c.hex).run();
}
}}
swatches={Object.values(colorMap).map((c) => c.value)}
components={{ input: ShadowColorButton }} />
{:else}
<button
aria-label="Shadow Color"
name="shadow_color"
aria-label="Unset Shadow Color"
{@attach tooltip}
onclick={() => {
shouldIgnoreInitInput = true;
shadowColorValue = "#ffffff";
editor.chain().focus().unsetShadowColor().run();
}}
class="p-1 {small
? 'text-sm'
: 'text-lg'} rounded-md font-medium hover:bg-white/3"
onclick={() => {
editor.chain().focus().setShadowColor(shadowColorValue).run();
}}>
: 'text-lg'} rounded-md bg-zinc-800 font-medium hover:bg-white/3">
<IconShadow />
</button>
{/if}
<!-- isAlpha is off because ARGB != RGBA and i want to get the update out -->
<ColorPicker
isAlpha={false}
bind:hex={shadowColorValue}
--cp-bg-color="#18181b"
--cp-text-color="white"
--cp-input-color="#0C0C0E"
--cp-button-hover-color="#18181b"
--input-size="20px"
textInputModes={["hex"]}
swatches={Object.values(colorMap).map((c) => c.value)}
label="" />
<div class="mx-2 h-5 w-px bg-zinc-600"></div>
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ export function addTypeSpecificValues(
case "atlas_object":
if (exportVersion.index >= 2) {
current.object = "atlas";
current.atlas = c.attrs?.atlas;
if(current.atlas) {
current.atlas = c.attrs?.atlas;
}
current.sprite = c.attrs?.sprite;

current.bold = undefined;
Expand Down
File renamed without changes.
2 changes: 0 additions & 2 deletions src/lib/text/nbt/optimiser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,10 @@ function mergeTextComponents(output: StringyMCText[]) {
// Find shared style/interactivity properties between consecutive objects
if (typeof current === "object" && typeof next === "object") {
const sharedProperties = getSharedStyleProps(current, next);
console.log("Shared Properties:", sharedProperties);

if (Object.keys(sharedProperties).length > 0) {
let group = [current];
collectAllFromIndex(i, group, output, sharedProperties);
console.log("Group Collected:", group);

if (group.length < 1) {
continue;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/tiptap/extensions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export interface SelectorAttributes {
}

export interface AtlasObjectAttributes {
atlas: string;
atlas?: string;
sprite: string;
}

Expand Down
5 changes: 4 additions & 1 deletion src/lib/tiptap/extensions/nodes/AtlasObjectNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ export const AtlasObjectNode = Node.create<NodeOptions>({
},

renderHTML({ HTMLAttributes, node }) {
const { atlas, sprite } = node.attrs;
let { atlas, sprite } = node.attrs;
if (!atlas) {
atlas = "minecraft:blocks"
}

return [
"span",
Expand Down
5 changes: 3 additions & 2 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { convert } from "$lib/text/nbt/nbt_or_json";
import { convert } from "$lib/text/nbt/export";

import {
AtlasObjectNode,
Expand All @@ -24,7 +24,7 @@
import MiniRenderer from "$lib/components/text/MiniRenderer.svelte";
import ColorPicker from "svelte-awesome-color-picker";

import { convertToTextOrEmpty, snbtToDocument } from "$lib/text/nbt/nbt";
import { convertToTextOrEmpty, snbtToDocument } from "$lib/text/nbt/import";
import { Editor, type JSONContent } from "@tiptap/core";
import Color from "@tiptap/extension-color";
import Placeholder from "@tiptap/extension-placeholder";
Expand Down Expand Up @@ -559,6 +559,7 @@
<div
class="font-minecraft w-full grow overflow-auto bg-zinc-800 first:focus:outline-none"
spellcheck="false"
id="wysiwyg-box"
bind:this={element}>
</div>

Expand Down
35 changes: 23 additions & 12 deletions src/tests/e2e/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@ test("home page loads", async ({ page }) => {

test("blank text updates with formatted output", async ({ page }) => {
await page.getByLabel("Keybinds").waitFor();
const textbox = page.getByRole("textbox").nth(1);
await textbox.click();
const textbox = page.locator("#wysiwyg-box>[role=textbox]").first();
await textbox.fill("lorem ipsum");
const output = page.locator("#outputbox").first();
await expect(output).toHaveText(`"lorem ipsum"`);
});

test("the bold button should work", async ({ page }) => {
const textbox = page.getByRole("textbox").nth(1);
await textbox.click();
const textbox = page.locator("#wysiwyg-box>[role=textbox]").first();
await textbox.fill("lorem ipsum");
await textbox.selectText();
let button = page.getByRole("button", { name: "Bold " });
Expand All @@ -34,8 +32,7 @@ test("the bold button should work", async ({ page }) => {
});

test("the italic button should work", async ({ page }) => {
const textbox = page.getByRole("textbox").nth(1);
await textbox.click();
const textbox = page.locator("#wysiwyg-box>[role=textbox]").first();
await textbox.fill("lorem ipsum");
await textbox.selectText();
let button = page.getByRole("button", { name: "Italic " });
Expand All @@ -48,8 +45,7 @@ test("the italic button should work", async ({ page }) => {
});

test("the strikethrough button should work", async ({ page }) => {
const textbox = page.getByRole("textbox").nth(1);
await textbox.click();
const textbox = page.locator("#wysiwyg-box>[role=textbox]").first();
await textbox.fill("lorem ipsum");
await textbox.selectText();
let button = page.getByRole("button", { name: "Strikethrough " });
Expand All @@ -62,8 +58,7 @@ test("the strikethrough button should work", async ({ page }) => {
});

test("the underline button should work", async ({ page }) => {
const textbox = page.getByRole("textbox").nth(1);
await textbox.click();
const textbox = page.locator("#wysiwyg-box>[role=textbox]").first();
await textbox.fill("lorem ipsum");
await textbox.selectText();
let button = page.getByRole("button", { name: "Underline " });
Expand All @@ -76,11 +71,27 @@ test("the underline button should work", async ({ page }) => {
});

test("the obfuscation button should work", async ({ page }) => {
const textbox = page.getByRole("textbox").nth(1);
await textbox.click();
const textbox = page.locator("#wysiwyg-box>[role=textbox]").first();
await textbox.fill("lorem ipsum");
await textbox.selectText();
let button = page.getByRole("button", { name: "Obfuscated " });
await button.click();
expect(await textbox.locator("p>span.obfuscated").count()).toBeGreaterThan(0);
});

test("the shadow color button should work", async ({ page }) => {
const textbox = page.locator("#wysiwyg-box>[role=textbox]").first();
await textbox.fill("lorem ipsum");
await textbox.selectText();
let button = page.getByRole("button", { name: "Shadow Color" });
await button.click();
const colorInput = page.locator('input[aria-label="hex color"]');
await colorInput.fill("#ff0000");
await colorInput.press("Enter");
expect(
await textbox.locator('p>span[style*="text-shadow"]').count(),
).toBeGreaterThan(0);
await expect(
textbox.locator('p>span[style*="text-shadow"]').first(),
).toHaveAttribute("style", "text-shadow: rgb(255, 0, 0) 2px 2px 0px;");
});
2 changes: 1 addition & 1 deletion src/tests/unit/snbt_importing.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { convertToTextOrEmpty, snbtToDocument } from "$lib/text/nbt/nbt";
import { convertToTextOrEmpty, snbtToDocument } from "../../lib/text/nbt/import";
import { describe, expect, it } from "vitest";
import { readTestDataFile, readTestJSONFile } from "./test_utils";

Expand Down
2 changes: 1 addition & 1 deletion src/tests/unit/translating_mc_json.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
addTypeSpecificValues,
translateJSON,
} from "$lib/text/nbt/nbt_or_json";
} from "$lib/text/nbt/export";
import {
versions,
type MinecraftText,
Expand Down
Loading