keep keep keep keep replace keep keep keep

text: `<span class=\"copyonly\">\`${ p1 }\`</span>${ p2 }`,

/* eslint-env mocha */
import 'babel-polyfill';
import assert from 'assert';
import './client.mocks.js';
import {original} from '../parser/original/original';
// import {marked} from '../parser/marked/marked';

const wrapper = (text, tag) => `<span class="copyonly">${ tag }</span>${ text }<span class="copyonly">${ tag }</span>`;
const boldWrapper = text => wrapper(`<strong>${ text }</strong>`, '*');
const italicWrapper = text => wrapper(`<em>${ text }</em>`, '_');
const strikeWrapper = text => wrapper(`<strike>${ text }</strike>`, '~');
const headerWrapper = (text, level) => `<h${ level }>${ text }</h${ level }>`;
const quoteWrapper = text => `<blockquote class="background-transparent-darker-before"><span class="copyonly">></span>${ text }</blockquote>`;
const linkWrapped = (link, title) => `<a href="${ link }" target="_blank" rel="noopener noreferrer">${ title }</a>`;
const inlinecodeWrapper = text => wrapper(`<span><code class="code-colors inline">${ text }</code></span>`, '`');
const codeWrapper = (text, lang) => `<pre><code class='code-colors hljs ${ lang }'><span class='copyonly'>\`\`\`
${ text }
\`\`\`</span></code></pre>`;

const bold = {
	'*Hello*': boldWrapper('Hello'),
	'**Hello**': boldWrapper('Hello'),
	'**Hello*': boldWrapper('Hello'),
	'*Hello**': boldWrapper('Hello'),
	'Hello': 'Hello',
	'*Hello': '*Hello',
	'Hello*': 'Hello*',
	'He*llo': 'He*llo',
	'***Hello***': '***Hello***',
	'***Hello**': '***Hello**',
	'*Hello* this is dog': `${ boldWrapper('Hello') } this is dog`,
	'Rocket cat says *Hello*': `Rocket cat says ${ boldWrapper('Hello') }`,
	'He said *Hello* to her': `He said ${ boldWrapper('Hello') } to her`,
	'**Hello** this is dog': `${ boldWrapper('Hello') } this is dog`,
	'Rocket cat says **Hello**': `Rocket cat says ${ boldWrapper('Hello') }`,
	'He said **Hello** to her': `He said ${ boldWrapper('Hello') } to her`
};

const italic = {
	'_Hello_': italicWrapper('Hello'),
	'__Hello__': italicWrapper('Hello'),
	'__Hello_': italicWrapper('Hello'),
	'_Hello__': italicWrapper('Hello'),
	'Hello': 'Hello',
	'_Hello': '_Hello',
	'Hello_': 'Hello_',
	'He_llo': 'He_llo',
	'___Hello___': '___Hello___',
	'___Hello__': '___Hello__',
	'_Hello_ this is dog': `${ italicWrapper('Hello') } this is dog`,
	'Rocket cat says _Hello_': `Rocket cat says ${ italicWrapper('Hello') }`,
	'He said _Hello_ to her': `He said ${ italicWrapper('Hello') } to her`,
	'__Hello__ this is dog': `${ italicWrapper('Hello') } this is dog`,
	'Rocket cat says __Hello__': `Rocket cat says ${ italicWrapper('Hello') }`,
	'He said __Hello__ to her': `He said ${ italicWrapper('Hello') } to her`
};

const strike = {
	'~Hello~': strikeWrapper('Hello'),
	'~~Hello~~': strikeWrapper('Hello'),
	'~~Hello~': strikeWrapper('Hello'),
	'~Hello~~': strikeWrapper('Hello'),
	'Hello': 'Hello',
	'~Hello': '~Hello',
	'Hello~': 'Hello~',
	'He~llo': 'He~llo',
	'~~~Hello~~~': '~~~Hello~~~',
	'~~~Hello~~': '~~~Hello~~',
	'~Hello~ this is dog': `${ strikeWrapper('Hello') } this is dog`,
	'Rocket cat says ~Hello~': `Rocket cat says ${ strikeWrapper('Hello') }`,
	'He said ~Hello~ to her': `He said ${ strikeWrapper('Hello') } to her`,
	'~~Hello~~ this is dog': `${ strikeWrapper('Hello') } this is dog`,
	'Rocket cat says ~~Hello~~': `Rocket cat says ${ strikeWrapper('Hello') }`,
	'He said ~~Hello~~ to her': `He said ${ strikeWrapper('Hello') } to her`
};

const headersLevel1 = {
	'# Hello': headerWrapper('Hello', 1),
	'# Rocket.Cat': headerWrapper('Rocket.Cat', 1),
	'# Hi': headerWrapper('Hi', 1),
	'# Hello this is dog': headerWrapper('Hello this is dog', 1),
	'# Rocket cat says Hello': headerWrapper('Rocket cat says Hello', 1),
	'# He said Hello to her': headerWrapper('He said Hello to her', 1),
	'#Hello': '#Hello',
	'#Hello#': '#Hello#',
	'He#llo': 'He#llo'
};

const headersLevel2 = {
	'## Hello': headerWrapper('Hello', 2),
	'## Rocket.Cat': headerWrapper('Rocket.Cat', 2),
	'## Hi': headerWrapper('Hi', 2),
	'## Hello this is dog': headerWrapper('Hello this is dog', 2),
	'## Rocket cat says Hello': headerWrapper('Rocket cat says Hello', 2),
	'## He said Hello to her': headerWrapper('He said Hello to her', 2),
	'##Hello': '##Hello',
	'##Hello##': '##Hello##',
	'He##llo': 'He##llo'
};

const headersLevel3 = {
	'### Hello': headerWrapper('Hello', 3),
	'### Rocket.Cat': headerWrapper('Rocket.Cat', 3),
	'### Hi': headerWrapper('Hi', 3),
	'### Hello this is dog': headerWrapper('Hello this is dog', 3),
	'### Rocket cat says Hello': headerWrapper('Rocket cat says Hello', 3),
	'### He said Hello to her': headerWrapper('He said Hello to her', 3),
	'###Hello': '###Hello',
	'###Hello###': '###Hello###',
	'He###llo': 'He###llo'
};

const headersLevel4 = {
	'#### Hello': headerWrapper('Hello', 4),
	'#### Rocket.Cat': headerWrapper('Rocket.Cat', 4),
	'#### Hi': headerWrapper('Hi', 4),
	'#### Hello this is dog': headerWrapper('Hello this is dog', 4),
	'#### Rocket cat says Hello': headerWrapper('Rocket cat says Hello', 4),
	'#### He said Hello to her': headerWrapper('He said Hello to her', 4),
	'####Hello': '####Hello',
	'####Hello####': '####Hello####',
	'He####llo': 'He####llo'
};

const quote = {
	'>Hello': quoteWrapper('Hello'),
	'>Rocket.Cat': quoteWrapper('Rocket.Cat'),
	'>Hi': quoteWrapper('Hi'),
	'> Hello this is dog': quoteWrapper(' Hello this is dog'),
	'> Rocket cat says Hello': quoteWrapper(' Rocket cat says Hello'),
	'> He said Hello to her': quoteWrapper(' He said Hello to her'),
	'> He said Hello to her ': quoteWrapper(' He said Hello to her '),
	'<Hello': '<Hello',
	'<Rocket.Cat>': '<Rocket.Cat>',
	' >Hi': ' >Hi',
	'Hello > this is dog': 'Hello > this is dog',
	'Roc>ket cat says Hello': 'Roc>ket cat says Hello',
	'He said Hello to her>': 'He said Hello to her>',
	'>Hello': '>Hello',
	'>Rocket.Cat': '>Rocket.Cat',
	'>Hi': '>Hi',
	'> Hello this is dog': '> Hello this is dog',
	'> Rocket cat says Hello': '> Rocket cat says Hello',
	'> He said Hello to her': '> He said Hello to her',
	'<Hello': '<Hello',
	'<Rocket.Cat>': '<Rocket.Cat>',
	' >Hi': ' >Hi',
	'Hello > this is dog': 'Hello > this is dog',
	'Roc>ket cat says Hello': 'Roc>ket cat says Hello',
	'He said Hello to her>': 'He said Hello to her>'
};

const link = {
	'<http://link|Text>': linkWrapped('http://link', 'Text'),
	'<https://open.rocket.chat/|Open Site For Rocket.Chat>': linkWrapped('https://open.rocket.chat/', 'Open Site For Rocket.Chat'),
	'<https://open.rocket.chat/ | Open Site For Rocket.Chat>': linkWrapped('https://open.rocket.chat/ ', ' Open Site For Rocket.Chat'),
	'<https://rocket.chat/|Rocket.Chat Site>': linkWrapped('https://rocket.chat/', 'Rocket.Chat Site'),
	'<https://rocket.chat/docs/developer-guides/testing/#testing|Testing Entry on Rocket.Chat Docs Site>': linkWrapped('https://rocket.chat/docs/developer-guides/testing/#testing', 'Testing Entry on Rocket.Chat Docs Site'),
	'<http://linkText>': '<http://linkText>',
	'<https:open.rocket.chat/ | Open Site For Rocket.Chat>': '<https:open.rocket.chat/ | Open Site For Rocket.Chat>',
	'https://open.rocket.chat/|Open Site For Rocket.Chat': 'https://open.rocket.chat/|Open Site For Rocket.Chat',
	'<www.open.rocket.chat/|Open Site For Rocket.Chat>': '<www.open.rocket.chat/|Open Site For Rocket.Chat>',
	'<htps://rocket.chat/|Rocket.Chat Site>': '<htps://rocket.chat/|Rocket.Chat Site>',
	'<ttps://rocket.chat/|Rocket.Chat Site>': '<ttps://rocket.chat/|Rocket.Chat Site>',
	'<tps://rocket.chat/|Rocket.Chat Site>': '<tps://rocket.chat/|Rocket.Chat Site>',
	'<open.rocket.chat/|Open Site For Rocket.Chat>': '<open.rocket.chat/|Open Site For Rocket.Chat>',
	'<htts://rocket.chat/docs/developer-guides/testing/#testing|Testing Entry on Rocket.Chat Docs Site>': '<htts://rocket.chat/docs/developer-guides/testing/#testing|Testing Entry on Rocket.Chat Docs Site>',

	'<http://link|Text>': linkWrapped('http://link', 'Text'),
	'<https://open.rocket.chat/|Open Site For Rocket.Chat>': linkWrapped('https://open.rocket.chat/', 'Open Site For Rocket.Chat'),
	'<https://open.rocket.chat/ | Open Site For Rocket.Chat>': linkWrapped('https://open.rocket.chat/ ', ' Open Site For Rocket.Chat'),
	'<https://rocket.chat/|Rocket.Chat Site>': linkWrapped('https://rocket.chat/', 'Rocket.Chat Site'),
	'<https://rocket.chat/docs/developer-guides/testing/#testing|Testing Entry on Rocket.Chat Docs Site>': linkWrapped('https://rocket.chat/docs/developer-guides/testing/#testing', 'Testing Entry on Rocket.Chat Docs Site'),
	'<http://linkText>': '<http://linkText>',
	'<https:open.rocket.chat/ | Open Site For Rocket.Chat>': '<https:open.rocket.chat/ | Open Site For Rocket.Chat>',
	'<www.open.rocket.chat/|Open Site For Rocket.Chat>': '<www.open.rocket.chat/|Open Site For Rocket.Chat>',
	'<htps://rocket.chat/|Rocket.Chat Site>': '<htps://rocket.chat/|Rocket.Chat Site>',
	'<ttps://rocket.chat/|Rocket.Chat Site>': '<ttps://rocket.chat/|Rocket.Chat Site>',
	'<tps://rocket.chat/|Rocket.Chat Site>': '<tps://rocket.chat/|Rocket.Chat Site>',
	'<open.rocket.chat/|Open Site For Rocket.Chat>': '<open.rocket.chat/|Open Site For Rocket.Chat>',
	'<htts://rocket.chat/docs/developer-guides/testing/#testing|Testing Entry on Rocket.Chat Docs Site>': '<htts://rocket.chat/docs/developer-guides/testing/#testing|Testing Entry on Rocket.Chat Docs Site>',

	'[Text](http://link)': linkWrapped('http://link', 'Text'),
	'[Open Site For Rocket.Chat](https://open.rocket.chat/)': linkWrapped('https://open.rocket.chat/', 'Open Site For Rocket.Chat'),
	'[ Open Site For Rocket.Chat](https://open.rocket.chat/ )': linkWrapped('https://open.rocket.chat/ ', ' Open Site For Rocket.Chat'),
	'[Rocket.Chat Site](https://rocket.chat/)': linkWrapped('https://rocket.chat/', 'Rocket.Chat Site'),
	'[Testing Entry on Rocket.Chat Docs Site](https://rocket.chat/docs/developer-guides/testing/#testing)': linkWrapped('https://rocket.chat/docs/developer-guides/testing/#testing', 'Testing Entry on Rocket.Chat Docs Site'),
	'[](http://linkText)': '[](http://linkText)',
	'[text]': '[text]',
	'[Open Site For Rocket.Chat](https:open.rocket.chat/)': '[Open Site For Rocket.Chat](https:open.rocket.chat/)',
	'[Open Site For Rocket.Chat](www.open.rocket.chat/)': '[Open Site For Rocket.Chat](www.open.rocket.chat/)',
	'[Rocket.Chat Site](htps://rocket.chat/)': '[Rocket.Chat Site](htps://rocket.chat/)',
	'[Rocket.Chat Site](ttps://rocket.chat/)': '[Rocket.Chat Site](ttps://rocket.chat/)',
	'[Rocket.Chat Site](tps://rocket.chat/)': '[Rocket.Chat Site](tps://rocket.chat/)',
	'[Open Site For Rocket.Chat](open.rocket.chat/)': '[Open Site For Rocket.Chat](open.rocket.chat/)',
	'[Testing Entry on Rocket.Chat Docs Site](htts://rocket.chat/docs/developer-guides/testing/#testing)': '[Testing Entry on Rocket.Chat Docs Site](htts://rocket.chat/docs/developer-guides/testing/#testing)'
};

