Skip to content

Commit 9ff0128

Browse files
authored
Add most options to the REPL (#4824)
* Refine options * Prepare to rework options * Migrate to new option handling * Refine dependencies * Extract helpers * Improve select styling * Add delete button * Improve internal ids for preserveModules * Change examples to not start with multiple chunks * Add new options and replace boolean,string-select -> select * Add more options including paths * Add input options * Add remaining advanced options * Add all remaining suitable options * Refine handling for treeshake * Fix remaining issues
1 parent b362fb9 commit 9ff0128

42 files changed

Lines changed: 934 additions & 169 deletions

Some content is hidden

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

docs/configuration-options/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1528,7 +1528,7 @@ See also [`output.interop`](#output-interop).
15281528
15291529
### output.exports
15301530
1531-
Type: `string`<br> CLI: `--exports <exportMode>`<br> Default: `'auto'`
1531+
Type: `"auto" | "default" | "named" | "none"`<br> CLI: `--exports <exportMode>`<br> Default: `'auto'`
15321532
15331533
What export mode to use. Defaults to `auto`, which guesses your intentions based on what the `input` module exports:
15341534
Lines changed: 145 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,91 @@
11
<template>
2-
<div class="options">
3-
<section>
4-
<h3>output.format</h3>
5-
<OptionsSelect
6-
:values="formats"
7-
:selected="optionsStore.options.format"
8-
@select="selected => (optionsStore.options.format = selected)"
9-
/>
10-
</section>
11-
<section v-if="optionsStore.options.format === 'amd' || optionsStore.options.format === 'umd'">
12-
<h3>output.amd.id</h3>
13-
<input v-model="optionsStore.options.amd.id" placeholder="leave blank for anonymous module" />
14-
</section>
15-
<section v-if="needsName">
16-
<h3>output.name</h3>
17-
<input v-model="optionsStore.options.name" />
18-
</section>
19-
<section v-if="importsThatNeedGLobals.length > 0">
20-
<h3>output.globals</h3>
21-
<div v-for="imported in importsThatNeedGLobals" :key="imported" class="input-with-label">
22-
<input v-model="optionsStore.options.globals[imported]" />
23-
<code>'{{ imported }}'</code>
24-
</div>
25-
</section>
2+
<div class="options-panel">
3+
<div class="options">
4+
<section v-for="option in optionsStore.options" :key="option.name">
5+
<h3>
6+
<a :href="getLinkForOption(option.name)">{{ option.name }}</a>
7+
<button
8+
v-if="option.removable"
9+
class="remove"
10+
@click="optionsStore.set(option.name, undefined)"
11+
>
12+
<span class="label">remove</span>
13+
<span class="icon-cancel"></span>
14+
</button>
15+
</h3>
16+
<SelectOption
17+
v-if="option.type === 'select'"
18+
:values="option.options"
19+
:selected="option.value"
20+
@select="selected => optionsStore.set(option.name, selected)"
21+
/>
22+
<input
23+
v-else-if="option.type === 'string'"
24+
:value="option.value"
25+
:placeholder="option.placeholder"
26+
@input="optionsStore.set(option.name, $event.target.value)"
27+
/>
28+
<div
29+
v-else-if="option.type === 'string-mapping'"
30+
v-for="imported in option.keys"
31+
:key="imported"
32+
class="input-with-label"
33+
>
34+
<input
35+
:value="option.value[imported]"
36+
@input="
37+
optionsStore.set(option.name, { ...option.value, [imported]: $event.target.value })
38+
"
39+
/>
40+
<code>'{{ imported }}'</code>
41+
</div>
42+
</section>
43+
</div>
44+
<div v-if="optionsStore.additionalAvailableOptions.length > 0" class="add-option">
45+
<span class="icon-plus"></span>
46+
<select
47+
@input="
48+
optionsStore.addOption($event.target.value);
49+
$event.target.value = '_';
50+
"
51+
>
52+
<option disabled selected value="_">add option</option>
53+
<option
54+
v-for="option in optionsStore.additionalAvailableOptions"
55+
:key="option"
56+
:value="option"
57+
>
58+
{{ option }}
59+
</option>
60+
</select>
61+
</div>
2662
</div>
2763
</template>
2864

2965
<script setup lang="ts">
30-
import { computed } from 'vue';
3166
import { useOptions } from '../stores/options';
32-
import { useRollupOutput } from '../stores/rollupOutput';
33-
import OptionsSelect from './OptionsSelect.vue';
67+
import SelectOption from './SelectOption.vue';
3468
35-
const rollupOutputStore = useRollupOutput();
3669
const optionsStore = useOptions();
3770
38-
const importsThatNeedGLobals = computed(() => {
39-
const { output } = rollupOutputStore.output;
40-
const { format } = optionsStore.options;
41-
if ((format !== 'iife' && format !== 'umd') || output.length === 0) return [];
42-
return output[0].imports.sort((a, b) => (a < b ? -1 : 1));
43-
});
44-
45-
const needsName = computed(() => {
46-
const { output } = rollupOutputStore.output;
47-
const { format } = optionsStore.options;
48-
if ((format !== 'iife' && format !== 'umd') || output.length === 0) return false;
49-
return output[0].exports.length > 0;
50-
});
51-
52-
const formats = ['es', 'amd', 'cjs', 'iife', 'umd', 'system'];
71+
const getLinkForOption = (option: string) =>
72+
`/configuration-options/#${option
73+
.toLowerCase()
74+
.split('.')
75+
.slice(0, option.startsWith('output.') ? 2 : 1)
76+
.join('-')}`;
5377
</script>
5478

5579
<style scoped>
80+
.options-panel {
81+
margin-bottom: 8px;
82+
}
83+
5684
.options {
5785
--bg-inactive: var(--vp-c-gray-light-3);
5886
--bg-active: var(--vp-c-bg);
5987
--bg-default: var(--vp-c-gray-light-5);
6088
border: 1px solid var(--vp-c-divider-light);
61-
margin: 0 0 1rem 0;
6289
line-height: 2rem;
6390
background-color: var(--bg-default);
6491
border-radius: 8px;
@@ -72,11 +99,22 @@ const formats = ['es', 'amd', 'cjs', 'iife', 'umd', 'system'];
7299
73100
h3 {
74101
padding: 0 0.5rem;
75-
color: var(--vp-c-text-2);
76102
margin: 6px 0 2px;
77103
font-size: 14px;
78104
font-weight: 500;
79105
line-height: 20px;
106+
display: flex;
107+
flex-direction: row;
108+
justify-content: space-between;
109+
}
110+
111+
h3 a {
112+
color: var(--vp-c-text-2);
113+
transition: 0.2s all;
114+
}
115+
116+
h3 a:hover {
117+
color: var(--vp-c-text-1);
80118
}
81119
82120
input {
@@ -101,4 +139,66 @@ section code {
101139
top: 0;
102140
padding: 0 0.5rem 0 1.5rem;
103141
}
142+
143+
.add-option {
144+
display: flex;
145+
flex-direction: row;
146+
justify-content: end;
147+
position: relative;
148+
color: var(--vp-c-text-2);
149+
transition: 0.2s all;
150+
margin-top: 4px;
151+
}
152+
153+
.add-option:hover {
154+
color: var(--vp-c-text-1);
155+
}
156+
157+
select {
158+
font-family: inherit;
159+
font-size: 14px;
160+
font-weight: 500;
161+
position: relative;
162+
cursor: pointer;
163+
appearance: none;
164+
background: transparent;
165+
padding-right: 20px;
166+
width: 100px;
167+
}
168+
169+
.icon-plus {
170+
font-size: 0.8em;
171+
position: absolute;
172+
right: 0;
173+
}
174+
175+
button.remove {
176+
color: var(--vp-c-brand);
177+
font-family: inherit;
178+
font-size: 14px;
179+
font-weight: 500;
180+
padding: 0.2em;
181+
margin: 0;
182+
background-color: transparent;
183+
border: none;
184+
cursor: pointer;
185+
outline: none;
186+
opacity: 0.6;
187+
transition: all 0.2s;
188+
line-height: 1rem;
189+
}
190+
191+
button.remove .label {
192+
opacity: 0;
193+
transition: all 0.2s;
194+
}
195+
196+
button.remove:hover,
197+
button.remove:active {
198+
opacity: 1;
199+
}
200+
button.remove:hover .label,
201+
button.remove:active .label {
202+
opacity: 1;
203+
}
104204
</style>

docs/repl/components/InputHeader.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,16 @@
1313
<script setup lang="ts">
1414
import examplesById from 'examples.json';
1515
import { useModules } from '../stores/modules';
16+
import { useOptions } from '../stores/options';
1617
1718
const modulesStore = useModules();
19+
const optionsStore = useOptions();
1820
const handleInput = (event: InputEvent) =>
1921
modulesStore.selectExample((event.target as HTMLSelectElement).value);
20-
const startOver = () => modulesStore.set([{ code: '', isEntry: true, name: 'main.js' }], '');
22+
const startOver = () => {
23+
modulesStore.set([{ code: '', isEntry: true, name: 'main.js' }], '');
24+
optionsStore.setAll({});
25+
};
2126
</script>
2227

2328
<style scoped>

docs/repl/components/OutputStatus.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const warnings = computed(() => rollupOutputStore.output.warnings);
4646
word-break: break-word;
4747
line-height: 1;
4848
border-radius: 8px;
49+
transition: all 0.2s;
4950
}
5051
5152
.success {

docs/repl/components/ReplOutput.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ import RollupVersion from './RollupVersion.vue';
2424
2525
const rollupOutputStore = useRollupOutput();
2626
const chunkModules = computed<Module[]>(() =>
27-
(
28-
rollupOutputStore.output.output.filter(
29-
(chunk): chunk is OutputChunk => chunk.type === 'chunk'
30-
) as OutputChunk[]
31-
).map(({ code, fileName }) => ({ code, isEntry: false, name: fileName }))
27+
rollupOutputStore.output.output.map(chunk => ({
28+
code: chunk.code || chunk.source,
29+
isEntry: false,
30+
name: chunk.fileName
31+
}))
3232
);
3333
</script>
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@
22
<div class="select">
33
<button
44
v-for="value in values"
5-
:key="value"
5+
:key="String(value)"
66
:class="{ selected: value === selected }"
77
@click="emit('select', value)"
88
>
9-
{{ value }}
9+
{{ String(value) }}
1010
</button>
1111
</div>
1212
</template>
1313

1414
<script setup lang="ts">
15-
defineProps<{ selected: string; values: string[] }>();
16-
const emit = defineEmits<{ (event: 'select', selected: string): void }>();
15+
defineProps<{ selected: unknown; values: unknown[] }>();
16+
const emit = defineEmits<{ (event: 'select', selected: unknown): void }>();
1717
</script>
1818

1919
<style scoped>

docs/repl/components/StatusMessage.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const isGuideUrl = (url: string) => url && url.startsWith(websitePrefix);
4040

4141
<style scoped>
4242
.message {
43-
line-height: 1;
43+
line-height: 1.2;
4444
}
4545
4646
.frame {

docs/repl/examples/00/example.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
{
2-
"title": "Dynamic imports"
2+
"title": "Tree-shaking",
3+
"options": {
4+
"treeshake": true
5+
}
36
}
Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,4 @@
1-
// DYNAMIC IMPORTS
2-
// Rollup supports automatic chunking and lazy-loading
3-
// via dynamic imports utilizing the import mechanism
4-
// of the host system.
5-
import square from './square.js';
1+
// TREE-SHAKING
2+
import { cube } from './maths.js';
63

7-
// Directly use some math
8-
console.log(square(2));
9-
10-
// Dynamically import the rest
11-
import('./maths.js').then(maths => {
12-
console.log(maths.square(5));
13-
console.log(maths.cube(5));
14-
});
4+
console.log(cube(5)); // 125
Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
1-
import square from './square.js';
1+
// maths.js
22

3-
export { default as square } from './square.js';
3+
// This function isn't used anywhere, so
4+
// Rollup excludes it from the bundle...
5+
export const square = x => x * x;
46

5-
export const cube = x => square(x) * x;
7+
// This function gets included
8+
// rewrite this as `square(x) * x`
9+
// and see what happens!
10+
export const cube = x => x * x * x;
11+
12+
// This "side effect" creates a global
13+
// variable and will not be removed.
14+
window.effect1 = 'created';
15+
16+
const includeEffect = false;
17+
if (includeEffect) {
18+
// On the other hand, this is never
19+
// executed and thus removed.
20+
window.effect1 = 'not created';
21+
}

0 commit comments

Comments
 (0)