Skip to content
On this page

CodeBlock

KCodeBlock is a code block component with built-in search and filter functionalities.

Searching highlights matching lines within the code while filtering shows only matching line (i.e. like the Unix grep command does).

Searching and filtering can happen by exact matches (the default) and by matching regular expressions. The search-related UI controls can also be interacted with using keyboard shortcuts.

EXPERIMENTAL COMPONENT

KCodeBlock is an experimental component. The component’s design and overall look and feel may change until it is in stable status.

html
<KCodeBlock
  id="code-block-default"
  :code="code"
  language="json"
  is-searchable
/>
1
2
3
4
5
6

Props

id

  • Type: string
  • Required: yes

An ID used to identify form elements like the search input and its label.

Note: If you use multiple instances of KCodeBlock in a document, you need to provide unique ID values.

code

  • Type: string
  • Required: yes

The code that will be rendered as a text node inside of a <pre><code></code></pre> fragment.

No additional formatting of the code takes places. It will be used as-is.

language

  • Type: string
  • Required: yes

The syntax language of props.code (e.g. 'json').

isSearchable

  • Type: boolean
  • Required: no
  • Default: false

Shows an actions bar with a search input and related action buttons.

html
<KCodeBlock
  id="code-block-is-searchable"
  :code="code"
  language="json"
  is-searchable
/>
1
2
3
4
5
6

isProcessing

  • Type: boolean
  • Required: no
  • Default: false

Allows controlling the processing state from outside the component. This allows a parent component to show the processing icon when it’s, for example, currently syntax highlighting the code.

html
<KCodeBlock
  id="code-block-is-processing"
  :code="code"
  language="json"
  is-processing
/>
1
2
3
4
5
6

query

  • Type: string
  • Required: no
  • Default: ''

Used as the initial value of the search input. Can be used to initialize a code block with a query which was read from client storage.

html
<KCodeBlock
  id="code-block-query"
  :code="code"
  language="json"
  is-searchable
  query="no"
/>
1
2
3
4
5
6
7

showCopyButton

  • Type: boolean
  • Required: no
  • Default: true

Controls whether to show a copy button which copies the original code (i.e. the value of props.code) to the clipboard.

html
<KCodeBlock
  id="code-block-show-copy-button"
  :code="code"
  language="json"
  :show-copy-button="false"
/>
1
2
3
4
5
6
  • Type: boolean
  • Required: no
  • Default: false

Controls whether to add links to the current line number.

You might need to turn this off for sites that already constantly use the fragment identifier in the URL like vue router’s hash-based navigation mode where all URL paths follow a first /#/ segment.

html
<KCodeBlock
  id="code-block-show-line-number-links"
  :code="code"
  language="json"
  :show-line-number-links="true"
/>
1
2
3
4
5
6

Events

code-block-render

  • Type: CodeBlockEventData
  • Trigger: Fired when the code block is rendered or re-rendered. This happens when:
    • the component’s mounted life cycle hook is fired
    • the filter mode is turned off
    • props.code changes

This event can be used as the trigger for applying syntax highlighting (e.g. via Prism’s highlightElement function, see Syntax highlighting for an integration example).

javascript
function highlight({ preElement, codeElement, language, code }) {
  if (!preElement.classList.contains(`language-${language}`)) {
    preElement.classList.add(`language-${language}`)
  }

  codeElement.innerHTML = code

  Prism.highlightElement(codeElement)
}
1
2
3
4
5
6
7
8
9

matching-lines-change

query-change

  • Type: string
  • Trigger: Fired when the component’s internal query state is updated. This happens when the user finished typing (with a delay of a few hundred milliseconds to avoid repeatedly triggering computations while the user is still typing).

Theming

VariableDefaultPurpose
--KCodeBlockBorderRadius5pxCode block border radius
--KCodeBlockFocusColorvar(--blue-500)General focus color
--KCodeBlockMatchHighlightColorvar(--blue-500)Current match highlight color
--KCodeBlockColorvar(--black-85)Code block text color
--KCodeBlockBackgroundColorvar(--grey-100)Code block background color
--KCodeBlockFontSizevar(--type-xs)Code block font size
--KCodeBlockFontFamilyMonovar(--font-family-mono)Code block font family
--KCodeBlockTabSize2Tab size for code blocks

Default shortcuts

This component has a few shortcuts for interacting with its search and filter features. All of them are scoped to the code block. When invoking them while focus is placed outside of a code block, their associated actions won’t trigger.

ShortcutDescription
Alt+F or Alt+GToggles filter mode
Alt+RToggles RegExp mode
Alt+CCopies the code
F3Jumps to next match
Shift+F3Jumps to previous match

Types

CodeBlockEventData

typescript
type CodeBlockEventData = {
  preElement: HTMLElement
  codeElement: HTMLElement
  code: string
  language: string
  query: string
  matchingLineNumbers: number[]
}
1
2
3
4
5
6
7
8

Syntax highlighting

The KCodeBlock component does not have syntax highlighting built in; however, your project can provide its own implementation.

PrismJS

Below is an integration example for the popular syntax highlighting library PrismJS.

It makes use of the code-block-render event to apply syntax highlighting.

html
<template>
  <KCodeBlock
    id="code-block"
    :code="code"
    language="json"
    :is-processing="isProcessing"
    is-searchable
    @code-block-render="highlight"
    @matching-lines-change="highlightLines"
  />
</template>

<script setup>
import { ref } from 'vue'
import { KCodeBlock } from '@kong/kongponents/KCodeBlock.vue'
import Prism from 'prismjs'
import 'prismjs/components/prism-json.min.js'

import 'prismjs/themes/prism.min.css'

Prism.manual = true

const code = `{
  "compilerOptions": {
    "target": "es2020",
    "module": "esnext",
    "moduleResolution": "node",
    "allowUnreachableCode": false,
    "exactOptionalPropertyTypes": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitReturns": true,
    "noUncheckedIndexedAccess": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "strict": true,
    "jsx": "preserve"
  },
  "include": [
    "./src",
    "./types"
  ]
}`

const isProcessing = ref(false)

/**
 * Applies PrismJS syntax highlighting.
 *
 * **Note**: Use higher-level functions like `Prism.highlightElement` for highlighting.
 * Lower-level functions like `Prism.highlight` don’t run any of the hooks
 * that are used to make plugins work.
 */
function highlight({ preElement, codeElement, language, code }) {
  isProcessing.value = true

  if (!Prism.languages[language]) {
    console.warn(`Prism: the language “${language}” isn’t enabled.`)
  }

  if (!preElement.classList.contains(`language-${language}`)) {
    // Adds the language-* class which tells Prism which language to highlight for.
    preElement.classList.add(`language-${language}`)
  }

  // Ensures Prism operates on the raw code and not on an already highlighted DOM fragment.
  codeElement.innerHTML = code

  Prism.highlightElement(codeElement)

  isProcessing.value = false
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

Released under the Apache-2.0 License.