<commit_before>var per = require('per');
var characters = require('./characters');
var split = require('./split');
var wrap = require('./wrap');
var word = require('./word');
var node = require('./node');
var runs = require('./runs');
var measure = require('./measure');
var range = require('./range');
var util = require('./util');

var wordCharRuns = function(positionedWord) {
    return positionedWord.children().map(function(char) {
        return char.part.run;
    });
};

var makeEditCommand = function(doc, start, count, words) {
    var selStart = doc.selection.start, selEnd = doc.selection.end;
    return function(redo) {
        var oldWords = Array.prototype.splice.apply(doc.words, [start, count].concat(words));
        var stack = doc[redo ? 'redo' : 'undo'];
        while (stack.length > 50) {
            stack.shift();
        }
        stack.push(makeEditCommand(doc, start, words.length, oldWords));
        doc.layout();
        doc.contentChanged.fire();
        doc.select(selStart, selEnd);
    };
};

var prototype = node.derive({
    load: function(runs) {
        var self = this;
        this.undo = [];
        this.redo = [];
        this.words = per(characters(runs)).per(split()).map(function(w) {
            return word(w, self.inlines);
        }).all();
        this.layout();
        this.contentChanged.fire();
        this.select(0, 0);
    },
    layout: function() {
        this.lines = per(this.words).per(wrap(this._width, this)).all();
        var lastLine = this.last();
        this.height = !lastLine ? 0 : lastLine.baseline + lastLine.descent;
    },
    plainText: function() {
        return this.words.map(function(word) {
            return word.plainText;
        }).join('');
    },
    runs: function(emit) {
        this.lines.forEach(function(line) {
            line.runs(emit);
        });
    },
    range: function(start, end) {
        return range(this, start, end);
    },
    documentRange: function() {
        return this.range(0, this.length());
    },
    selectedRange: function() {
        return this.range(this.selection.start, this.selection.end);
    },
    save: function() {
        return this.documentRange().save();
    },
    paragraphRange: function(start, end) {
        // find the character after the nearest newline before start
        var ch = this.characterByOrdinal(start), word;
        if (ch) {
            word = ch.word;
            while (word.ordinal > 0) {
                var prev = word.previous();
                if (prev.word.isNewLine()) {
                    break;
                }
                word = prev;
            }
            start = word.ordinal;
        }
        // find the nearest newline after end
        ch = this.characterByOrdinal(end);
        if (ch) {
            word = ch.word;
            while (!word.word.isNewLine()) {
                word = word.next();
            }
            end = word.ordinal;
        }
        return this.range(start, end);
    },
    insert: function(text) {
        this.select(this.selection.end + this.selectedRange().setText(text));
    },
    modifyInsertFormatting: function(attribute, value) {
        this.nextInsertFormatting[attribute] = value;
        this.notifySelectionChanged();
    },
    applyInsertFormatting: function(text) {
        var formatting = this.nextInsertFormatting;
        var insertFormattingProperties = Object.keys(formatting);
        if (insertFormattingProperties.length) {
            text.forEach(function(run) {
                insertFormattingProperties.forEach(function(property) {
                    run[property] = formatting[property];
                });
            });
        }
    },
    splice: function(start, end, text) {
        var startChar = this.characterByOrdinal(start),
            endChar = start === end ? startChar : this.characterByOrdinal(end);
        if (typeof text === 'string') {
            text = [
                Object.create((startChar.previous() || startChar).part.run, {
                    text: { value: text }
                })
            ];
        } else if (!Array.isArray(text)) {
            text = [{ text: text }];
        }

        this.applyInsertFormatting(text);

        var startWord = startChar.parent();
        var startWordIndex = this.words.indexOf(startWord.word);
        var startWordChars = wordCharRuns(startWord);

        var endWord = endChar.parent();
        var endWordIndex = endWord === startWord ? startWordIndex : this.words.indexOf(endWord.word);
        var endWordChars = endWord === startWord ? startWordChars : wordCharRuns(endWord);

        var prefix;
        if (startChar.ordinal === startWord.ordinal) {
            var previousWord = startWord.previous();
            if (previousWord) {
                prefix = wordCharRuns(previousWord);
                startWordIndex--;
            } else {
                prefix = [];
            }
        } else {
            prefix = startWordChars.slice(0, startChar.ordinal - startWord.ordinal);
        }

        var suffix;
        if (endChar.ordinal === endWord.ordinal) {
            if (endChar.ordinal === this.length()) {
                suffix = [];
                endWordIndex--;
            } else {
                suffix = wordCharRuns(endWord);
            }
        } else {
            suffix = endWordChars.slice(endChar.ordinal - endWord.ordinal);
        }

        var self = this;
        var oldLength = this.length();
        var newRuns = per(prefix).concat(text).concat(suffix).per(runs.consolidate()).all();
        var newWords = per(characters(newRuns))
            .per(split())
            .truthy()
            .map(function(w) {
                return word(w, self.inlines);
            })
            .all();

        this.redo.length = 0;
        makeEditCommand(this, startWordIndex, (endWordIndex - startWordIndex) + 1, newWords)();
        return this.length() - oldLength;
    },
    width: function(width) {
        if (arguments.length === 0) {
            return this._width;
        }
        this._width = width;
        this.layout();
    },
    first: function() {
        return this.lines[0];
    },
    last: function() {
        return this.lines[this.lines.length - 1];
    },
    children: function() {
        return this.lines;
    },
    length: function() {
        var lastLine = this.last();
        return !lastLine ? 0 : lastLine.last().last().ordinal;
    },
    draw: function(ctx, bottom) {
        bottom = bottom || Number.MAX_VALUE;
        measure.prepareContext(ctx);
        this.lines.some(function(line) {
            if (line.baseline - line.ascent > bottom) {
                return true;
            }
            line.draw(ctx);
        });
    },
    toggleCaret: function() {
        var old = this.caretVisible;
        if (this.selection.start === this.selection.end) {
            if (this.selectionJustChanged) {
                this.selectionJustChanged = false;
            } else {
                this.caretVisible = !this.caretVisible;
            }
        }
        return this.caretVisible !== old;
    },
    drawSelection: function(ctx, hasFocus) {
        if (this.selection.end === this.selection.start) {
            if (this.selectionJustChanged || hasFocus && this.caretVisible) {
                var char = this.characterByOrdinal(this.selection.start);
                if (char) {
                    var charBounds = char.bounds(),
                        lineBounds = char.word.line.bounds(true);
                    ctx.beginPath();
                    ctx.moveTo(charBounds.l, lineBounds.t);
                    ctx.lineTo(charBounds.l, lineBounds.t + lineBounds.h);
                    ctx.stroke();
                }
            }
        } else {
            ctx.save();
            ctx.fillStyle = hasFocus ? 'rgba(0, 100, 200, 0.3)' : 'rgba(160, 160, 160, 0.3)';
            this.selectedRange().parts(function(part) {
                var b = part.bounds(true);
                ctx.fillRect(b.l, b.t, b.w, b.h);
            });
            ctx.restore();
        }
    },
    notifySelectionChanged: function() {
        // When firing selectionChanged, we pass a function can be used
        // to obtain the formatting, as this highly likely to be needed
        var cachedFormatting = null;
        var self = this;
        var getFormatting = function() {
            if (!cachedFormatting) {
                cachedFormatting = self.selectedRange().getFormatting();
            }
            return cachedFormatting;
        };
        this.selectionChanged.fire(getFormatting);
    },
    select: function(ordinal, ordinalEnd, forceEvent) {
        var oldStart = this.selection.start, oldEnd = this.selection.end;
        this.selection.start = Math.max(0, ordinal);
        this.selection.end = Math.min(
            typeof ordinalEnd === 'number' ? ordinalEnd : this.selection.start,
            this.length()
        );
        this.selectionJustChanged = true;
        this.caretVisible = true;
        this.nextInsertFormatting = {};
        if (this.selection.start != oldStart || this.selection.end != oldEnd) {
            this.notifySelectionChanged();
        }
    },
    characterByOrdinal: function(index) {
        var result = null;
        if (this.lines.some(function(line) {
            result = line.characterByOrdinal(index);
            if (result) {
                return true;
            }
        })) {
            return result;
        }
    },
    characterByCoordinate: function(x, y, right) {
        var found, nextLine = false;
        this.children().some(function(line) {
            if (nextLine) {
                found = line.characterByOrdinal(line.ordinal);
                return true;
            }
            var bounds = line.bounds();
            if (bounds.contains(x, y)) {
                line.children().some(function(pword) {
                    bounds = pword.bounds();
                    if (bounds.contains(x, y)) {
                        pword.children().some(function(pchar) {
                            bounds = pchar.bounds();
                            if (bounds.contains(x, y)) {
                                if (!pchar.word.word.isNewLine() && (x - bounds.l) > (bounds.w / 2)) {
                                    found = pchar.next();
                                } else {
                                    found = pchar;
                                }
                                return true;
                            }
                        });
                        return true;
                    }
                });
                if (!found) {
                    if (right) {
                        nextLine = true;
                    } else {
                        found = line.last().last();
                    }
                } else {
                    return true;
                }
            }
        });
        if (!found) {
            found = this.last().last().last();
        }
        return found;
    },
    performUndo: function(redo) {
        var op = (redo ? this.redo : this.undo).pop();
        if (op) {
            op(!redo);
        }
    },
    canUndo: function(redo) {
        return redo ? !!this.redo.length : !!this.undo.length;
    }
});

exports = module.exports = function() {
    var doc = Object.create(prototype);
    doc._width = 0;
    doc.height = 0;
    doc.selection = { start: 0, end: 0 };
    doc.caretVisible = true;
    doc.inlines = function() {};
    doc.selectionChanged = util.event();
    doc.contentChanged = util.event();
    doc.load([]);
    return doc;
};
<commit_msg>Fixed selectionChanged event so it always fires when doc.select is called<commit_after>var per = require('per');
var characters = require('./characters');
var split = require('./split');
var wrap = require('./wrap');
var word = require('./word');
var node = require('./node');
var runs = require('./runs');
var measure = require('./measure');
var range = require('./range');
var util = require('./util');

var wordCharRuns = function(positionedWord) {
    return positionedWord.children().map(function(char) {
        return char.part.run;
    });
};

var makeEditCommand = function(doc, start, count, words) {
    var selStart = doc.selection.start, selEnd = doc.selection.end;
    return function(redo) {
        var oldWords = Array.prototype.splice.apply(doc.words, [start, count].concat(words));
        var stack = doc[redo ? 'redo' : 'undo'];
        while (stack.length > 50) {
            stack.shift();
        }
        stack.push(makeEditCommand(doc, start, words.length, oldWords));
        doc.layout();
        doc.contentChanged.fire();
        doc.select(selStart, selEnd);
    };
};

