diff --git a/.changeset/funny-falcons-act.md b/.changeset/funny-falcons-act.md new file mode 100644 index 0000000000..aebeea4f48 --- /dev/null +++ b/.changeset/funny-falcons-act.md @@ -0,0 +1,5 @@ +--- +'@evidence-dev/db-commons': patch +--- + +add more leniency for comments in queries diff --git a/.changeset/hungry-chefs-wave.md b/.changeset/hungry-chefs-wave.md new file mode 100644 index 0000000000..46f7723962 --- /dev/null +++ b/.changeset/hungry-chefs-wave.md @@ -0,0 +1,5 @@ +--- +'@evidence-dev/postgres': patch +--- + +apply `standardizeResult` to first batch of postgres results diff --git a/.changeset/lazy-hornets-call.md b/.changeset/lazy-hornets-call.md new file mode 100644 index 0000000000..84e3920489 --- /dev/null +++ b/.changeset/lazy-hornets-call.md @@ -0,0 +1,5 @@ +--- +'@evidence-dev/core-components': minor +--- + +add `noDefault` prop to `Dropdown`, support for multi-defaultValue diff --git a/.changeset/pretty-jobs-wait.md b/.changeset/pretty-jobs-wait.md new file mode 100644 index 0000000000..3abb6ccd52 --- /dev/null +++ b/.changeset/pretty-jobs-wait.md @@ -0,0 +1,6 @@ +--- +'@evidence-dev/postgres': patch +'@evidence-dev/universal-sql': patch +--- + +stop blocking advanced usage of json with usql diff --git a/.changeset/sharp-years-film.md b/.changeset/sharp-years-film.md new file mode 100644 index 0000000000..57b16743a0 --- /dev/null +++ b/.changeset/sharp-years-film.md @@ -0,0 +1,6 @@ +--- +'@evidence-dev/preprocess': patch +'@evidence-dev/core-components': patch +--- + +Add automatic links to headers diff --git a/.changeset/silver-tools-serve.md b/.changeset/silver-tools-serve.md new file mode 100644 index 0000000000..9d71b9564f --- /dev/null +++ b/.changeset/silver-tools-serve.md @@ -0,0 +1,5 @@ +--- +'@evidence-dev/component-utilities': patch +--- + +properly update `option` for other functions to use diff --git a/.changeset/smart-dryers-hunt.md b/.changeset/smart-dryers-hunt.md new file mode 100644 index 0000000000..b2d91a84be --- /dev/null +++ b/.changeset/smart-dryers-hunt.md @@ -0,0 +1,5 @@ +--- +'@evidence-dev/core-components': patch +--- + +Adds support for HTML contentType in DataTables diff --git a/.changeset/smooth-boats-tell.md b/.changeset/smooth-boats-tell.md new file mode 100644 index 0000000000..30d6435e67 --- /dev/null +++ b/.changeset/smooth-boats-tell.md @@ -0,0 +1,5 @@ +--- +'@evidence-dev/core-components': patch +--- + +Fixes bold, italic, strikethrough and code span sizing issues in markdown diff --git a/packages/datasources/postgres/index.cjs b/packages/datasources/postgres/index.cjs index cd05b2e17e..b64b631ae1 100644 --- a/packages/datasources/postgres/index.cjs +++ b/packages/datasources/postgres/index.cjs @@ -125,7 +125,7 @@ const runQuery = async (queryString, database, batchSize = 100000, closeBeforeRe // to avoid loss of accuracy in very large numbers. This is something to keep an eye on, // but for now, we are replacing the default parsing functions with the applicable // JavaScript parsing function for each data type: - var types = require('pg').types; + var types = pg.types; // Override bigint: types.setTypeParser(20, function (val) { @@ -142,6 +142,10 @@ const runQuery = async (queryString, database, batchSize = 100000, closeBeforeRe return parseFloat(val.replace(/[^0-9.]/g, '')); }); + // Override json / jsonb: + types.setTypeParser(types.builtins.JSON, String); + types.setTypeParser(types.builtins.JSONB, String); + var pool = new Pool(credentials); // Set schema if specified. Can't be done using the connection string / credentials. See issue: https://github.com/brianc/node-postgres/issues/1123#issuecomment-501510375 & solution: https://node-postgres.com/apis/pool#events @@ -168,7 +172,7 @@ const runQuery = async (queryString, database, batchSize = 100000, closeBeforeRe return { rows: async function* () { try { - yield firstBatch; + yield standardizeResult(firstBatch); let results; while ((results = await cursor.read(batchSize)) && results.length > 0) yield standardizeResult(results); diff --git a/packages/lib/component-utilities/src/echarts.js b/packages/lib/component-utilities/src/echarts.js index 98c8d08a9f..eae462ae91 100644 --- a/packages/lib/component-utilities/src/echarts.js +++ b/packages/lib/component-utilities/src/echarts.js @@ -169,7 +169,8 @@ export default (node, option) => { } }; - const updateChart = (option) => { + const updateChart = (newOption) => { + option = newOption; chart.setOption( { ...option.config, diff --git a/packages/lib/db-commons/index.cjs b/packages/lib/db-commons/index.cjs index b84f0e31a0..c7b55ce8e3 100644 --- a/packages/lib/db-commons/index.cjs +++ b/packages/lib/db-commons/index.cjs @@ -186,7 +186,8 @@ const cleanQuery = (query) => { let cleanedString = query.trim(); if (cleanedString.endsWith(';')) cleanedString = cleanedString.substring(0, cleanedString.length - 1); - return cleanedString; + // query might end with a line comment, which has to be ended + return cleanedString + '\n'; }; /** diff --git a/packages/lib/preprocess/index.cjs b/packages/lib/preprocess/index.cjs index f41d866554..62270c41ce 100644 --- a/packages/lib/preprocess/index.cjs +++ b/packages/lib/preprocess/index.cjs @@ -6,6 +6,8 @@ const addClasses = require('./src/add-classes.cjs'); // This is includes future proofing to add support for Prism highlighting const processFrontmatter = require('./src/frontmatter/process-frontmatter.cjs'); const injectPartials = require('./src/partials/inject-partials.cjs'); +const rehypeSlug = require('rehype-slug'); +const rehypeAutolinkHeadings = require('rehype-autolink-headings'); module.exports = function evidencePreprocess(componentDevelopmentMode = false) { return [ @@ -29,6 +31,14 @@ module.exports = function evidencePreprocess(componentDevelopmentMode = false) { { '*': 'markdown' } + ], + [rehypeSlug], + [ + rehypeAutolinkHeadings, + { + behavior: 'wrap', + properties: {} + } ] ] }), diff --git a/packages/lib/preprocess/package.json b/packages/lib/preprocess/package.json index bad942745d..04d76c4024 100644 --- a/packages/lib/preprocess/package.json +++ b/packages/lib/preprocess/package.json @@ -23,6 +23,8 @@ "mdsvex": "0.11.0", "prismjs": "^1.29.0", "remark-parse": "8.0.2", + "rehype-slug": "4.0.1", + "rehype-autolink-headings": "5.1.0", "svelte": "4.2.12", "svelte-preprocess": "5.1.3", "unified": "^9.1.0", diff --git a/packages/lib/universal-sql/src/calculateScore.js b/packages/lib/universal-sql/src/calculateScore.js index c26bf747b5..6466a68df2 100644 --- a/packages/lib/universal-sql/src/calculateScore.js +++ b/packages/lib/universal-sql/src/calculateScore.js @@ -108,6 +108,7 @@ export function duckdbTypeToEvidenceType(column_type) { case 'TIME': case 'TIME WITH TIME ZONE': // return 'bigint'; case 'BLOB': + case 'JSON': case 'BIT': // return 'Uint8Array'; return 'string'; default: diff --git a/packages/ui/core-components/src/lib/atoms/inputs/dropdown/Dropdown.svelte b/packages/ui/core-components/src/lib/atoms/inputs/dropdown/Dropdown.svelte index 0e2710dbc6..a53508042c 100644 --- a/packages/ui/core-components/src/lib/atoms/inputs/dropdown/Dropdown.svelte +++ b/packages/ui/core-components/src/lib/atoms/inputs/dropdown/Dropdown.svelte @@ -48,11 +48,21 @@ export let hideDuringPrint = true; - /** @type {string} */ - export let defaultValue = undefined; + export let disableSelectAll = false; + + /** @type {string | string[]} */ + export let defaultValue = []; + const _defaultValue = Array.isArray(defaultValue) ? defaultValue : [defaultValue]; + + export let noDefault = false; + if (noDefault) { + _defaultValue.length = 0; + } + + const hasDefault = noDefault || _defaultValue.length > 0; const ctx = { - hasBeenSet: defaultValue !== undefined, + hasBeenSet: hasDefault, handleSelect, multiple }; @@ -150,16 +160,16 @@ function useNewQuery(query) { items = query; - if (hasQuery && defaultValue) { + if (hasQuery && hasDefault) { ctx.hasBeenSet = true; if (browser) { (async () => { await query.fetch(); - $selectedValues = query.filter((x) => x.value == defaultValue); + $selectedValues = query.filter((x) => _defaultValue.find((d) => x.value == d)); selectedValuesToInput(); })(); } else { - $selectedValues = query.filter((x) => x.value == defaultValue); + $selectedValues = query.filter((x) => _defaultValue.find((d) => x.value == d)); selectedValuesToInput(); } } else { @@ -256,16 +266,18 @@ {/if} {#if multiple} - - { - $selectedValues = $items.map((x) => ({ label: x.label, value: x.value })); - selectedValuesToInput(); - }} - > - Select all - + {#if !disableSelectAll} + + { + $selectedValues = $items.map((x) => ({ label: x.label, value: x.value })); + selectedValuesToInput(); + }} + > + Select all + + {/if} { - // Headers may contain values that change in response to user input, so we create our anchors as just the position on the page. - header.id = encodeURIComponent(i + 1); - }); + headers = Array.from(document.querySelectorAll('h1.markdown, h2.markdown, h3.markdown')); } function observeDocumentChanges() { @@ -38,12 +34,8 @@ On this page - {#each headers as header, i} - + {#each headers as header} + {header.innerText} {/each} @@ -54,10 +46,6 @@ @apply block text-gray-600 text-xs transition-all duration-200 py-1; } - /* a.h1.first { - @apply mt-0; - } */ - a:hover { @apply underline; } @@ -66,6 +54,10 @@ @apply pl-0 text-gray-500; } + a.h3 { + @apply pl-4 text-gray-500; + } + a.h1 { @apply mt-3 font-semibold block bg-white shadow shadow-white; } diff --git a/packages/ui/core-components/src/lib/unsorted/viz/table/TableRow.svelte b/packages/ui/core-components/src/lib/unsorted/viz/table/TableRow.svelte index f2723f2b53..4b5056543d 100644 --- a/packages/ui/core-components/src/lib/unsorted/viz/table/TableRow.svelte +++ b/packages/ui/core-components/src/lib/unsorted/viz/table/TableRow.svelte @@ -161,6 +161,8 @@ neutralMax={column.neutralMax} chip={column.chip} /> + {:else if column.contentType === 'html' && row[column.id] !== undefined} + {@html row[column.id]} {:else} {formatValue( row[column.id], diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 57dd3fac2e..b468ac8bad 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -694,6 +694,12 @@ importers: prismjs: specifier: ^1.29.0 version: 1.29.0 + rehype-autolink-headings: + specifier: 5.1.0 + version: 5.1.0 + rehype-slug: + specifier: 4.0.1 + version: 4.0.1 remark-parse: specifier: 8.0.2 version: 8.0.2 @@ -15492,10 +15498,18 @@ packages: web-namespaces: 1.1.4 dev: false + /hast-util-has-property@1.0.4: + resolution: {integrity: sha512-ghHup2voGfgFoHMGnaLHOjbYFACKrRh9KFttdCzMCbFoBMJXiNi2+XTrPP8+q6cDJM/RSqlCfVWrjp1H201rZg==} + dev: false + /hast-util-has-property@2.0.1: resolution: {integrity: sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg==} dev: false + /hast-util-heading-rank@1.0.1: + resolution: {integrity: sha512-P6Hq7RCky9syMevlrN90QWpqWDXCxwIVOfQR2rK6P4GpY4bqjKEuCzoWSRORZ7vz+VgRpLnXimh+mkwvVFjbyQ==} + dev: false + /hast-util-heading-rank@3.0.0: resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==} dependencies: @@ -15561,6 +15575,10 @@ packages: zwitch: 1.0.5 dev: false + /hast-util-to-string@1.0.4: + resolution: {integrity: sha512-eK0MxRX47AV2eZ+Lyr18DCpQgodvaS3fAQO2+b9Two9F5HEoRPhiUMNzoXArMJfZi2yieFzUBMRl3HNJ3Jus3w==} + dev: false + /hast-util-to-string@2.0.0: resolution: {integrity: sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A==} dependencies: @@ -21046,6 +21064,15 @@ packages: dependencies: jsesc: 0.5.0 + /rehype-autolink-headings@5.1.0: + resolution: {integrity: sha512-ujU4/ALnWLJQubobQaMdC0h9nkzi7HlW9SOuCxZOkkJqhc/TrQ1cigIjMFQ2Tfc/es0KiFopKvwCUGw7Gw+mFw==} + dependencies: + extend: 3.0.2 + hast-util-has-property: 1.0.4 + hast-util-heading-rank: 1.0.1 + unist-util-visit: 2.0.3 + dev: false + /rehype-external-links@3.0.0: resolution: {integrity: sha512-yp+e5N9V3C6bwBeAC4n796kc86M4gJCdlVhiMTxIrJG5UHDMh+PJANf9heqORJbt1nrCbDwIlAZKjANIaVBbvw==} dependencies: @@ -21075,6 +21102,16 @@ packages: parse5: 6.0.1 dev: false + /rehype-slug@4.0.1: + resolution: {integrity: sha512-KIlJALf9WfHFF21icwTd2yI2IP+RQRweaxH9ChVGQwRYy36+hiomG4ZSe0yQRyCt+D/vE39LbAcOI/h4O4GPhA==} + dependencies: + github-slugger: 1.5.0 + hast-util-has-property: 1.0.4 + hast-util-heading-rank: 1.0.1 + hast-util-to-string: 1.0.4 + unist-util-visit: 2.0.3 + dev: false + /rehype-slug@6.0.0: resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==} dependencies: diff --git a/sites/docs/docs/components/dropdown.md b/sites/docs/docs/components/dropdown.md index 3139625f4b..4af5984580 100644 --- a/sites/docs/docs/components/dropdown.md +++ b/sites/docs/docs/components/dropdown.md @@ -123,6 +123,23 @@ where column_name like '${inputs.name_of_dropdown.value}' ``` ```` +### Multiple defaultValues + +````markdown + + +```sql filtered_query +select * +from source_name.table +where column_name like '${inputs.name_of_dropdown.value}' +``` +```` + ## Dropdown ### Options @@ -150,24 +167,38 @@ where column_name like '${inputs.name_of_dropdown.value}' - - value + value Column name from the query containing values to pick from No column name - - + defaultValue - Value to use when the dropdown is first loaded. Must be one of the options in the dropdown. + Value(s) to use when the dropdown is first loaded. Must be options in the values of the dropdown. Note: for multiple values, the array must be formatted as `defaultValue={[]}`, not `defaultValue=[]` No - First value in dropdown + + + noDefault + Stops any default from being selected. Overrides any set `defaultValue`. + No + true | false + false + + + disableSelectAll + Removes the `Select all` button. Recommended for large datasets. + No + true | false + false multiple Enables multi-select which returns a list No - boolean + true | false false @@ -198,6 +229,13 @@ where column_name like '${inputs.name_of_dropdown.value}' SQL where clause - + + hideDuringPrint + Hide the component when the report is printed + No + true | false + true + ## DropdownOption diff --git a/sites/example-project/src/app.css b/sites/example-project/src/app.css index 88e19df552..c541f829a1 100644 --- a/sites/example-project/src/app.css +++ b/sites/example-project/src/app.css @@ -172,7 +172,7 @@ } code.markdown { - @apply font-mono text-gray-800 text-sm bg-gray-50 border rounded px-1 select-all py-0.5; + @apply font-mono text-gray-800 text-[0.875em] bg-gray-50 border rounded px-1 select-all py-0.5; } form code { @@ -186,6 +186,18 @@ blockquote.markdown * { @apply text-gray-500; } + /* Ensure size and color are maintained for bold, italic, strikethrough */ + strong.markdown { + @apply text-[1em] text-inherit; + } + + em.markdown { + @apply text-[1em] text-inherit; + } + + del.markdown { + @apply text-[1em] text-inherit; + } table.markdown { @apply min-w-full border-collapse text-center mx-auto my-5; diff --git a/sites/example-project/src/pages/text-and-metrics/markdown/+page.md b/sites/example-project/src/pages/text-and-metrics/markdown/+page.md index 27d8bfb65f..010ccf8c47 100644 --- a/sites/example-project/src/pages/text-and-metrics/markdown/+page.md +++ b/sites/example-project/src/pages/text-and-metrics/markdown/+page.md @@ -15,6 +15,14 @@ title: Markdown ###### Heading Level 6 +# ~~Heading Level 1 with Strikethrough~~ + +# Heading Level 1 with _Italics_ + +# Heading Level 1 with **Bold** + +# Heading Level 1 with `code` + # Link Headers # [Link h1](/) @@ -67,7 +75,7 @@ _Italic_ ~~Strikethrough~~ Textsuperscript Textsubscript -Underline +# This is Underline and **Bold** ## Highlighting @@ -140,7 +148,7 @@ Link to [Google](https://google.com) | Column One | Column Two | Column Three | | :--------: | :--------: | :----------: | -| A | B | C | +| A `with code` | B | C | | 1 | 2 | 3 | | D | E | F | | 4 | 5 | 6 | diff --git a/sites/test-env/pages/dropdown.md b/sites/test-env/pages/dropdown.md index 230a622671..ab6517b8e3 100644 --- a/sites/test-env/pages/dropdown.md +++ b/sites/test-env/pages/dropdown.md @@ -47,7 +47,7 @@ select * from orders limit 1000 select * from orders where id in ${inputs.multiple_selected_order_ids.value} ``` - + Orders of {inputs.multiple_selected_order_ids.label} @@ -71,7 +71,7 @@ Orders of {inputs.multiple_selected_order_ids.label} ## Small Demo - + ```selected_items