Skip to content

Commit

Permalink
feat(snippet): manually select the language of a code snippet
Browse files Browse the repository at this point in the history
  • Loading branch information
tericcabrel committed Nov 1, 2023
1 parent 07297d8 commit 3be5818
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { extractLanguageFromName, lineHighlightToString } from '../../../../util
import { useToast } from '../../../toast/provider';
import { SnippetTextEditor } from './editor';
import { SnippetFormValues, formSchema } from './form-schema';
import { generateSnippetLanguageOptions } from './utils';

type Props = {
closeModal: () => void;
Expand Down Expand Up @@ -65,7 +66,7 @@ console.log(content);`,
contentHighlighted: values.codeHighlighted,
description: values.description,
folderId,
language: extractLanguageFromName(values.name),
language: values.language?.id ?? extractLanguageFromName(values.name),
lineHighlight: lineHighlightToString(values.lineHighlight),
name: values.name,
theme: values.theme.id,
Expand Down Expand Up @@ -117,6 +118,7 @@ console.log(content);`,
<FormProvider {...formMethods}>
<SnippetTextEditor
highlighter={highlighter}
languageOptions={generateSnippetLanguageOptions()}
codeHighlightOptions={CODE_HIGHLIGHT_OPTIONS}
themeOptions={THEME_OPTIONS}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ export const useFormEditor = () => {
const code = watch('code');
const name = watch('name');
const theme = watch('theme');
const language = watch('language');
const lineHighlight = watch('lineHighlight');
const codeHighlight = watch('codeHighlight');
const isSnippetPrivate = watch('isPrivate');

const language = getLanguageFromExtension(name);
const codeLanguage = language?.id ?? getLanguageFromExtension(name);

useEffect(() => {
const lineHighlightClone = new Map(lineHighlight);
Expand Down Expand Up @@ -56,7 +57,7 @@ export const useFormEditor = () => {
}, [codeHighlight]);

const onHighlight = (highlighter?: Highlighter) => (code: string) => {
return highlightSnippet({ code, highlighter, language, lineHighlight, theme: theme.id });
return highlightSnippet({ code, highlighter, language: codeLanguage, lineHighlight, theme: theme.id });
};

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import { useFormEditor } from './hooks/use-form-editor';
type Props = {
codeHighlightOptions: SelectOption[];
highlighter?: Highlighter;
languageOptions: SelectOption[];
themeOptions: SelectOption[];
};

const SnippetTextEditor = ({ codeHighlightOptions, highlighter, themeOptions }: Props) => {
const SnippetTextEditor = ({ codeHighlightOptions, highlighter, languageOptions, themeOptions }: Props) => {
const { control, setValue } = useFormContext<EditorFormValues>();
const { code, handleEditorSelect, isSnippetPrivate, onHighlight, theme } = useFormEditor();

Expand Down Expand Up @@ -55,6 +56,13 @@ const SnippetTextEditor = ({ codeHighlightOptions, highlighter, themeOptions }:
/>
</div>
<div className="flex space-x-3">
<Controller
name="language"
control={control}
render={({ field }) => (
<SelectInput className="w-36" options={languageOptions} placeholder="Language" {...field} />
)}
/>
<Controller
name="codeHighlight"
control={control}
Expand Down
11 changes: 11 additions & 0 deletions packages/front/src/components/directory/snippets/form/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { capitalize } from 'lodash';
import { BUNDLED_LANGUAGES } from 'shiki';

import { SelectOption } from '../../../../typings/components';

export const generateSnippetLanguageOptions = (): SelectOption[] => {
return BUNDLED_LANGUAGES.map((language) => ({
id: language.id,
label: capitalize(language.id),
}));
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { extractLanguageFromName, lineHighlightToString } from '../../../../util
import { useToast } from '../../../toast/provider';
import { SnippetTextEditor } from './editor';
import { SnippetFormValues, formSchema } from './form-schema';
import { generateSnippetLanguageOptions } from './utils';

type Props = {
snippet: SnippetItem;
Expand Down Expand Up @@ -42,13 +43,15 @@ const ViewSnippet = ({ snippet }: Props) => {
});

const submitUpdateSnippet = async (values: SnippetFormValues) => {
console.log('Values => ', values);

await updateSnippet({
id: snippet.id,
input: {
content: values.code,
contentHighlighted: values.codeHighlighted,
description: values.description,
language: extractLanguageFromName(values.name),
language: values.language?.id ?? extractLanguageFromName(values.name),
lineHighlight: lineHighlightToString(values.lineHighlight),
name: values.name,
theme: values.theme.id,
Expand All @@ -68,6 +71,7 @@ const ViewSnippet = ({ snippet }: Props) => {
<FormProvider {...formMethods}>
<SnippetTextEditor
highlighter={highlighter}
languageOptions={generateSnippetLanguageOptions()}
codeHighlightOptions={CODE_HIGHLIGHT_OPTIONS}
themeOptions={THEME_OPTIONS}
/>
Expand Down
7 changes: 5 additions & 2 deletions packages/front/src/forms/select-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ type Props = {
label?: string;
onChange: (value: SelectOption) => void;
options: SelectOption[];
placeholder?: string;
value?: SelectOption;
};

const SelectInput = forwardRef<HTMLDivElement, Props>((props: Props, ref) => {
const { className = 'w-40', label, onChange, options, value: selectedValue } = props;
const { className = 'w-40', label, onChange, options, placeholder = 'Select value...', value: selectedValue } = props;

const generateOptionClasses = (isActive: boolean) => {
return classNames(
Expand All @@ -35,7 +36,9 @@ const SelectInput = forwardRef<HTMLDivElement, Props>((props: Props, ref) => {
{label && <Listbox.Label className="block text-sm font-medium text-gray-700">{label}</Listbox.Label>}
<div className="mt-1 relative">
<Listbox.Button className="bg-white relative w-full border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default sm:text-sm">
<span className="block truncate">{selectedValue?.label}</span>
<span className={`block truncate ${selectedValue?.label ? '' : 'text-gray-400'}`}>
{selectedValue?.label ?? placeholder}
</span>
<span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
<SelectorIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
</span>
Expand Down
1 change: 1 addition & 0 deletions packages/front/src/typings/snippet-form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export type EditorFormValues = {
codeHighlighted: string;
description: string;
isPrivate: boolean;
language: SelectOption;
lineHighlight: Array<[number, string]>;
name: string;
theme: SelectOption;
Expand Down
2 changes: 1 addition & 1 deletion packages/front/src/utils/snippets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const lineHighlightToString = (value: Array<[number, string]>) => {

export const extractLanguageFromName = (name: string): string => {
if (!name.includes('.')) {
return 'plain';
return 'txt';
}

const nameArrayPart = name.split('.');
Expand Down

0 comments on commit 3be5818

Please sign in to comment.