var prototype = node.derive({
    load: function(runs) {
        var self = this;
        this.undo = [];
        this.redo = [];
        this.words = per(characters(runs)).per(split()).map(function(w) {
            return word(w, self.inlines);
        }).all();
        this.layout();
        this.contentChanged.fire();
        this.select(0, 0);
    },
    layout: function() {
        this.lines = per(this.words).per(wrap(this._width, this)).all();
        var lastLine = this.last();
        this.height = !lastLine ? 0 : lastLine.baseline + lastLine.descent;
    },
    plainText: function() {
        return this.words.map(function(word) {
            return word.plainText;
        }).join('');
    },
    runs: function(emit) {
        this.lines.forEach(function(line) {
            line.runs(emit);
        });
    },
    range: function(start, end) {
        return range(this, start, end);
    },
    documentRange: function() {
        return this.range(0, this.length());
    },
    selectedRange: function() {
        return this.range(this.selection.start, this.selection.end);
    },
    save: function() {
        return this.documentRange().save();
    },
    paragraphRange: function(start, end) {
        // find the character after the nearest newline before start
        var ch = this.characterByOrdinal(start), word;
        if (ch) {
            word = ch.word;
            while (word.ordinal > 0) {
                var prev = word.previous();
                if (prev.word.isNewLine()) {
                    break;
                }
                word = prev;
            }
            start = word.ordinal;
        }
        // find the nearest newline after end
        ch = this.characterByOrdinal(end);
        if (ch) {
            word = ch.word;
            while (!word.word.isNewLine()) {
                word = word.next();
            }
            end = word.ordinal;
        }
        return this.range(start, end);
    },
    insert: function(text) {
        this.select(this.selection.end + this.selectedRange().setText(text));
    },
    modifyInsertFormatting: function(attribute, value) {
        this.nextInsertFormatting[attribute] = value;
        this.notifySelectionChanged();
    },
    applyInsertFormatting: function(text) {
        var formatting = this.nextInsertFormatting;
        var insertFormattingProperties = Object.keys(formatting);
        if (insertFormattingProperties.length) {
            text.forEach(function(run) {
                insertFormattingProperties.forEach(function(property) {
                    run[property] = formatting[property];
                });
            });
        }
    },
    splice: function(start, end, text) {
        var startChar = this.characterByOrdinal(start),
            endChar = start === end ? startChar : this.characterByOrdinal(end);
        if (typeof text === 'string') {
            text = [
                Object.create((startChar.previous() || startChar).part.run, {
                    text: { value: text }
                })
            ];
        } else if (!Array.isArray(text)) {
            text = [{ text: text }];
        }

        this.applyInsertFormatting(text);

        var startWord = startChar.parent();
        var startWordIndex = this.words.indexOf(startWord.word);
        var startWordChars = wordCharRuns(startWord);

        var endWord = endChar.parent();
        var endWordIndex = endWord === startWord ? startWordIndex : this.words.indexOf(endWord.word);
        var endWordChars = endWord === startWord ? startWordChars : wordCharRuns(endWord);

        var prefix;
        if (startChar.ordinal === startWord.ordinal) {
            var previousWord = startWord.previous();
            if (previousWord) {
                prefix = wordCharRuns(previousWord);
                startWordIndex--;
            } else {
                prefix = [];
            }
        } else {
            prefix = startWordChars.slice(0, startChar.ordinal - startWord.ordinal);
        }

        var suffix;
        if (endChar.ordinal === endWord.ordinal) {
            if (endChar.ordinal === this.length()) {
                suffix = [];
                endWordIndex--;
            } else {
                suffix = wordCharRuns(endWord);
            }
        } else {
            suffix = endWordChars.slice(endChar.ordinal - endWord.ordinal);
        }

        var self = this;
        var oldLength = this.length();
        var newRuns = per(prefix).concat(text).concat(suffix).per(runs.consolidate()).all();
        var newWords = per(characters(newRuns))
            .per(split())
            .truthy()
            .map(function(w) {
                return word(w, self.inlines);
            })
            .all();

        this.redo.length = 0;
        makeEditCommand(this, startWordIndex, (endWordIndex - startWordIndex) + 1, newWords)();
        return this.length() - oldLength;
    },
    width: function(width) {
        if (arguments.length === 0) {
            return this._width;
        }
        this._width = width;
        this.layout();
    },
    first: function() {
        return this.lines[0];
    },
    last: function() {
        return this.lines[this.lines.length - 1];
    },
    children: function() {
        return this.lines;
    },
    length: function() {
        var lastLine = this.last();
        return !lastLine ? 0 : lastLine.last().last().ordinal;
    },
    draw: function(ctx, bottom) {
        bottom = bottom || Number.MAX_VALUE;
        measure.prepareContext(ctx);
        this.lines.some(function(line) {
            if (line.baseline - line.ascent > bottom) {
                return true;
            }
            line.draw(ctx);
        });
    },
    toggleCaret: function() {
        var old = this.caretVisible;
        if (this.selection.start === this.selection.end) {
            if (this.selectionJustChanged) {
                this.selectionJustChanged = false;
            } else {
                this.caretVisible = !this.caretVisible;
            }
        }
        return this.caretVisible !== old;
    },
    drawSelection: function(ctx, hasFocus) {
        if (this.selection.end === this.selection.start) {
            if (this.selectionJustChanged || hasFocus && this.caretVisible) {
                var char = this.characterByOrdinal(this.selection.start);
                if (char) {
                    var charBounds = char.bounds(),
                        lineBounds = char.word.line.bounds(true);
                    ctx.beginPath();
                    ctx.moveTo(charBounds.l, lineBounds.t);
                    ctx.lineTo(charBounds.l, lineBounds.t + lineBounds.h);
                    ctx.stroke();
                }
            }
        } else {
            ctx.save();
            ctx.fillStyle = hasFocus ? 'rgba(0, 100, 200, 0.3)' : 'rgba(160, 160, 160, 0.3)';
            this.selectedRange().parts(function(part) {
                var b = part.bounds(true);
                ctx.fillRect(b.l, b.t, b.w, b.h);
            });
            ctx.restore();
        }
    },
    notifySelectionChanged: function() {
        // When firing selectionChanged, we pass a function can be used
        // to obtain the formatting, as this highly likely to be needed
        var cachedFormatting = null;
        var self = this;
        var getFormatting = function() {
            if (!cachedFormatting) {
                cachedFormatting = self.selectedRange().getFormatting();
            }
            return cachedFormatting;
        };
        this.selectionChanged.fire(getFormatting);
    },
    select: function(ordinal, ordinalEnd) {
        this.selection.start = Math.max(0, ordinal);
        this.selection.end = Math.min(
            typeof ordinalEnd === 'number' ? ordinalEnd : this.selection.start,
            this.length()
        );
        this.selectionJustChanged = true;
        this.caretVisible = true;
        this.nextInsertFormatting = {};

        /*  NB. always fire this even if the positions stayed the same. The
            event means that the formatting of the selection has changed
            (which can happen either by moving the selection range or by
            altering the formatting)
        */
        this.notifySelectionChanged();
    },
    characterByOrdinal: function(index) {
        var result = null;
        if (this.lines.some(function(line) {
            result = line.characterByOrdinal(index);
            if (result) {
                return true;
            }
        })) {
            return result;
        }
    },
    characterByCoordinate: function(x, y, right) {
        var found, nextLine = false;
        this.children().some(function(line) {
            if (nextLine) {
                found = line.characterByOrdinal(line.ordinal);
                return true;
            }
            var bounds = line.bounds();
            if (bounds.contains(x, y)) {
                line.children().some(function(pword) {
                    bounds = pword.bounds();
                    if (bounds.contains(x, y)) {
                        pword.children().some(function(pchar) {
                            bounds = pchar.bounds();
                            if (bounds.contains(x, y)) {
                                if (!pchar.word.word.isNewLine() && (x - bounds.l) > (bounds.w / 2)) {
                                    found = pchar.next();
                                } else {
                                    found = pchar;
                                }
                                return true;
                            }
                        });
                        return true;
                    }
                });
                if (!found) {
                    if (right) {
                        nextLine = true;
                    } else {
                        found = line.last().last();
                    }
                } else {
                    return true;
                }
            }
        });
        if (!found) {
            found = this.last().last().last();
        }
        return found;
    },
    performUndo: function(redo) {
        var op = (redo ? this.redo : this.undo).pop();
        if (op) {
            op(!redo);
        }
    },
    canUndo: function(redo) {
        return redo ? !!this.redo.length : !!this.undo.length;
    }
});

exports = module.exports = function() {
    var doc = Object.create(prototype);
    doc._width = 0;
    doc.height = 0;
    doc.selection = { start: 0, end: 0 };
    doc.caretVisible = true;
    doc.inlines = function() {};
    doc.selectionChanged = util.event();
    doc.contentChanged = util.event();
    doc.load([]);
    return doc;
};
<|endoftext|>


<commit_before>const Observable = require('@sanity/observable')
const createCache = require('./utils/createCache')
const canonicalize = require('./utils/canonicalize')
const omit = require('lodash/omit')
const {BufferedDocument, Mutation} = require('@sanity/mutator')

function TODO(msg = 'TODO') {
  return function todo() {
    throw new Error(msg)
  }
}
const NOOP = () => {
}