const inlinecode = {
	'`code`': inlinecodeWrapper('code'),
	'`code` begin': `${ inlinecodeWrapper('code') } begin`,
	'End `code`': `End ${ inlinecodeWrapper('code') }`,
	'Middle `code` middle': `Middle ${ inlinecodeWrapper('code') } middle`,
	'`code`begin': `${ inlinecodeWrapper('code') }begin`,
	'End`code`': 'End`code`',
	'Middle`code`middle': 'Middle`code`middle'
};

const code = {
	'```code```': codeWrapper('code', 'clean'),
	'```code': codeWrapper('<span class="hljs-selector-tag">code</span>\n', 'stylus'),
	'```code\n': codeWrapper('code\n', 'stylus'),
	'```\ncode\n```': codeWrapper('code\n', 'stylus'),
	'```code\n```': codeWrapper('code\n', 'stylus'),
	'```\ncode```': codeWrapper('code', 'clean'),
	'```javascript\nvar a = \'log\';\nconsole.log(a);```': codeWrapper('var a = \'log\';\nconsole.log(a);', 'javascript'),
	'```*code*```': codeWrapper('*code*', 'armasm'),
	'```**code**```': codeWrapper('**code**', 'armasm'),
	'```_code_```': codeWrapper('_code_', 'sqf'),
	'```__code__```': codeWrapper('__code__', 'markdown')
};

const defaultObjectTest = (result, object, objectKey) => {
	return assert.equal(result.html, object[objectKey]);
};

const testObject = (object, parser = original, test = defaultObjectTest) => {
	Object.keys(object).forEach((objectKey) => {
		describe(objectKey, () => {
			const result = parser({html: objectKey});
			result.tokens.forEach((token) => {
				result.html = result.html.replace(token.token, token.text);
			});
			it(`should be equal to ${ object[objectKey] }`, () => {
				test(result, object, objectKey);
			});
		});
	});
};

describe('Original', function() {
	describe('Bold', () => testObject(bold));

	describe('Italic', () => testObject(italic));

	describe('Strike', () => testObject(strike));

	describe('Headers', () => {
		describe('Level 1', () => testObject(headersLevel1));

		describe('Level 2', () => testObject(headersLevel2));

		describe('Level 3', () => testObject(headersLevel3));

		describe('Level 4', () => testObject(headersLevel4));
	});

	describe('Quote', () => testObject(quote));

	describe('Link', () => testObject(link));

	describe('Inline Code', () => testObject(inlinecode));

	describe('Code', () => testObject(code));
});

// describe.only('Marked', function() {
// 	describe('Bold', () => testObject(bold, marked));

// 	describe('Italic', () => testObject(italic, marked));

// 	describe('Strike', () => testObject(strike, marked));

// 	describe('Headers', () => {
// 		describe('Level 1', () => testObject(headersLevel1, marked));

// 		describe('Level 2', () => testObject(headersLevel2, marked));

// 		describe('Level 3', () => testObject(headersLevel3, marked));

// 		describe('Level 4', () => testObject(headersLevel4, marked));
// 	});

// 	describe('Quote', () => testObject(quote, marked));
// });


const token = ` =!=${ Random.id() }=!=`;

Bạn có chắc chắn muốn kết thúc cuộc trò chuyện này?

Bạn có chắc chắn muốn kết thúc cuộc trò chuyện và bộ phận chuyển đổi này?

Làm thế nào thân thiện là các đại lý trò chuyện?

Làm thế nào hiểu được các đại lý trò chuyện?

Làm thế nào đáp ứng được đại lý trò chuyện?

Bạn cảm thấy hài lòng với cuộc trò chuyện này như thế nào?

Vui lòng dành một chút thời gian để trả lời một cuộc khảo sát nhanh về trò chuyện này

Được hỗ trợ bởi

Đánh giá mỗi câu hỏi theo sự hài lòng của bạn, 1 nghĩa là bạn hoàn toàn không hài lòng và 5 có nghĩa là bạn hoàn toàn hài lòng.

Cảm ơn! Chúng tôi sẽ sớm liên hệ lại với bạn.

Chúng tôi không trực tuyến ngay bây giờ. Xin vui lòng, để lại tin nhắn.

Chúng tôi đang offline. Xin lỗi vì sự bất tiện.


RocketChat.Migrations.add({
	version: 51,
	up() {
		RocketChat.models.Rooms.find({ t: 'l', 'v.token': { $exists: true }, label: { $exists: false }}).forEach(function(room) {
			const user = RocketChat.models.Users.findOne({ 'profile.token': room.v.token });
			if (user) {
				RocketChat.models.Rooms.update({ _id: room._id }, {
					$set: {
						label: user.name || user.username,
						'v._id': user._id
					}
				});
				RocketChat.models.Subscriptions.update({ rid: room._id }, {
					$set: {
						name: user.name || user.username
					}
				}, { multi: true });
			}
		});
	}
});


import _ from 'underscore';
import moment from 'moment';

Meteor.methods({
	deleteMessage(message) {
		if (!Meteor.userId()) {
			return false;
		}

		//We're now only passed in the `_id` property to lower the amount of data sent to the server
		message = ChatMessage.findOne({ _id: message._id });

		const hasPermission = RocketChat.authz.hasAtLeastOnePermission('delete-message', message.rid);
		const forceDelete = RocketChat.authz.hasAtLeastOnePermission('force-delete-message', message.rid);
		const deleteAllowed = RocketChat.settings.get('Message_AllowDeleting');
		let deleteOwn = false;

		if (message && message.u && message.u._id) {
			deleteOwn = message.u._id === Meteor.userId();
		}
		if (!(forceDelete || hasPermission || (deleteAllowed && deleteOwn))) {
			return false;
		}
		const blockDeleteInMinutes = RocketChat.settings.get('Message_AllowDeleting_BlockDeleteInMinutes');
		if (!forceDelete && _.isNumber(blockDeleteInMinutes) && blockDeleteInMinutes !== 0) {
			const msgTs = moment(message.ts);
			const currentTsDiff = moment().diff(msgTs, 'minutes');
			if (currentTsDiff > blockDeleteInMinutes) {
				return false;
			}

		}

		Tracker.nonreactive(function() {
			ChatMessage.remove({
				_id: message._id,
				'u._id': Meteor.userId()
			});
		});
	}
});


'End `code`': `End ${ inlinecodeWrapper('code') }`,

'Middle `code` middle': `Middle ${ inlinecodeWrapper('code') } middle`,

'`code`begin': `${ inlinecodeWrapper('code') }begin`,

keep keep keep replace replace keep keep keep keep keep

'End`code`': `End${ inlinecodeWrapper('code') }`,

'Middle`code`middle': `Middle${ inlinecodeWrapper('code') }middle`


class ImporterWebsocketReceiverDef {
	constructor() {
		this.streamer = new Meteor.Streamer('importers');

		this.callbacks = [];
		RocketChat.CachedCollectionManager.onLogin(() => {
			this.streamer.on('progress', this.progressUpdated.bind(this));
		});
	}

	progressUpdated(progress) {
		this.callbacks.forEach((c) => c(progress));
	}

	registerCallback(callback) {
		if (typeof callback !== 'function') {
			throw new Error('Callback must be a function.');
		}

		this.callbacks.push(callback);
	}

	unregisterCallback(callback) {
		const i = this.callbacks.indexOf(callback);
		if (i >= 0) {
			this.callbacks.splice(i, 1);
		}
	}
}

export const ImporterWebsocketReceiver = new ImporterWebsocketReceiverDef();


/*
 * Markdown is a named function that will parse markdown syntax
 * @param {Object} message - The message object
 */
import s from 'underscore.string';
import { Meteor } from 'meteor/meteor';
import { Blaze } from 'meteor/blaze';
import { RocketChat } from 'meteor/rocketchat:lib';

import { marked } from './parser/marked/marked.js';
import { original } from './parser/original/original.js';

import { code } from './parser/original/code.js';

const parsers = {
	original,
	marked
};

class MarkdownClass {
	parse(text) {
		const message = {
			html: s.escapeHTML(text)
		};
		return this.mountTokensBack(this.parseMessageNotEscaped(message)).html;
	}

	parseNotEscaped(text) {
		const message = {
			html: text
		};
		return this.mountTokensBack(this.parseMessageNotEscaped(message)).html;
	}

	parseMessageNotEscaped(message) {
		const parser = RocketChat.settings.get('Markdown_Parser');

		if (parser === 'disabled') {
			return message;
		}

		if (typeof parsers[parser] === 'function') {
			return parsers[parser](message);
		}
		return parsers['original'](message);
	}

	mountTokensBack(message, useHtml = true) {
		if (message.tokens && message.tokens.length > 0) {
			for (const {token, text, noHtml} of message.tokens) {
				message.html = message.html.replace(token, () => useHtml ? text : noHtml); // Uses lambda so doesn't need to escape $
			}
		}

		return message;
	}

	code(...args) {
		return code(...args);
	}
}

const Markdown = new MarkdownClass;
RocketChat.Markdown = Markdown;

// renderMessage already did html escape
const MarkdownMessage = (message) => {
	if (s.trim(message != null ? message.html : undefined)) {
		message = Markdown.parseMessageNotEscaped(message);
	}

	return message;
};

RocketChat.callbacks.add('renderMessage', MarkdownMessage, RocketChat.callbacks.priority.HIGH, 'markdown');

if (Meteor.isClient) {
	Blaze.registerHelper('RocketChatMarkdown', text => Markdown.parse(text));
	Blaze.registerHelper('RocketChatMarkdownUnescape', text => Markdown.parseNotEscaped(text));
}


//! moment.js locale configuration
//! locale : Luxembourgish [lb]
//! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz

