Skip to content

Commit

Permalink
Fix document to document xrefs in preview when the documents are incl…
Browse files Browse the repository at this point in the history
…uded (#872)

Co-authored-by: Michael Bird <[email protected]>
Co-authored-by: Guillaume Grossetie <[email protected]>
  • Loading branch information
3 people authored Oct 11, 2024
1 parent 7366a04 commit ffd3ffa
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 46 deletions.
47 changes: 30 additions & 17 deletions src/asciidocEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,12 @@ export type AsciidoctorBuiltInBackends = 'html5' | 'docbook5'
const previewConfigurationManager = new AsciidocPreviewConfigurationManager()

export class AsciidocEngine {
private stylesdir: string

constructor (
readonly contributionProvider: AsciidocContributionProvider,
readonly asciidoctorConfigProvider: AsciidoctorConfigProvider,
readonly asciidoctorExtensionsProvider: AsciidoctorExtensionsProvider,
readonly asciidoctorDiagnosticProvider: AsciidoctorDiagnosticProvider
) {
// Asciidoctor.js in the browser environment works with URIs however for desktop clients
// the "stylesdir" attribute is expected to look like a file system path (especially on Windows)
if ('browser' in process && (process as any).browser === true) {
this.stylesdir = vscode.Uri.joinPath(contributionProvider.extensionUri, 'media').toString()
} else {
this.stylesdir = vscode.Uri.joinPath(contributionProvider.extensionUri, 'media').fsPath
}
}

// Export
Expand All @@ -59,7 +50,7 @@ export class AsciidocEngine {
await this.asciidoctorConfigProvider.activate(registry, textDocumentUri)
asciidoctorProcessor.restoreBuiltInSyntaxHighlighter()

const baseDir = AsciidocTextDocument.fromTextDocument(textDocument).getBaseDir()
const baseDir = AsciidocTextDocument.fromTextDocument(textDocument).baseDir
const options: { [key: string]: any } = {
attributes: {
'env-vscode': '',
Expand Down Expand Up @@ -92,10 +83,16 @@ export class AsciidocEngine {
context: vscode.ExtensionContext,
editor: WebviewResourceProvider,
line?: number
): Promise<{html: string, document?: Asciidoctor.Document}> {
): Promise<{ html: string, document?: Asciidoctor.Document }> {
const textDocument = await vscode.workspace.openTextDocument(documentUri)
const { html, document } = await this.convertFromTextDocument(textDocument, context, editor, line)
return { html, document }
const {
html,
document,
} = await this.convertFromTextDocument(textDocument, context, editor, line)
return {
html,
document,
}
}

public async convertFromTextDocument (
Expand All @@ -112,7 +109,10 @@ export class AsciidocEngine {
// load the Asciidoc header only to get kroki-server-url attribute
const text = textDocument.getText()
const attributes = AsciidoctorAttributesConfig.getPreviewAttributes()
const document = processor.load(text, { attributes, header_only: true })
const document = processor.load(text, {
attributes,
header_only: true,
})
const isRougeSourceHighlighterEnabled = document.isAttribute('source-highlighter', 'rouge')
if (isRougeSourceHighlighterEnabled) {
// Force the source highlighter to Highlight.js (since Rouge is not supported)
Expand Down Expand Up @@ -150,8 +150,7 @@ export class AsciidocEngine {
cursor,
antoraDocumentContext.getContentCatalog(),
antoraConfig
)
))
)))
}
if (context && editor) {
highlightjsAdapter.register(asciidoctorProcessor.highlightjsBuiltInSyntaxHighlighter, context, editor)
Expand All @@ -160,12 +159,26 @@ export class AsciidocEngine {
}
const antoraSupport = AntoraSupportManager.getInstance(context.workspaceState)
const antoraAttributes = await antoraSupport.getAttributes(textDocumentUri)
const baseDir = AsciidocTextDocument.fromTextDocument(textDocument).getBaseDir()
const asciidocTextDocument = AsciidocTextDocument.fromTextDocument(textDocument)
const baseDir = asciidocTextDocument.baseDir
const documentDirectory = asciidocTextDocument.dirName
const documentBasename = asciidocTextDocument.fileName
const documentExtensionName = asciidocTextDocument.extensionName
const documentFilePath = asciidocTextDocument.filePath
const templateDirs = this.getTemplateDirs()
const options: { [key: string]: any } = {
attributes: {
...attributes,
...antoraAttributes,
// The following attributes are "intrinsic attributes" but they are not set when the input is a string
// like we are doing, in that case it is expected that the attributes are set here for the API:
// https://docs.asciidoctor.org/asciidoc/latest/attributes/document-attributes-ref/#intrinsic-attributes
// this can be set since safe mode is 'UNSAFE'
...(documentDirectory && { docdir: documentDirectory }),
...(documentFilePath && { docfile: documentFilePath }),
...(documentBasename && { docname: documentBasename }),
docfilesuffix: documentExtensionName,
filetype: asciidoctorWebViewConverter.outfilesuffix.substring(1), // remove the leading '.'
'!data-uri': '', // disable data-uri since Asciidoctor.js is unable to read files from a VS Code workspace.
},
backend: 'webview-html5',
Expand Down
4 changes: 2 additions & 2 deletions src/asciidocLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class AsciidocLoader {
memoryLogger,
registry,
} = await this.prepare(textDocument)
const baseDir = AsciidocTextDocument.fromTextDocument(textDocument).getBaseDir()
const baseDir = AsciidocTextDocument.fromTextDocument(textDocument).baseDir
const attributes = AsciidoctorAttributesConfig.getPreviewAttributes()
const doc = this.processor.load(textDocument.getText(), this.getOptions(attributes, registry, baseDir))
this.asciidoctorDiagnosticProvider.reportErrors(memoryLogger, textDocument)
Expand Down Expand Up @@ -94,7 +94,7 @@ export class AsciidocIncludeItemsLoader extends AsciidocLoader {
registry,
} = await this.prepare(textDocument)
this.asciidoctorIncludeItemsProvider.activate(registry)
const baseDir = AsciidocTextDocument.fromTextDocument(textDocument).getBaseDir()
const baseDir = AsciidocTextDocument.fromTextDocument(textDocument).baseDir
const attributes = AsciidoctorAttributesConfig.getPreviewAttributes()
this.asciidoctorIncludeItemsProvider.reset()
this.processor.load(textDocument.getText(), this.getOptions(attributes, registry, baseDir))
Expand Down
62 changes: 54 additions & 8 deletions src/asciidocTextDocument.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,77 @@ interface DocumentWithUri {
}

export class AsciidocTextDocument {
private uri: Uri
public baseDir: string | undefined
public dir: string | undefined
public dirName: string | undefined
public extensionName: string
public fileName: string | undefined
public filePath: string | undefined

private constructor () {
private constructor (private uri: Uri) {
this.baseDir = AsciidocTextDocument.getBaseDir(uri)
this.dirName = AsciidocTextDocument.getDirName(uri)
this.extensionName = AsciidocTextDocument.getExtensionName(uri)
this.fileName = AsciidocTextDocument.getFileName(uri)
this.filePath = AsciidocTextDocument.getFilePath(uri)
}

public static fromTextDocument (textDocument: DocumentWithUri): AsciidocTextDocument {
const asciidocTextDocument = new AsciidocTextDocument()
asciidocTextDocument.uri = textDocument.uri
return asciidocTextDocument
return new AsciidocTextDocument(textDocument.uri)
}

/**
* Get the base directory.
* @private
*/
public getBaseDir (): string | undefined {
private static getBaseDir (uri: Uri): string | undefined {
const useWorkspaceAsBaseDir = vscode.workspace.getConfiguration('asciidoc', null).get('useWorkspaceRootAsBaseDirectory')
if (useWorkspaceAsBaseDir) {
const workspaceFolder = getWorkspaceFolder(this.uri)
const workspaceFolder = getWorkspaceFolder(uri)
if (workspaceFolder) {
return workspaceFolder.uri.fsPath
}
}
return AsciidocTextDocument.getDirName(uri)
}

private static getDirName (uri: Uri): string | undefined {
return 'browser' in process && (process as any).browser === true
? undefined
: path.dirname(path.resolve(this.uri.fsPath))
: path.dirname(path.resolve(uri.fsPath))
}

/**
* Return the extension name of the file without the '.'.
* @param uri
* @private
*/
private static getExtensionName (uri: Uri): string {
const textDocumentExt = path.extname(uri.path)
return textDocumentExt.startsWith('.') ? textDocumentExt.substring(1) : ''
}

/**
* Return the file name without the file extension.
* @param uri
* @private
*/
public static getFileName (uri: Uri): string | undefined {
if ('browser' in process && (process as any).browser === true) {
return undefined
}
return path.parse(uri.fsPath).name
}

/**
* Return the filesystem path of the URI.
* @param uri
* @private
*/
public static getFilePath (uri: Uri): string | undefined {
if ('browser' in process && (process as any).browser === true) {
return undefined
}
return uri.fsPath
}
}
19 changes: 8 additions & 11 deletions src/commands/exportAsPDF.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { exec, spawn, SpawnOptions } from 'child_process'
import { uuidv4 } from 'uuid'
import { AsciidocEngine } from '../asciidocEngine'
import { Command } from '../commandManager'
import { Logger } from '../logger'
import { Asciidoctor } from '@asciidoctor/core'
import { AsciidocTextDocument } from '../asciidocTextDocument'
import { getAsciidoctorConfigContent } from '../features/asciidoctorConfig'
Expand All @@ -16,7 +15,7 @@ export class ExportAsPDF implements Command {
public readonly id = 'asciidoc.exportAsPDF'
private readonly exportAsPdfStatusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100)

constructor (private readonly engine: AsciidocEngine, private readonly context: vscode.ExtensionContext, private readonly logger: Logger) {
constructor (private readonly engine: AsciidocEngine, private readonly context: vscode.ExtensionContext) {
}

public async execute () {
Expand All @@ -31,11 +30,9 @@ export class ExportAsPDF implements Command {
await vscode.window.showWarningMessage('Unable to get the workspace folder, aborting.')
return
}
const workspacePath = workspaceFolder.uri.fsPath
const docNameWithoutExtension = path.parse(doc.uri.fsPath).name

const baseDirectory = AsciidocTextDocument.fromTextDocument(doc).getBaseDir()
const pdfFilename = vscode.Uri.file(path.join(baseDirectory, docNameWithoutExtension + '.pdf'))
const asciidocTextDocument = AsciidocTextDocument.fromTextDocument(doc)
const baseDirectory = asciidocTextDocument.baseDir
const pdfFilename = vscode.Uri.file(path.join(baseDirectory, asciidocTextDocument.fileName + '.pdf'))

const asciidocPdfConfig = vscode.workspace.getConfiguration('asciidoc.pdf')
const pdfOutputUri = await vscode.window.showSaveDialog({ defaultUri: pdfFilename })
Expand All @@ -51,9 +48,9 @@ export class ExportAsPDF implements Command {
text = `${asciidoctorConfigContent}
${text}`
}

const pdfEnfine = asciidocPdfConfig.get('engine')
if (pdfEnfine === 'asciidoctor-pdf') {
const workspacePath = workspaceFolder.uri.fsPath
const pdfEngine = asciidocPdfConfig.get('engine')
if (pdfEngine === 'asciidoctor-pdf') {
const asciidoctorPdfCommand = await this.resolveAsciidoctorPdfCommand(asciidocPdfConfig, workspacePath)
if (asciidoctorPdfCommand === undefined) {
return
Expand Down Expand Up @@ -84,7 +81,7 @@ ${text}`
} finally {
this.exportAsPdfStatusBarItem.hide()
}
} else if (pdfEnfine === 'wkhtmltopdf') {
} else if (pdfEngine === 'wkhtmltopdf') {
let wkhtmltopdfCommandPath = asciidocPdfConfig.get('wkhtmltopdfCommandPath', '')
if (wkhtmltopdfCommandPath === '') {
wkhtmltopdfCommandPath = `wkhtmltopdf${process.platform === 'win32' ? '.exe' : ''}`
Expand Down
2 changes: 1 addition & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export async function activate (context: vscode.ExtensionContext) {
commandManager.register(new commands.ShowPreviewSecuritySelectorCommand(previewSecuritySelector, previewManager))
commandManager.register(new commands.ShowAsciidoctorExtensionsTrustModeSelectorCommand(asciidoctorExtensionsTrustModeSelector))
commandManager.register(new commands.OpenDocumentLinkCommand(asciidocLoader))
commandManager.register(new commands.ExportAsPDF(asciidocEngine, context, logger))
commandManager.register(new commands.ExportAsPDF(asciidocEngine, context))
commandManager.register(new commands.PasteImage(asciidocLoader))
commandManager.register(new commands.ToggleLockCommand(previewManager))
commandManager.register(new commands.ShowPreviewCommand(previewManager))
Expand Down
Loading

0 comments on commit ffd3ffa

Please sign in to comment.