Skip to content
This repository was archived by the owner on Jul 30, 2025. It is now read-only.

Commit 3704a2c

Browse files
committed
feat(plugins/plugin-client-common): support execution of markdown code blocks!
1 parent 29f2f35 commit 3704a2c

File tree

21 files changed

+533
-93
lines changed

21 files changed

+533
-93
lines changed

package-lock.json

Lines changed: 70 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/src/webapp/tab.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,21 @@ export function splitFor(topLevelTab: Tab) {
121121
* @param incognito Execute the command quietly but do not display the result in the Terminal
122122
*
123123
*/
124-
export function pexecInCurrentTab(command: string, topLevelTab?: Tab, isInternalCallpath = false, incognito = false) {
124+
export function pexecInCurrentTab(
125+
command: string,
126+
topLevelTab?: Tab,
127+
isInternalCallpath = false,
128+
incognito = false,
129+
execUUID?: string
130+
) {
125131
const split = splitFor(topLevelTab)
126132

127133
if (split) {
128134
const tab = split // "tab" is the old name for the split in the repl/exec code
129135

130136
return isInternalCallpath
131-
? split.REPL.qexec(command, undefined, undefined, { tab }) // "quiet" exec i.e. don't display the fact that we are executing a command
132-
: split.REPL.pexec(command, { tab, echo: !incognito, noHistory: true }) // normal exec, display the Input/Output in the UI
137+
? split.REPL.qexec(command, undefined, undefined, { tab, execUUID }) // "quiet" exec i.e. don't display the fact that we are executing a command
138+
: split.REPL.pexec(command, { tab, echo: !incognito, noHistory: true, execUUID }) // normal exec, display the Input/Output in the UI
133139
} else {
134140
return Promise.reject(
135141
new Error(

plugins/plugin-client-common/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"react-markdown": "7.1.1",
3232
"rehype-raw": "6.1.0",
3333
"rehype-slug": "5.0.0",
34+
"remark-code-frontmatter": "1.0.0",
3435
"remark-collapse": "0.1.2",
3536
"remark-emoji": "3.0.2",
3637
"remark-frontmatter": "4.0.1",

plugins/plugin-client-common/src/components/Client/LoadingCard.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,7 @@ interface Props {
3030
export default class LoadingCard extends React.PureComponent<Props> {
3131
public render() {
3232
return (
33-
<Card
34-
titleInHeader
35-
bodyInHeader
36-
title={strings('Successfully connected to your cluster')}
37-
repl={this.props.repl}
38-
icon={KuiIcon}
39-
>
33+
<Card titleInHeader bodyInHeader title={strings('Successfully connected to your cluster')} icon={KuiIcon}>
4034
{strings('loadingDone:content')}
4135
</Card>
4236
)

plugins/plugin-client-common/src/components/Content/Commentary.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
import React from 'react'
18-
import { CommentaryResponse, REPL, i18n } from '@kui-shell/core'
18+
import { CommentaryResponse, Tab, i18n } from '@kui-shell/core'
1919

2020
import Card from '../spi/Card'
2121
import Button from '../spi/Button'
@@ -28,11 +28,10 @@ interface State {
2828
isEdit: boolean
2929
textValue: string
3030
lastAppliedTextValue: string
31-
repl?: REPL
3231
}
3332

3433
type Props = CommentaryResponse['props'] & {
35-
tabUUID: string
34+
tab: Tab
3635
willUpdateResponse?: (text: string) => void
3736
willRemove?: () => void
3837
willUpdateCommand?: (command: string) => void
@@ -221,7 +220,7 @@ export default class Commentary extends React.PureComponent<Props, State> {
221220
return (
222221
<React.Suspense fallback={<div />}>
223222
<SimpleEditor
224-
tabUUID={this.props.tabUUID}
223+
tabUUID={this.props.tab.uuid}
225224
content={this.state.textValue}
226225
className="kui--source-ref-editor kui--commentary-editor"
227226
readonly={false}

plugins/plugin-client-common/src/components/Content/Editor/SimpleEditor.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ type Props = Pick<MonacoOptions, 'fontSize'> & {
3434
onContentChange?: (content: string) => void
3535
scrollIntoView?: boolean
3636

37+
/** Focus on initial render (this is the default for !readonly) */
38+
focus?: boolean
39+
3740
/** Font size adjustment factor, based off getKuiFontSize(), i.e. the default font size for the theme and client */
3841
fontSizeAdjust?: number
3942

@@ -85,8 +88,12 @@ export default class SimpleEditor extends React.Component<Props, State> {
8588
/** Called whenever we have proposed (props,state); we derive a new State */
8689
public static getDerivedStateFromProps(props: Props, state: State) {
8790
if (state.editor) {
88-
if (state.editor.getValue() !== props.content) {
91+
const model = state.editor.getModel()
92+
const currentLanguage = model.getLanguageId()
93+
const newLanguage = SimpleEditor.language(props.contentType)
94+
if (model.getValue() !== props.content || currentLanguage !== newLanguage) {
8995
state.editor.setValue(props.content)
96+
Monaco.setModelLanguage(model, newLanguage)
9097
}
9198
}
9299

@@ -134,6 +141,10 @@ export default class SimpleEditor extends React.Component<Props, State> {
134141
}
135142
}
136143

144+
private static language(contentType: string): string {
145+
return /^(ba)?sh$/.test(contentType) ? 'shell' : contentType
146+
}
147+
137148
/** Called when we have a ready wrapper (monaco's init requires an wrapper */
138149
private initMonaco(props: Props, state: State) {
139150
const cleaners = []
@@ -144,7 +155,7 @@ export default class SimpleEditor extends React.Component<Props, State> {
144155
value: props.content,
145156
readOnly: props.readonly !== undefined ? props.readonly : true,
146157
fontSize: props.fontSize || getKuiFontSize() * (props.fontSizeAdjust || 1),
147-
language: /^(ba)?sh$/.test(props.contentType) ? 'shell' : props.contentType,
158+
language: SimpleEditor.language(props.contentType),
148159
simple: props.simple
149160
}
150161
const overrides: Monaco.IStandaloneEditorConstructionOptions = { theme: props.light ? 'vs' : 'vs-dark' }
@@ -158,7 +169,7 @@ export default class SimpleEditor extends React.Component<Props, State> {
158169

159170
this.registerKeyboardShortcuts(editor)
160171

161-
if (options.readOnly && props.simple) {
172+
if (/* options.readOnly && */ props.simple) {
162173
// if we know 1) the height of the content won't change, and
163174
// 2) we are running in "simple" mode (this is mostly the case
164175
// for inline editor components, as opposed to editor
@@ -177,7 +188,7 @@ export default class SimpleEditor extends React.Component<Props, State> {
177188
editor.onDidChangeModelContent(SimpleEditor.onChange(props, editor))
178189
}
179190

180-
if (!options.readOnly) {
191+
if (!options.readOnly && this.props.focus !== false) {
181192
setTimeout(() => editor.focus())
182193
}
183194

plugins/plugin-client-common/src/components/Content/Editor/lib/defaults.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ export default (options: Options): editor.IEditorConstructionOptions => ({
3939
fontFamily: 'var(--font-monospace)',
4040
fontSize: options.fontSize || getKuiFontSize(),
4141

42+
// don't show those little bits and borders in the scrollbar in "simple" mode
43+
overviewRulerBorder: options.simple,
44+
overviewRulerLanes: options.simple ? 0 : undefined,
45+
4246
// specifics for readOnly mode
4347
glyphMargin: !options.readOnly && !options.simple, // needed for error indicators
4448

plugins/plugin-client-common/src/components/Content/KuiContent.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ export default class KuiContent extends React.PureComponent<KuiMMRProps, State>
104104
return (
105105
<Markdown
106106
tab={tab}
107-
repl={tab.REPL}
108107
fullpath={isFile(response) ? response.spec.fullpath : undefined}
109108
source={mode.content}
110109
/>

0 commit comments

Comments
 (0)