function createBufferedDocument(documentId, server) {

  const serverEvents$ = Observable.from(server.byId(documentId)).share()
  const bufferedDocs$ = serverEvents$
    .first(event => event.type === 'snapshot')
    .map(event => event.document)
    .map(snapshot => {
      const bufferedDocument = new BufferedDocument(snapshot)

      serverEvents$
        .filter(event => event.type === 'mutation')
        .map(event => bufferedDocument.arrive(new Mutation(event)))

      bufferedDocument.commitHandler = function commitHandler(opts) {
        const payload = opts.mutation.params

        // TODO:
        // right now the BufferedDocument just commits fire-and-forget-ish
        // We should be able to handle failures and retry here

        server.mutate(omit(payload, 'resultRev'))
          .subscribe({
            next: opts.success,
            error: opts.failure
          })
      }

      const rebase$ = new Observable(rebaseObserver => {
        bufferedDocument.onRebase = edge => {
          rebaseObserver.next({type: 'rebase', document: edge})
        }
        return () => {
          bufferedDocument.onRebase = NOOP
        }
      }).share()

      const mutation$ = new Observable(mutationObserver => {
        bufferedDocument.onMutation = ({mutation, remote}) => {
          mutationObserver.next({
            type: 'mutation',
            document: bufferedDocument.LOCAL,
            mutations: mutation.mutations,
            origin: remote ? 'remote' : 'local'
          })
        }
        return () => {
          bufferedDocument.onMutation = NOOP
        }
      }).share()

      return {
        events: new Observable(observer => {
          observer.next({type: 'snapshot', document: bufferedDocument.LOCAL})
          return mutation$
            .merge(rebase$)
            .subscribe(observer)
        }),
        patch(patches) {
          const mutations = patches
            .map(patch => Object.assign({}, patch, {id: documentId}))
            .map(patch => ({patch: patch}))

          bufferedDocument.add(new Mutation({mutations: mutations}))
        },
        create(document) {
          const mutation = {
            create: Object.assign({id: documentId}, document)
          }
          bufferedDocument.add(new Mutation({mutations: [mutation]}))
        },
        delete() {
          bufferedDocument.add(new Mutation({mutations: [{delete: {id: documentId}}]}))
        },
        commit() {
          return new Observable(observer => {
            // todo: connect observable with request from bufferedDocument.commit somehow
            bufferedDocument.commit()
            observer.next()
            observer.complete()
          })
        }
      }
    })
    .share()

  let current
  function getCurrent() {
    if (current) {
      return Observable.of(current)
    }
    return bufferedDocs$.first().do(next => {
      current = next
    })
  }

  return {
    events: getCurrent().mergeMap(bufferedDoc => bufferedDoc.events),
    patch(patches) {
      getCurrent().subscribe(bufferedDoc => bufferedDoc.patch(patches))
    },
    create(document) {
      return getCurrent().mergeMap(bufferedDoc => bufferedDoc.create(document))
    },
    delete() {
      return getCurrent().subscribe(bufferedDoc => bufferedDoc.delete())
    },
    commit() {
      return getCurrent().mergeMap(bufferedDoc => bufferedDoc.commit())
    }
  }
}

const identity = val => val

module.exports = function createDocumentStore({serverConnection}) {

  const RECORDS_CACHE = createCache()

  const server = {
    byId: canonicalize(identity, serverConnection.byId),
    query: canonicalize(identity, serverConnection.query),
    mutate: serverConnection.mutate,
    delete: serverConnection.delete,
  }

  return {
    byId,
    byIds,
    query,
    create,
    checkout,
    patch: patchDoc,
    delete: deleteDoc,
    createOrReplace: TODO('Not implemented yet'),
    createIfNotExists: TODO('Not implemented yet'),
  }

  function patchDoc(documentId, patches) {
    return checkout(documentId)
      .patch(patches)
      .commit()
  }

  function deleteDoc(documentId) {
    return checkout(documentId)
      .delete()
      .commit()
  }

  function byId(documentId) {
    return checkout(documentId).events
  }

  function checkout(documentId) {
    return RECORDS_CACHE.fetch(documentId, () => createBufferedDocument(documentId, server))
  }

  function byIds(documentIds) {
    return new Observable(observer => {
      const documentSubscriptions = documentIds
        .map(id => byId(id).subscribe(observer))

      return () => {
        documentSubscriptions.map(subscription => subscription.unsubscribe())
      }
    })
  }

  function query(_query, params) {
    return Observable.from(serverConnection.query(_query, params))
  }

  function create(document) {
    return Observable.from(serverConnection.create(document))
  }
}
<commit_msg>[document-store] Fix issue with listener being disposed too early<commit_after>const Observable = require('@sanity/observable')
const createCache = require('./utils/createCache')
const canonicalize = require('./utils/canonicalize')
const omit = require('lodash/omit')
const {BufferedDocument, Mutation} = require('@sanity/mutator')

function TODO(msg = 'TODO') {
  return function todo() {
    throw new Error(msg)
  }
}
const NOOP = () => {}

function createBufferedDocument(documentId, server) {

  const serverEvents$ = Observable.from(server.byId(documentId)).share()

  const bufferedDocs$ = serverEvents$
    .filter(event => event.type === 'snapshot')
    .map(event => event.document)
    .map(snapshot => {
      const bufferedDocument = new BufferedDocument(snapshot)

      bufferedDocument.commitHandler = function commitHandler(opts) {
        const payload = opts.mutation.params

        // TODO:
        // right now the BufferedDocument just commits fire-and-forget-ish
        // We should be able to handle failures and retry here

        server.mutate(omit(payload, 'resultRev'))
          .subscribe({
            next: opts.success,
            error: opts.failure
          })
      }

      const rebase$ = new Observable(rebaseObserver => {
        bufferedDocument.onRebase = edge => {
          rebaseObserver.next({type: 'rebase', document: edge})
        }
        return () => {
          bufferedDocument.onRebase = NOOP
        }
      }).share()

      const mutation$ = new Observable(mutationObserver => {
        bufferedDocument.onMutation = ({mutation, remote}) => {
          mutationObserver.next({
            type: 'mutation',
            document: bufferedDocument.LOCAL,
            mutations: mutation.mutations,
            origin: remote ? 'remote' : 'local'
          })
        }

        const serverMutations = serverEvents$
          .filter(event => event.type === 'mutation')
          // .do(event => {
          //   console.log('server event arrived', event)
          // })
          .subscribe(event => bufferedDocument.arrive(new Mutation(event)))

        return () => {
          serverMutations.unsubscribe()
          bufferedDocument.onMutation = NOOP
        }
      }).share()

      return {
        events: new Observable(observer => {
          observer.next({type: 'snapshot', document: bufferedDocument.LOCAL})
          return mutation$
            .merge(rebase$)
            .subscribe(observer)
        }),
        patch(patches) {
          const mutations = patches
            .map(patch => Object.assign({}, patch, {id: documentId}))
            .map(patch => ({patch: patch}))

          bufferedDocument.add(new Mutation({mutations: mutations}))
        },
        create(document) {
          const mutation = {
            create: Object.assign({id: documentId}, document)
          }
          bufferedDocument.add(new Mutation({mutations: [mutation]}))
        },
        delete() {
          bufferedDocument.add(new Mutation({mutations: [{delete: {id: documentId}}]}))
        },
        commit() {
          return new Observable(observer => {
            // todo: connect observable with request from bufferedDocument.commit somehow
            bufferedDocument.commit()
            observer.next()
            observer.complete()
          })
        }
      }
    })
    .share()

  let currentBuffered
  const cachedBuffered = new Observable(observer => {
    if (currentBuffered) {
      observer.next(currentBuffered)
      observer.complete()
    }
    return bufferedDocs$.do(doc => {
      currentBuffered = doc
    })
      .subscribe(observer)
  })

  return {
    events: cachedBuffered.switchMap(bufferedDoc => bufferedDoc.events),
    patch(patches) {
      cachedBuffered.subscribe(bufferedDoc => bufferedDoc.patch(patches))
    },
    create(document) {
      return cachedBuffered.switchMap(bufferedDoc => bufferedDoc.create(document))
    },
    delete() {
      return cachedBuffered.subscribe(bufferedDoc => bufferedDoc.delete())
    },
    commit() {
      return cachedBuffered.switchMap(bufferedDoc => bufferedDoc.commit())
    }
  }
}

const identity = val => val

module.exports = function createDocumentStore({serverConnection}) {

  const RECORDS_CACHE = createCache()

  const server = {
    byId: canonicalize(identity, serverConnection.byId),
    query: canonicalize(identity, serverConnection.query),
    mutate: serverConnection.mutate,
    delete: serverConnection.delete,
  }

  return {
    byId,
    byIds,
    query,
    create,
    checkout,
    patch: patchDoc,
    delete: deleteDoc,
    createOrReplace: TODO('Not implemented yet'),
    createIfNotExists: TODO('Not implemented yet'),
  }

  function patchDoc(documentId, patches) {
    return checkout(documentId)
      .patch(patches)
      .commit()
  }

  function deleteDoc(documentId) {
    return checkout(documentId)
      .delete()
      .commit()
  }

  function byId(documentId) {
    return checkout(documentId).events
  }

  function checkout(documentId) {
    return RECORDS_CACHE.fetch(documentId, () => createBufferedDocument(documentId, server))
  }

  function byIds(documentIds) {
    return new Observable(observer => {
      const documentSubscriptions = documentIds
        .map(id => byId(id).subscribe(observer))

      return () => {
        documentSubscriptions.map(subscription => subscription.unsubscribe())
      }
    })
  }

  function query(_query, params) {
    return Observable.from(serverConnection.query(_query, params))
  }

  function create(document) {
    return Observable.from(serverConnection.create(document))
  }
}
<|endoftext|>


<commit_before>"use strict";

var packageJson                 = require("../package.json");
var BatchUpdater                = require("batch-updater");
var partial                     = require("lodash.partial");
var forEach                     = require("lodash.forEach");
var unique                      = require("lodash.uniq");
var ElementResizeDetector       = require("element-resize-detector");
var PluginHandler               = require("./plugin-handler");
var Reporter                    = require("./reporter");
var IdGenerator                 = require("./id-generator");
var IdHandler                   = require("./id-handler");
var CycleDetector               = require("./cycle-detector");
var BreakpointStateCalculator   = require("./breakpoint-state-calculator");
var StyleResolver               = require("./style-resolver");

// Core plugins
var elqBreakpoints              = require("./plugin/elq-breakpoints/elq-breakpoints.js");
var elqMinMaxSerializer         = require("./plugin/elq-minmax-serializer/elq-minmax-serializer.js");
var elqMirror                   = require("./plugin/elq-mirror/elq-mirror.js");

