mirror of
https://github.com/EthanMarti/infio-copilot.git
synced 2026-01-16 08:21:55 +00:00
fix style css in ts
This commit is contained in:
parent
8d253faddc
commit
0f42ce3b80
@ -2,6 +2,7 @@ import { Check, CopyIcon, Loader2 } from 'lucide-react'
|
|||||||
import { PropsWithChildren, useMemo, useState } from 'react'
|
import { PropsWithChildren, useMemo, useState } from 'react'
|
||||||
|
|
||||||
import { useDarkModeContext } from '../../contexts/DarkModeContext'
|
import { useDarkModeContext } from '../../contexts/DarkModeContext'
|
||||||
|
import { InfioBlockAction } from '../../utils/parse-infio-block'
|
||||||
|
|
||||||
import { MemoizedSyntaxHighlighterWrapper } from './SyntaxHighlighterWrapper'
|
import { MemoizedSyntaxHighlighterWrapper } from './SyntaxHighlighterWrapper'
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ export default function MarkdownActionBlock({
|
|||||||
filename?: string
|
filename?: string
|
||||||
startLine?: number
|
startLine?: number
|
||||||
endLine?: number
|
endLine?: number
|
||||||
action?: 'edit' | 'new' | 'reference'
|
action?: InfioBlockAction
|
||||||
}>) {
|
}>) {
|
||||||
const [copied, setCopied] = useState(false)
|
const [copied, setCopied] = useState(false)
|
||||||
const { isDarkMode } = useDarkModeContext()
|
const { isDarkMode } = useDarkModeContext()
|
||||||
@ -67,7 +68,7 @@ export default function MarkdownActionBlock({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
{action === 'edit' && (
|
{action === InfioBlockAction.Edit && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onApply({
|
onApply({
|
||||||
@ -88,7 +89,7 @@ export default function MarkdownActionBlock({
|
|||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
{action === 'new' && (
|
{action === InfioBlockAction.New && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onApply({
|
onApply({
|
||||||
|
|||||||
@ -2,7 +2,8 @@ import React, { useMemo } from 'react'
|
|||||||
import Markdown from 'react-markdown'
|
import Markdown from 'react-markdown'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ParsedinfioBlock,
|
InfioBlockAction,
|
||||||
|
ParsedInfioBlock,
|
||||||
parseinfioBlocks,
|
parseinfioBlocks,
|
||||||
} from '../../utils/parse-infio-block'
|
} from '../../utils/parse-infio-block'
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ function ReactMarkdown({
|
|||||||
children: string
|
children: string
|
||||||
isApplying: boolean
|
isApplying: boolean
|
||||||
}) {
|
}) {
|
||||||
const blocks: ParsedinfioBlock[] = useMemo(
|
const blocks: ParsedInfioBlock[] = useMemo(
|
||||||
() => parseinfioBlocks(children),
|
() => parseinfioBlocks(children),
|
||||||
[children],
|
[children],
|
||||||
)
|
)
|
||||||
@ -35,7 +36,7 @@ function ReactMarkdown({
|
|||||||
<Markdown key={index} className="infio-markdown">
|
<Markdown key={index} className="infio-markdown">
|
||||||
{block.content}
|
{block.content}
|
||||||
</Markdown>
|
</Markdown>
|
||||||
) : block.startLine && block.endLine && block.filename && block.action === 'reference' ? (
|
) : block.startLine && block.endLine && block.filename && block.action === InfioBlockAction.Reference ? (
|
||||||
<MarkdownReferenceBlock
|
<MarkdownReferenceBlock
|
||||||
key={index}
|
key={index}
|
||||||
filename={block.filename}
|
filename={block.filename}
|
||||||
|
|||||||
@ -538,9 +538,8 @@ export function useMenuAnchorRef(
|
|||||||
containerDiv.setAttribute('aria-label', 'Typeahead menu')
|
containerDiv.setAttribute('aria-label', 'Typeahead menu')
|
||||||
containerDiv.setAttribute('id', 'typeahead-menu')
|
containerDiv.setAttribute('id', 'typeahead-menu')
|
||||||
containerDiv.setAttribute('role', 'listbox')
|
containerDiv.setAttribute('role', 'listbox')
|
||||||
containerDiv.style.display = 'block'
|
containerDiv.classList.add('infio-utils-lexical-menu-container')
|
||||||
containerDiv.style.position = 'absolute'
|
parent.append(containerDiv)
|
||||||
parent.append(containerDiv)
|
|
||||||
}
|
}
|
||||||
anchorElementRef.current = containerDiv
|
anchorElementRef.current = containerDiv
|
||||||
rootElement.setAttribute('aria-controls', 'typeahead-menu')
|
rootElement.setAttribute('aria-controls', 'typeahead-menu')
|
||||||
|
|||||||
@ -86,7 +86,7 @@ class InlineSuggestionWidget extends WidgetType {
|
|||||||
toDOM() {
|
toDOM() {
|
||||||
const span = document.createElement("span");
|
const span = document.createElement("span");
|
||||||
span.textContent = this.display_suggestion;
|
span.textContent = this.display_suggestion;
|
||||||
span.style.opacity = "0.4"; // TODO replace with css
|
span.classList.add("infio-utils-display-suggestion-opacity");
|
||||||
span.onclick = () => {
|
span.onclick = () => {
|
||||||
cancelSuggestion(this.view);
|
cancelSuggestion(this.view);
|
||||||
}
|
}
|
||||||
|
|||||||
1631
src/styles.css
Normal file
1631
src/styles.css
Normal file
File diff suppressed because it is too large
Load Diff
@ -28,7 +28,13 @@ function fileToBase64(file: File): Promise<string> {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.readAsDataURL(file)
|
reader.readAsDataURL(file)
|
||||||
reader.onload = () => resolve(reader.result as string)
|
reader.onload = () => {
|
||||||
|
if (typeof reader.result === 'string') {
|
||||||
|
resolve(reader.result)
|
||||||
|
} else {
|
||||||
|
reject(new Error('Unexpected file reader result type'))
|
||||||
|
}
|
||||||
|
}
|
||||||
reader.onerror = () => reject(new Error('Failed to read file'))
|
reader.onerror = () => reject(new Error('Failed to read file'))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { App, Editor, MarkdownView, TFile, TFolder, Vault } from 'obsidian'
|
import { App, Editor, MarkdownView, TFile, TFolder, Vault, WorkspaceLeaf } from 'obsidian'
|
||||||
|
|
||||||
import { MentionableBlockData } from '../types/mentionable'
|
import { MentionableBlockData } from '../types/mentionable'
|
||||||
|
|
||||||
@ -60,7 +60,11 @@ export function getOpenFiles(app: App): TFile[] {
|
|||||||
try {
|
try {
|
||||||
const leaves = app.workspace.getLeavesOfType('markdown')
|
const leaves = app.workspace.getLeavesOfType('markdown')
|
||||||
|
|
||||||
return leaves.map((v) => (v.view as MarkdownView).file).filter((v) => !!v)
|
return leaves
|
||||||
|
.filter((v): v is WorkspaceLeaf & { view: MarkdownView & { file: TFile } } =>
|
||||||
|
v.view instanceof MarkdownView && !!v.view.file
|
||||||
|
)
|
||||||
|
.map((v) => v.view.file)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@ -111,9 +115,8 @@ export function openMarkdownFile(
|
|||||||
if (existingLeaf) {
|
if (existingLeaf) {
|
||||||
app.workspace.setActiveLeaf(existingLeaf, { focus: true })
|
app.workspace.setActiveLeaf(existingLeaf, { focus: true })
|
||||||
|
|
||||||
if (startLine) {
|
if (startLine && existingLeaf.view instanceof MarkdownView) {
|
||||||
const view = existingLeaf.view as MarkdownView
|
existingLeaf.view.setEphemeralState({ line: startLine - 1 }) // -1 because line is 0-indexed
|
||||||
view.setEphemeralState({ line: startLine - 1 }) // -1 because line is 0-indexed
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const leaf = app.workspace.getLeaf('tab')
|
const leaf = app.workspace.getLeaf('tab')
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import { requestUrl } from 'obsidian'
|
import { requestUrl } from 'obsidian'
|
||||||
|
|
||||||
|
type OllamaTagsResponse = {
|
||||||
|
models: { name: string }[]
|
||||||
|
}
|
||||||
|
|
||||||
export async function getOllamaModels(ollamaUrl: string) {
|
export async function getOllamaModels(ollamaUrl: string) {
|
||||||
try {
|
try {
|
||||||
const response = (await requestUrl(`${ollamaUrl}/api/tags`)).json as {
|
const response: OllamaTagsResponse = await requestUrl(`${ollamaUrl}/api/tags`).json
|
||||||
models: { name: string }[]
|
|
||||||
}
|
|
||||||
return response.models.map((model) => model.name)
|
return response.models.map((model) => model.name)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return []
|
return []
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ParsedinfioBlock, parseinfioBlocks } from './parse-infio-block'
|
import { InfioBlockAction, ParsedInfioBlock, parseinfioBlocks } from './parse-infio-block'
|
||||||
|
|
||||||
describe('parseinfioBlocks', () => {
|
describe('parseinfioBlocks', () => {
|
||||||
it('should parse a string with infio_block elements', () => {
|
it('should parse a string with infio_block elements', () => {
|
||||||
@ -22,7 +22,7 @@ print("Hello, world!")
|
|||||||
</infio_block>
|
</infio_block>
|
||||||
Some text after`
|
Some text after`
|
||||||
|
|
||||||
const expected: ParsedinfioBlock[] = [
|
const expected: ParsedInfioBlock[] = [
|
||||||
{ type: 'string', content: 'Some text before\n' },
|
{ type: 'string', content: 'Some text before\n' },
|
||||||
{
|
{
|
||||||
type: 'infio_block',
|
type: 'infio_block',
|
||||||
@ -58,7 +58,7 @@ print("Hello, world!")
|
|||||||
<infio_block language="python"></infio_block>
|
<infio_block language="python"></infio_block>
|
||||||
`
|
`
|
||||||
|
|
||||||
const expected: ParsedinfioBlock[] = [
|
const expected: ParsedInfioBlock[] = [
|
||||||
{ type: 'string', content: '\n ' },
|
{ type: 'string', content: '\n ' },
|
||||||
{
|
{
|
||||||
type: 'infio_block',
|
type: 'infio_block',
|
||||||
@ -76,7 +76,7 @@ print("Hello, world!")
|
|||||||
it('should handle input without infio_block elements', () => {
|
it('should handle input without infio_block elements', () => {
|
||||||
const input = 'Just a regular string without any infio_block elements.'
|
const input = 'Just a regular string without any infio_block elements.'
|
||||||
|
|
||||||
const expected: ParsedinfioBlock[] = [{ type: 'string', content: input }]
|
const expected: ParsedInfioBlock[] = [{ type: 'string', content: input }]
|
||||||
|
|
||||||
const result = parseinfioBlocks(input)
|
const result = parseinfioBlocks(input)
|
||||||
expect(result).toEqual(expected)
|
expect(result).toEqual(expected)
|
||||||
@ -100,7 +100,7 @@ print("Hello, world!")
|
|||||||
</infio_block>
|
</infio_block>
|
||||||
End`
|
End`
|
||||||
|
|
||||||
const expected: ParsedinfioBlock[] = [
|
const expected: ParsedInfioBlock[] = [
|
||||||
{ type: 'string', content: 'Start\n' },
|
{ type: 'string', content: 'Start\n' },
|
||||||
{
|
{
|
||||||
type: 'infio_block',
|
type: 'infio_block',
|
||||||
@ -139,7 +139,7 @@ print("Hello, world!")
|
|||||||
# Unfinished infio_block
|
# Unfinished infio_block
|
||||||
|
|
||||||
Some text after without closing tag`
|
Some text after without closing tag`
|
||||||
const expected: ParsedinfioBlock[] = [
|
const expected: ParsedInfioBlock[] = [
|
||||||
{ type: 'string', content: 'Start\n' },
|
{ type: 'string', content: 'Start\n' },
|
||||||
{
|
{
|
||||||
type: 'infio_block',
|
type: 'infio_block',
|
||||||
@ -158,7 +158,7 @@ Some text after without closing tag`,
|
|||||||
|
|
||||||
it('should handle infio_block with startline and endline attributes', () => {
|
it('should handle infio_block with startline and endline attributes', () => {
|
||||||
const input = `<infio_block language="markdown" startline="2" endline="5"></infio_block>`
|
const input = `<infio_block language="markdown" startline="2" endline="5"></infio_block>`
|
||||||
const expected: ParsedinfioBlock[] = [
|
const expected: ParsedInfioBlock[] = [
|
||||||
{
|
{
|
||||||
type: 'infio_block',
|
type: 'infio_block',
|
||||||
content: '',
|
content: '',
|
||||||
@ -171,4 +171,32 @@ Some text after without closing tag`,
|
|||||||
const result = parseinfioBlocks(input)
|
const result = parseinfioBlocks(input)
|
||||||
expect(result).toEqual(expected)
|
expect(result).toEqual(expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should parse infio_block with action attribute', () => {
|
||||||
|
const input = `<infio_block type="edit"></infio_block>`
|
||||||
|
const expected: ParsedInfioBlock[] = [
|
||||||
|
{
|
||||||
|
type: 'infio_block',
|
||||||
|
content: '',
|
||||||
|
action: InfioBlockAction.Edit,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const result = parseinfioBlocks(input)
|
||||||
|
expect(result).toEqual(expected)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle invalid action attribute', () => {
|
||||||
|
const input = `<infio_block type="invalid"></infio_block>`
|
||||||
|
const expected: ParsedInfioBlock[] = [
|
||||||
|
{
|
||||||
|
type: 'infio_block',
|
||||||
|
content: '',
|
||||||
|
action: undefined,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const result = parseinfioBlocks(input)
|
||||||
|
expect(result).toEqual(expected)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
import { parseFragment } from 'parse5'
|
import { parseFragment } from 'parse5'
|
||||||
|
|
||||||
export type ParsedinfioBlock =
|
export enum InfioBlockAction {
|
||||||
|
Edit = 'edit',
|
||||||
|
New = 'new',
|
||||||
|
Reference = 'reference'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ParsedInfioBlock =
|
||||||
| { type: 'string'; content: string }
|
| { type: 'string'; content: string }
|
||||||
| {
|
| {
|
||||||
type: 'infio_block'
|
type: 'infio_block'
|
||||||
@ -9,11 +15,15 @@ export type ParsedinfioBlock =
|
|||||||
filename?: string
|
filename?: string
|
||||||
startLine?: number
|
startLine?: number
|
||||||
endLine?: number
|
endLine?: number
|
||||||
action?: 'edit' | 'new' | 'reference'
|
action?: InfioBlockAction
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseinfioBlocks(input: string): ParsedinfioBlock[] {
|
function isInfioBlockAction(value: string): value is InfioBlockAction {
|
||||||
const parsedResult: ParsedinfioBlock[] = []
|
return Object.values<string>(InfioBlockAction).includes(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseinfioBlocks(input: string): ParsedInfioBlock[] {
|
||||||
|
const parsedResult: ParsedInfioBlock[] = []
|
||||||
const fragment = parseFragment(input, {
|
const fragment = parseFragment(input, {
|
||||||
sourceCodeLocationInfo: true,
|
sourceCodeLocationInfo: true,
|
||||||
})
|
})
|
||||||
@ -36,7 +46,11 @@ export function parseinfioBlocks(input: string): ParsedinfioBlock[] {
|
|||||||
const filename = node.attrs.find((attr) => attr.name === 'filename')?.value
|
const filename = node.attrs.find((attr) => attr.name === 'filename')?.value
|
||||||
const startLine = node.attrs.find((attr) => attr.name === 'startline')?.value
|
const startLine = node.attrs.find((attr) => attr.name === 'startline')?.value
|
||||||
const endLine = node.attrs.find((attr) => attr.name === 'endline')?.value
|
const endLine = node.attrs.find((attr) => attr.name === 'endline')?.value
|
||||||
const action = node.attrs.find((attr) => attr.name === 'type')?.value as 'edit' | 'new' | 'reference'
|
const actionValue = node.attrs.find((attr) => attr.name === 'type')?.value
|
||||||
|
const action = actionValue && isInfioBlockAction(actionValue)
|
||||||
|
? actionValue
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
|
||||||
const children = node.childNodes
|
const children = node.childNodes
|
||||||
if (children.length === 0) {
|
if (children.length === 0) {
|
||||||
|
|||||||
@ -449,17 +449,13 @@ When writing out new markdown blocks, remember not to include "line_number|" at
|
|||||||
*/
|
*/
|
||||||
private async getWebsiteContent(url: string): Promise<string> {
|
private async getWebsiteContent(url: string): Promise<string> {
|
||||||
if (isYoutubeUrl(url)) {
|
if (isYoutubeUrl(url)) {
|
||||||
try {
|
// TODO: pass language based on user preferences
|
||||||
// TODO: pass language based on user preferences
|
const { title, transcript } =
|
||||||
const { title, transcript } =
|
await YoutubeTranscript.fetchTranscriptAndMetadata(url)
|
||||||
await YoutubeTranscript.fetchTranscriptAndMetadata(url)
|
|
||||||
|
|
||||||
return `Title: ${title}
|
return `Title: ${title}
|
||||||
Video Transcript:
|
Video Transcript:
|
||||||
${transcript.map((t) => `${t.offset}: ${t.text}`).join('\n')}`
|
${transcript.map((t) => `${t.offset}: ${t.text}`).join('\n')}`
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching YouTube transcript', error)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await requestUrl({ url })
|
const response = await requestUrl({ url })
|
||||||
|
|||||||
@ -1602,3 +1602,12 @@ button.infio-chat-input-model-select {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.infio-utils-display-suggestion-opacity {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infio-utils-lexical-menu-container {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user