| | |
| | |
| | |
| |
|
| | import { find } from 'unist-util-find' |
| | import { h } from 'hastscript' |
| | import octicons from '@primer/octicons' |
| | import { parse } from 'parse5' |
| | import { fromParse5 } from 'hast-util-from-parse5' |
| | import { getPreMeta } from './code-header' |
| | import { generatePromptId } from '../lib/prompt-id' |
| |
|
| | |
| | |
| | export function getPrompt( |
| | node: any, |
| | tree: any, |
| | code: string, |
| | ): { element: any; promptContent: string } | null { |
| | const hasPrompt = Boolean(getPreMeta(node).prompt) |
| | if (!hasPrompt) return null |
| |
|
| | const { promptContent, ariaLabel } = buildPromptData(node, tree, code) |
| | const promptLink = `https://github.com/copilot?prompt=${encodeURIComponent(promptContent.trim())}` |
| | |
| | const promptId: string = generatePromptId(promptContent) |
| |
|
| | const element = h( |
| | 'a', |
| | { |
| | href: promptLink, |
| | target: '_blank', |
| | class: ['btn', 'btn-sm', 'mr-1', 'tooltipped', 'tooltipped-nw', 'no-underline'], |
| | 'aria-label': ariaLabel, |
| | 'aria-describedby': promptId, |
| | }, |
| | copilotIcon(), |
| | ) |
| |
|
| | return { element, promptContent } |
| | } |
| |
|
| | |
| | |
| | function buildPromptData( |
| | node: any, |
| | tree: any, |
| | code: string, |
| | ): { promptContent: string; ariaLabel: string } { |
| | |
| | const ref = getPreMeta(node).ref |
| |
|
| | if (!ref) { |
| | |
| | return promptOnly(code) |
| | } |
| |
|
| | |
| | const matchingCodeEl = findMatchingCode(ref, tree) |
| | if (!matchingCodeEl) { |
| | console.warn(`Can't find referenced code block with id=${ref}`) |
| | return promptOnly(code) |
| | } |
| | |
| | |
| | const matchingCode = (matchingCodeEl as any)?.children[0].children[0].value || null |
| | return promptAndContext(code, matchingCode) |
| | } |
| |
|
| | function promptOnly(code: string): { promptContent: string; ariaLabel: string } { |
| | return { |
| | promptContent: code, |
| | ariaLabel: 'Run this prompt in Copilot Chat', |
| | } |
| | } |
| |
|
| | function promptAndContext( |
| | code: string, |
| | matchingCode: string, |
| | ): { promptContent: string; ariaLabel: string } { |
| | return { |
| | promptContent: `${matchingCode}\n${code}`, |
| | ariaLabel: 'Run this prompt with context in Copilot Chat', |
| | } |
| | } |
| |
|
| | |
| | |
| | function findMatchingCode(ref: string, tree: any): any { |
| | return find(tree, (node: any) => { |
| | |
| | return node.type === 'element' && (node as any).tagName === 'pre' && getPreMeta(node).id === ref |
| | }) |
| | } |
| |
|
| | |
| | |
| | function copilotIcon(): any { |
| | const copilotIconHtml = octicons.copilot.toSVG() |
| | const copilotIconAst = parse(String(copilotIconHtml), { sourceCodeLocationInfo: true }) |
| | |
| | const copilotIconElement = fromParse5(copilotIconAst, { file: copilotIconHtml as any }) |
| | return copilotIconElement |
| | } |
| |
|