module.exports = function Elq(options) {
    options = options || {};

    var elq                         = {};
    var reporter                    = options.reporter || Reporter();
    var defaultUnit                 = options.defaultUnit || "px";
    var cycleDetection              = options.cycleDetection || false;
    var idGenerator                 = IdGenerator();
    var idHandler                   = IdHandler(idGenerator);
    var cycleDetector               = CycleDetector(idHandler);
    var pluginHandler               = PluginHandler(reporter);
    var styleResolver               = StyleResolver();
    var breakpointStateCalculator   = BreakpointStateCalculator({ styleResolver: styleResolver });
    var elementResizeDetector       = ElementResizeDetector({ idHandler: idHandler, reporter: reporter, strategy: "scroll" });
    var BatchUpdater                = createBatchUpdaterConstructorWithDefaultOptions({ reporter: reporter });

    var batchUpdater                = BatchUpdater();
    var globalListeners             = {};

    function notifyListeners(element, event, args) {
        var listeners = element.elq.listeners[event] || [];
        listeners = listeners.concat(globalListeners[event] || []);

        var listenerArguments = [element].concat(args || []);

        forEach(listeners, function (callback) {
            callback.apply(null, listenerArguments);
        });
    }

    function updateBreakpoints(element, batchProcessor) {
        var breakpoints = [];

        forEach(pluginHandler.getMethods("getBreakpoints"), function (getBreakpoints) {
            breakpoints = breakpoints.concat(getBreakpoints(element) || []);
        });

        if (!breakpoints.length) {
            return;
        }

        // Filter so that we only got unique breakpoints.
        breakpoints = unique(breakpoints, function uniqueFunction(bp) {
            return bp.dimension + bp.value + bp.type;
        });

        var breakpointStates = breakpointStateCalculator.getBreakpointStates(element, breakpoints);

        if (!breakpointStates) {
            // Unable to resolve style for element. Probably due to it being detached from the DOM.
            return;
        }

        // TODO: This should instead be hashed. Also, maybe there is a more effective way of doing this.
        var breakpointStatesHash = JSON.stringify(breakpointStates);

        if (element.elq.currentBreakpointStatesHash !== breakpointStatesHash) {
            if (cycleDetection && element.elq.cycleCheck) {
                if (cycleDetector.isUpdateCyclic(element, breakpointStatesHash)) {
                    reporter.warn("Cyclic rules detected! Breakpoint classes has not been updated. Element: ", element);
                    return;
                }
            }

            element.elq.currentBreakpointStatesHash = breakpointStatesHash;

            if (element.elq.serialize) {
                pluginHandler.callMethods("serializeBreakpointStates", [element, breakpointStates]);
            }

            notifyListeners(element, "breakpointStatesChanged", [breakpointStates]);
        }
    }

    function initElement(element) {
        element.elq = element.elq || {
            listeners: {},
            updateBreakpoints: false,
            resizeDetection: false,
            id: idGenerator.generate()
        };
    }

    function isInited(element) {
        return !!(element.elq && element.elq.id);
    }

    function activate(elements) {
        function toArray(collection) {
            if (!Array.isArray(collection)) {
                var array = [];
                forEach(elements, function (element) {
                    array.push(element);
                });
                return array;
            } else {
                return collection;
            }
        }

        if (!elements) {
            return;
        }

        if (elements.length === undefined) {
            elements = [elements];
        }

        // Convert collection to array for plugins.
        elements = toArray(elements);

        // Get possible extra elements by plugins.
        forEach(pluginHandler.getMethods("getExtraElements"), function (getExtraElements) {
            forEach(elements, function (element) {
                var extraElements = getExtraElements(element) || [];
                elements.push.apply(elements, extraElements);
            });
        });

        // Add the elq object to all elements before activating them, since a plugin may need to listen to elements
        // that has not yet been started.
        forEach(elements, function (element) {
            if (!isInited(elements)) {
                initElement(element);
            }
        });

        // Filter out possible duplicates.
        elements = unique(elements, function (element) {
            return element.elq.id;
        });

        forEach(elements, function (element) {
            pluginHandler.callMethods("activate", [element]);
        });

        var manualBatchUpdater = BatchUpdater({ async: false, auto: false });

        //Before listening to each element (which is a heavy task) it is important to apply the right classes
        //to the elements so that a correct render can occur before the installation.
        forEach(elements, function (element) {
            if (element.elq.updateBreakpoints) {
                updateBreakpoints(element, manualBatchUpdater);
            }
        });

        function onElementResizeProxy(element) {
            notifyListeners(element, "resize");

            if (element.elq.updateBreakpoints) {
                updateBreakpoints(element, batchUpdater);
            }
        }

        forEach(elements, function listenToLoop(element) {
            if (element.elq.resizeDetection) {
                elementResizeDetector.listenTo({
                    callOnAdd: true, // TODO: Shouldn't this be false?
                    batchUpdater: batchUpdater
                }, element, onElementResizeProxy);
            }
        });

        //Force everything currently in the batch to execute synchronously.
        //Important that his is done after the listenToLoop since it reads the DOM style and the batch will write to the DOM.
        manualBatchUpdater.force();
    }

    function listenTo(element, event, callback) {
        function attachListener(listeners) {
            if (!listeners[event]) {
                listeners[event] = [];
            }

            listeners[event].push(callback);
        }

        // The element parameter may be omitted, in order to setup a global listener (i.e., a listener that listens to the event of all elements).
        if (!callback) {
            callback = event;
            event = element;
            element = null;
        }

        if (element) {
            // A local element event listener.

            if (!isInited(element)) {
                initElement(element);
            }

            // TODO: If event is "resize" but the element is current element.elq.resizeDetection = false,
            // it would perhaps be nice to start listening to this element.

            attachListener(element.elq.listeners);
        } else {
            // A global event listener that emits for the event of all elements.
            attachListener(globalListeners);
        }
    }

    //Public
    elq.getVersion          = getVersion;
    elq.getName             = getName;
    elq.use                 = partial(pluginHandler.register, elq);
    elq.using               = pluginHandler.isRegistered;
    elq.activate            = activate;
    elq.listenTo            = listenTo;

    //Create an object copy of the currently attached API methods, that will be exposed as the public API.
    var publicElq           = copy(elq);

    //Functions only accesible by plugins.
    elq.idHandler           = idHandler;
    elq.reporter            = reporter;
    elq.cycleDetector       = cycleDetector;
    elq.BatchUpdater        = BatchUpdater;
    elq.pluginHandler       = pluginHandler;

    // Register core plugins
    // TODO: These should be registered at a higher level, such as index.js so that they can be omitted in a slim build.

    elq.use(elqBreakpoints, {
        defaultUnit: defaultUnit
    });

    elq.use(elqMinMaxSerializer);
    elq.use(elqMirror);

    return publicElq;
};

function getVersion() {
    return packageJson.version;
}

function getName() {
    return packageJson.name;
}

function copy(o) {
    var c = {};

    for (var key in o) {
        if (o.hasOwnProperty(key)) {
            c[key] = o[key];
        }
    }

    return c;
}

function createBatchUpdaterConstructorWithDefaultOptions(globalOptions) {
    globalOptions = globalOptions || {};

    function createBatchUpdaterOptionsProxy(options) {
        options = options || globalOptions;

        for (var prop in globalOptions) {
            if (globalOptions.hasOwnProperty(prop) && !options.hasOwnProperty(prop)) {
                options[prop] = globalOptions[prop];
            }
        }

        return BatchUpdater(options);
    }

    return createBatchUpdaterOptionsProxy;
}
<commit_msg>Now checking elq.activate arguments better to not treat HTML form nodes as a collection<commit_after>"use strict";

var packageJson                 = require("../package.json");
var BatchUpdater                = require("batch-updater");
var partial                     = require("lodash.partial");
var forEach                     = require("lodash.forEach");
var unique                      = require("lodash.uniq");
var ElementResizeDetector       = require("element-resize-detector");
var PluginHandler               = require("./plugin-handler");
var Reporter                    = require("./reporter");
var IdGenerator                 = require("./id-generator");
var IdHandler                   = require("./id-handler");
var CycleDetector               = require("./cycle-detector");
var BreakpointStateCalculator   = require("./breakpoint-state-calculator");
var StyleResolver               = require("./style-resolver");

// Core plugins
var elqBreakpoints              = require("./plugin/elq-breakpoints/elq-breakpoints.js");
var elqMinMaxSerializer         = require("./plugin/elq-minmax-serializer/elq-minmax-serializer.js");
var elqMirror                   = require("./plugin/elq-mirror/elq-mirror.js");

