Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/markdown editor #126

Draft
wants to merge 45 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
22167f9
🙈 use experimental-https for dev server
Fredkiss3 Jan 7, 2024
881f256
🔧 only include workspace symbols in search
Fredkiss3 Jan 7, 2024
11caa79
🚸 prevent double submission with submit-button
Fredkiss3 Jan 7, 2024
f614154
✨ interpret new lines as `<br>` in markdown
Fredkiss3 Jan 7, 2024
12107b7
💄 some ui fixes
Fredkiss3 Jan 7, 2024
d5c7d60
🚧 wip
Fredkiss3 Jan 7, 2024
7d59ec7
🚧 some changes
Fredkiss3 Jan 7, 2024
43f1821
👷 only deploy :dev image for PRs
Fredkiss3 Jan 7, 2024
49b128d
🚧 editor work in progress
Fredkiss3 Jan 7, 2024
637213c
👷 don't upload build SHA github artifacts
Fredkiss3 Jan 7, 2024
a9a14ae
✨ undo/redo + tab features
Fredkiss3 Jan 7, 2024
0316354
✨ add quote/unquote toolbar action + fix preloading markdown
Fredkiss3 Jan 7, 2024
81c14b3
🐛 disable toolbar buttons when not visible
Fredkiss3 Jan 7, 2024
cda6718
Merge branch 'main' into feat/markdown-editor
Fredkiss3 Jan 7, 2024
7764e38
✨ add link done
Fredkiss3 Jan 8, 2024
660188d
🎨 always add trailing commas
Fredkiss3 Jan 8, 2024
62e63aa
✨ strike through feature
Fredkiss3 Jan 8, 2024
acd258e
✨ handle pasting link into text area
Fredkiss3 Jan 8, 2024
4f9eaf0
⏪ don't always add trailing comma
Fredkiss3 Jan 8, 2024
867110e
🚧 WIP : add lists
Fredkiss3 Jan 8, 2024
9907640
⬆️ upgrade next to canary
Fredkiss3 Jan 10, 2024
39ba187
Merge branch 'main' into feat/markdown-editor
Fredkiss3 Jan 12, 2024
03c3797
Merge branch 'main' into feat/markdown-editor
Fredkiss3 Jan 17, 2024
f881128
🚧 some changes
Fredkiss3 Jan 17, 2024
dfb190f
🔥 remove unused code
Fredkiss3 Jan 18, 2024
69cf432
🐛 fix bug with dropdown not focusing the textarea again.
Fredkiss3 Jan 18, 2024
3232d83
♻️ refactor
Fredkiss3 Jan 18, 2024
4ca3368
✨ handle list with selected characters
Fredkiss3 Jan 18, 2024
c47a4d6
💄 Fix list items styling
Fredkiss3 Jan 18, 2024
cc80119
💄 remove button support
Fredkiss3 Jan 18, 2024
7a96cd7
♻️ add more unsupported tags
Fredkiss3 Jan 18, 2024
50e3b01
Merge branch 'main' into feat/markdown-editor
Fredkiss3 Jan 28, 2024
a36c391
♻️ non functionning preview, but no error
Fredkiss3 Jan 28, 2024
613fec3
♻️ pass render markdown action from the root server component down
Fredkiss3 Jan 29, 2024
297ff2b
⚡️ fetch user and repository in parallel
Fredkiss3 Jan 29, 2024
905b834
💄 cut links off by 150 chars max
Fredkiss3 Jan 29, 2024
aa1d68e
💄 tweak `h-` tags styling
Fredkiss3 Jan 29, 2024
6df1bcb
♻️ don't put the promise into another transition
Fredkiss3 Jan 29, 2024
4cda2ae
🐛 correctly format quotes action
Fredkiss3 Jan 29, 2024
4284110
♻️ don't recreate the promise map on every render
Fredkiss3 Jan 29, 2024
1d0f45a
🚧 add some fuild font CSS
Fredkiss3 Jan 29, 2024
becc387
♻️ use `has` instead of `get` (same thing honestly)🤷
Fredkiss3 Jan 29, 2024
96cdb17
💄 fix markdown styling
Fredkiss3 Jan 29, 2024
e71fef2
Merge branch 'main' into feat/markdown-editor
Fredkiss3 Jan 31, 2024
fa7d304
🚧 wip
Fredkiss3 Feb 11, 2024
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
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"db:fetch-issues": "set -a; . ./.env.local; set +a && tsx --tsconfig ./tsconfig.script.json ./scripts/fetchIssues.ts"
},
"dependencies": {
"@ariakit/react": "^0.4.1",
"@headlessui/react": "^1.7.17",
"@mdx-js/mdx": "^3.0.0",
"@neshca/cache-handler": "^0.6.2",
Expand All @@ -32,6 +33,7 @@
"@rsc-cache/next": "^1.1.1",
"@t3-oss/env-nextjs": "^0.6.1",
"@tanstack/react-query": "^5.0.0",
"@types/textarea-caret": "^3.0.3",
"bright": "^0.8.4",
"client-only": "^0.0.1",
"cmdk": "^0.2.0",
Expand Down Expand Up @@ -63,6 +65,7 @@
"sharp": "^0.32.5",
"tailwind-merge": "^1.14.0",
"text-field-edit": "^4.0.0",
"textarea-caret": "^3.1.0",
"vfile": "^6.0.1",
"zod": "^3.22.2",
"zod-form-data": "^2.0.1",
Expand Down
45 changes: 45 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion src/actions/issue.action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { issueSearchListOutputValidator } from "~/models/dto/issue-search-output
import { searchIssues } from "~/models/issues/search";

import { getAuthedUser } from "./auth.action";
import { cache } from "react";

import type { IssueSearchFilters } from "~/lib/shared/utils.shared";
import { IssueHoverCardContents } from "~/components/hovercard/issue-hovercard-contents";
Expand Down
15 changes: 5 additions & 10 deletions src/actions/markdown.action.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
"use server";

import { Markdown } from "~/components/markdown/markdown";
import { renderRSCtoString } from "~/components/custom-rsc-renderer/render-rsc-to-string";

export async function getMarkdownPreview(
content: string,
repositoryPath: `${string}/${string}`
) {
return await renderRSCtoString(
<Markdown content={content} repository={repositoryPath} />
);
export async function getIssueNumbersStartingWithNumber(issueNo: number) {
// ...
}
export async function getUserMentionsByUsername(username: string) {
// ...
}
4 changes: 3 additions & 1 deletion src/components/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ export const Button = React.forwardRef<
// we check disabled here because we want to apply a different styling
const isDisabled =
("disabled" in restProps && restProps["disabled"] === true) ||
("aria-disabled" in restProps && restProps["aria-disabled"] === true);
("aria-disabled" in restProps &&
(restProps["aria-disabled"] === true ||
restProps["aria-disabled"] === "true"));

const commonClasses = clsx(
"items-center justify-center gap-2 text-sm",
Expand Down
101 changes: 75 additions & 26 deletions src/components/markdown-editor/markdown-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MarkdownIcon } from "@primer/octicons-react";
import { Button } from "~/components/button";
import { MarkdownEditorPreview } from "~/components/markdown-editor/markdown-editor-preview";
import { MarkdownEditorToolbar } from "~/components/markdown-editor/markdown-editor-toolbar";
import * as Ariakit from "@ariakit/react";

// utils
import { clsx, isValidURL } from "~/lib/shared/utils.shared";
Expand All @@ -17,6 +18,7 @@ import { enableTabToIndent } from "indent-textarea";

// types
import type { TextareaProps } from "~/components/textarea";
import type { EventFor } from "~/lib/types";

export type MarkdownEditorProps = Omit<TextareaProps, "value"> & {
renderMarkdownAction: (
Expand Down Expand Up @@ -82,7 +84,7 @@ export function MarkdownEditor({
}
}, [selectedTab]);

function pasteLinkToTextarea(text: string) {
const pasteLinkToTextarea = React.useCallback((text: string) => {
const textArea = textAreaRef.current;
if (textArea && isValidURL(text)) {
const textContent = textArea.value;
Expand All @@ -109,7 +111,28 @@ export function MarkdownEditor({
}
}
return false;
}
}, []);

const [textAreaValue, setTextAreaValue] =
React.useState(lastSavedTextContent);
const [trigger, setTrigger] = React.useState<string | null>(null);
const [caretOffset, setCaretOffset] = React.useState<number | null>(null);

const combobox = Ariakit.useComboboxStore();

const searchValue = combobox.useState("value");
const deferredSearchValue = React.useDeferredValue(searchValue);

// Re-calculates the position of the combobox popover in case the changes on
// the textarea value have shifted the trigger character.
// eslint-disable-next-line react-hooks/exhaustive-deps
React.useEffect(combobox.render, [combobox, textAreaValue]);

const onKeyDown = (event: EventFor<"textarea", "onKeyDown">) => {
if (event.key === "ArrowLeft" || event.key === "ArrowRight") {
combobox.hide();
}
};

return (
<>
Expand Down Expand Up @@ -182,31 +205,57 @@ export function MarkdownEditor({
</Tabs.List>

<div className="p-2 bg-backdrop rounded-b-md">
<Tabs.Content value={TABS.EDITOR} asChild>
<Textarea
rows={12}
{...props}
defaultValue={lastSavedTextContent}
label={label}
onPaste={(ev) => {
const isEventHandled = pasteLinkToTextarea(
ev.clipboardData.getData("text/plain")
);
<Tabs.Content value={TABS.EDITOR}>
<Ariakit.Combobox
store={combobox}
autoSelect
value={textAreaValue}
// We'll overwrite how the combobox popover is shown, so we disable
// the default behaviors.
showOnClick={false}
showOnChange={false}
showOnKeyPress={false}
// To the combobox state, we'll only set the value after the trigger
// character (the search value), so we disable the default behavior.
setValueOnChange={false}
className="combobox"
render={
<Textarea
rows={12}
{...props}
defaultValue={lastSavedTextContent}
value={textAreaValue}
onChange={(e) => setTextAreaValue(e.currentTarget.value)}
// onChange={onChange}
onKeyDown={onKeyDown}
label={label}
// We need to re-calculate the position of the combobox popover
// when the textarea contents are scrolled.
onScroll={combobox.render}
// Hide the combobox popover whenever the selection changes.
onPointerDown={combobox.hide}
onPaste={(ev) => {
const isEventHandled = pasteLinkToTextarea(
ev.clipboardData.getData("text/plain")
);

if (isEventHandled) ev.preventDefault();
}}
className="text-sm"
name={selectedTab === "EDITOR" ? props.name : ""}
hideLabel
ref={(ref) => {
textAreaRef.current = ref;
if (ref) {
enableTabToIndent(ref);
}
}}
style={{
height: textAreaHeight > 0 ? `${textAreaHeight}px` : "auto"
}}
if (isEventHandled) ev.preventDefault();
}}
className="text-sm"
name={selectedTab === "EDITOR" ? props.name : ""}
hideLabel
ref={(ref) => {
textAreaRef.current = ref;
if (ref) {
enableTabToIndent(ref);
}
}}
style={{
height:
textAreaHeight > 0 ? `${textAreaHeight}px` : "auto"
}}
/>
}
/>
</Tabs.Content>
<Tabs.Content
Expand Down
Loading
Loading