Skip to content

Commit ca9ef0b

Browse files
committed
Merge branch 'main' into chat-shiny-bind
2 parents e9aa501 + afc7698 commit ca9ef0b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+255
-304
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Changes
1111

12+
* Express mode's `app_opts()` requires all arguments to be keyword-only. If you are using positional arguments, you will need to update your code. (#1895)
13+
1214
* The `.get_latest_stream_result()` method on `ui.MarkdownStream()` was deprecated in favor of the new `.latest_stream` property. Call `.result()` on the property to get the latest result, `.status` to check the status, and `.cancel()` to cancel the stream.
1315

1416
### Bug fixes

js/build.ts

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,59 @@
1-
import { BuildOptions, build } from "esbuild";
1+
import { BuildOptions, build, type Metafile } from "esbuild";
22
import { sassPlugin } from "esbuild-sass-plugin";
33
import * as fs from "node:fs/promises";
44

55
let minify = true;
6+
let metafile = true;
67
process.argv.forEach((val, index) => {
78
if (val === "--minify=false") {
89
console.log("Disabling minification");
910
minify = false;
1011
}
12+
if (val === "--metafile=false") {
13+
console.log("Disabling metafile generation");
14+
metafile = false;
15+
}
1116
});
1217

1318
const outDir = "../shiny/www/py-shiny";
1419

20+
const allEsbuildMetadata: Array<Metafile> = [];
21+
22+
function mergeMetadatas(metadatas: Array<Metafile>): Metafile {
23+
// Merge all the metafile objects together
24+
const mergedMetadata: Metafile = {
25+
inputs: {},
26+
outputs: {},
27+
};
28+
29+
metadatas.forEach((metafile) => {
30+
Object.entries(metafile.inputs).forEach(([key, value]) => {
31+
if (
32+
mergedMetadata.inputs[key] &&
33+
JSON.stringify(mergedMetadata.inputs[key]) !== JSON.stringify(value)
34+
) {
35+
// It's very possible for multiple MetaFile objects to refer to the same input.
36+
// But if that input has different values in the different Metafile objects,
37+
// that could cause inaccuracies when we merge them. I think it's possible they
38+
// could have different values if tree-shaking is enabled -- this will detect
39+
// those cases and warn the user, and if it happens we can figure out how to
40+
// handle it.
41+
console.error(
42+
`Different values found for key in metadata: ${key}. Overwriting.`
43+
);
44+
}
45+
mergedMetadata.inputs[key] = value;
46+
});
47+
Object.entries(metafile.outputs).forEach(([key, value]) => {
48+
if (mergedMetadata.outputs[key]) {
49+
console.error(`Duplicate key found in metadata: ${key}. Overwriting.`);
50+
}
51+
mergedMetadata.outputs[key] = value;
52+
});
53+
});
54+
55+
return mergedMetadata;
56+
}
1557
async function bundle_helper(
1658
options: BuildOptions
1759
): Promise<ReturnType<typeof build> | undefined> {
@@ -20,8 +62,10 @@ async function bundle_helper(
2062
format: "esm",
2163
bundle: true,
2264
minify: minify,
23-
sourcemap: true,
24-
metafile: false,
65+
// No need to clean up old source maps, as `minify==false` only during `npm run watch-fast`
66+
// GHA will run `npm run build` which will minify
67+
sourcemap: minify,
68+
metafile: metafile,
2569
outdir: outDir,
2670
...options,
2771
});
@@ -34,15 +78,10 @@ async function bundle_helper(
3478
}
3579
);
3680