module.exports = function Elq(options) {
    options = options || {};

    var elq                         = {};
    var reporter                    = options.reporter || Reporter();
    var defaultUnit                 = options.defaultUnit || "px";
    var cycleDetection              = options.cycleDetection || false;
    var idGenerator                 = IdGenerator();
    var idHandler                   = IdHandler(idGenerator);
    var cycleDetector               = CycleDetector(idHandler);
    var pluginHandler               = PluginHandler(reporter);
    var styleResolver               = StyleResolver();
    var breakpointStateCalculator   = BreakpointStateCalculator({ styleResolver: styleResolver });
    var elementResizeDetector       = ElementResizeDetector({ idHandler: idHandler, reporter: reporter, strategy: "scroll" });
    var BatchUpdater                = createBatchUpdaterConstructorWithDefaultOptions({ reporter: reporter });

    var batchUpdater                = BatchUpdater();
    var globalListeners             = {};

    function notifyListeners(element, event, args) {
        var listeners = element.elq.listeners[event] || [];
        listeners = listeners.concat(globalListeners[event] || []);

        var listenerArguments = [element].concat(args || []);

        forEach(listeners, function (callback) {
            callback.apply(null, listenerArguments);
        });
    }

    function updateBreakpoints(element, batchProcessor) {
        var breakpoints = [];

        forEach(pluginHandler.getMethods("getBreakpoints"), function (getBreakpoints) {
            breakpoints = breakpoints.concat(getBreakpoints(element) || []);
        });

        if (!breakpoints.length) {
            return;
        }

        // Filter so that we only got unique breakpoints.
        breakpoints = unique(breakpoints, function uniqueFunction(bp) {
            return bp.dimension + bp.value + bp.type;
        });

        var breakpointStates = breakpointStateCalculator.getBreakpointStates(element, breakpoints);

        if (!breakpointStates) {
            // Unable to resolve style for element. Probably due to it being detached from the DOM.
            return;
        }

        // TODO: This should instead be hashed. Also, maybe there is a more effective way of doing this.
        var breakpointStatesHash = JSON.stringify(breakpointStates);

        if (element.elq.currentBreakpointStatesHash !== breakpointStatesHash) {
            if (cycleDetection && element.elq.cycleCheck) {
                if (cycleDetector.isUpdateCyclic(element, breakpointStatesHash)) {
                    reporter.warn("Cyclic rules detected! Breakpoint classes has not been updated. Element: ", element);
                    return;
                }
            }

            element.elq.currentBreakpointStatesHash = breakpointStatesHash;

            if (element.elq.serialize) {
                pluginHandler.callMethods("serializeBreakpointStates", [element, breakpointStates]);
            }

            notifyListeners(element, "breakpointStatesChanged", [breakpointStates]);
        }
    }

    function initElement(element) {
        element.elq = element.elq || {
            listeners: {},
            updateBreakpoints: false,
            resizeDetection: false,
            id: idGenerator.generate()
        };
    }

    function isInited(element) {
        return !!(element.elq && element.elq.id);
    }

    function activate(elements) {
        function isCollection(obj) {
            return Array.isArray(obj) || obj.length !== undefined;
        }

        function toArray(collection) {
            if (!Array.isArray(collection)) {
                var array = [];
                forEach(elements, function (element) {
                    array.push(element);
                });
                return array;
            } else {
                return collection;
            }
        }

        function isElement(obj) {
            return obj && obj.nodeType === 1;
        }

        if (!elements) {
            return;
        }

        if (isElement(elements)) {
            // A single element has been passed in.
            elements = [elements];
        } else if (isCollection(elements)) {
            // Convert collection to array for plugins.
            elements = toArray(elements);
        } else {
            return reporter.error("Invalid arguments. Must be a DOM element or a collection of DOM elements.");
        }

        // Get possible extra elements by plugins.
        forEach(pluginHandler.getMethods("getExtraElements"), function (getExtraElements) {
            forEach(elements, function (element) {
                var extraElements = getExtraElements(element) || [];
                elements.push.apply(elements, extraElements);
            });
        });

        // Add the elq object to all elements before activating them, since a plugin may need to listen to elements
        // that has not yet been started.
        forEach(elements, function (element) {
            if (!isInited(elements)) {
                initElement(element);
            }
        });

        // Filter out possible duplicates.
        elements = unique(elements, function (element) {
            return element.elq.id;
        });

        forEach(elements, function (element) {
            pluginHandler.callMethods("activate", [element]);
        });

        var manualBatchUpdater = BatchUpdater({ async: false, auto: false });

        //Before listening to each element (which is a heavy task) it is important to apply the right classes
        //to the elements so that a correct render can occur before the installation.
        forEach(elements, function (element) {
            if (element.elq.updateBreakpoints) {
                updateBreakpoints(element, manualBatchUpdater);
            }
        });

        function onElementResizeProxy(element) {
            notifyListeners(element, "resize");

            if (element.elq.updateBreakpoints) {
                updateBreakpoints(element, batchUpdater);
            }
        }

        forEach(elements, function listenToLoop(element) {
            if (element.elq.resizeDetection) {
                elementResizeDetector.listenTo({
                    callOnAdd: true, // TODO: Shouldn't this be false?
                    batchUpdater: batchUpdater
                }, element, onElementResizeProxy);
            }
        });

        //Force everything currently in the batch to execute synchronously.
        //Important that his is done after the listenToLoop since it reads the DOM style and the batch will write to the DOM.
        manualBatchUpdater.force();
    }

    function listenTo(element, event, callback) {
        function attachListener(listeners) {
            if (!listeners[event]) {
                listeners[event] = [];
            }

            listeners[event].push(callback);
        }

        // The element parameter may be omitted, in order to setup a global listener (i.e., a listener that listens to the event of all elements).
        if (!callback) {
            callback = event;
            event = element;
            element = null;
        }

        if (element) {
            // A local element event listener.

            if (!isInited(element)) {
                initElement(element);
            }

            // TODO: If event is "resize" but the element is current element.elq.resizeDetection = false,
            // it would perhaps be nice to start listening to this element.

            attachListener(element.elq.listeners);
        } else {
            // A global event listener that emits for the event of all elements.
            attachListener(globalListeners);
        }
    }

    //Public
    elq.getVersion          = getVersion;
    elq.getName             = getName;
    elq.use                 = partial(pluginHandler.register, elq);
    elq.using               = pluginHandler.isRegistered;
    elq.activate            = activate;
    elq.listenTo            = listenTo;

    //Create an object copy of the currently attached API methods, that will be exposed as the public API.
    var publicElq           = copy(elq);

    //Functions only accesible by plugins.
    elq.idHandler           = idHandler;
    elq.reporter            = reporter;
    elq.cycleDetector       = cycleDetector;
    elq.BatchUpdater        = BatchUpdater;
    elq.pluginHandler       = pluginHandler;

    // Register core plugins
    // TODO: These should be registered at a higher level, such as index.js so that they can be omitted in a slim build.

    elq.use(elqBreakpoints, {
        defaultUnit: defaultUnit
    });

    elq.use(elqMinMaxSerializer);
    elq.use(elqMirror);

    return publicElq;
};

function getVersion() {
    return packageJson.version;
}

function getName() {
    return packageJson.name;
}

function copy(o) {
    var c = {};

    for (var key in o) {
        if (o.hasOwnProperty(key)) {
            c[key] = o[key];
        }
    }

    return c;
}

function createBatchUpdaterConstructorWithDefaultOptions(globalOptions) {
    globalOptions = globalOptions || {};

    function createBatchUpdaterOptionsProxy(options) {
        options = options || globalOptions;

        for (var prop in globalOptions) {
            if (globalOptions.hasOwnProperty(prop) && !options.hasOwnProperty(prop)) {
                options[prop] = globalOptions[prop];
            }
        }

        return BatchUpdater(options);
    }

    return createBatchUpdaterOptionsProxy;
}
<|endoftext|>


<commit_before>'use strict';

var exec = require('child_process').exec;
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var rimraf = require('rimraf');
var plugin = require('../../lib/plugin.js');

module.exports = function(manager, app, docker) {

  manager.registerTask('init', function(done) {
    manager.init(app, done);
  });

  manager.registerTask('start', function(done) {
    manager.start(app, done);
  });

  manager.registerTask('stop', function(done) {
    manager.stop(app, done);
  });

  manager.registerTask('restart', function(done) {
    manager.stop(app, function(err) {
      if (err) {
        done(err);
      } else {
        manager.start(app, done);
      }
    });
  });

  manager.registerTask('kill', function(done) {
    manager.kill(app, done);
  });

  manager.registerTask('remove', function(done) {
    manager.remove(app, done);
  });

  manager.registerTask('pull', function(done) {
    manager.pull(app, done);
  });

  manager.registerTask('build', function(done) {
    manager.build(app, done);
  });

  app.on('post-init', function() {
    var a = _.cloneDeep(app);
    delete a.components;
    fs.writeFileSync(path.resolve(app.dataPath, 'app.json'), JSON.stringify(a));
  });

  app.on('post-remove', function() {
    rimraf(app.dataPath, function (er) {
      if (er) throw er
    });
  });

};
<commit_msg>#104: clean up some code from #97<commit_after>'use strict';

var exec = require('child_process').exec;
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var rimraf = require('rimraf');
var plugin = require('../../lib/plugin.js');

module.exports = function(manager, app, docker) {

  manager.registerTask('init', function(done) {
    manager.init(app, done);
  });

  manager.registerTask('start', function(done) {
    manager.start(app, done);
  });

  manager.registerTask('stop', function(done) {
    manager.stop(app, done);
  });

  manager.registerTask('restart', function(done) {
    manager.stop(app, function(err) {
      if (err) {
        done(err);
      } else {
        manager.start(app, done);
      }
    });
  });

  manager.registerTask('kill', function(done) {
    manager.kill(app, done);
  });

  manager.registerTask('remove', function(done) {
    manager.remove(app, done);
  });

  manager.registerTask('pull', function(done) {
    manager.pull(app, done);
  });

  manager.registerTask('build', function(done) {
    manager.build(app, done);
  });

  app.on('post-init', function() {
    var a = _.cloneDeep(app);
    delete a.components;
    fs.writeFileSync(path.resolve(app.dataPath, 'app.json'), JSON.stringify(a));
  });

  app.on('post-remove', function() {
    rimraf(app.dataPath, function(er) {
      if (er) {throw er; }
    });
  });

};
<|endoftext|>


<commit_before>const fs = require('fs')
const stylelint = require('stylelint')
const matchAll = require('string.prototype.matchall')
const globby = require('globby')

const ruleName = 'primer/no-undefined-vars'
const messages = stylelint.utils.ruleMessages(ruleName, {
  rejected: varName => `${varName} is not defined`
})

// Match CSS variable definitions (e.g. --color-text-primary:)
const variableDefinitionRegex = /(--[\w|-]*):/g

// Match CSS variable references (e.g var(--color-text-primary))
// eslint-disable-next-line no-useless-escape
const variableReferenceRegex = /var\(([^\)]*)\)/g

module.exports = stylelint.createPlugin(ruleName, (enabled, options = {}) => {
  if (!enabled) {
    return noop
  }

  const {files = ['**/*.scss', '!node_modules']} = options

  const definedVariables = getDefinedVariables(files)

  return (root, result) => {
    root.walkRules(rule => {
      rule.walkDecls(decl => {
        for (const [, variableName] of matchAll(decl.value, variableReferenceRegex)) {
          if (!definedVariables.has(variableName)) {
            stylelint.utils.report({
              message: messages.rejected(variableName),
              node: decl,
              result,
              ruleName
            })
          }
        }
      })
    })
  }
})

function getDefinedVariables(files) {
  const definedVariables = new Set()

  for (const file of globby.sync(files)) {
    const css = fs.readFileSync(file, 'utf-8')
    for (const [, variableName] of matchAll(css, variableDefinitionRegex)) {
      definedVariables.add(variableName)
    }
  }

  return definedVariables
}

function noop() {}

module.exports.ruleName = ruleName
module.exports.messages = messages
<commit_msg>Add verbose mode<commit_after>const fs = require('fs')
const stylelint = require('stylelint')
const matchAll = require('string.prototype.matchall')
const globby = require('globby')

const ruleName = 'primer/no-undefined-vars'
const messages = stylelint.utils.ruleMessages(ruleName, {
  rejected: varName => `${varName} is not defined`
})

// Match CSS variable definitions (e.g. --color-text-primary:)
const variableDefinitionRegex = /(--[\w|-]*):/g

// Match CSS variable references (e.g var(--color-text-primary))
// eslint-disable-next-line no-useless-escape
const variableReferenceRegex = /var\(([^\)]*)\)/g

module.exports = stylelint.createPlugin(ruleName, (enabled, options = {}) => {
  if (!enabled) {
    return noop
  }

  const {files = ['**/*.scss', '!node_modules'], verbose = false} = options
  // eslint-disable-next-line no-console
  const log = verbose ? (...args) => console.warn(...args) : noop
  const definedVariables = getDefinedVariables(files, log)

  return (root, result) => {
    root.walkRules(rule => {
      rule.walkDecls(decl => {
        for (const [, variableName] of matchAll(decl.value, variableReferenceRegex)) {
          if (!definedVariables.has(variableName)) {
            stylelint.utils.report({
              message: messages.rejected(variableName),
              node: decl,
              result,
              ruleName
            })
          }
        }
      })
    })
  }
})

