Skip to content

Commit

Permalink
Add logs and experimentalLogSideEffects to REPL
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastaegert committed Dec 2, 2023
1 parent fda165d commit 61ef59c
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 55 deletions.
22 changes: 22 additions & 0 deletions LICENSE.md
Expand Up @@ -50,6 +50,28 @@ License: MIT
By: Rich Harris
Repository: rollup/plugins

> The MIT License (MIT)
>
> Copyright (c) 2019 RollupJS Plugin Contributors (https://github.com/rollup/plugins/graphs/contributors)
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.
---------------------------------------

## anymatch
Expand Down
41 changes: 33 additions & 8 deletions docs/repl/components/OutputStatus.vue
@@ -1,19 +1,37 @@
<template>
<div
class="status"
:class="waiting ? 'waiting' : error ? 'error' : warnings.length > 0 ? 'warnings' : 'success'"
:class="
waiting
? 'waiting'
: error
? 'error'
: hasWarnings
? 'warnings'
: logs.length > 0
? 'logs'
: 'success'
"
>
<span v-if="waiting">
<span class="repl-icon-attention"></span>
Loading Rollup...
</span>
<StatusMessage v-else-if="error" :message="error" isError />
<span v-else-if="warnings.length > 0">
<span v-else-if="hasWarnings">
<span class="repl-icon-attention" />
Rollup completed with warnings:
<ul class="warning-list">
<li v-for="(warning, i) in warnings" :key="i" class="warning">
<StatusMessage :message="warning" />
<ul class="log-list">
<li v-for="([, log], i) in logs" :key="i" class="log">
<StatusMessage :message="log" />
</li>
</ul>
</span>
<span v-else-if="logs.length > 0">
Rollup completed with logs:
<ul class="log-list">
<li v-for="([, log], i) in logs" :key="i" class="log">
<StatusMessage :message="log" />
</li>
</ul>
</span>
Expand All @@ -26,6 +44,7 @@

<script setup lang="ts">
import { computed } from 'vue';
import { LOGLEVEL_WARN } from '../../../src/utils/logging';
import { useRollup } from '../stores/rollup';
import { useRollupOutput } from '../stores/rollupOutput';
import StatusMessage from './StatusMessage.vue';
Expand All @@ -35,7 +54,8 @@ const rollupOutputStore = useRollupOutput();
const waiting = computed(() => !(rollupStore.loaded.instance || rollupStore.loaded.error));
const error = computed(() => rollupOutputStore.output.error);
const warnings = computed(() => rollupOutputStore.output.warnings);
const logs = computed(() => rollupOutputStore.output.logs);
const hasWarnings = computed(() => logs.value.some(([level]) => level === LOGLEVEL_WARN));
</script>

<style scoped>
Expand All @@ -62,7 +82,12 @@ const warnings = computed(() => rollupOutputStore.output.warnings);
color: var(--warning-color);
}
.warning {
.logs {
background-color: var(--log-background);
color: var(--log-color);
}
.log {
margin-top: 16px;
}
Expand All @@ -75,7 +100,7 @@ const warnings = computed(() => rollupOutputStore.output.warnings);
font-size: 1em;
}
.warning-list {
.log-list {
list-style-type: none;
padding-inline-start: 0;
margin-top: 10px;
Expand Down
29 changes: 16 additions & 13 deletions docs/repl/components/ReplEditor.vue
Expand Up @@ -5,8 +5,9 @@
<script setup lang="ts">
import type { EditorView } from '@codemirror/view';
import { onMounted, onUnmounted, ref, watch } from 'vue';
import type { RollupLog } from '../../../src/rollup/types';
import type { AddWarnings } from '../helpers/editor';
import type { LogLevel, RollupLog } from '../../../src/rollup/types';
import { LOGLEVEL_ERROR } from '../../../src/utils/logging';
import type { AddLogs } from '../helpers/editor';
import { getFileNameFromMessage } from '../helpers/messages';
import { useRollupOutput } from '../stores/rollupOutput';
Expand All @@ -18,14 +19,14 @@ const properties = defineProps<{
}>();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const emit = defineEmits<{ (event: 'update:code', code: string): void }>();
let addWarningsEffect: AddWarnings;
let addLogsEffect: AddLogs;
let editor: EditorView;
// eslint-disable-next-line vue/no-setup-props-destructure
let previousCode = properties.code;
onMounted(async () => {
const { createEditor, addWarnings } = await import('../helpers/editor');
addWarningsEffect = addWarnings;
const { createEditor, addLogs } = await import('../helpers/editor');
addLogsEffect = addLogs;
editor = createEditor(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
editorContainer.value!,
Expand All @@ -52,24 +53,26 @@ onMounted(async () => {
);
if (properties.moduleName && !properties.readonly) {
const addMarkers = (messages: RollupLog[], type: 'warning' | 'error') => {
const addMarkers = (messages: [LogLevel | 'error', RollupLog][]) => {
const relevantMessages = messages.filter(
(message): message is RollupLog & { pos: number } =>
typeof message.pos === 'number' &&
getFileNameFromMessage(message) === `/${properties.moduleName}`
(message): message is [LogLevel | 'error', RollupLog & { pos: number }] =>
typeof message[1].pos === 'number' &&
getFileNameFromMessage(message[1]) === `/${properties.moduleName}`
);
editor.dispatch({ effects: [addWarningsEffect.of({ messages: relevantMessages, type })] });
if (relevantMessages.length > 0) {
editor.dispatch({ effects: [addLogsEffect.of({ messages: relevantMessages })] });
}
};
const outputStore = useRollupOutput();
watch(
() => outputStore.output,
({ error, warnings }) => {
({ error, logs }) => {
if (error) {
addMarkers([error], 'error');
addMarkers([[LOGLEVEL_ERROR, error]]);
} else {
addMarkers(warnings, 'warning');
addMarkers(logs);
}
}
);
Expand Down
2 changes: 2 additions & 0 deletions docs/repl/components/ReplMain.vue
Expand Up @@ -141,6 +141,8 @@ h2 {
.repl {
height: calc(100% - 3.6em);
--log-color: #181818;
--log-background: #80bdff;
--warning-color: #181818;
--warning-background: #eed245;
--error-color: white;
Expand Down
61 changes: 39 additions & 22 deletions docs/repl/helpers/editor.ts
Expand Up @@ -7,45 +7,44 @@ import { EditorState, StateEffect, StateField } from '@codemirror/state';
import type { ViewUpdate } from '@codemirror/view';
import { Decoration, dropCursor, EditorView, keymap, lineNumbers } from '@codemirror/view';
import { tags } from '@lezer/highlight';
import type { LogLevel } from '../../../src/rollup/types';

export type AddWarnings = StateEffectType<{
messages: { message: string; pos: number }[];
type: 'error' | 'warning';
export type AddLogs = StateEffectType<{
messages: [level: LogLevel | 'error', { message: string; pos: number }][];
}>;

export const addWarnings: AddWarnings = StateEffect.define<{
messages: { message: string; pos: number }[];
type: 'error' | 'warning';
export const addLogs: AddLogs = StateEffect.define<{
messages: [level: LogLevel | 'error', { message: string; pos: number }][];
}>();

const warningsField = StateField.define({
create() {
return Decoration.none;
},
provide: field => EditorView.decorations.from(field),
update(warnings, transaction) {
let hasWarning = false;
update(logs, transaction) {
let hasLog = false;
for (const effect of transaction.effects) {
if (effect.is(addWarnings)) {
if (!hasWarning) {
hasWarning = true;
warnings = Decoration.none;
if (effect.is(addLogs)) {
if (!hasLog) {
hasLog = true;
logs = Decoration.none;
}
warnings = warnings.update({
logs = logs.update({
add: effect.value.messages
.sort((a, b) => a.pos - b.pos)
.map(({ pos, message }) =>
.sort((a, b) => a[1].pos - b[1].pos)
.map(([level, { pos, message }]) =>
Decoration.mark({
attributes: {
class: `cm-rollup-${effect.value.type}`,
class: `cm-rollup-${level}`,
title: message
}
}).range(pos, pos + 1)
)
});
}
}
return warnings;
return logs;
}
});

Expand Down Expand Up @@ -86,15 +85,33 @@ const theme = EditorView.baseTheme({
},
'.cm-rollup-error': {
backgroundColor: 'var(--error-background)',
borderRadius: '2px',
color: 'var(--error-color)',
margin: '-1px',
padding: '1px'
margin: '-2px',
padding: '2px'
},
'.cm-rollup-warning': {
'.cm-rollup-error > span': {
color: 'var(--error-color)'
},
'.cm-rollup-info': {
backgroundColor: 'var(--log-background)',
borderRadius: '2px',
color: 'var(--log-color)',
margin: '-2px',
padding: '2px'
},
'.cm-rollup-info > span': {
color: 'var(--log-color)'
},
'.cm-rollup-warn': {
backgroundColor: 'var(--warning-background)',
borderRadius: '2px',
color: 'var(--warning-color)',
margin: '-1px',
padding: '1px'
margin: '-2px',
padding: '2px'
},
'.cm-rollup-warn > span': {
color: 'var(--warning-color)'
},
'.cm-scroller': {
borderBottomLeftRadius: '8px',
Expand Down
4 changes: 4 additions & 0 deletions docs/repl/stores/options.ts
Expand Up @@ -122,6 +122,9 @@ export const useOptions = defineStore('options2', () => {
defaultValue: 'undefined',
name: 'context'
});
const optionExperimentalLogSideEffects = getBoolean({
name: 'experimentalLogSideEffects'
});
const optionOutputAmdAutoId = getBoolean({
available: () => isAmdFormat.value,
name: 'output.amd.autoId'
Expand Down Expand Up @@ -402,6 +405,7 @@ export const useOptions = defineStore('options2', () => {

const optionList: OptionType[] = [
optionContext,
optionExperimentalLogSideEffects,
optionOutputAmdAutoId,
optionOutputAmdBasePath,
optionOutputAmdDefine,
Expand Down
24 changes: 12 additions & 12 deletions docs/repl/stores/rollupOutput.ts
@@ -1,6 +1,7 @@
import { defineStore } from 'pinia';
import { ref, watch } from 'vue';
import type {
LogLevel,
OutputOptions,
RollupError,
RollupLog,
Expand All @@ -18,8 +19,8 @@ import { useRollup } from './rollup';
interface GeneratedRollupOutput {
error: RollupError | null;
externalImports: string[];
logs: [LogLevel, RollupLog][];
output: RollupOutput['output'] | never[];
warnings: RollupLog[];
}

interface BundleRequest {
Expand Down Expand Up @@ -55,15 +56,14 @@ async function bundle({ rollup: { instance }, modules, options, setOutput }: Bun
modulesById.set(module.name, module);
}

const warnings: RollupLog[] = [];
const logs: [LogLevel, RollupLog][] = [];
const externalImports = new Set<string>();

const rollupOptions: RollupOptions = {
...options,
input: modules.filter((module, index) => index === 0 || module.isEntry).map(({ name }) => name),
onwarn(warning) {
warnings.push(warning);
logWarning(warning);
onLog(level, log) {
logs.push([level, log]);
},
plugins: [
{
Expand Down Expand Up @@ -105,8 +105,8 @@ async function bundle({ rollup: { instance }, modules, options, setOutput }: Bun
setOutput({
error: null,
externalImports: [...externalImports].sort((a, b) => (a < b ? -1 : 1)),
output: generated.output,
warnings
logs,
output: generated.output
});
} catch (error) {
console.log(
Expand All @@ -115,7 +115,7 @@ async function bundle({ rollup: { instance }, modules, options, setOutput }: Bun
error,
JSON.parse(JSON.stringify(error))
);
setOutput({ error: error as Error, externalImports: [], output: [], warnings });
setOutput({ error: error as Error, externalImports: [], logs, output: [] });
logWarning(error as Error);
}
console.groupEnd();
Expand All @@ -128,8 +128,8 @@ export const useRollupOutput = defineStore('rollupOutput', () => {
const output = ref<GeneratedRollupOutput>({
error: null,
externalImports: [],
output: [],
warnings: []
logs: [],
output: []
});
let bundleDebounceTimeout: ReturnType<typeof setTimeout> | undefined;
let nextBundleRequest: BundleRequest | null = null;
Expand All @@ -148,8 +148,8 @@ export const useRollupOutput = defineStore('rollupOutput', () => {
bundleRequest.setOutput({
error: bundleRequest.rollup.error,
externalImports: [],
output: [],
warnings: []
logs: [],
output: []
});
return;
}
Expand Down

0 comments on commit 61ef59c

Please sign in to comment.