37-
if (options.metafile) {
38-
// Save metafile
39-
const data_frame_results = result;
40-
await fs.writeFile(
41-
"esbuild-metadata.json",
42-
JSON.stringify(data_frame_results.metafile)
43-
);
44-
console.log("Metadata file written to esbuild-metadata.json");
81+
if (result.metafile) {
82+
allEsbuildMetadata.push(result.metafile);
4583
}
84+
4685
return result;
4786
} catch (error) {
4887
console.error("Build failed:", error);
@@ -53,57 +92,49 @@ const opts: Array<BuildOptions> = [
5392
{
5493
entryPoints: { "data-frame/data-frame": "data-frame/index.tsx" },
5594
plugins: [sassPlugin({ type: "css-text", sourceMap: false })],
56-
metafile: true,
5795
},
5896
{
5997
entryPoints: {
6098
"text-area/textarea-autoresize": "text-area/textarea-autoresize.ts",
6199
},
62-
minify: false,
63-
sourcemap: false,
64100
},
65101
{
66102
entryPoints: {
67103
"page-output/page-output": "page-output/page-output.ts",
68104
},
69-
minify: false,
70-
sourcemap: false,
71105
},
72106
{
73107
entryPoints: { "spin/spin": "spin/spin.scss" },
74108
plugins: [sassPlugin({ type: "css", sourceMap: false })],
75-
metafile: true,
76109
},
77110
{
78111
entryPoints: {
79112
"markdown-stream/markdown-stream": "markdown-stream/markdown-stream.ts",
80113
},
81-
minify: true,
82-
sourcemap: true,
83114
},
84115
{
85116
entryPoints: {
86117
"markdown-stream/markdown-stream": "markdown-stream/markdown-stream.scss",
87118
},
88119
plugins: [sassPlugin({ type: "css", sourceMap: false })],
89-
metafile: true,
90120
},
91121
{
92122
entryPoints: {
93123
"chat/chat": "chat/chat.ts",
94124
},
95-
minify: true,
96-
sourcemap: true,
97125
},
98126
{
99127
entryPoints: { "chat/chat": "chat/chat.scss" },
100128
plugins: [sassPlugin({ type: "css", sourceMap: false })],
101-
metafile: true,
102129
},
103130
];
104131

105-
// Run function to avoid top level await
106-
async function main(): Promise<void> {
132+
(async () => {
107133
await Promise.all(opts.map(bundle_helper));
108-
}
109-
main();
134+
135+
if (metafile) {
136+
const mergedMetadata = mergeMetadatas(allEsbuildMetadata);
137+
await fs.writeFile("esbuild-metadata.json", JSON.stringify(mergedMetadata));
138+
console.log("Metadata file written to esbuild-metadata.json");
139+
}
140+
})();

js/chat/chat.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ shiny-chat-container {
3232
text-underline-offset: 4px;
3333
text-decoration-thickness: 2px;
3434

35-
padding: 2px;
35+
padding-inline: 2px;
3636

3737
&:hover {
3838
text-decoration-style: solid;

js/chat/chat.ts

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ class ChatInput extends LightElement {
231231
if (this.valueIsEmpty) return;
232232
if (this.disabled) return;
233233

234-
Shiny.setInputValue!(this.id, this.value, { priority: "event" });
234+
window.Shiny.setInputValue!(this.id, this.value, { priority: "event" });
235235

236236
// Emit event so parent element knows to insert the message
237237
const sentEvent = new CustomEvent("shiny-chat-input-sent", {
@@ -534,33 +534,30 @@ customElements.define(CHAT_MESSAGES_TAG, ChatMessages);
534534
customElements.define(CHAT_INPUT_TAG, ChatInput);
535535
customElements.define(CHAT_CONTAINER_TAG, ChatContainer);
536536

537-
$(function () {
538-
Shiny.addCustomMessageHandler(
539-
"shinyChatMessage",
540-
async function (message: ShinyChatMessage) {
541-
542-
if (message.obj?.html_deps) {
543-
await renderDependencies(message.obj.html_deps);
544-
}
537+
window.Shiny.addCustomMessageHandler(
538+
"shinyChatMessage",
539+
async function (message: ShinyChatMessage) {
540+
if (message.obj?.html_deps) {
541+
await renderDependencies(message.obj.html_deps);
542+
}
545543

546-
const evt = new CustomEvent(message.handler, {
547-
detail: message.obj,
548-
});
544+
const evt = new CustomEvent(message.handler, {
545+
detail: message.obj,
546+
});
549547

550-
const el = document.getElementById(message.id);
548+
const el = document.getElementById(message.id);
551549

552-
if (!el) {
553-
showShinyClientMessage({
554-
status: "error",
555-
message: `Unable to handle Chat() message since element with id
550+
if (!el) {
551+
showShinyClientMessage({
552+
status: "error",
553+
message: `Unable to handle Chat() message since element with id
556554
${message.id} wasn't found. Do you need to call .ui() (Express) or need a
557555
chat_ui('${message.id}') in the UI (Core)?
558556
`,
559-
});
560-
return;
561-
}
562-
563-
el.dispatchEvent(evt);
557+
});
558+
return;
564559
}
565-
);
566-
});
560+
561+
el.dispatchEvent(evt);
562+
}
563+
);

js/data-frame/index.tsx

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
527527
useEffect(() => {
528528
if (!htmlDeps) return;
529529
// Register the Shiny HtmlDependencies
530-
Shiny.renderDependenciesAsync([...htmlDeps]);
530+
window.Shiny.renderDependenciesAsync([...htmlDeps]);
531531
}, [htmlDeps]);
532532

533533
useEffect(() => {
@@ -701,7 +701,7 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
701701
} else {
702702
console.error("Unhandled row selection mode:", selectionModes);
703703
}
704-
Shiny.setInputValue!(`${id}_cell_selection`, shinyValue);
704+
window.Shiny.setInputValue!(`${id}_cell_selection`, shinyValue);
705705
}, [id, selection, selectionModes, table, table.getSortedRowModel]);
706706

707707
useEffect(() => {
@@ -714,10 +714,10 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
714714
desc: sortObj.desc,
715715
});
716716
});
717-
Shiny.setInputValue!(`${id}_sort`, shinySort);
717+
window.Shiny.setInputValue!(`${id}_sort`, shinySort);
718718

719719
// Deprecated as of 2024-05-21
720-
Shiny.setInputValue!(`${id}_column_sort`, shinySort);
720+
window.Shiny.setInputValue!(`${id}_column_sort`, shinySort);
721721
}, [columns, id, sorting]);
722722
useEffect(() => {
723723
if (!id) return;
@@ -732,10 +732,10 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
732732
value: filterObj.value as FilterValue,
733733
});
734734
});
735-
Shiny.setInputValue!(`${id}_filter`, shinyFilter);
735+
window.Shiny.setInputValue!(`${id}_filter`, shinyFilter);
736736

737737
// Deprecated as of 2024-05-21
738-
Shiny.setInputValue!(`${id}_column_filter`, shinyFilter);
738+
window.Shiny.setInputValue!(`${id}_column_filter`, shinyFilter);
739739
}, [id, columnFilters, columns]);
740740
useEffect(() => {
741741
if (!id) return;
@@ -744,10 +744,10 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
744744
// Already prefiltered rows!
745745
.getSortedRowModel()
746746
.rows.map((row) => row.index);
747-
Shiny.setInputValue!(`${id}_data_view_rows`, shinyRows);
747+
window.Shiny.setInputValue!(`${id}_data_view_rows`, shinyRows);
748748

749749
// Legacy value as of 2024-05-13
750-
Shiny.setInputValue!(`${id}_data_view_indices`, shinyRows);
750+
window.Shiny.setInputValue!(`${id}_data_view_indices`, shinyRows);
751751
}, [
752752
id,
753753
table,
@@ -773,7 +773,7 @@ const ShinyDataGrid: FC<ShinyDataGridProps<unknown>> = ({
773773
.filter((x): x is number => x !== null)
774774
.sort();
775775
}
776-
Shiny.setInputValue!(`${id}_selected_rows`, shinyValue);
776+
window.Shiny.setInputValue!(`${id}_selected_rows`, shinyValue);
777777
}, [id, selection, selectionModes, table]);
778778

779779
// ### End row selection ############################################################
@@ -1083,7 +1083,7 @@ function useVirtualizerMeasureWorkaround(
10831083
return measureElementWithRetry;
10841084
}
10851085

1086-
class ShinyDataFrameOutputBinding extends Shiny.OutputBinding {
1086+
class ShinyDataFrameOutputBinding extends window.Shiny.OutputBinding {
10871087
find(scope: HTMLElement | JQuery<HTMLElement>): JQuery<HTMLElement> {
10881088
return $(scope).find("shiny-data-frame");
10891089
}
@@ -1103,7 +1103,7 @@ class ShinyDataFrameOutputBinding extends Shiny.OutputBinding {
11031103
el.clearError();
11041104
}
11051105
}
1106-
Shiny.outputBindings.register(
1106+
window.Shiny.outputBindings.register(
11071107
new ShinyDataFrameOutputBinding(),
11081108
"shinyDataFrame"
11091109
);
@@ -1214,12 +1214,13 @@ customElements.define("shiny-data-frame", ShinyDataFrameOutput);
12141214
// react listener.
12151215
// It would be better to have something similar to session.send_input_message
12161216
// for updating outputs, but that requires changes to ShinyJS.
1217-
$(function () {
1218-
Shiny.addCustomMessageHandler("shinyDataFrameMessage", function (message) {
1217+
window.Shiny.addCustomMessageHandler(
1218+
"shinyDataFrameMessage",
1219+
function (message) {
12191220
const evt = new CustomEvent(message.handler, {
12201221
detail: message.obj,
12211222
});
12221223
const el = document.getElementById(message.id);
12231224
el?.dispatchEvent(evt);
1224-
});
1225-
});
1225+
}
1226+
);

js/markdown-stream/markdown-stream.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,9 @@ async function handleMessage(
335335
}
336336
}
337337

338-
$(function () {
339-
Shiny.addCustomMessageHandler("shinyMarkdownStreamMessage", handleMessage);
340-
});
338+
window.Shiny.addCustomMessageHandler(
339+
"shinyMarkdownStreamMessage",
340+
handleMessage
341+
);
341342

342343
export { MarkdownElement, contentToHTML };

0 commit comments

Comments
 (0)