function getDefinedVariables(files, log) {
  const definedVariables = new Set()

  for (const file of globby.sync(files)) {
    const css = fs.readFileSync(file, 'utf-8')
    for (const [, variableName] of matchAll(css, variableDefinitionRegex)) {
      log(`${variableName} defined in ${file}`)
      definedVariables.add(variableName)
    }
  }

  return definedVariables
}

function noop() {}

module.exports.ruleName = ruleName
module.exports.messages = messages
<|endoftext|>


<commit_before>module.exports = {
  builtins: {
    Symbol: "symbol",
    Promise: "promise",
    Map: "map",
    WeakMap: "weak-map",
    Set: "set",
    WeakSet: "weak-set",
    Observable: "observable",
    setImmediate: "set-immediate",
    clearImmediate: "clear-immediate",
    asap: "asap"
    //parseFloat: "parse-float", // temporary disabled
    //parseInt: "parse-int" // temporary disabled
  },

  methods: {
    Array: {
      concat: "array/concat", // deprecated
      copyWithin: "array/copy-within",
      entries: "array/entries",
      every: "array/every",
      fill: "array/fill",
      filter: "array/filter",
      findIndex: "array/find-index",
      find: "array/find",
      forEach: "array/for-each",
      from: "array/from",
      includes: "array/includes",
      indexOf: "array/index-of",
      //isArray: "array/is-array", // temporary disabled
      join: "array/join",
      keys: "array/keys",
      lastIndexOf: "array/last-index-of",
      map: "array/map",
      of: "array/of",
      pop: "array/pop", // deprecated
      push: "array/push", // deprecated
      reduceRight: "array/reduce-right",
      reduce: "array/reduce",
      reverse: "array/reverse", // deprecated
      shift: "array/shift", // deprecated
      slice: "array/slice", // deprecated
      some: "array/some",
      sort: "array/sort",
      splice: "array/splice",
      unshift: "array/unshift", // deprecated
      values: "array/values"
    },

    JSON: {
      stringify: "json/stringify"
    },

    Object: {
      assign: "object/assign",
      create: "object/create",
      defineProperties: "object/define-properties",
      defineProperty: "object/define-property",
      entries: "object/entries",
      freeze: "object/freeze",
      getOwnPropertyDescriptor: "object/get-own-property-descriptor",
      getOwnPropertyDescriptors: "object/get-own-property-descriptors",
      getOwnPropertyNames: "object/get-own-property-names",
      getOwnPropertySymbols: "object/get-own-property-symbols",
      getPrototypeOf: "object/get-prototype-of",
      isExtensible: "object/is-extensible",
      isFrozen: "object/is-frozen",
      isSealed: "object/is-sealed",
      is: "object/is",
      keys: "object/keys",
      preventExtensions: "object/prevent-extensions",
      seal: "object/seal",
      setPrototypeOf: "object/set-prototype-of",
      values: "object/values"
    },

    RegExp: {
      escape: "regexp/escape" // deprecated
    },

    Math: {
      acosh: "math/acosh",
      asinh: "math/asinh",
      atanh: "math/atanh",
      cbrt: "math/cbrt",
      clz32: "math/clz32",
      cosh: "math/cosh",
      expm1: "math/expm1",
      fround: "math/fround",
      hypot: "math/hypot",
      imul: "math/imul",
      log10: "math/log10",
      log1p: "math/log1p",
      log2: "math/log2",
      sign: "math/sign",
      sinh: "math/sinh",
      tanh: "math/tanh",
      trunc: "math/trunc",
      iaddh: "math/iaddh",
      isubh: "math/isubh",
      imulh: "math/imulh",
      umulh: "math/umulh"
    },

    Symbol: {
      asyncIterator: "symbol/async-iterator",
      for: "symbol/for",
      hasInstance: "symbol/has-instance",
      isConcatSpreadable: "symbol/is-concat-spreadable",
      iterator: "symbol/iterator",
      keyFor: "symbol/key-for",
      match: "symbol/match",
      observable: "symbol/observable",
      replace: "symbol/replace",
      search: "symbol/search",
      species: "symbol/species",
      split: "symbol/split",
      toPrimitive: "symbol/to-primitive",
      toStringTag: "symbol/to-string-tag",
      unscopables: "symbol/unscopables"
    },

    String: {
      at: "string/at",
      codePointAt: "string/code-point-at",
      endsWith: "string/ends-with",
      fromCodePoint: "string/from-code-point",
      includes: "string/includes",
      matchAll: "string/match-all",
      padLeft: "string/pad-left", // deprecated
      padRight: "string/pad-right", // deprecated
      padStart: "string/pad-start",
      padEnd: "string/pad-end",
      raw: "string/raw",
      repeat: "string/repeat",
      startsWith: "string/starts-with",
      trim: "string/trim",
      trimLeft: "string/trim-left",
      trimRight: "string/trim-right",
      trimStart: "string/trim-start",
      trimEnd: "string/trim-end"
    },

    Number: {
      EPSILON: "number/epsilon",
      isFinite: "number/is-finite",
      isInteger: "number/is-integer",
      isNaN: "number/is-nan",
      isSafeInteger: "number/is-safe-integer",
      MAX_SAFE_INTEGER: "number/max-safe-integer",
      MIN_SAFE_INTEGER: "number/min-safe-integer",
      parseFloat: "number/parse-float",
      parseInt: "number/parse-int"
    },

    Reflect: {
      apply: "reflect/apply",
      construct: "reflect/construct",
      defineProperty: "reflect/define-property",
      deleteProperty: "reflect/delete-property",
      enumerate: "reflect/enumerate", // deprecated
      getOwnPropertyDescriptor: "reflect/get-own-property-descriptor",
      getPrototypeOf: "reflect/get-prototype-of",
      get: "reflect/get",
      has: "reflect/has",
      isExtensible: "reflect/is-extensible",
      ownKeys: "reflect/own-keys",
      preventExtensions: "reflect/prevent-extensions",
      setPrototypeOf: "reflect/set-prototype-of",
      set: "reflect/set",
      defineMetadata: "reflect/define-metadata",
      deleteMetadata: "reflect/delete-metadata",
      getMetadata: "reflect/get-metadata",
      getMetadataKeys: "reflect/get-metadata-keys",
      getOwnMetadata: "reflect/get-own-metadata",
      getOwnMetadataKeys: "reflect/get-own-metadata-keys",
      hasMetadata: "reflect/has-metadata",
      hasOwnMetadata: "reflect/has-own-metadata",
      metadata: "reflect/metadata"
    },

    System: {
      global: "system/global"
    },

    Error: {
      isError: "error/is-error" // deprecated
    },

    Date: {
      //now: "date/now" // temporary disabled
    },

    Function: {
      // Warning: /virtual/ method - prototype, not static, version
      //bind: "function/virtual/bind" // temporary disabled
    }
  }
};
<commit_msg>[7.0] removed old code from transform-runtime (#5142)<commit_after>module.exports = {
  builtins: {
    Symbol: "symbol",
    Promise: "promise",
    Map: "map",
    WeakMap: "weak-map",
    Set: "set",
    WeakSet: "weak-set",
    Observable: "observable",
    setImmediate: "set-immediate",
    clearImmediate: "clear-immediate",
    asap: "asap"
    //parseFloat: "parse-float", // temporary disabled
    //parseInt: "parse-int" // temporary disabled
  },

  methods: {
    Array: {
      copyWithin: "array/copy-within",
      entries: "array/entries",
      every: "array/every",
      fill: "array/fill",
      filter: "array/filter",
      findIndex: "array/find-index",
      find: "array/find",
      forEach: "array/for-each",
      from: "array/from",
      includes: "array/includes",
      indexOf: "array/index-of",
      //isArray: "array/is-array", // temporary disabled
      join: "array/join",
      keys: "array/keys",
      lastIndexOf: "array/last-index-of",
      map: "array/map",
      of: "array/of",
      reduceRight: "array/reduce-right",
      reduce: "array/reduce",
      some: "array/some",
      sort: "array/sort",
      splice: "array/splice",
      values: "array/values"
    },

    JSON: {
      stringify: "json/stringify"
    },

    Object: {
      assign: "object/assign",
      create: "object/create",
      defineProperties: "object/define-properties",
      defineProperty: "object/define-property",
      entries: "object/entries",
      freeze: "object/freeze",
      getOwnPropertyDescriptor: "object/get-own-property-descriptor",
      getOwnPropertyDescriptors: "object/get-own-property-descriptors",
      getOwnPropertyNames: "object/get-own-property-names",
      getOwnPropertySymbols: "object/get-own-property-symbols",
      getPrototypeOf: "object/get-prototype-of",
      isExtensible: "object/is-extensible",
      isFrozen: "object/is-frozen",
      isSealed: "object/is-sealed",
      is: "object/is",
      keys: "object/keys",
      preventExtensions: "object/prevent-extensions",
      seal: "object/seal",
      setPrototypeOf: "object/set-prototype-of",
      values: "object/values"
    },

    Math: {
      acosh: "math/acosh",
      asinh: "math/asinh",
      atanh: "math/atanh",
      cbrt: "math/cbrt",
      clz32: "math/clz32",
      cosh: "math/cosh",
      expm1: "math/expm1",
      fround: "math/fround",
      hypot: "math/hypot",
      imul: "math/imul",
      log10: "math/log10",
      log1p: "math/log1p",
      log2: "math/log2",
      sign: "math/sign",
      sinh: "math/sinh",
      tanh: "math/tanh",
      trunc: "math/trunc",
      iaddh: "math/iaddh",
      isubh: "math/isubh",
      imulh: "math/imulh",
      umulh: "math/umulh"
    },

    Symbol: {
      asyncIterator: "symbol/async-iterator",
      for: "symbol/for",
      hasInstance: "symbol/has-instance",
      isConcatSpreadable: "symbol/is-concat-spreadable",
      iterator: "symbol/iterator",
      keyFor: "symbol/key-for",
      match: "symbol/match",
      observable: "symbol/observable",
      replace: "symbol/replace",
      search: "symbol/search",
      species: "symbol/species",
      split: "symbol/split",
      toPrimitive: "symbol/to-primitive",
      toStringTag: "symbol/to-string-tag",
      unscopables: "symbol/unscopables"
    },

    String: {
      at: "string/at",
      codePointAt: "string/code-point-at",
      endsWith: "string/ends-with",
      fromCodePoint: "string/from-code-point",
      includes: "string/includes",
      matchAll: "string/match-all",
      padStart: "string/pad-start",
      padEnd: "string/pad-end",
      raw: "string/raw",
      repeat: "string/repeat",
      startsWith: "string/starts-with",
      trim: "string/trim",
      trimLeft: "string/trim-left",
      trimRight: "string/trim-right",
      trimStart: "string/trim-start",
      trimEnd: "string/trim-end"
    },

    Number: {
      EPSILON: "number/epsilon",
      isFinite: "number/is-finite",
      isInteger: "number/is-integer",
      isNaN: "number/is-nan",
      isSafeInteger: "number/is-safe-integer",
      MAX_SAFE_INTEGER: "number/max-safe-integer",
      MIN_SAFE_INTEGER: "number/min-safe-integer",
      parseFloat: "number/parse-float",
      parseInt: "number/parse-int"
    },

    Reflect: {
      apply: "reflect/apply",
      construct: "reflect/construct",
      defineProperty: "reflect/define-property",
      deleteProperty: "reflect/delete-property",
      getOwnPropertyDescriptor: "reflect/get-own-property-descriptor",
      getPrototypeOf: "reflect/get-prototype-of",
      get: "reflect/get",
      has: "reflect/has",
      isExtensible: "reflect/is-extensible",
      ownKeys: "reflect/own-keys",
      preventExtensions: "reflect/prevent-extensions",
      setPrototypeOf: "reflect/set-prototype-of",
      set: "reflect/set",
      defineMetadata: "reflect/define-metadata",
      deleteMetadata: "reflect/delete-metadata",
      getMetadata: "reflect/get-metadata",
      getMetadataKeys: "reflect/get-metadata-keys",
      getOwnMetadata: "reflect/get-own-metadata",
      getOwnMetadataKeys: "reflect/get-own-metadata-keys",
      hasMetadata: "reflect/has-metadata",
      hasOwnMetadata: "reflect/has-own-metadata",
      metadata: "reflect/metadata"
    },

    System: {
      global: "system/global"
    },

    Date: {
      //now: "date/now" // temporary disabled
    },

    Function: {
      // Warning: /virtual/ method - prototype, not static, version
      //bind: "function/virtual/bind" // temporary disabled
    }
  }
};
<|endoftext|>


