Merge branch 'sveltejs:master' into master

pull/6453/head
Jatin Hemnani 5 years ago committed by GitHub
commit f38b1211ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,56 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: 'Bug'
assignees: ''
---
## Is this about svelte@next? This project is currently in a pre-release stage and breaking changes may occur at any time. Please do not post any kind of bug reports or questions on GitHub about it.
**Describe the bug**
A clear and concise description of what the bug is.
**Logs**
Please include browser console and server logs around the time this bug occurred.
**To Reproduce**
To help us help you, if you've found a bug please consider the following:
* If you can demonstrate the bug using https://svelte.dev/repl, please do.
* If that's not possible, we recommend creating a small repo that illustrates the problem.
* Reproductions should be small, self-contained, correct examples http://sscce.org.
Occasionally, this won't be possible, and that's fine we still appreciate you raising the issue. But please understand that Svelte is run by unpaid volunteers in their free time, and issues that follow these instructions will get fixed faster.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Stacktraces**
If you have a stack trace to include, we recommend putting inside a `<details>` block for the sake of the thread's readability:
<details>
<summary>Stack trace</summary>
Stack trace goes here...
</details>
**Information about your Svelte project:**
To make your life easier, just run `npx envinfo --system --npmPackages svelte,rollup,webpack --binaries --browsers` and paste the output here.
- Your browser and the version: (e.x. Chrome 52.1, Firefox 48.0, IE 10)
- Your operating system: (e.x. OS X 10, Ubuntu Linux 19.10, Windows XP, etc)
- Svelte version (Please check you can reproduce the issue with the latest release!)
- Whether your project uses Webpack or Rollup
**Severity**
How severe an issue is this bug to you? Is this annoying, blocking some users, blocking an upgrade or blocking your usage of Svelte entirely?
Note: the more honest and specific you are here the more we will take you seriously.
**Additional context**
Add any other context about the problem here.

