fix style css in ts

This commit is contained in:
duanfuxiang 2025-01-07 14:18:18 +08:00
parent 8d253faddc
commit 0f42ce3b80
12 changed files with 1729 additions and 39 deletions

View File

@ -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({

View File

@ -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}

View File

@ -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')

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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'))
}) })
} }

View 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')

View File

@ -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 []

View File

@ -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)
})
}) })

View File

@ -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) {

View File

@ -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 })

View File

@ -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;
}