import React from "react"; import Highlight, { defaultProps } from "prism-react-renderer"; import { TgetLineProps, TgetTokenProps, StyleObj, Token, } from "../../types/prism-types"; import { TSourceMapping, useSourceMapping } from "../../logic/sourceMapping"; import { useCompletionMapping, ICompletionDetail, TCompletionMapping, } from "../../logic/completionMapping"; function getCompletionFromSourceToken( matcheeToken: Token, completionMapping: TCompletionMapping, sourceMapping: TSourceMapping ): ICompletionDetail | null { const matchingSourceDetails = sourceMapping.mappingArray.find( ({ token: tmpToken }) => matcheeToken === tmpToken ); if (matchingSourceDetails === undefined) { return null; } const { start: sourceStart, end: sourceEnd } = matchingSourceDetails; let closestCompletion: ICompletionDetail | null = null; let closestMatchScore = -Infinity; completionMapping.completionDetails.forEach((tmpCompletionDetails) => { const { start: compStart, end: compEnd } = tmpCompletionDetails; const sourceLen = sourceEnd - sourceStart; const compLen = compEnd - compStart; // If not intersecting at all, ignore if (compEnd < sourceStart || compStart > sourceEnd) { return; } const intersectionStart = Math.max(sourceStart, compStart); const intersectionEnd = Math.min(sourceEnd, compEnd); const intersectionDistance = intersectionEnd - intersectionStart; // Exclusion = Total Len - (2 * intersection) const exclusionDistance = sourceLen + compLen - intersectionDistance; const score = intersectionDistance - exclusionDistance; if (score >= closestMatchScore) { closestCompletion = tmpCompletionDetails; closestMatchScore = score; } }); return closestCompletion; } interface IPreRendererProps { className: string; style: StyleObj; tokens: Token[][]; getLineProps: TgetLineProps; getTokenProps: TgetTokenProps; } function PreRenderer({ className, style, tokens, getLineProps, getTokenProps, }: IPreRendererProps) { const sourceMapping = useSourceMapping(); sourceMapping.reset(); return (
      {tokens.map((line, i) => (
        
      ))}
    
); } interface ILineRendererProps { line: Token[]; getLineProps: TgetLineProps; getTokenProps: TgetTokenProps; } function LineRenderer({ line, getLineProps, getTokenProps, }: ILineRendererProps) { return (
{/* Refactor into TokenRenderer */} {line.map((token, i) => ( ))}
); } interface ITokenRendererProps { token: Token; isLastTokenInLine: boolean; getTokenProps: TgetTokenProps; } function TokenRenderer({ token, isLastTokenInLine, getTokenProps, }: ITokenRendererProps) { const completionMapping = useCompletionMapping(); const sourceMapping = useSourceMapping(); const refFn = sourceMapping.registerToken(token); if (isLastTokenInLine) { sourceMapping.registerLineEnd(); } const onClickToken = (tmpToken: Token) => { const matchingCompletion = getCompletionFromSourceToken( tmpToken, completionMapping, sourceMapping ); if (matchingCompletion !== null) { console.log( `Clicked: ${tmpToken.content} => Completion (${matchingCompletion.completionType},${matchingCompletion.completionValueString})` ); } }; return ( onClickToken(token)} /> ); } interface ISourceViewerProps { code: string; onChangeCode(newCode: string): void; } export function SourceViewer(props: ISourceViewerProps) { const { code } = props; return (
{/* Title of code section */}
Code
{/* Code viewer */} {({ className, style, tokens, getLineProps, getTokenProps }) => ( )}
); }