@ -0,0 +1,50 @@
name: "\U0001F41E Bug report"
description: Report an issue with Svelte
labels: ["triage: bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: textarea
id: bug-description
attributes:
label: Describe the bug
description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks!
placeholder: Bug description
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Reproduction
description: Please provide a link to a repo or REPL that can reproduce the problem you ran into. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "need reproduction" label. If no reproduction is provided within a reasonable time-frame, the issue will be closed.
placeholder: Reproduction
validations:
required: true
- type: textarea
id: logs
attributes:
label: Logs
description: "Please include browser console and server logs around the time this bug occurred. Optional if provided reproduction. Please try not to insert an image but copy paste the log text."
render: shell
- type: textarea
id: system-info
attributes:
label: System Info
description: Output of `npx envinfo --system --npmPackages svelte,rollup,webpack --binaries --browsers`
render: shell
placeholder: System, Binaries, Browsers
validations:
required: true
- type: dropdown
id: severity
attributes:
label: Severity
description: Select the severity of this issue
options:
- annoyance
- blocking an upgrade
- blocking all usage of svelte
validations:
required: true

@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Discord Chat
url: https://svelte.dev/chat
about: Ask questions and discuss with other Svelte users in real time.

@ -1,28 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: 'New Feature'
assignees: ''
---
<!--
If you'd like to propose an implementation for a large new feature or change then please create an RFC:
https://github.com/sveltejs/rfcs
-->
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. For example: I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**How important is this feature to you?**
Note: the more honest and specific you are here the more we will take you seriously.
**Additional context**
Add any other context or screenshots about the feature request here.

@ -0,0 +1,42 @@
name: "Feature Request"
description: Request a new Svelte feature
labels: [enhancement]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to request this feature! If your feature request is complex or substantial enough to warrant in-depth discussion, maintainers may close the issue and ask you to open an [RFC](https://github.com/sveltejs/rfcs).
- type: textarea
id: problem
attributes:
label: Describe the problem
description: Please provide a clear and concise description the problem this feature would solve. The more information you can provide here, the better.
placeholder: I'm always frustrated when...
validations:
required: true
- type: textarea
id: solution
attributes:
label: Describe the proposed solution
description: Please provide a clear and concise description of what you would like to happen.
placeholder: I would like to see...
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
description: "Please provide a clear and concise description of any alternative solutions or features you've considered."
validations:
required: true
- type: dropdown
id: importance
attributes:
label: Importance
description: How important is this feature to you?
options:
- nice to have
- would make my life easier
- i cannot use svelte without it
validations:
required: true

@ -1,12 +0,0 @@
---
name: Questions and help
about: If you think you need help with something related to Svelte
title: ''
labels: 'Question'
assignees: ''
---
This issue tracker is intended to collect bug reports and feature requests.
For help with installation, information on how features work, or questions about specific features of Svelte, please come and join us in the [Svelte Discord](https://svelte.dev/chat), or ask your question on [Stack Overflow](https://stackoverflow.com/questions/tagged/svelte). Any issues open for help requests will be closed to keep from clogging up the issue tracker.

51
.github/stale.yml vendored

@ -0,0 +1,51 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- popular
- pinned
- security
- "[Status] Maybe Later"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: false
# Label to use when marking as stale
staleLabel: stale-bot
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
pulls:
daysUntilStale: 180
daysUntilClose: 25
markComment: >
This pull request has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
closeComment: >
This pull request has been closed as it was previously marked as stale and saw no subsequent activity.
issues:
daysUntilStale: 90
daysUntilClose: 14
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
closeComment: >
This issue has been closed as it was previously marked as stale and saw no subsequent activity.

@ -277,6 +277,15 @@ To apply styles to a selector globally, use the `:global(...)` modifier.
to this component */
color: goldenrod;
}
p:global(.red) {
/* this will apply to all <p> elements belonging to this
component with a class of red, even if class="red" does
not initially appear in the markup, and is instead
added at runtime. This is useful when the class
of the element is dynamically applied, for instance
when updating the element's classList property directly. */
}
</style>
```
@ -291,3 +300,23 @@ The `-global-` part will be removed when compiled, and the keyframe then be refe
@keyframes -global-my-animation-name {...}
</style>
```
---
There should only be 1 top-level `<style>` tag per component.
However, it is possible to have `<style>` tag nested inside other elements or logic blocks.
In that case, the `<style>` tag will be inserted as-is into the DOM, no scoping or processing will be done on the `<style>` tag.
```html
<div>
<style>
/* this style tag will be inserted as-is */
div {
/* this will apply to all `<div>` elements in the DOM */
color: red;
}
</style>
</div>
```

@ -0,0 +1,255 @@
---
title: Accessibility warnings
---
Accessibility (shortened to a11y) isn't always easy to get right, but Svelte will help by warning you if you write inaccessible markup.
Here is a list of accessibility checks Svelte will do it for you.
---
### `a11y-accesskey`
Enforce no `accesskey` on element. Access keys are HTML attributes that allow web developers to assign keyboard shortcuts to elements. Inconsistencies between keyboard shortcuts and keyboard commands used by screenreader and keyboard only users create accessibility complications so to avoid complications, access keys should not be used.
```sv
<!-- A11y: Avoid using accesskey -->
<div accessKey='z'></div>
```
---
### `a11y-aria-attributes`
Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for example `meta`, `html`, `script`, `style`. This rule enforces that these DOM elements do not contain the `aria-*` props.
```sv
<!-- A11y: <meta> should not have aria-* attributes -->
<meta aria-hidden="false">
```
---
### `a11y-autofocus`
Enforce that `autofocus` is not used on elements. Autofocusing elements can cause usability issues for sighted and non-sighted users, alike.
```sv
<!-- A11y: Avoid using autofocus -->
<input autofocus>
```
---
### `a11y-distracting-elements`
Enforces that no distracting elements are used. Elements that can be visually distracting can cause accessibility issues with visually impaired users. Such elements are most likely deprecated, and should be avoided.
The following elements are visually distracting: `<marquee>` and `<blink>`.
```sv
<!-- A11y: Avoid <marquee> elements -->
<marquee />
```
---
### `a11y-hidden`
Certain DOM elements are useful for screen readers navigation and should not be hidden.
```sv
<!-- A11y: <h2> element should not be hidden -->
<h2 aria-hidden>invisible header</h2>
```
---
### `a11y-img-redundant-alt`
Enforce img alt attribute does not contain the word image, picture, or photo. Screenreaders already announce `img` elements as an image. There is no need to use words such as _image_, _photo_, and/or _picture_.
```sv
<img src="foo" alt="Foo eating a sandwich." />
<!-- aria-hidden, won't be announced by screen reader -->
<img src="bar" aria-hidden alt="Picture of me taking a photo of an image" />
<!-- A11y: Screenreaders already announce <img> elements as an image. -->
<img src="foo" alt="Photo of foo being weird." />
<!-- A11y: Screenreaders already announce <img> elements as an image. -->
<img src="bar" alt="Image of me at a bar!" />
<!-- A11y: Screenreaders already announce <img> elements as an image. -->
<img src="foo" alt="Picture of baz fixing a bug." />
```
---
### `a11y-invalid-attribute`
Enforce that accessibility attribute should have valid value
```sv
<!-- A11y: '' is not a valid href attribute -->
<a href=''>invalid</a>
```
---
### `a11y-label-has-associated-control`
Enforce that a label tag has a text label and an associated control.
There are two supported ways to associate a label with a control:
- Wrapping a control in a label tag.
- Adding `for` to a label and assigning it a DOM ID string that indicates an input on the page.
```sv
<label for="id">B</label>
<label>C <input type="text" /></label>
<!-- A11y: A form label must be associated with a control. -->
<label>A</label>
```
---
### `a11y-media-has-caption`
Providing captions for media is essential for deaf users to follow along. Captions should be a transcription or translation of the dialogue, sound effects, relevant musical cues, and other relevant audio information. Not only is this important for accessibility, but can also be useful for all users in the case that the media is unavailable (similar to `alt` text on an image when an image is unable to load).
The captions should contain all important and relevant information to understand the corresponding media. This may mean that the captions are not a 1:1 mapping of the dialogue in the media content. However, captions are not necessary for video components with the `muted` attribute.
```sv
<video><track kind="captions"/></video>
<audio muted></audio>
<!-- A11y: Media elements must have a <track kind=\"captions\"> -->
<video></video>
<!-- A11y: Media elements must have a <track kind=\"captions\"> -->
<video><track /></video>
```
---
### `a11y-misplaced-role`
Certain reserved DOM elements do not support ARIA roles, states and properties. This is often because they are not visible, for example `meta`, `html`, `script`, `style`. This rule enforces that these DOM elements do not contain the `role` props.
```sv
<!-- A11y: <meta> should not have role attribute -->
<meta role="tooltip">
```
---
### `a11y-misplaced-scope`
The scope scope should be used only on `<th>` elements.
```sv
<!-- A11y: The scope attribute should only be used with <th> elements -->
<div scope/>
```
---
### `a11y-missing-attribute`
Enforce that element should have required accessibility attribute
```sv
<!-- A11y: <input type=\"image\"> element should have an alt, aria-label or aria-labelledby attribute -->
<input type="image">
<!-- A11y: <html> element should have a lang attribute -->
<html></html>
<!-- A11y: <a> element should have an href attribute -->
<a>text</a>
```
---
### `a11y-missing-content`
Enforce that heading elements (`h1`, `h2`, etc.) and anchors have content and that the content is accessible to screen readers
```sv
<!-- A11y: <a> element should have child content -->
<a href='/foo'></a>
<!-- A11y: <h1> element should have child content -->
<h1></h1>
```
---
### `a11y-no-onchange`
Enforce usage of `on:blur` over/in parallel with `on:change` on select menu elements for accessibility. `on:blur` should be used instead of `on:change`, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users. `on:blur` is a more declarative action by the user: for instance in a dropdown, using the arrow keys to toggle between options will trigger the `on:change` event in some browsers. Regardless, when a change of context results from an `on:blur` event or an `on:change` event, the user should be notified of the change unless it occurs below the currently focused element.
```sv
<select on:change={e => {}} on:blur={e => {}}>
<option>foo</option>
<option>bar</option>
</select>
<!-- A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users. -->
<select on:change={e => {}}>
<option>foo</option>
<option>bar</option>
</select>
```
---
### `a11y-positive-tabindex`
Avoid positive `tabIndex` property values to synchronize the flow of the page with keyboard tab order.
```sv
<!-- A11y: avoid tabindex values above zero -->
<div tabindex='1'/>
```
---
### `a11y-structure`
Warns when accessibility related elements are not in a right structure.
```sv
<!-- A11y: <figcaption> must be an immediate child of <figure> -->
<div>
<figcaption>Image caption</figcaption>
</div>
```
---
### `a11y-unknown-aria-attribute`
Invalid aria attribute. Enforces valid `aria-*` property based on [WAI-ARIA States and Properties spec](https://www.w3.org/WAI/PF/aria-1.1/states_and_properties)
```sv
<!-- A11y: Unknown aria attribute 'aria-labeledby' (did you mean 'labelledby'?) -->
<input type="image" aria-labeledby="foo">
```
---
### `a11y-unknown-role`
Elements with ARIA roles must use a valid, non-abstract ARIA role. A reference to role definitions can be found at [WAI-ARIA](https://www.w3.org/TR/wai-aria/#role_definitions) site.
```sv
<!-- A11y: Unknown role 'toooltip' (did you mean 'tooltip'?) -->
<div role="toooltip"></div>
```

@ -1,11 +1,11 @@
<script>
let count = 0;
function handleClick() {
function incrementCount() {
count += 1;
}
</script>
<button on:click={handleClick}>
<button on:click={incrementCount}>
Clicked {count} {count === 1 ? 'time' : 'times'}
</button>
</button>

@ -7,15 +7,15 @@ At the heart of Svelte is a powerful system of *reactivity* for keeping the DOM
To demonstrate it, we first need to wire up an event handler. Replace line 9 with this:
```html
<button on:click={handleClick}>
<button on:click={incrementCount}>
```
Inside the `handleClick` function, all we need to do is change the value of `count`:
Inside the `incrementCount` function, all we need to do is change the value of `count`:
```js
function handleClick() {
function incrementCount() {
count += 1;
}
```
Svelte 'instruments' this assignment with some code that tells it the DOM will need to be updated.
Svelte 'instruments' this assignment with some code that tells it the DOM will need to be updated.

@ -11,34 +11,34 @@
<h2>Size</h2>
<label>
<input type=radio group={scoops} value={1}>
<input type=radio group={scoops} name="scoops" value={1}>
One scoop
</label>
<label>
<input type=radio group={scoops} value={2}>
<input type=radio group={scoops} name="scoops" value={2}>
Two scoops
</label>
<label>
<input type=radio group={scoops} value={3}>
<input type=radio group={scoops} name="scoops" value={3}>
Three scoops
</label>
<h2>Flavours</h2>
<label>
<input type=checkbox group={flavours} value="Cookies and cream">
<input type=checkbox group={flavours} name="flavours" value="Cookies and cream">
Cookies and cream
</label>
<label>
<input type=checkbox group={flavours} value="Mint choc chip">
<input type=checkbox group={flavours} name="flavours" value="Mint choc chip">
Mint choc chip
</label>
<label>
<input type=checkbox group={flavours} value="Raspberry ripple">
<input type=checkbox group={flavours} name="flavours" value="Raspberry ripple">
Raspberry ripple
</label>

@ -17,17 +17,17 @@
<h2>Size</h2>
<label>
<input type=radio bind:group={scoops} value={1}>
<input type=radio bind:group={scoops} name="scoops" value={1}>
One scoop
</label>
<label>
<input type=radio bind:group={scoops} value={2}>
<input type=radio bind:group={scoops} name="scoops" value={2}>
Two scoops
</label>
<label>
<input type=radio bind:group={scoops} value={3}>
<input type=radio bind:group={scoops} name="scoops" value={3}>
Three scoops
</label>
@ -35,7 +35,7 @@
{#each menu as flavour}
<label>
<input type=checkbox bind:group={flavours} value={flavour}>
<input type=checkbox bind:group={flavours} name="flavours" value={flavour}>
{flavour}
</label>
{/each}

@ -7,7 +7,7 @@ If you have multiple inputs relating to the same value, you can use `bind:group`
Add `bind:group` to each input:
```html
<input type=radio bind:group={scoops} value={1}>
<input type=radio bind:group={scoops} name="scoops" value={1}>
```
In this case, we could make the code simpler by moving the checkbox inputs into an `each` block. First, add a `menu` variable to the `<script>` block...
@ -27,7 +27,7 @@ let menu = [
{#each menu as flavour}
<label>
<input type=checkbox bind:group={flavours} value={flavour}>
<input type=checkbox bind:group={flavours} name="flavours" value={flavour}>
{flavour}
</label>
{/each}

@ -3,10 +3,10 @@
let value = `Some words are *italic*, some are **bold**`;
</script>
<textarea value={value}></textarea>
{@html marked(value)}
<textarea value={value}></textarea>
<style>
textarea { width: 100%; height: 200px; }
</style>
</style>

@ -3,10 +3,10 @@
let value = `Some words are *italic*, some are **bold**`;
</script>
<textarea bind:value></textarea>
{@html marked(value)}
<textarea bind:value></textarea>
<style>
textarea { width: 100%; height: 200px; }
</style>
</style>

@ -0,0 +1,5 @@
<script>
import InputField from './InputField.svelte';
</script>
<InputField />

@ -0,0 +1,9 @@
<script>
let input;
export function focus() {
input.focus();
}
</script>
<input bind:this={input} />

@ -0,0 +1,9 @@
<script>
import InputField from './InputField.svelte';
let field;
</script>
<InputField bind:this={field}/>
<button on:click={() => field.focus()}>Focus field</button>

@ -0,0 +1,9 @@
<script>
let input;
export function focus() {
input.focus();
}
</script>
<input bind:this={input} />

@ -0,0 +1,19 @@
---
title: Binding to component instances
---
Just as you can bind to DOM elements, you can bind to component instances themselves. For example, we can bind the instance of `<InputField>` to a prop named `field` in the same way we did when binding DOM Elements
```html
<InputField bind:this={field} />
```
Now we can programmatically interact with this component using `field`.
```html
<button on:click="{() => field.focus()}">
Focus field
</button>
```
> Note that we can't do `{field.focus}` since field is undefined when the button is first rendered and throws an error.

@ -1,10 +1,20 @@
<script>
import { onDestroy } from 'svelte';
import Timer from './Timer.svelte';
let open = false;
let seconds = 0;
const toggle = () => (open = !open);
const handleTick = () => (seconds += 1);
</script>
<p>
The page has been open for
{seconds} {seconds === 1 ? 'second' : 'seconds'}
</p>
<div>
<button on:click={toggle}>{open ? 'Close' : 'Open'} Timer</button>
<p>
The Timer component has been open for
{seconds} {seconds === 1 ? 'second' : 'seconds'}
</p>
{#if open}
<Timer callback={handleTick} />
{/if}
</div>

@ -0,0 +1,20 @@
<script>
import { onInterval } from './utils.js';
export let callback;
export let interval = 1000;
onInterval(callback, interval);
</script>
<p>
This component executes a callback every
{interval} millisecond{interval === 1 ? '' : 's'}
</p>
<style>
p {
border: 1px solid blue;
padding: 5px;
}
</style>

@ -1,5 +1,9 @@
import { onDestroy } from 'svelte';
export function onInterval(callback, milliseconds) {
// implementation goes here
const interval = setInterval(callback, milliseconds);
onDestroy(() => {
// Fix the memory leak here
});
}

@ -1,11 +1,20 @@
<script>
import { onInterval } from './utils.js';
import Timer from './Timer.svelte';
let open = true;
let seconds = 0;
onInterval(() => seconds += 1, 1000);
const toggle = () => (open = !open);
const handleTick = () => (seconds += 1);
</script>
<p>
The page has been open for
{seconds} {seconds === 1 ? 'second' : 'seconds'}
</p>
<div>
<button on:click={toggle}>{open ? 'Close' : 'Open'} Timer</button>
<p>
The Timer component has been open for
{seconds} {seconds === 1 ? 'second' : 'seconds'}
</p>
{#if open}
<Timer callback={handleTick} />
{/if}
</div>

@ -0,0 +1,20 @@
<script>
import { onInterval } from './utils.js';
export let callback;
export let interval = 1000;
onInterval(callback, interval);
</script>
<p>
This component executes a callback every
{interval} millisecond{interval === 1 ? '' : 's'}
</p>
<style>
p {
border: 1px solid blue;
padding: 5px;
}
</style>

@ -10,8 +10,8 @@ For example, we can add a `setInterval` function when our component initialises,
<script>
import { onDestroy } from 'svelte';
let seconds = 0;
const interval = setInterval(() => seconds += 1, 1000);
let counter = 0;
const interval = setInterval(() => counter += 1, 1000);
onDestroy(() => clearInterval(interval));
</script>
@ -37,7 +37,9 @@ export function onInterval(callback, milliseconds) {
<script>
import { onInterval } from './utils.js';
let seconds = 0;
onInterval(() => seconds += 1, 1000);
let counter = 0;
onInterval(() => counter += 1, 1000);
</script>
```
```
Open and close the timer a few times and make sure the counter keeps ticking and the CPU load increases. This is due to a memory leak as the previous timers are not deleted. Don't forget to refresh the page before solving the example.

@ -19,7 +19,7 @@ setContext(key, {
});
```
The context object can be anything you like. Like [lifecycle functions](tutorial/onmount), `setContext` and `getContext` must be called during component initialisation; since `map` isn't created until the component has mounted, our context object contains a `getMap` function rather than `map` itself.
The context object can be anything you like. Like [lifecycle functions](tutorial/onmount), `setContext` and `getContext` must be called during component initialisation. Calling it afterwards - for example inside `onMount` - will throw an error. In this example, since `map` isn't created until the component has mounted, our context object contains a `getMap` function rather than `map` itself.
On the other side of the equation, in `MapMarker.svelte`, we can now get a reference to the Mapbox instance:

@ -3,39 +3,35 @@
let root = [
{
type: 'folder',
name: 'Important work stuff',
files: [
{ type: 'file', name: 'quarterly-results.xlsx' }
{ name: 'quarterly-results.xlsx' }
]
},
{
type: 'folder',
name: 'Animal GIFs',
files: [
{
type: 'folder',
name: 'Dogs',
files: [
{ type: 'file', name: 'treadmill.gif' },
{ type: 'file', name: 'rope-jumping.gif' }
{ name: 'treadmill.gif' },
{ name: 'rope-jumping.gif' }
]
},
{
type: 'folder',
name: 'Goats',
files: [
{ type: 'file', name: 'parkour.gif' },
{ type: 'file', name: 'rampage.gif' }
{ name: 'parkour.gif' },
{ name: 'rampage.gif' }
]
},
{ type: 'file', name: 'cat-roomba.gif' },
{ type: 'file', name: 'duck-shuffle.gif' },
{ type: 'file', name: 'monkey-on-a-pig.gif' }
{ name: 'cat-roomba.gif' },
{ name: 'duck-shuffle.gif' },
{ name: 'monkey-on-a-pig.gif' }
]
},
{ type: 'file', name: 'TODO.md' }
{ name: 'TODO.md' }
];
</script>
<Folder name="Home" files={root} expanded/>
<Folder name="Home" files={root} expanded/>

@ -16,7 +16,7 @@
<ul>
{#each files as file}
<li>
{#if file.type === 'folder'}
{#if file.files}
<!-- show folder -->
{:else}
<File {...file}/>
@ -49,4 +49,4 @@
li {
padding: 0.2em 0;
}
</style>
</style>

@ -3,39 +3,35 @@
let root = [
{
type: 'folder',
name: 'Important work stuff',
files: [
{ type: 'file', name: 'quarterly-results.xlsx' }
{ name: 'quarterly-results.xlsx' }
]
},
{
type: 'folder',
name: 'Animal GIFs',
files: [
{
type: 'folder',
name: 'Dogs',
files: [
{ type: 'file', name: 'treadmill.gif' },
{ type: 'file', name: 'rope-jumping.gif' }
{ name: 'treadmill.gif' },
{ name: 'rope-jumping.gif' }
]
},
{
type: 'folder',
name: 'Goats',
files: [
{ type: 'file', name: 'parkour.gif' },
{ type: 'file', name: 'rampage.gif' }
{ name: 'parkour.gif' },
{ name: 'rampage.gif' }
]
},
{ type: 'file', name: 'cat-roomba.gif' },
{ type: 'file', name: 'duck-shuffle.gif' },
{ type: 'file', name: 'monkey-on-a-pig.gif' }
{ name: 'cat-roomba.gif' },
{ name: 'duck-shuffle.gif' },
{ name: 'monkey-on-a-pig.gif' }
]
},
{ type: 'file', name: 'TODO.md' }
{ name: 'TODO.md' }
];
</script>
<Folder name="Home" files={root} expanded/>
<Folder name="Home" files={root} expanded/>

@ -16,7 +16,7 @@
<ul>
{#each files as file}
<li>
{#if file.type === 'folder'}
{#if file.files}
<svelte:self {...file}/>
{:else}
<File {...file}/>
@ -49,4 +49,4 @@
li {
padding: 0.2em 0;
}
</style>
</style>

@ -7,7 +7,7 @@ Svelte provides a variety of built-in elements. The first, `<svelte:self>`, allo
It's useful for things like this folder tree view, where folders can contain *other* folders. In `Folder.svelte` we want to be able to do this...
```html
{#if file.type === 'folder'}
{#if file.files}
<Folder {...file}/>
{:else}
<File {...file}/>
@ -17,7 +17,7 @@ It's useful for things like this folder tree view, where folders can contain *ot
...but that's impossible, because a module can't import itself. Instead, we use `<svelte:self>`:
```html
{#if file.type === 'folder'}
{#if file.files}
<svelte:self {...file}/>
{:else}
<File {...file}/>

@ -4,7 +4,11 @@ import sirv from 'sirv';
import * as sapper from '@sapper/server';
import { sanitize_user, authenticate } from './utils/auth';
const { PORT = 3000 } = process.env;
if (!process.env.PORT) {
process.env.PORT = 3000;
}
const { PORT } = process.env;
const app = polka({
onError: (err, req, res) => {

@ -2,7 +2,7 @@ import { custom_event, append, insert, detach, listen, attr } from './dom';
import { SvelteComponent } from './Component';
export function dispatch_dev<T=any>(type: string, detail?: T) {
document.dispatchEvent(custom_event(type, { version: '__VERSION__', ...detail }));
document.dispatchEvent(custom_event(type, { version: '__VERSION__', ...detail }, true));
}
export function append_dev(target: Node, node: Node) {

@ -521,9 +521,9 @@ export function toggle_class(element, name, toggle) {
element.classList[toggle ? 'add' : 'remove'](name);
}
export function custom_event<T=any>(type: string, detail?: T) {
export function custom_event<T=any>(type: string, detail?: T, bubbles: boolean = false) {
const e: CustomEvent<T> = document.createEvent('CustomEvent');
e.initCustomEvent(type, false, false, detail);
e.initCustomEvent(type, bubbles, false, detail);
return e;
}

Loading…
Cancel
Save