examples/composition/todomvc.html HTML 242 lines View on github.com → Search inside
1<script src="../../dist/vue.min.js"></script>2<link3  rel="stylesheet"4  href="../../node_modules/todomvc-app-css/index.css"5/>67<div id="app">8  <section class="todoapp">9    <header class="header">10      <h1>todos</h1>11      <input12        class="new-todo"13        autofocus14        autocomplete="off"15        placeholder="What needs to be done?"16        v-model="state.newTodo"17        @keyup.enter="addTodo"18      />19    </header>20    <section class="main" v-show="state.todos.length">21      <input22        id="toggle-all"23        class="toggle-all"24        type="checkbox"25        v-model="state.allDone"26      />27      <label for="toggle-all">Mark all as complete</label>28      <ul class="todo-list">29        <li30          v-for="todo in state.filteredTodos"31          class="todo"32          :key="todo.id"33          :class="{ completed: todo.completed, editing: todo === state.editedTodo }"34        >35          <div class="view">36            <input class="toggle" type="checkbox" v-model="todo.completed" />37            <label @dblclick="editTodo(todo)">{{ todo.title }}</label>38            <button class="destroy" @click="removeTodo(todo)"></button>39          </div>40          <input41            class="edit"42            type="text"43            v-model="todo.title"44            v-todo-focus="todo === state.editedTodo"45            @blur="doneEdit(todo)"46            @keyup.enter="doneEdit(todo)"47            @keyup.escape="cancelEdit(todo)"48          />49        </li>50      </ul>51    </section>52    <footer class="footer" v-show="state.todos.length">53      <span class="todo-count">54        <strong>{{ state.remaining }}</strong>55        <span>{{ state.remainingText }}</span>56      </span>57      <ul class="filters">58        <li>59          <a href="#/all" :class="{ selected: state.visibility === 'all' }"60            >All</a61          >62        </li>63        <li>64          <a65            href="#/active"66            :class="{ selected: state.visibility === 'active' }"67            >Active</a68          >69        </li>70        <li>71          <a72            href="#/completed"73            :class="{ selected: state.visibility === 'completed' }"74            >Completed</a75          >76        </li>77      </ul>7879      <button80        class="clear-completed"81        @click="removeCompleted"82        v-show="state.todos.length > state.remaining"83      >84        Clear completed85      </button>86    </footer>87  </section>88</div>8990<script>91  const { reactive, computed, watchEffect, onMounted, onUnmounted } = Vue9293  const STORAGE_KEY = 'todos-vuejs-3.x-composition'94  const todoStorage = {95    fetch() {96      const todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')97      todos.forEach((todo, index) => {98        todo.id = index99      })100      todoStorage.uid = todos.length101      return todos102    },103    save(todos) {104      localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))105    }106  }107108  const filters = {109    all(todos) {110      return todos111    },112    active(todos) {113      return todos.filter(todo => {114        return !todo.completed115      })116    },117    completed(todos) {118      return todos.filter(function (todo) {119        return todo.completed120      })121    }122  }123124  function pluralize(n) {125    return n === 1 ? 'item' : 'items'126  }127128  new Vue({129    setup() {130      const state = reactive({131        todos: todoStorage.fetch(),132        editedTodo: null,133        newTodo: '',134        beforeEditCache: '',135        visibility: 'all',136        remaining: computed(() => {137          return filters.active(state.todos).length138        }),139        remainingText: computed(() => {140          return ` ${pluralize(state.remaining)} left`141        }),142        filteredTodos: computed(() => {143          return filters[state.visibility](state.todos)144        }),145        allDone: computed({146          get: function () {147            return state.remaining === 0148          },149          set: function (value) {150            state.todos.forEach(todo => {151              todo.completed = value152            })153          }154        })155      })156157      watchEffect(() => {158        todoStorage.save(state.todos)159      })160161      onMounted(() => {162        window.addEventListener('hashchange', onHashChange)163        onHashChange()164      })165166      onUnmounted(() => {167        window.removeEventListener('hashchange', onHashChange)168      })169170      function onHashChange() {171        const visibility = window.location.hash.replace(/#\/?/, '')172        if (filters[visibility]) {173          state.visibility = visibility174        } else {175          window.location.hash = ''176          state.visibility = 'all'177        }178      }179180      function addTodo() {181        const value = state.newTodo && state.newTodo.trim()182        if (!value) {183          return184        }185        state.todos.push({186          id: todoStorage.uid++,187          title: value,188          completed: false189        })190        state.newTodo = ''191      }192193      function removeTodo(todo) {194        state.todos.splice(state.todos.indexOf(todo), 1)195      }196197      function editTodo(todo) {198        state.beforeEditCache = todo.title199        state.editedTodo = todo200      }201202      function doneEdit(todo) {203        if (!state.editedTodo) {204          return205        }206        state.editedTodo = null207        todo.title = todo.title.trim()208        if (!todo.title) {209          removeTodo(todo)210        }211      }212213      function cancelEdit(todo) {214        state.editedTodo = null215        todo.title = state.beforeEditCache216      }217218      function removeCompleted() {219        state.todos = filters.active(state.todos)220      }221222      return {223        state,224        addTodo,225        removeTodo,226        editTodo,227        doneEdit,228        cancelEdit,229        removeCompleted230      }231    },232233    directives: {234      'todo-focus': (el, { value }) => {235        if (value) {236          el.focus()237        }238      }239    }240  }).$mount('#app')241</script>

Security findings 1

Inline JavaScript detected; move to external files with CSP for security and maintainability
security inline-script
<script>

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.