;(function (global, factory) {
   typeof exports === 'object' && typeof module !== 'undefined'
       && typeof require === 'function' ? factory(require('../moment')) :
   typeof define === 'function' && define.amd ? define(['../moment'], factory) :
   factory(global.moment)
}(this, function (moment) { 'use strict';

    function processRelativeTime(number, withoutSuffix, key, isFuture) {
        var format = {
            'm': ['eng Minutt', 'enger Minutt'],
            'h': ['eng Stonn', 'enger Stonn'],
            'd': ['een Dag', 'engem Dag'],
            'M': ['ee Mount', 'engem Mount'],
            'y': ['ee Joer', 'engem Joer']
        };
        return withoutSuffix ? format[key][0] : format[key][1];
    }
    function processFutureTime(string) {
        var number = string.substr(0, string.indexOf(' '));
        if (eifelerRegelAppliesToNumber(number)) {
            return 'a ' + string;
        }
        return 'an ' + string;
    }
    function processPastTime(string) {
        var number = string.substr(0, string.indexOf(' '));
        if (eifelerRegelAppliesToNumber(number)) {
            return 'viru ' + string;
        }
        return 'virun ' + string;
    }
    /**
     * Returns true if the word before the given number loses the '-n' ending.
     * e.g. 'an 10 Deeg' but 'a 5 Deeg'
     *
     * @param number {integer}
     * @returns {boolean}
     */
    function eifelerRegelAppliesToNumber(number) {
        number = parseInt(number, 10);
        if (isNaN(number)) {
            return false;
        }
        if (number < 0) {
            // Negative Number --> always true
            return true;
        } else if (number < 10) {
            // Only 1 digit
            if (4 <= number && number <= 7) {
                return true;
            }
            return false;
        } else if (number < 100) {
            // 2 digits
            var lastDigit = number % 10, firstDigit = number / 10;
            if (lastDigit === 0) {
                return eifelerRegelAppliesToNumber(firstDigit);
            }
            return eifelerRegelAppliesToNumber(lastDigit);
        } else if (number < 10000) {
            // 3 or 4 digits --> recursively check first digit
            while (number >= 10) {
                number = number / 10;
            }
            return eifelerRegelAppliesToNumber(number);
        } else {
            // Anything larger than 4 digits: recursively check first n-3 digits
            number = number / 1000;
            return eifelerRegelAppliesToNumber(number);
        }
    }

    var lb = moment.defineLocale('lb', {
        months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
        monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
        monthsParseExact : true,
        weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'),
        weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'),
        weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'),
        weekdaysParseExact : true,
        longDateFormat: {
            LT: 'H:mm [Auer]',
            LTS: 'H:mm:ss [Auer]',
            L: 'DD.MM.YYYY',
            LL: 'D. MMMM YYYY',
            LLL: 'D. MMMM YYYY H:mm [Auer]',
            LLLL: 'dddd, D. MMMM YYYY H:mm [Auer]'
        },
        calendar: {
            sameDay: '[Haut um] LT',
            sameElse: 'L',
            nextDay: '[Muer um] LT',
            nextWeek: 'dddd [um] LT',
            lastDay: '[Gëschter um] LT',
            lastWeek: function () {
                // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule
                switch (this.day()) {
                    case 2:
                    case 4:
                        return '[Leschten] dddd [um] LT';
                    default:
                        return '[Leschte] dddd [um] LT';
                }
            }
        },
        relativeTime : {
            future : processFutureTime,
            past : processPastTime,
            s : 'e puer Sekonnen',
            m : processRelativeTime,
            mm : '%d Minutten',
            h : processRelativeTime,
            hh : '%d Stonnen',
            d : processRelativeTime,
            dd : '%d Deeg',
            M : processRelativeTime,
            MM : '%d Méint',
            y : processRelativeTime,
            yy : '%d Joer'
        },
        ordinalParse: /\d{1,2}\./,
        ordinal: '%d.',
        week: {
            dow: 1, // Monday is the first day of the week.
            doy: 4  // The week that contains Jan 4th is the first week of the year.
        }
    });

    return lb;

}));


"use strict";

jest.mock("@lerna/run-lifecycle");
jest.mock("read-package-json");
jest.mock("libnpmpublish");
jest.mock("fs-extra");

// mocked modules
const fs = require("fs-extra");
const { publish } = require("libnpmpublish");
const readJSON = require("read-package-json");
const runLifecycle = require("@lerna/run-lifecycle");

// helpers
const path = require("path");
const Package = require("@lerna/package");

// file under test
const npmPublish = require("..");

expect.extend(require("@lerna-test/figgy-pudding-matchers"));

describe("npm-publish", () => {
  const mockTarData = Buffer.from("MOCK");
  const mockManifest = { _normalized: true };

  fs.readFile.mockName("fs.readFile").mockResolvedValue(mockTarData);
  publish.mockName("libnpmpublish").mockResolvedValue();
  readJSON.mockName("read-package-json").mockImplementation((file, cb) => cb(null, mockManifest));
  runLifecycle.mockName("@lerna/run-lifecycle").mockResolvedValue();

  const tarFilePath = "/tmp/test-1.10.100.tgz";
  const rootPath = path.normalize("/test");
  const pkg = new Package(
    { name: "test", version: "1.10.100" },
    path.join(rootPath, "npmPublish/test"),
    rootPath
  );

  it("calls external libraries with correct arguments", async () => {
    const opts = new Map().set("tag", "published-tag");

    await npmPublish(pkg, tarFilePath, opts);

    expect(fs.readFile).toHaveBeenCalledWith(tarFilePath);
    expect(readJSON).toHaveBeenCalledWith(pkg.manifestLocation, expect.any(Function));
    expect(publish).toHaveBeenCalledWith(
      mockManifest,
      mockTarData,
      expect.figgyPudding({
        dryRun: false,
        projectScope: "test",
        tag: "published-tag",
      })
    );
  });

  it("defaults opts.tag to 'latest'", async () => {
    await npmPublish(pkg, tarFilePath);

    expect(publish).toHaveBeenCalledWith(
      mockManifest,
      mockTarData,
      expect.figgyPudding({
        tag: "latest",
      })
    );
  });

  it("overrides pkg.publishConfig.tag when opts.tag is not defaulted", async () => {
    readJSON.mockImplementationOnce((file, cb) =>
      cb(null, {
        publishConfig: {
          tag: "beta",
        },
      })
    );
    const opts = new Map().set("tag", "temp-tag");

    await npmPublish(pkg, tarFilePath, opts);

    expect(publish).toHaveBeenCalledWith(
      expect.objectContaining({
        publishConfig: {
          tag: "temp-tag",
        },
      }),
      mockTarData,
      expect.figgyPudding({
        tag: "temp-tag",
      })
    );
  });

  it("respects pkg.publishConfig.tag when opts.tag matches default", async () => {
    readJSON.mockImplementationOnce((file, cb) =>
      cb(null, {
        publishConfig: {
          tag: "beta",
        },
      })
    );

    await npmPublish(pkg, tarFilePath);

    expect(publish).toHaveBeenCalledWith(
      expect.objectContaining({
        publishConfig: {
          tag: "beta",
        },
      }),
      mockTarData,
      expect.figgyPudding({
        tag: "latest",
      })
    );
  });

  it("respects opts.dryRun", async () => {
    const opts = new Map().set("dryRun", true);

    await npmPublish(pkg, tarFilePath, opts);

    expect(publish).not.toHaveBeenCalled();
    expect(runLifecycle).toHaveBeenCalledTimes(2);
  });

  it("calls publish lifecycles", async () => {
    const aFiggyPudding = expect.figgyPudding({
      projectScope: "test",
    });

    await npmPublish(pkg, tarFilePath);

    expect(runLifecycle).toHaveBeenCalledWith(pkg, "publish", aFiggyPudding);
    expect(runLifecycle).toHaveBeenLastCalledWith(pkg, "postpublish", aFiggyPudding);
  });

  it("catches libnpm errors", async () => {
    publish.mockImplementationOnce(() => {
      const err = new Error("whoopsy");
      err.code = "E401";
      err.body = {
        error: "doodle",
      };
      return Promise.reject(err);
    });

    const log = {
      verbose: jest.fn(),
      silly: jest.fn(),
      error: jest.fn(),
    };
    const opts = new Map().set("log", log);

    try {
      await npmPublish(pkg, tarFilePath, opts);
    } catch (err) {
      expect(err.message).toBe("whoopsy");
      expect(err.name).toBe("ValidationError");
      expect(log.error).toHaveBeenLastCalledWith("E401", "doodle");
      expect(process.exitCode).toBe(1);
    }

    publish.mockImplementationOnce(() => {
      const err = new Error("lolwut");
      err.code = "E404";
      err.errno = 9001;
      return Promise.reject(err);
    });

    try {
      await npmPublish(pkg, tarFilePath, opts);
    } catch (err) {
      expect(err.message).toBe("lolwut");
      expect(log.error).toHaveBeenLastCalledWith("E404", "lolwut");
      expect(process.exitCode).toBe(9001);
    }

    expect.hasAssertions();
  });
});


"use strict";

jest.mock("pacote/packument");

// mocked module(s)
const getPackument = require("pacote/packument");

// helpers
const PackageGraph = require("@lerna/package-graph");
const { getPackages } = require("@lerna/project");
const initFixture = require("@lerna-test/init-fixture")(__dirname);

// file under test
const getUnpublishedPackages = require("../lib/get-unpublished-packages");

getPackument.mockImplementation(async pkg => {
  if (pkg === "package-1") {
    return {
      versions: {},
    };
  }

  if (pkg === "package-2") {
    return {
      versions: {
        "1.0.0": {},
      },
    };
  }

  throw new Error("package does not exist");
});

test("getUnpublishedPackages", async () => {
  const cwd = await initFixture("licenses-names");
  const packages = await getPackages(cwd);
  const packageGraph = new PackageGraph(packages);

  const opts = new Map();
  const pkgs = await getUnpublishedPackages(packageGraph, opts);

  expect(pkgs).toMatchInlineSnapshot(`
Array [
  PackageGraphNode {
    "externalDependencies": Map {},
    "localDependencies": Map {},
    "localDependents": Map {},
    "name": "package-1",
  },
  PackageGraphNode {
    "externalDependencies": Map {},
    "localDependencies": Map {},
    "localDependents": Map {},
    "name": "package-3",
  },
  PackageGraphNode {
    "externalDependencies": Map {},
    "localDependencies": Map {},
    "localDependents": Map {},
    "name": "package-4",
  },
  PackageGraphNode {
    "externalDependencies": Map {},
    "localDependencies": Map {},
    "localDependents": Map {},
    "name": "package-5",
  },
]
`);
});

test("getUnpublishedPackages with private package", async () => {
  const cwd = await initFixture("public-private");
  const packages = await getPackages(cwd);
  const packageGraph = new PackageGraph(packages);

  const opts = new Map();
  const pkgs = await getUnpublishedPackages(packageGraph, opts);

  expect(pkgs).toMatchInlineSnapshot(`
Array [
  PackageGraphNode {
    "externalDependencies": Map {},
    "localDependencies": Map {},
    "localDependents": Map {},
    "name": "package-1",
  },
]
`);
});


"use strict";

const log = require("npmlog");

const ChildProcessUtilities = require("@lerna/child-process");
const getOpts = require("@lerna/get-npm-exec-opts");

module.exports = runScript;
module.exports.stream = stream;

function runScript(script, { args, npmClient, pkg, reject = true }) {
  log.silly("npmRunScript", script, args, pkg.name);

  const argv = ["run", script, ...args];
  const opts = makeOpts(pkg, reject);

  return ChildProcessUtilities.exec(npmClient, argv, opts);
}

function stream(script, { args, npmClient, pkg, prefix, reject = true }) {
  log.silly("npmRunScript.stream", [script, args, pkg.name]);

  const argv = ["run", script, ...args];
  const opts = makeOpts(pkg, reject);

  return ChildProcessUtilities.spawnStreaming(npmClient, argv, opts, prefix && pkg.name);
}

function makeOpts(pkg, reject) {
  return Object.assign(getOpts(pkg), {
    reject,
  });
}


"use strict";

// eslint-disable-next-line import/no-extraneous-dependencies, node/no-extraneous-require
const Project = require("@lerna/project");

module.exports = updateLernaConfig;

/**
 * Update lerna config inside a test case.
 *
 * @param {String} testDir where target lerna.json exists
 * @param {Object} updates mixed into existing JSON via Object.assign
 */
function updateLernaConfig(testDir, updates) {
  const project = new Project(testDir);

  Object.assign(project.config, updates);

  return project.serializeConfig();
}


const tarFilePath = "/tmp/test-1.10.100.tgz";

const rootPath = path.normalize("/test");

{ name: "@scope/test", version: "1.10.100" },


# `@lerna/npm-dist-tag`

> An internal Lerna tool

## Usage

You probably shouldn't, at least directly.