<commit_before>var sys = require('sys')
var _   = require('underscore')

desc('Default task.');
task('default', [], function (params) {
  console.log('Jake is working.');
  console.log(sys.inspect(arguments));
});

namespace('db', function () {

    desc('Insert day cares for test environment.');
    task('seed_day_cares_for_test', [], function (params) {
        process.env.NODE_ENV = 'test';
        DayCare = require('./models/day_care');
        DayCare.find({}, null, null, function(err, dayCares) {
            for (var i = 0; i < dayCares.length; i++) {
                dayCares[i].remove();
            }

            for (var i = 1; i < 4; i++) {
                dayCare = new DayCare({name: 'daycare' + i})
                dayCare.save()
            }
        });

    });

    desc('Insert day cares for development environment.');
    task('seed_day_cares_for_development', [], function (params) {
        process.env.NODE_ENV = 'development';
        DayCare = require('./models/day_care');
//        PictureSet = require('./models/picture_set');
//        Picture = require('./models/picture');
        DayCare.find({}, null, null, function(err, dayCares) {
            for (var i = 0; i < dayCares.length; i++) {
                dayCares[i].remove();
            }

            for (var i = 1; i < 4; i++) {
                pictureSets = [
                    {type: 'profile', name: 'Profile pictures', description: 'Your profile pictures.',
                     pictures: [
                        {primary: true, description: 'Our logo', url: '/images/seeds/profile_pic.jpg'}
                     ]
                    },
                    {type: 'daycare', name: 'Inside our day care', description: 'This is how our day care looks inside.',
                     pictures: [
                        {primary: false, description: 'Inside our day care 1', url: '/images/seeds/daycare1.jpg'},
                        {primary: true, description: 'Inside our day care 2', url: '/images/seeds/daycare2.jpg'},
                        {primary: false, description: 'Inside our day care 3', url: '/images/seeds/daycare3.jpg'}
                     ]
                    },
                    {type: 'daycare', name: 'Outside our day care', description: 'This is how our day care looks outside.',
                     pictures: [
                        {primary: false, description: 'Outside our day care 1', url: '/images/seeds/daycare1.jpg'},
                        {primary: true, description: 'Outside our day care 2', url: '/images/seeds/daycare2.jpg'},
                        {primary: false, description: 'Outside our day care 3', url: '/images/seeds/daycare3.jpg'}
                     ]
                    },
                    {type: 'daycare', name: 'Our playground', description: 'This is how our playground looks like.',
                     pictures: [
                        {primary: true, description: 'Playground 1', url: '/images/seeds/daycare1.jpg'},
                        {primary: false, description: 'Playground 2', url: '/images/seeds/daycare2.jpg'},
                        {primary: false, description: 'Playground 3', url: '/images/seeds/daycare3.jpg'}
                     ]
                    },
                    {type: 'default', name: 'New Year party.', description: 'Pictures from New Year party.',
                     pictures: [
                        {primary: false, description: 'New Year 1', url: '/images/seeds/daycare1.jpg'},
                        {primary: false, description: 'New Year 2', url: '/images/seeds/daycare2.jpg'},
                        {primary: true, description: 'New Year 3', url: '/images/seeds/daycare3.jpg'}
                     ]
                    },
                    {type: 'default', name: 'Halloween party.', description: 'Trick or treat on Halloween.'}
                ];
                dayCare = new DayCare({name: 'daycare' + i, picture_sets: pictureSets});
                dayCare.save()
            }
        });

    });

    desc('Insert tags.');
    task('seed_tags', [], function (params) {
      require('./models/db_connect');
      Tag = require('./models/tag');
      Tag.remove()

      var generalAproachesToLearning = [
        "Play-Based", "Co-op", "Montessori"
      ];
      var learningPhilosophyAndToolsLanguage = [
        "Oral language", "Nursery rhymes", "poems", "songs", "Storybook", "reading", "Emerging", "literacy skills"
      ];
      var learningPhilosophyAndToolsCognitiveDev = [
        "Math & number sense", "Time & space", "Sci. reasoning/physical world", "Music", "Visual arts", "Physical activity", "Other subjects taught (specify)"
      ];
      var homeSchoolConnections = [
        "Notes", "Phone Calls", "Voice Mail", "Email", "Special Meetings", "Two or More Regular Conferences", "Drop-Off", "Pick-Up", "Regular newsletter/printed updates circulated to the whole school"
      ];
      homeSchoolSeparations = [
        "Pre-entry meetings with parents at school", "Extra staff dedicated to handle separation", "Small group sessions", "Parents in classroom early on", "Abbreviated schedule at start of school year"
      ];
      var certificates = [
        "CPR Certified", "First Aid Certified", "FIA Accepted", "Latchkey", "Educational Programs", "National Accreditation (NAFCC)", "Smoke-Free Environment", "Special Needs Children Accepted", "Do You Have Webcams available in your classes"
      ];
      var indoors = [
        "Clean restrooms and food preparation areas (with separate sinks)", "Adequate heating and ventilation", "Children are supervised at all times, even when they are sleeping", "Screened heating vents/heaters",
     "Inaccessible electrical outlets, stoves, and pilot lights", "Fire extinguishers and smoke detectors", "Adequate fire exits (at least two)", "Sharp edges are padded", "Cabinets have 'child proof' guards",
     "Adequate first-aid kit (indoors and out)", "Place for children's clothes and belongings", "Quiet nap area", "Dramatic play area (dress-up clothes, toy stove and sink, strollers)", "Low tables and chairs",
     "Musical toys", "Stuffed animals and dolls", "Record/cassette player (records/cassettes)", "Blocks and block accessories", "Age-appropriate manipulative toys (puzzles, etc.)", "Art supplies, clay, play dough",
     "Children's artwork displayed", "Age-appropriate books"
      ];
      var outdoors = [
        "Playground surrounded by a fence", "playground equipment is safe, with no sharp edges, and kept in good shape", "the soil and playground surfaces are often checked for dangerous substances and hazards", "Yard free of debris",
     "Drinking water available", "Sand or digging area", "Water play supplies", "Sturdy climbing equipment (with cushioning material beneath)", "Tricycles and other mobility toys", "Easels and paint", "Grass, shade trees, garden area"
      ];
      var forInfants = [
        "Toys that are a safe size (non-swallowable) and that can be easily sanitized", "Colorful mobiles and pictures", "Outdoor area with safe crawling space", "Equipment that infants can crawl over and through",
     "Wheel toys that are safe for toddlers to ride on, push, and be given rides in", "Sanitary diaper changing area accessible to running water", "Toilet-training procedures communicated to parents",
     "Daily observation charts recording feeding, napping, and diapering/toileting",
     "All child care staff, volunteers, and substitutes have been trained on and implementing infant back sleeping and safe sleep policies to reduce the risk of SIDS (Sudden Infant Death Syndrome)",
     "Caregivers always keep a hand on the child while diapering", "Caregivers clean and sanitize the surface after finishing the changing process of diapering"
      ];
      var healthAndSafetyIssues = [
        "Children are supervised at all times, even when they are sleeping", "The child care program have records proving that the other children in care are up-to-date on all their required immunizations",
     "The child care program have an emergency plan if a child is injured, sick, or lost", "All caregivers been trained how to prevent child abuse, how to recognize signs of child abuse, and  how to report suspected child abuse",
     "The caregivers were trained and the medications  are labeled to make sure the right child gets the right amount of the right medication at the right time", "The child care program has a first aid kit",
     "The staff have training in infant and child first aid, CPR, and infectious diseases", "The staff has been trained to understand and meet the needs of children of different ages",
     "All caregivers and children wash their hands often, especially before eating and after using the bathroom or changing diapers", "A health evaluation is required for a child to enter the program",
     "Emergency phone numbers are clearly posted (work/home, your pediatrician, a friend or relative, fire, police)", "Procedures are established to care for a child who becomes sick or is injured",
     "Every child has access to and wears a seat belt when traveling in a vehicle", "Car seats are provided for children who require them", "The facility has an earthquake or emergency evacuation plan",
     "The provider has emergency supplies stored in case of an earthquake", "Medicines, poisons, and pointed items are kept out of children's sight and reach"
      ];
      var transportationPolicies = [
        "Parents bring their children to and from school.", "Private bus service available.", "Located close to public transportation."
      ];

      var tagsToSeed = {
        general_aproach_to_learning: generalAproachesToLearning,
        learning_philosophy_and_tools_language: learningPhilosophyAndToolsLanguage,
        learning_philosophy_and_tools_cognitive_dev: learningPhilosophyAndToolsCognitiveDev,
        home_school_connections: homeSchoolConnections,
        home_school_separations: homeSchoolSeparations,
        certificates: certificates,
        indoors: indoors,
        outdoors: outdoors,
        for_infants: forInfants,
        health_and_safety_issues: healthAndSafetyIssues,
        transportation_policies: transportationPolicies
      };

      _.each(tagsToSeed, function (tags, tagType) {
        _.each(tags, function (tagName) {
          var tag = new Tag({type: tagType, name: tagName});
          tag.save()
        });
      });
    });

    desc('Repair locations.');
    task('repair_users_locations', [], function (params) {
        process.env.NODE_ENV = 'development';
        require('./models/db_connect');
        var User = require('./models/user');
        User.update({}, {location: []}, {safe: false, multi: true}).run();

    });

});<commit_msg>Reset location<commit_after>var sys = require('sys')
var _   = require('underscore')