Install [lerna](https://www.npmjs.com/package/lerna) for access to the `lerna` CLI.


"use strict";

const fs = require("fs-extra");
const log = require("npmlog");
const { publish } = require("libnpmpublish");
const pify = require("pify");
const readJSON = require("read-package-json");
const figgyPudding = require("figgy-pudding");
const runLifecycle = require("@lerna/run-lifecycle");

module.exports = npmPublish;

const readJSONAsync = pify(readJSON);

const PublishConfig = figgyPudding(
  {
    "dry-run": { default: false },
    dryRun: "dry-run",
    log: { default: log },
    "project-scope": {},
    projectScope: "project-scope",
    tag: { default: "latest" },
  },
  {
    other() {
      // open it up for the sake of tests
      return true;
    },
  }
);

function npmPublish(pkg, tarFilePath, _opts) {
  const opts = PublishConfig(_opts, {
    projectScope: pkg.name,
  });

  opts.log.verbose("publish", pkg.name);

  let chain = Promise.resolve();

  if (!opts.dryRun) {
    chain = chain.then(() => Promise.all([fs.readFile(tarFilePath), readJSONAsync(pkg.manifestLocation)]));
    chain = chain.then(([tarData, manifest]) => {
      // non-default tag needs to override publishConfig.tag,
      // which is merged over opts.tag in libnpmpublish
      if (
        opts.tag !== "latest" &&
        manifest.publishConfig &&
        manifest.publishConfig.tag &&
        manifest.publishConfig.tag !== opts.tag
      ) {
        // eslint-disable-next-line no-param-reassign
        manifest.publishConfig.tag = opts.tag;
      }

      return publish(manifest, tarData, opts).catch(err => {
        opts.log.silly("", err);
        opts.log.error(err.code, (err.body && err.body.error) || err.message);

        // avoid dumping logs, this isn't a lerna problem
        err.name = "ValidationError";

        // ensure process exits non-zero
        process.exitCode = "errno" in err ? err.errno : 1;

        // re-throw to break chain upstream
        throw err;
      });
    });
  }

  chain = chain.then(() => runLifecycle(pkg, "publish", opts));
  chain = chain.then(() => runLifecycle(pkg, "postpublish", opts));

  return chain;
}


"use strict";

// local modules _must_ be explicitly mocked
jest.mock("../lib/get-packages-without-license");
jest.mock("../lib/verify-npm-package-access");
jest.mock("../lib/get-npm-username");
jest.mock("../lib/get-unpublished-packages");
// FIXME: better mock for version command
jest.mock("../../version/lib/git-push");
jest.mock("../../version/lib/is-anything-committed");
jest.mock("../../version/lib/is-behind-upstream");
jest.mock("../../version/lib/remote-branch-exists");

// mocked or stubbed modules
const npmDistTag = require("@lerna/npm-dist-tag");
const npmPublish = require("@lerna/npm-publish");
const packDirectory = require("@lerna/pack-directory");
const PromptUtilities = require("@lerna/prompt");
const collectUpdates = require("@lerna/collect-updates");
const getNpmUsername = require("../lib/get-npm-username");
const verifyNpmPackageAccess = require("../lib/verify-npm-package-access");

// helpers
const loggingOutput = require("@lerna-test/logging-output");
const initFixture = require("@lerna-test/init-fixture")(__dirname);

// file under test
const lernaPublish = require("@lerna-test/command-runner")(require("../command"));

expect.extend(require("@lerna-test/figgy-pudding-matchers"));

describe("PublishCommand", () => {
  describe("cli validation", () => {
    let cwd;

    beforeAll(async () => {
      cwd = await initFixture("normal");
    });

    it("exits early when no changes found", async () => {
      collectUpdates.setUpdated(cwd);

      await lernaPublish(cwd)();

      const logMessages = loggingOutput("success");
      expect(logMessages).toContain("No changed packages to publish");
      expect(verifyNpmPackageAccess).not.toHaveBeenCalled();
    });

    it("exits non-zero with --scope", async () => {
      try {
        await lernaPublish(cwd)("--scope", "package-1");
      } catch (err) {
        expect(err.exitCode).toBe(1);
        expect(err.message).toBe("Unknown argument: scope");
      }

      expect.assertions(2);
    });

    it("exits non-zero with --since", async () => {
      try {
        await lernaPublish(cwd)("--since", "master");
      } catch (err) {
        expect(err.exitCode).toBe(1);
        expect(err.message).toBe("Unknown argument: since");
      }

      expect.assertions(2);
    });

    it("errors when --git-head is passed without from-package positional", async () => {
      try {
        await lernaPublish(cwd)("--git-head", "deadbeef");
      } catch (err) {
        expect(err.message).toBe("--git-head is only allowed with 'from-package' positional");
      }

      expect.hasAssertions();
    });
  });

  describe("with implied versioning", () => {
    it("publishes changed packages", async () => {
      const testDir = await initFixture("normal");

      await lernaPublish(testDir)();

      expect(PromptUtilities.confirm).toHaveBeenLastCalledWith(
        "Are you sure you want to publish these packages?"
      );
      expect(packDirectory.registry).toMatchInlineSnapshot(`
Set {
  "package-1",
  "package-3",
  "package-4",
  "package-2",
}
`);
      expect(npmPublish.registry).toMatchInlineSnapshot(`
Map {
  "package-1" => "latest",
  "package-3" => "latest",
  "package-4" => "latest",
  "package-2" => "latest",
}
`);
      expect(npmPublish.order()).toEqual([
        "package-1",
        "package-3",
        "package-4",
        "package-2",
        // package-5 is private
      ]);
      expect(npmDistTag.remove).not.toHaveBeenCalled();
      expect(npmDistTag.add).not.toHaveBeenCalled();

      expect(getNpmUsername).toHaveBeenCalled();
      expect(getNpmUsername).toHaveBeenLastCalledWith(
        expect.figgyPudding({ registry: "https://registry.npmjs.org/" })
      );

      expect(verifyNpmPackageAccess).toHaveBeenCalled();
      expect(verifyNpmPackageAccess).toHaveBeenLastCalledWith(
        expect.any(Array),
        "lerna-test",
        expect.figgyPudding({ registry: "https://registry.npmjs.org/" })
      );
    });

    it("publishes changed independent packages", async () => {
      const testDir = await initFixture("independent");

      await lernaPublish(testDir)();

      expect(npmPublish.order()).toEqual([
        "package-1",
        "package-3",
        "package-4",
        "package-2",
        // package-5 is private
      ]);
    });

    it("--skip-npm yields immediately to VersionCommand with warning", async () => {
      const cwd = await initFixture("normal");

      await lernaPublish(cwd)("--skip-npm");

      expect(npmPublish.order()).toHaveLength(0);

      const logMessages = loggingOutput("warn");
      expect(logMessages).toContain("Instead of --skip-npm, call `lerna version` directly");
    });

    it("throws an error in fixed mode when --independent is passed", async () => {
      const testDir = await initFixture("normal");

      try {
        await lernaPublish(testDir)("--independent");
      } catch (err) {
        expect(err.message).toMatch("independent");
      }

      expect.assertions(1);
    });
  });

  describe("--registry", () => {
    it("passes registry to npm commands", async () => {
      const testDir = await initFixture("normal");
      const registry = "https://my-private-registry";

      await lernaPublish(testDir)("--registry", registry);

      expect(npmPublish).toHaveBeenCalledWith(
        expect.objectContaining({ name: "package-1" }),
        "/TEMP_DIR/package-1-MOCKED.tgz",
        expect.objectContaining({ registry })
      );
    });

    it("overwrites yarn registry proxy with https://registry.npmjs.org/", async () => {
      const testDir = await initFixture("normal");
      const registry = "https://registry.yarnpkg.com";

      await lernaPublish(testDir)("--registry", registry);

      expect(npmPublish).toHaveBeenCalledWith(
        expect.objectContaining({ name: "package-1" }),
        "/TEMP_DIR/package-1-MOCKED.tgz",
        expect.objectContaining({ registry: "https://registry.npmjs.org/" })
      );

      const logMessages = loggingOutput("warn");
      expect(logMessages).toContain("Yarn's registry proxy is broken, replacing with public npm registry");
      expect(logMessages).toContain("If you don't have an npm token, you should exit and run `npm login`");
    });

    it("skips validation on any other third-party registry", async () => {
      const testDir = await initFixture("normal");
      const registry = "https://my-incompatible-registry.com";

      await lernaPublish(testDir)("--registry", registry);

      const logMessages = loggingOutput("notice");
      expect(logMessages).toContain("Skipping all user and access validation due to third-party registry");
    });
  });

  describe("--no-verify-access", () => {
    it("skips package access verification", async () => {
      const cwd = await initFixture("normal");

      await lernaPublish(cwd)("--no-verify-access");

      expect(verifyNpmPackageAccess).not.toHaveBeenCalled();
    });

    it("is implied when npm username is undefined", async () => {
      getNpmUsername.mockImplementationOnce(() => Promise.resolve());

      const cwd = await initFixture("normal");

      await lernaPublish(cwd)("--registry", "https://my-private-registry");

      expect(verifyNpmPackageAccess).not.toHaveBeenCalled();
    });
  });

  describe("--contents", () => {
    it("allows you to do fancy angular crap", async () => {
      const cwd = await initFixture("lifecycle");

      await lernaPublish(cwd)("--contents", "dist");

      for (const name of ["package-1", "package-2"]) {
        expect(packDirectory).toHaveBeenCalledWith(
          expect.objectContaining({ name }),
          expect.stringContaining(`packages/${name}/dist`),
          expect.any(Object)
        );
      }
    });
  });

  describe("in a cyclical repo", () => {
    it("should throw an error with --reject-cycles", async () => {
      expect.assertions(1);

      try {
        const testDir = await initFixture("toposort");

        await lernaPublish(testDir)("--reject-cycles");
      } catch (err) {
        expect(err.message).toMatch("Dependency cycles detected, you should fix these!");
      }
    });
  });
});


"use strict";

const filterable = require("@lerna/filter-options");

/**
 * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module
 */
exports.command = "add <pkg> [globs..]";

exports.describe = "Add a single dependency to matched packages";

exports.builder = yargs => {
  yargs
    .positional("pkg", {
      describe: "Package name to add as a dependency",
      type: "string",
    })
    .positional("globs", {
      describe: "Optional package directory globs to match",
      type: "array",
    })
    .options({
      D: {
        group: "Command Options:",
        type: "boolean",
        alias: "dev",
        describe: "Save to devDependencies",
      },
      E: {
        group: "Command Options:",
        type: "boolean",
        alias: "exact",
        describe: "Save version exactly",
      },
      registry: {
        group: "Command Options:",
        describe: "Use the specified registry for all npm client operations.",
        type: "string",
        requiresArg: true,
      },
      "no-bootstrap": {
        group: "Command Options:",
        describe: "Do not automatically chain `lerna bootstrap` after changes are made.",
        type: "boolean",
      },
      bootstrap: {
        // proxy for --no-bootstrap
        hidden: true,
        type: "boolean",
      },
    })
    .example(
      "$0 add module-1 packages/prefix-*",
      "Adds the module-1 package to the packages in the 'prefix-' prefixed folders"
    )
    .example("$0 add module-1 --scope=module-2", "Install module-1 to module-2")
    .example("$0 add module-1 --scope=module-2 --dev", "Install module-1 to module-2 in devDependencies")
    .example("$0 add module-1", "Install module-1 in all modules except module-1")
    .example("$0 add module-1 --no-bootstrap", "Skip automatic `lerna bootstrap`")
    .example("$0 add babel-core", "Install babel-core in all modules");

  return filterable(yargs);
};

exports.handler = function handler(argv) {
  return require(".")(argv);
};


it("calls publish lifecycles", async () => {

const aFiggyPudding = expect.figgyPudding({


"use strict";

// mocked modules
const output = require("@lerna/output");
const collectUpdates = require("@lerna/collect-updates");

// helpers
const initFixture = require("@lerna-test/init-fixture")(__dirname);

// file under test
const lernaLs = require("@lerna-test/command-runner")(require("../command"));

// remove quotes around top-level strings
expect.addSnapshotSerializer({
  test(val) {
    return typeof val === "string";
  },
  serialize(val, config, indentation, depth) {
    // top-level strings don't need quotes, but nested ones do (object properties, etc)
    return depth ? `"${val}"` : val;
  },
});

// normalize temp directory paths in snapshots
expect.addSnapshotSerializer(require("@lerna-test/serialize-windows-paths"));
expect.addSnapshotSerializer(require("@lerna-test/serialize-tempdir"));

describe("lerna ls", () => {
  describe("in a basic repo", () => {
    let testDir;

    beforeAll(async () => {
      testDir = await initFixture("basic");
    });

    it("should list public packages", async () => {
      await lernaLs(testDir)();
      expect(output.logged()).toMatchInlineSnapshot(`
package-1
package-2
package-3
package-4
`);
    });

    it("should also list private packages with --all", async () => {
      await lernaLs(testDir)("--all");
      expect(output.logged()).toMatchInlineSnapshot(`
package-1
package-2
package-3
package-4
package-5 (PRIVATE)
`);
    });

    it("lists public package versions and relative paths with --long", async () => {
      await lernaLs(testDir)("--long");
      expect(output.logged()).toMatchInlineSnapshot(`
package-1 v1.0.0 packages/package-1
package-2 v1.0.0 packages/package-2
package-3 v1.0.0 packages/package-3
package-4 v1.0.0 packages/package-4
`);
    });

    it("lists all package versions and relative paths with --long --all", async () => {
      await lernaLs(testDir)("-la");
      expect(output.logged()).toMatchInlineSnapshot(`
package-1 v1.0.0 packages/package-1
package-2 v1.0.0 packages/package-2
package-3 v1.0.0 packages/package-3
package-4 v1.0.0 packages/package-4
package-5 v1.0.0 packages/package-5 (PRIVATE)
`);
    });

    it("lists public package locations with --parseable", async () => {
      await lernaLs(testDir)("--parseable");
      expect(output.logged()).toMatchInlineSnapshot(`
__TEST_ROOTDIR__/packages/package-1
__TEST_ROOTDIR__/packages/package-2
__TEST_ROOTDIR__/packages/package-3
__TEST_ROOTDIR__/packages/package-4
`);
    });

    it("lists all package locations with --parseable --all", async () => {
      await lernaLs(testDir)("-pa");
      expect(output.logged()).toMatchInlineSnapshot(`
__TEST_ROOTDIR__/packages/package-1
__TEST_ROOTDIR__/packages/package-2
__TEST_ROOTDIR__/packages/package-3
__TEST_ROOTDIR__/packages/package-4
__TEST_ROOTDIR__/packages/package-5
`);
    });

    it("lists public package locations with --parseable --long", async () => {
      await lernaLs(testDir)("--parseable", "--long");
      expect(output.logged()).toMatchInlineSnapshot(`
__TEST_ROOTDIR__/packages/package-1:package-1:1.0.0
__TEST_ROOTDIR__/packages/package-2:package-2:1.0.0
__TEST_ROOTDIR__/packages/package-3:package-3:1.0.0
__TEST_ROOTDIR__/packages/package-4:package-4:1.0.0
`);
    });

    it("lists all package locations with --parseable --long --all", async () => {
      await lernaLs(testDir)("-pal");
      expect(output.logged()).toMatchInlineSnapshot(`
__TEST_ROOTDIR__/packages/package-1:package-1:1.0.0
__TEST_ROOTDIR__/packages/package-2:package-2:1.0.0
__TEST_ROOTDIR__/packages/package-3:package-3:1.0.0
__TEST_ROOTDIR__/packages/package-4:package-4:1.0.0
__TEST_ROOTDIR__/packages/package-5:package-5:1.0.0:PRIVATE
`);
    });

    it("lists packages matching --scope", async () => {
      await lernaLs(testDir)("--scope", "package-1");
      expect(output.logged()).toMatchInlineSnapshot(`package-1`);
    });

    it("does not list packages matching --ignore", async () => {
      await lernaLs(testDir)("--ignore", "package-@(2|3|4|5)");
      expect(output.logged()).toMatchInlineSnapshot(`package-1`);
    });

    it("does not list private packages with --no-private", async () => {
      await lernaLs(testDir)("--no-private");
      expect(output.logged()).not.toMatch("package-5 v1.0.0 (private)");
    });

    it("does not emit empty stdout", async () => {
      collectUpdates.setUpdated(testDir);
      await lernaLs(testDir)("--since", "deadbeef");
      expect(output).not.toHaveBeenCalled();
      expect(collectUpdates).toHaveBeenLastCalledWith(
        expect.any(Array),
        expect.any(Map),
        expect.any(Object),
        expect.objectContaining({ since: "deadbeef" })
      );
    });
  });

  describe("in a repo with packages outside of packages/", () => {
    it("should list packages", async () => {
      const testDir = await initFixture("extra");
      await lernaLs(testDir)();
      expect(output.logged()).toMatchInlineSnapshot(`
package-3
package-1
package-2
`);
    });
  });

  describe("--include-filtered-dependencies", () => {
    it("should list packages, including filtered ones", async () => {
      const testDir = await initFixture("include-filtered-dependencies");
      await lernaLs(testDir)("--scope", "@test/package-2", "--include-filtered-dependencies");
      expect(output.logged()).toMatchInlineSnapshot(`
@test/package-2
@test/package-1
`);
    });
  });

  describe("--include-filtered-dependents", () => {
    it("should list packages, including filtered ones", async () => {
      const testDir = await initFixture("include-filtered-dependencies");
      await lernaLs(testDir)("--scope", "@test/package-1", "--include-filtered-dependents");
      expect(output.logged()).toMatchInlineSnapshot(`
@test/package-1
@test/package-2
`);
    });
  });

  describe("with an undefined version", () => {
    it("replaces version with MISSING", async () => {
      const testDir = await initFixture("undefined-version");
      await lernaLs(testDir)("--long");
      expect(output.logged()).toMatchInlineSnapshot(`package-1 MISSING packages/package-1`);
    });

    it("appends MISSING flag to long parseable output", async () => {
      const testDir = await initFixture("undefined-version");
      await lernaLs(testDir)("--long", "--parseable");
      expect(output.logged()).toMatchInlineSnapshot(`__TEST_ROOTDIR__/packages/package-1:package-1:MISSING`);
    });
  });

  describe("--json", () => {
    it("should list packages as json objects", async () => {
      const testDir = await initFixture("basic");
      await lernaLs(testDir)("--json", "-a");

      // Output should be a parseable string
      const jsonOutput = JSON.parse(output.logged());
      expect(jsonOutput).toEqual([
        {
          location: expect.stringContaining("package-1"),
          name: "package-1",
          private: false,
          version: "1.0.0",
        },
        {
          location: expect.stringContaining("package-2"),
          name: "package-2",
          private: false,
          version: "1.0.0",
        },
        {
          location: expect.stringContaining("package-3"),
          name: "package-3",
          private: false,
          version: "1.0.0",
        },
        {
          location: expect.stringContaining("package-4"),
          name: "package-4",
          private: false,
          version: "1.0.0",
        },
        {
          location: expect.stringContaining("package-5"),
          name: "package-5",
          private: true,
          version: "1.0.0",
        },
      ]);
    });

    it("emits empty array with no results", async () => {
      const testDir = await initFixture("basic");

      collectUpdates.setUpdated(testDir);
      await lernaLs(testDir)("--since", "deadbeef", "--json");

      expect(JSON.parse(output.logged())).toEqual([]);
    });
  });

  describe("in a Yarn workspace", () => {
    it("should use package.json/workspaces setting", async () => {
      const testDir = await initFixture("yarn-workspaces");
      await lernaLs(testDir)();
      expect(output.logged()).toMatchInlineSnapshot(`
package-1
package-2
`);
    });
  });

  describe("with terribly complicated dependency cycles", () => {
    // for reference: 1->2, 1->3, 1->4, 2->4, 2->5, 3->4, 3->6, 4->1, 4->4,  5->4, 6->4, 7->4
    // We design the package tree in a very specific way. We want to test several different things
    // * A package depending on itself isn't added twice (package 4)
    // * A package being added twice in the same stage of the expansion isn't added twice (package 4)
    // * A package that has already been processed wont get added twice (package 1)
    it("should list all packages with no repeats", async () => {
      const testDir = await initFixture("cycles-and-repeated-deps");
      await lernaLs(testDir)("--scope", "package-1", "--include-filtered-dependencies");

      // should follow all transitive deps and pass all packages except 7 with no repeats
      expect(output.logged()).toMatchInlineSnapshot(`
package-1
package-2
package-3
package-4
package-5
package-6
`);
    });
  });

  describe("with fancy 'packages' configuration", () => {
    it("lists globstar-nested packages", async () => {
      const testDir = await initFixture("globstar");
      await lernaLs(testDir)();
      expect(output.logged()).toMatchInlineSnapshot(`
globstar
package-2
package-4
package-1
package-3
package-5
`);
    });

    it("lists packages under explicitly configured node_modules directories", async () => {
      const testDir = await initFixture("explicit-node-modules");
      await lernaLs(testDir)();
      expect(output.logged()).toMatchInlineSnapshot(`
alle-pattern-root
package-1
package-2
package-3
package-4
@scoped/package-5
`);
    });

    it("throws an error when globstars and explicit node_modules configs are mixed", async () => {
      expect.assertions(1);

      const testDir = await initFixture("mixed-globstar");

      try {
        await lernaLs(testDir)();
      } catch (err) {
        expect(err.message).toMatch("An explicit node_modules package path does not allow globstars");
      }
    });
  });
});


const { publish } = require("libnpmpublish");

const readJSON = require("read-package-json");

const figgyPudding = require("figgy-pudding");

const runLifecycle = require("@lerna/run-lifecycle");


"use strict";

const execa = require("execa");

module.exports = getCommitMessage;

function getCommitMessage(cwd, format = "%B") {
  return execa.stdout("git", ["log", "-1", `--pretty=format:${format}`], { cwd });
}


function npmPublish(pkg, tarFilePath, _opts) {

// pass only the package scope to libnpmpublish


{
  "name": "test",
  "devDependencies": {
    "lerna": "500.0.0",
  }
}


"use strict";

const cliRunner = require("@lerna-test/cli-runner");
const commitChangeToPackage = require("@lerna-test/commit-change-to-package");
const gitTag = require("@lerna-test/git-tag");
const initFixture = require("@lerna-test/init-fixture")(__dirname);

test("includes dependents", async () => {
  const cwd = await initFixture("normal");

  await gitTag(cwd, "v1.0.0");
  await commitChangeToPackage(cwd, "package-1", "change", { change: true });

  const { stdout } = await cliRunner(cwd)("changed");
  expect(stdout).toMatchInlineSnapshot(`
package-1
package-2
package-3
`);
});

test("no changes since release", async () => {
  const cwd = await initFixture("normal");

  await gitTag(cwd, "v1.0.0");

  try {
    await cliRunner(cwd)("changed");
  } catch (err) {
    expect(err.message).toMatch("No changed packages found");
    expect(err.code).toBe(1);
  }

  expect.hasAssertions();
});

test("no reachable tags", async () => {
  const cwd = await initFixture("normal");

  const { stdout } = await cliRunner(cwd)("changed");
  expect(stdout).toMatchInlineSnapshot(`
package-1
package-2
package-3
package-4
`);
});

test("--force-publish package-2", async () => {
  const cwd = await initFixture("normal");

  await gitTag(cwd, "v1.0.0");

  const { stdout } = await cliRunner(cwd)("changed", "--force-publish", "package-2");
  expect(stdout).toMatchInlineSnapshot(`
package-2
package-3
`);
});

test("--ignore-changes **/package-2/package.json", async () => {
  const cwd = await initFixture("normal");

  await gitTag(cwd, "v1.0.0");
  await commitChangeToPackage(cwd, "package-2", "change", { change: true });
  await commitChangeToPackage(cwd, "package-3", "change", { change: true });

  const { stdout } = await cliRunner(cwd)("changed", "--ignore-changes", "**/package-2/package.json");
  expect(stdout).toMatchInlineSnapshot(`"package-3"`);
});

test("listable flags", async () => {
  const cwd = await initFixture("normal");

  await gitTag(cwd, "v1.0.0");
  await commitChangeToPackage(cwd, "package-1", "change", { change: true });
  await commitChangeToPackage(cwd, "package-4", "change", { change: true });

  const { stdout } = await cliRunner(cwd)("changed", "-alp");
  expect(stdout).toMatchInlineSnapshot(`
__TEST_ROOTDIR__/packages/package-1:package-1:1.0.0
__TEST_ROOTDIR__/packages/package-2:package-2:1.0.0
__TEST_ROOTDIR__/packages/package-3:package-3:1.0.0
__TEST_ROOTDIR__/packages/package-4:package-4:1.0.0
__TEST_ROOTDIR__/packages/package-5:package-5:1.0.0:PRIVATE
`);
});


"description": "An internal Lerna tool",


@lerna/symlink-binary

An internal Lerna tool


@lerna-test/git-commit

A local test helper


"use strict";

/**
 * @see https://github.com/yargs/yargs/blob/master/docs/advanced.md#providing-a-command-module
 */
exports.command = "import <dir>";

exports.describe = "Import a package into the monorepo with commit history";

exports.builder = yargs =>
  yargs
    .positional("dir", { describe: "The path to an external git repository that contains an npm package" })
    .options({
      flatten: {
        group: "Command Options:",
        describe: "Import each merge commit as a single change the merge introduced",
        type: "boolean",
      },
      dest: {
        group: "Command Options:",
        describe: "Import destination directory for the external git repository",
        type: "string",
      },
      y: {
        group: "Command Options:",
        describe: "Skip all confirmation prompts",
        alias: "yes",
        type: "boolean",
      },
    });

exports.handler = function handler(argv) {
  return require(".")(argv);
};


keep keep keep keep add keep keep keep keep keep


root: true
extends:
  - airbnb-base
  - plugin:jest/recommended
  - plugin:node/recommended
  - plugin:prettier/recommended
plugins:
  - jest
  - node
  - prettier
rules:
  class-methods-use-this:
    - error
    - exceptMethods:
        - defaultOptions
        - otherCommandConfigs
        - requiresGit
  consistent-return: off
  curly:
    - error
    - all
  max-len:
    - error
    - 110 # keep in sync with .prettierrc.yaml printWidth
    - 2
  no-param-reassign:
    - error
    - props: true
      ignorePropertyModificationsFor:
        - err # Error decoration
        - obj # .reduce() object
        - pkg # Package instance
  no-restricted-syntax:
    - error
    - ForInStatement
    - LabeledStatement
    - WithStatement
  no-underscore-dangle:
    - error
    - allowAfterThis: true
  no-use-before-define:
    - error
    - functions: false
      classes: false
  strict: off
overrides:
  - files: "commands/*/command.js"
    rules:
      global-require: off
  - files:
      - "integration/**"
      - "**/__tests__/**"
      - "**/__mocks__/**"
      - "**/__helpers__/**"
    env:
      jest: true
    rules:
      # dev dependencies are hoisted to the root
      import/no-extraneous-dependencies: off
      # mocked modules are imported before helpers
      import/order: off
      node/no-extraneous-require: off
      node/no-unpublished-require: off
      node/no-unsupported-features/es-syntax:
        - error
        - ignores:
            - asyncFunctions
            # jest transpiles fast-async
      no-console: off
  - files:
      - "test/fixtures/**"
      - "**/__fixtures__/**"
    rules:
      global-require: off
      import/no-extraneous-dependencies: off
      import/no-unresolved: off
      node/no-extraneous-require: off
      node/no-missing-require:
        - error
        - allowModules:
            - "@integration/package-1"
            - "@integration/package-2"
      no-console: off
      strict: off
  - files:
      - "utils/map-to-registry/lib/map-to-registry.js"
      - "utils/npm-conf/lib/nerf-dart.js"
    rules:
      # Allow legacy url API
      node/no-deprecated-api: off


const BreadcrumbsItem = [{
  href: 'string',
  disabled: 'boolean',
  link: 'boolean',
  text: 'string | number',
  to: 'string | object',
}]

module.exports = {
  'v-breadcrumbs': {
    props: [{
      name: 'items',
      example: BreadcrumbsItem,
    }],
    slots: [
      {
        name: 'divider',
        props: undefined,
      },
      {
        name: 'item',
        props: {
          item: 'any[]',
        },
      },
    ],
  },
}


<template>
  <v-carousel>
    <v-carousel-item
      v-for="(item,i) in items"
      :key="i"
      :src="item.src"
      reverse-transition="fade-transition"
      transition="fade-transition"
    ></v-carousel-item>
  </v-carousel>
</template>

<script>
  export default {
    data () {
      return {
        items: [
          {
            src: 'https://cdn.vuetifyjs.com/images/carousel/squirrel.jpg',
          },
          {
            src: 'https://cdn.vuetifyjs.com/images/carousel/sky.jpg',
          },
          {
            src: 'https://cdn.vuetifyjs.com/images/carousel/bird.jpg',
          },
          {
            src: 'https://cdn.vuetifyjs.com/images/carousel/planet.jpg',
          },
        ],
      }
    },
  }
</script>


<template>
  <v-card>
    <v-toolbar
      color="cyan"
      dark
      flat
    >
      <v-app-bar-nav-icon></v-app-bar-nav-icon>

      <v-toolbar-title>Your Dashboard</v-toolbar-title>

      <v-btn icon>
        <v-icon>mdi-magnify</v-icon>
      </v-btn>

      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>

      <template v-slot:extension>
        <v-tabs
          v-model="tab"
          align-with-title
          background-color="transparent"
        >
          <v-tabs-slider color="yellow"></v-tabs-slider>

          <v-tab v-for="item in items" :key="item">
            {{ item }}
          </v-tab>
        </v-tabs>
      </template>
    </v-toolbar>

    <v-tabs-items v-model="tab">
      <v-tab-item
        v-for="item in items"
        :key="item"
      >
        <v-card flat>
          <v-card-text v-text="text"></v-card-text>
        </v-card>
      </v-tab-item>
    </v-tabs-items>
  </v-card>
</template>


import Vue from 'vue'

import Vuetify, {
  VBtn,
  VCard,
  VCardText,
  directives,
} from 'vuetify/lib'

Vuetify.install(Vue)

Vuetify.install(Vue, {})

Vuetify.install(Vue, {
  components: {
    VBtn,
    VCard,
    VCardText,
  },
  directives,
})

/* eslint-disable-next-line no-new */
new Vue({
  vuetify: new Vuetify(),
})


disabled: 'boolean',
link: 'boolean',
text: 'string | number',
to: 'string | object',


// Styles
import './VLabel.sass'

// Mixins
import Colorable from '../../mixins/colorable'
import Themeable, { functionalThemeClasses } from '../../mixins/themeable'

// Types
import { VNode } from 'vue'
import mixins from '../../util/mixins'

// Helpers
import { convertToUnit } from '../../util/helpers'

/* @vue/component */
export default mixins(Themeable).extend({
  name: 'v-label',

  functional: true,

  props: {
    absolute: Boolean,
    color: {
      type: String,
      default: 'primary',
    },
    disabled: Boolean,
    focused: Boolean,
    for: String,
    left: {
      type: [Number, String],
      default: 0,
    },
    right: {
      type: [Number, String],
      default: 'auto',
    },
    value: Boolean,
  },

  render (h, ctx): VNode {
    const { children, listeners, props } = ctx
    const data = {
      staticClass: 'v-label',
      class: {
        'v-label--active': props.value,
        'v-label--is-disabled': props.disabled,
        ...functionalThemeClasses(ctx),
      },
      attrs: {
        for: props.for,
        'aria-hidden': !props.for,
      },
      on: listeners,
      style: {
        left: convertToUnit(props.left),
        right: convertToUnit(props.right),
        position: props.absolute ? 'absolute' : 'relative',
      },
      ref: 'label',
    }

    return h('label', Colorable.options.methods.setTextColor(props.focused && props.color, data), children)
  },
})


<template>
  <v-container fluid>
    <v-radio-group v-model="column" column>
      <v-radio label="Option 1" value="radio-1"></v-radio>
      <v-radio label="Option 2" value="radio-2"></v-radio>
    </v-radio-group>
    <hr>
    <v-radio-group v-model="row" row>
      <v-radio label="Option 1" value="radio-1"></v-radio>
      <v-radio label="Option 2" value="radio-2"></v-radio>
    </v-radio-group>
  </v-container>
</template>

<script>
  export default {
    data () {
      return {
        column: null,
        row: null,
      }
    },
  }
</script>


{
"title": "header",
"titleText": "headerText",
"file": "components/VBreadcrumb",
"children": [
{
"type": "section",
"children": [

{
"type": "section",
"children": [
{
"type": "alert",
"lang": "headerAlert1",
"value": "info"
}
]
},

header

simple/large simple/divider intermediate/icon-dividers intermediate/item-slot


// Components
import VAutocomplete from '../VAutocomplete'

// Utilities
import {
  mount,
  Wrapper,
} from '@vue/test-utils'
import { keyCodes } from '../../../util/helpers'

describe('VAutocomplete.ts', () => {
  type Instance = InstanceType<typeof VAutocomplete>
  let mountFunction: (options?: object) => Wrapper<Instance>

  beforeEach(() => {
    document.body.setAttribute('data-app', 'true')

    mountFunction = (options = {}) => {
      return mount(VAutocomplete, {
        ...options,
        mocks: {
          $vuetify: {
            lang: {
              t: (val: string) => val,
            },
            theme: {
              dark: false,
            },
          },
        },
      })
    }
  })

  it('should have explicit tabindex passed through when autocomplete', () => {
    const wrapper = mountFunction({
      attrs: {
        tabindex: 10,
      },
    })

    expect(wrapper.vm.$refs.input.tabIndex).toBe(10)
    expect(wrapper.vm.$el.tabIndex).toBe(-1)
  })

  it('should emit search input changes', async () => {
    const wrapper = mountFunction({
      propsData: {
      },
    })

    const input = wrapper.find('input')
    const element = input.element as HTMLInputElement

    const update = jest.fn()
    wrapper.vm.$on('update:search-input', update)

    element.value = 'test'
    input.trigger('input')

    await wrapper.vm.$nextTick()

    expect(update).toHaveBeenCalledWith('test')
  })

  it('should filter autocomplete search results', async () => {
    const wrapper = mountFunction({
      propsData: { items: ['foo', 'bar'] },
    })

    wrapper.setData({ internalSearch: 'foo' })

    expect(wrapper.vm.filteredItems).toHaveLength(1)
    expect(wrapper.vm.filteredItems[0]).toBe('foo')
  })

  it('should filter numeric primitives', () => {
    const wrapper = mountFunction({
      propsData: {
        items: [1, 2],
      },
    })

    wrapper.setData({ internalSearch: 1 })

    expect(wrapper.vm.filteredItems).toHaveLength(1)
    expect(wrapper.vm.filteredItems[0]).toBe(1)
  })

  it('should activate when search changes and not active', async () => {
    const wrapper = mountFunction({
      propsData: {
        items: [1, 2, 3, 4],
        multiple: true,
      },
    })

    wrapper.vm.isMenuActive = true
    await wrapper.vm.$nextTick()
    wrapper.setData({ internalSearch: 2 })
    await wrapper.vm.$nextTick()

    expect(wrapper.vm.isMenuActive).toBe(true)
  })

  it('should set searchValue to null when deactivated', async () => {
    const wrapper = mountFunction({
      propsData: {
        items: [1, 2, 3, 4],
        multiple: true,
      },
    })

    await wrapper.vm.$nextTick()

    const input = wrapper.find('input')
    const element = input.element as HTMLInputElement

    input.trigger('focus')
    element.value = '2'
    input.trigger('input')

    expect(wrapper.vm.internalSearch).toBe('2')

    wrapper.setProps({
      multiple: false,
      value: 1,
    })

    await wrapper.vm.$nextTick()

    expect(wrapper.vm.internalSearch).toBe(1)

    input.trigger('focus')
    element.value = '3'
    input.trigger('input')
    input.trigger('blur')

    expect(wrapper.vm.internalSearch).toBe('3')
  })

  it('should render role=combobox correctly when autocomplete', async () => {
    const wrapper = mountFunction()

    expect(wrapper.vm.$el.getAttribute('role')).toBeFalsy()

    const input = wrapper.find('.v-input__slot')
    expect(input.element.getAttribute('role')).toBe('combobox')
  })

  it('should not duplicate items after items update when caching is turned on', async () => {
    const wrapper = mountFunction({
      propsData: {
        cacheItems: true,
        returnObject: true,
        itemText: 'text',
        itemValue: 'id',
        items: [],
      },
    })

    wrapper.setProps({ items: [{ id: 1, text: 'A' }] })
    expect(wrapper.vm.computedItems).toHaveLength(1)
    wrapper.setProps({ items: [{ id: 1, text: 'A' }] })
    expect(wrapper.vm.computedItems).toHaveLength(1)
  })

  it('should cache items passed via prop', async () => {
    const wrapper = mountFunction({
      propsData: {
        cacheItems: true,
        items: [1, 2, 3, 4],
      },
    })

    expect(wrapper.vm.computedItems).toHaveLength(4)

    wrapper.setProps({ items: [5] })

    expect(wrapper.vm.computedItems).toHaveLength(5)
  })

  it('should not filter text with no items', async () => {
    const wrapper = mountFunction({
      propsData: {
        eager: true,
        items: ['foo', 'bar'],
      },
    })

    await wrapper.vm.$nextTick()

    wrapper.setProps({ searchInput: 'asdf' })

    // Wait for watcher
    await wrapper.vm.$nextTick()

    const tile = wrapper.find('.v-list-item__title')

    expect(tile.text()).toBe('$vuetify.noDataText')
  })

  it('should not display menu when tab focused', async () => {
    const wrapper = mountFunction({
      propsData: {
        items: [1, 2],
        value: 1,
      },
    })

    const input = wrapper.find('input')
    input.trigger('focus')

    await wrapper.vm.$nextTick()

    expect(wrapper.vm.isMenuActive).toBe(false)
  })

  // eslint-disable-next-line max-statements
  it('should change selected index', async () => {
    const wrapper = mountFunction({
      attachToDocument: true,
      propsData: {
        items: ['foo', 'bar', 'fizz'],
        multiple: true,
        value: ['foo', 'bar', 'fizz'],
      },
    })

    await wrapper.vm.$nextTick()

    expect(wrapper.vm.selectedIndex).toBe(-1)
    expect(wrapper.vm.selectedItems).toHaveLength(3)

    // Right arrow
    wrapper.vm.changeSelectedIndex(keyCodes.right)
    expect(wrapper.vm.selectedIndex).toBe(0)

    wrapper.vm.changeSelectedIndex(keyCodes.right)
    expect(wrapper.vm.selectedIndex).toBe(1)

    wrapper.vm.changeSelectedIndex(keyCodes.right)
    expect(wrapper.vm.selectedIndex).toBe(2)

    // Left arrow
    wrapper.vm.changeSelectedIndex(keyCodes.left)
    expect(wrapper.vm.selectedIndex).toBe(1)

    wrapper.vm.changeSelectedIndex(keyCodes.left)
    expect(wrapper.vm.selectedIndex).toBe(0)

    wrapper.vm.changeSelectedIndex(keyCodes.left)
    expect(wrapper.vm.selectedIndex).toBe(-1)

    wrapper.vm.changeSelectedIndex(keyCodes.left)
    expect(wrapper.vm.selectedIndex).toBe(2)

    wrapper.vm.changeSelectedIndex(keyCodes.left)
    expect(wrapper.vm.selectedIndex).toBe(1)

    // Delete key
    wrapper.vm.changeSelectedIndex(keyCodes.backspace)
    await wrapper.vm.$nextTick()
    expect(wrapper.vm.selectedIndex).toBe(1)

    wrapper.vm.changeSelectedIndex(keyCodes.left)
    expect(wrapper.vm.selectedIndex).toBe(0)

    wrapper.vm.changeSelectedIndex(keyCodes.backspace)
    await wrapper.vm.$nextTick()
    expect(wrapper.vm.selectedIndex).toBe(0)

    // Should not change index if search is dirty
    wrapper.setProps({ searchInput: 'foo' })
    wrapper.vm.changeSelectedIndex(keyCodes.backspace)

    expect(wrapper.vm.selectedIndex).toBe(0)
    expect(wrapper.vm.selectedItems).toHaveLength(1)

    wrapper.setProps({ searchInput: undefined })

    // Should not proceed if keyCode doesn't match
    wrapper.vm.changeSelectedIndex(99)
    await wrapper.vm.$nextTick()

    expect(wrapper.vm.selectedIndex).toBe(0)
    expect(wrapper.vm.selectedItems).toHaveLength(1)

    wrapper.vm.changeSelectedIndex(keyCodes.backspace)
    await wrapper.vm.$nextTick()

    expect(wrapper.vm.selectedItems).toHaveLength(0)
    expect(wrapper.vm.selectedIndex).toBe(-1)

    // Should not change/error if called with no selection
    wrapper.vm.changeSelectedIndex(keyCodes.backspace)
    await wrapper.vm.$nextTick()

    expect(wrapper.vm.selectedIndex).toBe(-1)

    wrapper.setProps({ value: ['foo', 'bar', 'fizz'] })

    await wrapper.vm.$nextTick()

    expect(wrapper.vm.selectedItems).toHaveLength(3)

    wrapper.vm.selectedIndex = 2

    // Simulating removing items when an index already selected
    wrapper.setProps({ value: ['foo', 'bar'] })

    await wrapper.vm.$nextTick()

    expect(wrapper.vm.selectedIndex).toBe(2)

    // Backspace
    wrapper.vm.changeSelectedIndex(keyCodes.delete)
    expect(wrapper.vm.selectedIndex).toBe(-1)
  })

  it('should conditionally show the menu', async () => {
    const wrapper = mountFunction({
      attachToDocument: true,
      propsData: {
        items: ['foo', 'bar', 'fizz'],
      },
    })

    const slot = wrapper.find('.v-input__slot')
    const input = wrapper.find('input')

    // Focus input should only focus
    input.trigger('focus')

    expect(wrapper.vm.isFocused).toBe(true)
    expect(wrapper.vm.menuCanShow).toBe(true)
    expect(wrapper.vm.isMenuActive).toBe(false)

    // Clicking input should open menu
    slot.trigger('click')

    expect(wrapper.vm.isMenuActive).toBe(true)
    expect(wrapper.vm.menuCanShow).toBe(true)

    wrapper.setProps({ searchInput: 'foo' })

    expect(wrapper.vm.isMenuActive).toBe(true)
    expect(wrapper.vm.menuCanShow).toBe(true)

    // Should close menu but keep focus
    input.trigger('keydown.esc')

    expect(wrapper.vm.isFocused).toBe(true)
    expect(wrapper.vm.isMenuActive).toBe(false)
    expect(wrapper.vm.menuCanShow).toBe(true)

    // TODO: Add expects for tags when impl
  })

  it('should have the correct selected item', async () => {
    const wrapper = mountFunction({
      propsData: {
        items: ['foo', 'bar', 'fizz'],
        multiple: true,
        value: ['foo'],
      },
    })

    expect(wrapper.vm.selectedItem).toBeNull()

    wrapper.setProps({
      multiple: false,
      value: 'foo',
    })

    expect(wrapper.vm.selectedItem).toBe('foo')
  })

  it('should reset lazySearch', async () => {
    const wrapper = mountFunction({
      propsData: {
        chips: true,
        items: ['foo', 'bar', 'fizz'],
        searchInput: 'foo',
      },
    })

    expect(wrapper.vm.lazySearch).toBe('foo')
    expect(wrapper.vm.hasSlot).toBe(true)

    wrapper.setData({ isMenuActive: true })
    await wrapper.vm.$nextTick()
    wrapper.setData({ isMenuActive: false })
    await wrapper.vm.$nextTick()

    expect(wrapper.vm.lazySearch).toBeUndefined()
  })

  it('should select input text on focus', async () => {
    const wrapper = mountFunction()
    const select = jest.fn()
    wrapper.vm.$refs.input.select = select

    const input = wrapper.find('input')
    input.trigger('focus')

    await wrapper.vm.$nextTick()

    expect(wrapper.vm.isFocused).toBe(true)
    expect(select).toHaveBeenCalledTimes(1)

    input.trigger('keydown.tab')

    await wrapper.vm.$nextTick()

    expect(wrapper.vm.isFocused).toBe(false)
    expect(select).toHaveBeenCalledTimes(1)
  })

  it('should not respond to click', () => {
    const onFocus = jest.fn()
    const wrapper = mountFunction({
      propsData: { disabled: true },
      methods: { onFocus },
    })
    const slot = wrapper.find('.v-input__slot')

    slot.trigger('click')

    expect(onFocus).not.toHaveBeenCalled()

    wrapper.setProps({ disabled: false, readonly: true })

    slot.trigger('click')

    expect(onFocus).not.toHaveBeenCalled()

    wrapper.setProps({ readonly: false })

    slot.trigger('click')

    expect(onFocus).toHaveBeenCalled()
  })

  it('should react to keydown', () => {
    const activateMenu = jest.fn()
    const changeSelectedIndex = jest.fn()
    const onEscDown = jest.fn()
    const onTabDown = jest.fn()
    const wrapper = mountFunction({
      methods: {
        activateMenu,
        changeSelectedIndex,
        onEscDown,
        onTabDown,
      },
    })

    const input = wrapper.find('input')
    const element = input.element as HTMLInputElement

    expect(wrapper.vm.isMenuActive).toBe(false)

    input.trigger('keydown.enter')
    input.trigger('keydown.space')
    input.trigger('keydown.up')
    input.trigger('keydown.down')

    expect(activateMenu).toHaveBeenCalledTimes(4)

    input.trigger('keydown.esc')

    expect(onEscDown).toHaveBeenCalledTimes(1)

    input.trigger('keydown.tab')

    expect(onTabDown).toHaveBeenCalledTimes(1)

    // Skip menu activation
    wrapper.setData({ isMenuActive: true })

    element.value = 'foo'
    input.trigger('input')

    wrapper.setProps({ hideSelected: true })

    expect(wrapper.vm.genSelections()).toEqual([])
  })
})


Use this when using actions inside the picker

Automatically save the selected value. This updates the internal previous value so if cancel is clicked, it will not revert the user changes

Defines the header color. If not specified it will use the color defined by color prop or the default picker color

Allows the use of the mousewheel in the picker


"headerText": "The `v-breadcrumbs` component is a navigational helper for pages. It can accept a **Material Icons** icon or text characters as a divider. An array of objects can be passed to the **items** property of the component.  Additionally, slots exists for more control of the breadcrumbs, either utilizing `v-breadcrumbs-item` or other custom markup.",

"desc": "By default, breadcrumbs use a text divider. This can be any string."

"headerAlert1": "By default `v-breadcrumbs` will disable all crumbs up to the current page in a nested paths. You can prevent this behavior by using `exact: true` on each applicable breadcrumb in the `items` array.",


@import '../../styles/styles.sass'
@import './_variables.scss'

// Theme
+theme(v-list-item) using ($material)
  &--disabled
    color: map-deep-get($material, 'text', 'disabled')

  &:not(.v-list-item--active):not(.v-list-item--disabled)
    color: map-deep-get($material, 'text', 'primary') !important

  .v-list-item__mask
    color: map-deep-get($material, 'text', 'disabled')
    background: map-deep-get($material, 'expansion-panels', 'focus')

  .v-list-item__subtitle,
  .v-list-item__action-text
    color: map-deep-get($material, 'text', 'secondary')

  +states($material)

  &.v-list-item--highlighted
    &::before
      opacity: map-deep-get($material, 'states', 'pressed')

// Block
.v-list-item
  align-items: center
  display: flex
  flex: 1 1 100%
  letter-spacing: normal
  min-height: $list-item-min-height
  outline: none
  padding: 0 16px
  position: relative
  text-decoration: none
  user-select: none

  &--disabled
    pointer-events: none

// Element
.v-list-item__action
  align-self: center
  margin: 12px 0

  // Remove all margins when used
  // in an item action. If user
  // wants this they can not
  // use this component
  .v-input,
  .v-input__control,
  .v-input__slot,
  .v-input--selection-controls__input
    margin: 0 !important

  .v-input
    padding: 0

    .v-messages
      display: none

.v-list-item__action-text
  font-size: map-deep-get($headings, 'caption', 'size')

.v-list-item__avatar
  align-self: center
  justify-content: flex-start
  margin-bottom: $list-item-avatar-margin-y
  margin-top: $list-item-avatar-margin-y

  &.v-list-item__avatar--horizontal
    margin-bottom: 8px
    margin-top: 8px

    &:first-child
      +ltr()
        margin-left: $list-item-avatar-horizontal-margin-x
      +rtl()
        margin-right: $list-item-avatar-horizontal-margin-x

    &:last-child
      +ltr()
        margin-left: $list-item-avatar-horizontal-margin-x
      +rtl()
        margin-right: $list-item-avatar-horizontal-margin-x

.v-list-item__content
  align-items: center
  align-self: center
  display: flex
  flex-wrap: wrap
  flex: 1 1
  overflow: hidden
  padding: 12px 0

  > *
    line-height: 1.1
    flex: 1 0 100%

    &:not(:last-child)
      margin-bottom: 2px

.v-list-item__icon
  align-self: flex-start
  margin: 16px 0

// https://github.com/vuetifyjs/vuetify/issues/7930
.v-list-item__action,
.v-list-item__avatar,
.v-list-item__icon
  &:last-of-type:not(:only-child)
    +ltr()
      margin-left: 16px
    +rtl()
      margin-right: 16px

.v-list-item__avatar
  &:first-child
    +ltr()
      margin-right: 24px
    +rtl()
      margin-left: 24px

.v-list-item__action,
.v-list-item__icon
  &:first-child
    +ltr()
      margin-right: 32px
    +rtl()
      margin-left: 32px

.v-list-item__action,
.v-list-item__avatar,
.v-list-item__icon
  display: inline-flex
  min-width: 24px

// Increased specificity to beat
// out default typography rules
// line height plays a role in
// proper element sizing
.v-list-item .v-list-item__title,
.v-list-item .v-list-item__subtitle
  line-height: 1.2

.v-list-item__title,
.v-list-item__subtitle
  flex: 1 1 100%
  overflow: hidden
  text-overflow: ellipsis
  white-space: nowrap

.v-list-item__title
  align-self: center
  font-size: $list-item-title-font-size

  > .v-badge
    margin-top: 16px

.v-list-item__subtitle
  font-size: $list-item-subtitle-font-size

// Modifier
.v-list-item--dense,
.v-list--dense .v-list-item
  min-height: 40px

  .v-list-item__icon
    margin-top: 8px
    margin-bottom: 8px

  .v-list-item__content
    padding: 8px 0

  .v-list-item__title,
  .v-list-item__subtitle
    font-size: $list-item-dense-title-font-size
    font-weight: $list-item-dense-title-font-weight
    line-height: 1rem

  &.v-list-item--two-line
    min-height: 60px

  &.v-list-item--three-line
    min-height: 76px

.v-list-item--link
  cursor: pointer

  &:before
    background-color: currentColor
    bottom: 0
    content: ''
    left: 0
    opacity: 0
    pointer-events: none
    position: absolute
    right: 0
    top: 0
    transition: $primary-transition

// https://github.com/vuetifyjs/vuetify/issues/8327
.v-list .v-list-item--active
  color: inherit

  .v-icon
    color: inherit

.v-list-item__action--stack
  align-items: flex-end
  align-self: stretch
  justify-content: space-between
  white-space: nowrap
  flex-direction: column

.v-list--two-line .v-list-item,
.v-list--three-line .v-list-item,
.v-list-item--two-line,
.v-list-item--three-line
  .v-list-item__avatar:not(.v-list-item__avatar--horizontal),
  .v-list-item__icon
    margin-bottom: $list-item-icon-margin-y
    margin-top: $list-item-icon-margin-y

.v-list--two-line .v-list-item,
.v-list-item--two-line
  min-height: $list-item-two-line-min-height

  .v-list-item__icon
    margin-bottom: 32px

.v-list--three-line .v-list-item,
.v-list-item--three-line
  min-height: $list-item-three-line-min-height

  .v-list-item__avatar,
  .v-list-item__action
    align-self: flex-start
    margin-top: 16px
    margin-bottom: 16px

  .v-list-item__content
    align-self: stretch

  .v-list-item__subtitle
    white-space: initial
    -webkit-line-clamp: 2
    -webkit-box-orient: vertical
    display: -webkit-box


<template>
  <div class="text-center">
    <v-menu transition="scale-transition">
      <template v-slot:activator="{ on }">
        <v-btn
          dark
          color="primary"
          v-on="on"
        >
          Scale Transition
        </v-btn>
      </template>
      <v-list>
        <v-list-item v-for="n in 5" :key="n" @click="">
          <v-list-item-title v-text="'Item ' + n"></v-list-item-title>
        </v-list-item>
      </v-list>
    </v-menu>
  </div>
</template>


import Vue from 'vue'

// Return target's cumulative offset from the top
export function getOffset (target: any): number {
  if (typeof target === 'number') {
    return target
  }

  let el = $(target)
  if (!el) {
    throw typeof target === 'string'
      ? new Error(`Target element "${target}" not found.`)
      : new TypeError(`Target must be a Number/Selector/HTMLElement/VueComponent, received ${type(target)} instead.`)
  }

  let totalOffset = 0
  while (el) {
    totalOffset += el.offsetTop
    el = el.offsetParent as HTMLElement
  }

  return totalOffset
}

export function getContainer (container: any): HTMLElement {
  const el = $(container)

  if (el) return el

  throw typeof container === 'string'
    ? new Error(`Container element "${container}" not found.`)
    : new TypeError(`Container must be a Selector/HTMLElement/VueComponent, received ${type(container)} instead.`)
}

function type (el: any) {
  return el == null ? el : el.constructor.name
}

function $ (el: any): HTMLElement | null {
  if (typeof el === 'string') {
    return document.querySelector<HTMLElement>(el)
  } else if (el && el._isVue) {
    return (el as Vue).$el as HTMLElement
  } else if (el instanceof HTMLElement) {
    return el
  } else {
    return null
  }
}


.DS_Store
node_modules/
tmp/
*.log
.idea/
yarn.lock
package-lock.json
.nyc_output/
coverage/
.tmp*
.vscode
dist/


import { encodeURL, escapeHTML } from 'hexo-util';
import { postFindOneFactory } from './';

/**
 * Post link tag
 *
 * Syntax:
 *   {% post_link slug | title [title] [escape] %}
 */
export = ctx => {
  return function postLinkTag(args) {
    const slug = args.shift();
    if (!slug) {
      throw new Error(`Post not found: "${slug}" doesn't exist for {% post_link %}`);
    }

    let escape = args[args.length - 1];
    if (escape === 'true' || escape === 'false') {
      args.pop();
    } else {
      escape = 'true';
    }

    const factory = postFindOneFactory(ctx);
    const post = factory({ slug }) || factory({ title: slug });
    if (!post) {
      throw new Error(`Post not found: post_link ${slug}.`);
    }

    let title = args.length ? args.join(' ') : post.title;
    // Let attribute be the true post title so it appears in tooltip.
    const attrTitle = escapeHTML(post.title);
    if (escape === 'true') title = escapeHTML(title);

    const link = encodeURL(new URL(post.path, ctx.config.url).pathname);

    return `<a href="${link}" title="${attrTitle}">${title}</a>`;
  };
};


import warehouse from 'warehouse';

export = ctx => {
  const PostCategory = new warehouse.Schema({
    post_id: {type: warehouse.Schema.Types.CUID, ref: 'Post'},
    category_id: {type: warehouse.Schema.Types.CUID, ref: 'Category'}
  });

  return PostCategory;
};


import { createSha1Hash, Permalink, slugize } from 'hexo-util';
import { basename } from 'path';
let permalink;

function postPermalinkFilter(data) {
  const { config } = this;
  const { id, _id, slug, title, date, __permalink } = data;

  if (__permalink) {
    if (!__permalink.startsWith('/')) return `/${__permalink}`;
    return __permalink;
  }

  const hash = slug && date
    ? createSha1Hash().update(slug + date.unix().toString()).digest('hex').slice(0, 12)
    : null;
  const meta = {
    id: id || _id,
    title: slug,
    name: typeof slug === 'string' ? basename(slug) : '',
    post_title: slugize(title, {transform: 1}),
    year: date.format('YYYY'),
    month: date.format('MM'),
    day: date.format('DD'),
    hour: date.format('HH'),
    minute: date.format('mm'),
    second: date.format('ss'),
    i_month: date.format('M'),
    i_day: date.format('D'),
    hash,
    category: config.default_category
  };

  if (!permalink || permalink.rule !== config.permalink) {
    permalink = new Permalink(config.permalink, {});
  }

  const { categories } = data;

  if (categories.length) {
    meta.category = categories.last().slug;
  }

  const keys = Object.keys(data);

  for (const key of keys) {
    if (Object.prototype.hasOwnProperty.call(meta, key)) continue;

    // Use Object.getOwnPropertyDescriptor to copy getters to avoid "Maximum call
    // stack size exceeded" error
    Object.defineProperty(meta, key, Object.getOwnPropertyDescriptor(data, key));
  }

  if (config.permalink_defaults) {
    const keys2 = Object.keys(config.permalink_defaults);

    for (const key of keys2) {
      if (Object.prototype.hasOwnProperty.call(meta, key)) continue;

      meta[key] = config.permalink_defaults[key];
    }
  }

  return permalink.stringify(meta);
}

export = postPermalinkFilter;


hexo

A fast, simple & powerful blog framework, powered by Node.js.

mocha test/index.js --require ts-node/register

c8 --reporter=lcovonly npm test -- --no-parallel

Tommy Chen <tommy351@gmail.com> (https://zespia.tw)

Abner Chou <hi@abnerchou.me> (https://abnerchou.me)


import { exists, unlink } from 'hexo-fs';
import Promise from 'bluebird';

export = ctx => {
  if (ctx._dbLoaded) return Promise.resolve();

  const db = ctx.database;
  const { path } = db.options;
  const { log } = ctx;

  return exists(path).then(exist => {
    if (!exist) return;

    log.debug('Loading database.');
    return db.load();
  }).then(() => {
    ctx._dbLoaded = true;
  }).catch(() => {
    log.error('Database load failed. Deleting database.');
    return unlink(path);
  });
};


export = ctx => {
  const { filter } = ctx.extend;

  filter.register('after_post_render', require('./external_link'));
  filter.register('after_post_render', require('./excerpt'));
};


keep keep keep keep replace keep keep keep keep


'use strict';

const Promise = require('bluebird');

describe('post', () => {
  const Hexo = require('../../../dist/hexo');
  const hexo = new Hexo(__dirname, {silent: true});
  const Post = hexo.model('Post');
  const generator = Promise.method(require('../../../dist/plugins/generator/post').bind(hexo));

  hexo.config.permalink = ':title/';

  function locals() {
    hexo.locals.invalidate();
    return hexo.locals.toObject();
  }

  before(() => hexo.init());

  it('default layout', async () => {
    const post = await Post.insert({
      source: 'foo',
      slug: 'bar'
    });
    const data = await generator(locals());
    post.__post = true;

    data.should.eql([
      {
        path: 'bar/',
        layout: ['post', 'page', 'index'],
        data: post
      }
    ]);

    post.remove();
  });

  it('custom layout', async () => {
    const post = await Post.insert({
      source: 'foo',
      slug: 'bar',
      layout: 'photo'
    });
    const data = await generator(locals());
    data[0].layout.should.eql(['photo', 'post', 'page', 'index']);

    post.remove();
  });

  it('layout disabled', async () => {
    const post = await Post.insert({
      source: 'foo',
      slug: 'bar',
      layout: false
    });
    const data = await generator(locals());
    should.not.exist(data[0].layout);

    post.remove();
  });

  it('prev/next post', async () => {
    const posts = await Post.insert([
      {source: 'foo', slug: 'foo', date: 1e8},
      {source: 'bar', slug: 'bar', date: 1e8 + 1},
      {source: 'baz', slug: 'baz', date: 1e8 - 1}
    ]);
    const data = await generator(locals());
    should.not.exist(data[0].data.prev);
    data[0].data.next._id.should.eq(posts[0]._id);
    data[1].data.prev._id.should.eq(posts[1]._id);
    data[1].data.next._id.should.eq(posts[2]._id);
    data[2].data.prev._id.should.eq(posts[0]._id);
    should.not.exist(data[2].data.next);

    await Promise.all(posts.map(post => post.remove()));
  });
});