desc('Default task.');
task('default', [], function (params) {
  console.log('Jake is working.');
  console.log(sys.inspect(arguments));
});

namespace('db', function () {

    desc('Insert day cares for test environment.');
    task('seed_day_cares_for_test', [], function (params) {
        process.env.NODE_ENV = 'test';
        DayCare = require('./models/day_care');
        DayCare.find({}, null, null, function(err, dayCares) {
            for (var i = 0; i < dayCares.length; i++) {
                dayCares[i].remove();
            }

            for (var i = 1; i < 4; i++) {
                dayCare = new DayCare({name: 'daycare' + i})
                dayCare.save()
            }
        });

    });

    desc('Insert day cares for development environment.');
    task('seed_day_cares_for_development', [], function (params) {
        process.env.NODE_ENV = 'development';
        DayCare = require('./models/day_care');
//        PictureSet = require('./models/picture_set');
//        Picture = require('./models/picture');
        DayCare.find({}, null, null, function(err, dayCares) {
            for (var i = 0; i < dayCares.length; i++) {
                dayCares[i].remove();
            }

            for (var i = 1; i < 4; i++) {
                pictureSets = [
                    {type: 'profile', name: 'Profile pictures', description: 'Your profile pictures.',
                     pictures: [
                        {primary: true, description: 'Our logo', url: '/images/seeds/profile_pic.jpg'}
                     ]
                    },
                    {type: 'daycare', name: 'Inside our day care', description: 'This is how our day care looks inside.',
                     pictures: [
                        {primary: false, description: 'Inside our day care 1', url: '/images/seeds/daycare1.jpg'},
                        {primary: true, description: 'Inside our day care 2', url: '/images/seeds/daycare2.jpg'},
                        {primary: false, description: 'Inside our day care 3', url: '/images/seeds/daycare3.jpg'}
                     ]
                    },
                    {type: 'daycare', name: 'Outside our day care', description: 'This is how our day care looks outside.',
                     pictures: [
                        {primary: false, description: 'Outside our day care 1', url: '/images/seeds/daycare1.jpg'},
                        {primary: true, description: 'Outside our day care 2', url: '/images/seeds/daycare2.jpg'},
                        {primary: false, description: 'Outside our day care 3', url: '/images/seeds/daycare3.jpg'}
                     ]
                    },
                    {type: 'daycare', name: 'Our playground', description: 'This is how our playground looks like.',
                     pictures: [
                        {primary: true, description: 'Playground 1', url: '/images/seeds/daycare1.jpg'},
                        {primary: false, description: 'Playground 2', url: '/images/seeds/daycare2.jpg'},
                        {primary: false, description: 'Playground 3', url: '/images/seeds/daycare3.jpg'}
                     ]
                    },
                    {type: 'default', name: 'New Year party.', description: 'Pictures from New Year party.',
                     pictures: [
                        {primary: false, description: 'New Year 1', url: '/images/seeds/daycare1.jpg'},
                        {primary: false, description: 'New Year 2', url: '/images/seeds/daycare2.jpg'},
                        {primary: true, description: 'New Year 3', url: '/images/seeds/daycare3.jpg'}
                     ]
                    },
                    {type: 'default', name: 'Halloween party.', description: 'Trick or treat on Halloween.'}
                ];
                dayCare = new DayCare({name: 'daycare' + i, picture_sets: pictureSets});
                dayCare.save()
            }
        });

    });

    desc('Insert tags.');
    task('seed_tags', [], function (params) {
      require('./models/db_connect');
      Tag = require('./models/tag');
      Tag.remove()

      var generalAproachesToLearning = [
        "Play-Based", "Co-op", "Montessori"
      ];
      var learningPhilosophyAndToolsLanguage = [
        "Oral language", "Nursery rhymes", "poems", "songs", "Storybook", "reading", "Emerging", "literacy skills"
      ];
      var learningPhilosophyAndToolsCognitiveDev = [
        "Math & number sense", "Time & space", "Sci. reasoning/physical world", "Music", "Visual arts", "Physical activity", "Other subjects taught (specify)"
      ];
      var homeSchoolConnections = [
        "Notes", "Phone Calls", "Voice Mail", "Email", "Special Meetings", "Two or More Regular Conferences", "Drop-Off", "Pick-Up", "Regular newsletter/printed updates circulated to the whole school"
      ];
      homeSchoolSeparations = [
        "Pre-entry meetings with parents at school", "Extra staff dedicated to handle separation", "Small group sessions", "Parents in classroom early on", "Abbreviated schedule at start of school year"
      ];
      var certificates = [
        "CPR Certified", "First Aid Certified", "FIA Accepted", "Latchkey", "Educational Programs", "National Accreditation (NAFCC)", "Smoke-Free Environment", "Special Needs Children Accepted", "Do You Have Webcams available in your classes"
      ];
      var indoors = [
        "Clean restrooms and food preparation areas (with separate sinks)", "Adequate heating and ventilation", "Children are supervised at all times, even when they are sleeping", "Screened heating vents/heaters",
     "Inaccessible electrical outlets, stoves, and pilot lights", "Fire extinguishers and smoke detectors", "Adequate fire exits (at least two)", "Sharp edges are padded", "Cabinets have 'child proof' guards",
     "Adequate first-aid kit (indoors and out)", "Place for children's clothes and belongings", "Quiet nap area", "Dramatic play area (dress-up clothes, toy stove and sink, strollers)", "Low tables and chairs",
     "Musical toys", "Stuffed animals and dolls", "Record/cassette player (records/cassettes)", "Blocks and block accessories", "Age-appropriate manipulative toys (puzzles, etc.)", "Art supplies, clay, play dough",
     "Children's artwork displayed", "Age-appropriate books"
      ];
      var outdoors = [
        "Playground surrounded by a fence", "playground equipment is safe, with no sharp edges, and kept in good shape", "the soil and playground surfaces are often checked for dangerous substances and hazards", "Yard free of debris",
     "Drinking water available", "Sand or digging area", "Water play supplies", "Sturdy climbing equipment (with cushioning material beneath)", "Tricycles and other mobility toys", "Easels and paint", "Grass, shade trees, garden area"
      ];
      var forInfants = [
        "Toys that are a safe size (non-swallowable) and that can be easily sanitized", "Colorful mobiles and pictures", "Outdoor area with safe crawling space", "Equipment that infants can crawl over and through",
     "Wheel toys that are safe for toddlers to ride on, push, and be given rides in", "Sanitary diaper changing area accessible to running water", "Toilet-training procedures communicated to parents",
     "Daily observation charts recording feeding, napping, and diapering/toileting",
     "All child care staff, volunteers, and substitutes have been trained on and implementing infant back sleeping and safe sleep policies to reduce the risk of SIDS (Sudden Infant Death Syndrome)",
     "Caregivers always keep a hand on the child while diapering", "Caregivers clean and sanitize the surface after finishing the changing process of diapering"
      ];
      var healthAndSafetyIssues = [
        "Children are supervised at all times, even when they are sleeping", "The child care program have records proving that the other children in care are up-to-date on all their required immunizations",
     "The child care program have an emergency plan if a child is injured, sick, or lost", "All caregivers been trained how to prevent child abuse, how to recognize signs of child abuse, and  how to report suspected child abuse",
     "The caregivers were trained and the medications  are labeled to make sure the right child gets the right amount of the right medication at the right time", "The child care program has a first aid kit",
     "The staff have training in infant and child first aid, CPR, and infectious diseases", "The staff has been trained to understand and meet the needs of children of different ages",
     "All caregivers and children wash their hands often, especially before eating and after using the bathroom or changing diapers", "A health evaluation is required for a child to enter the program",
     "Emergency phone numbers are clearly posted (work/home, your pediatrician, a friend or relative, fire, police)", "Procedures are established to care for a child who becomes sick or is injured",
     "Every child has access to and wears a seat belt when traveling in a vehicle", "Car seats are provided for children who require them", "The facility has an earthquake or emergency evacuation plan",
     "The provider has emergency supplies stored in case of an earthquake", "Medicines, poisons, and pointed items are kept out of children's sight and reach"
      ];
      var transportationPolicies = [
        "Parents bring their children to and from school.", "Private bus service available.", "Located close to public transportation."
      ];

      var tagsToSeed = {
        general_aproach_to_learning: generalAproachesToLearning,
        learning_philosophy_and_tools_language: learningPhilosophyAndToolsLanguage,
        learning_philosophy_and_tools_cognitive_dev: learningPhilosophyAndToolsCognitiveDev,
        home_school_connections: homeSchoolConnections,
        home_school_separations: homeSchoolSeparations,
        certificates: certificates,
        indoors: indoors,
        outdoors: outdoors,
        for_infants: forInfants,
        health_and_safety_issues: healthAndSafetyIssues,
        transportation_policies: transportationPolicies
      };

      _.each(tagsToSeed, function (tags, tagType) {
        _.each(tags, function (tagName) {
          var tag = new Tag({type: tagType, name: tagName});
          tag.save()
        });
      });
    });

    desc('Repair locations.');
    task('repair_users_locations', [], function (params) {
        process.env.NODE_ENV = 'development';
        require('./models/db_connect');
        var User = require('./models/user');
        User.update({}, {location: []}, {safe: false, multi: true}).run();

    });

    desc('Repair locations in production.');
    task('repair_users_locations_prod', [], function (params) {
        process.env.NODE_ENV = 'production';
        require('./models/db_connect');
        var User = require('./models/user');
        User.update({}, {location: []}, {safe: false, multi: true}).run();

    });

});<|endoftext|>