chore: Lint shared directory
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// @flow
|
||||
import { trim } from 'lodash';
|
||||
import { trim } from "lodash";
|
||||
|
||||
type Domain = {
|
||||
tld: string,
|
||||
@@ -11,14 +11,14 @@ type Domain = {
|
||||
// a large list of possible TLD's which increase the size of the bundle
|
||||
// unneccessarily for our usecase of trusted input.
|
||||
export function parseDomain(url: string): ?Domain {
|
||||
if (typeof url !== 'string') return null;
|
||||
if (typeof url !== "string") return null;
|
||||
|
||||
// strip extermeties and whitespace from input
|
||||
const normalizedDomain = trim(url.replace(/(https?:)?\/\//, ''));
|
||||
const parts = normalizedDomain.split('.');
|
||||
const normalizedDomain = trim(url.replace(/(https?:)?\/\//, ""));
|
||||
const parts = normalizedDomain.split(".");
|
||||
|
||||
// ensure the last part only includes something that looks like a TLD
|
||||
function cleanTLD(tld = '') {
|
||||
function cleanTLD(tld = "") {
|
||||
return tld.split(/[/:?]/)[0];
|
||||
}
|
||||
|
||||
@@ -28,14 +28,14 @@ export function parseDomain(url: string): ?Domain {
|
||||
return {
|
||||
subdomain: parts[0],
|
||||
domain: parts[1],
|
||||
tld: cleanTLD(parts.slice(2).join('.')),
|
||||
tld: cleanTLD(parts.slice(2).join(".")),
|
||||
};
|
||||
}
|
||||
if (parts.length === 2) {
|
||||
return {
|
||||
subdomain: '',
|
||||
subdomain: "",
|
||||
domain: parts[0],
|
||||
tld: cleanTLD(parts.slice(1).join('.')),
|
||||
tld: cleanTLD(parts.slice(1).join(".")),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ export function parseDomain(url: string): ?Domain {
|
||||
|
||||
export function getCookieDomain(domain: string) {
|
||||
// TODO: All the process.env parsing needs centralizing
|
||||
return process.env.SUBDOMAINS_ENABLED === 'true' ||
|
||||
return process.env.SUBDOMAINS_ENABLED === "true" ||
|
||||
process.env.SUBDOMAINS_ENABLED === true
|
||||
? stripSubdomain(domain)
|
||||
: domain;
|
||||
@@ -61,69 +61,69 @@ export function stripSubdomain(hostname: string) {
|
||||
export function isCustomSubdomain(hostname: string) {
|
||||
const parsed = parseDomain(hostname);
|
||||
if (!parsed) return false;
|
||||
if (!parsed.subdomain || parsed.subdomain === 'www') return false;
|
||||
if (!parsed.subdomain || parsed.subdomain === "www") return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export const RESERVED_SUBDOMAINS = [
|
||||
'about',
|
||||
'account',
|
||||
'admin',
|
||||
'advertising',
|
||||
'api',
|
||||
'assets',
|
||||
'archive',
|
||||
'beta',
|
||||
'billing',
|
||||
'blog',
|
||||
'cache',
|
||||
'cdn',
|
||||
'code',
|
||||
'community',
|
||||
'dashboard',
|
||||
'developer',
|
||||
'developers',
|
||||
'forum',
|
||||
'help',
|
||||
'home',
|
||||
'http',
|
||||
'https',
|
||||
'imap',
|
||||
'localhost',
|
||||
'mail',
|
||||
'marketing',
|
||||
'mobile',
|
||||
'new',
|
||||
'news',
|
||||
'newsletter',
|
||||
'ns1',
|
||||
'ns2',
|
||||
'ns3',
|
||||
'ns4',
|
||||
'password',
|
||||
'profile',
|
||||
'sandbox',
|
||||
'script',
|
||||
'scripts',
|
||||
'setup',
|
||||
'signin',
|
||||
'signup',
|
||||
'site',
|
||||
'smtp',
|
||||
'support',
|
||||
'status',
|
||||
'static',
|
||||
'stats',
|
||||
'test',
|
||||
'update',
|
||||
'updates',
|
||||
'ws',
|
||||
'wss',
|
||||
'web',
|
||||
'websockets',
|
||||
'www',
|
||||
'www1',
|
||||
'www2',
|
||||
'www3',
|
||||
'www4',
|
||||
"about",
|
||||
"account",
|
||||
"admin",
|
||||
"advertising",
|
||||
"api",
|
||||
"assets",
|
||||
"archive",
|
||||
"beta",
|
||||
"billing",
|
||||
"blog",
|
||||
"cache",
|
||||
"cdn",
|
||||
"code",
|
||||
"community",
|
||||
"dashboard",
|
||||
"developer",
|
||||
"developers",
|
||||
"forum",
|
||||
"help",
|
||||
"home",
|
||||
"http",
|
||||
"https",
|
||||
"imap",
|
||||
"localhost",
|
||||
"mail",
|
||||
"marketing",
|
||||
"mobile",
|
||||
"new",
|
||||
"news",
|
||||
"newsletter",
|
||||
"ns1",
|
||||
"ns2",
|
||||
"ns3",
|
||||
"ns4",
|
||||
"password",
|
||||
"profile",
|
||||
"sandbox",
|
||||
"script",
|
||||
"scripts",
|
||||
"setup",
|
||||
"signin",
|
||||
"signup",
|
||||
"site",
|
||||
"smtp",
|
||||
"support",
|
||||
"status",
|
||||
"static",
|
||||
"stats",
|
||||
"test",
|
||||
"update",
|
||||
"updates",
|
||||
"ws",
|
||||
"wss",
|
||||
"web",
|
||||
"websockets",
|
||||
"www",
|
||||
"www1",
|
||||
"www2",
|
||||
"www3",
|
||||
"www4",
|
||||
];
|
||||
|
||||
@@ -1,149 +1,149 @@
|
||||
/* eslint-disable flowtype/require-valid-file-annotation */
|
||||
import { stripSubdomain, parseDomain, isCustomSubdomain } from './domains';
|
||||
import { stripSubdomain, parseDomain, isCustomSubdomain } from "./domains";
|
||||
|
||||
// test suite is based on subset of parse-domain module we want to support
|
||||
// https://github.com/peerigon/parse-domain/blob/master/test/parseDomain.test.js
|
||||
describe('#parseDomain', () => {
|
||||
it('should remove the protocol', () => {
|
||||
expect(parseDomain('http://example.com')).toMatchObject({
|
||||
subdomain: '',
|
||||
domain: 'example',
|
||||
tld: 'com',
|
||||
describe("#parseDomain", () => {
|
||||
it("should remove the protocol", () => {
|
||||
expect(parseDomain("http://example.com")).toMatchObject({
|
||||
subdomain: "",
|
||||
domain: "example",
|
||||
tld: "com",
|
||||
});
|
||||
expect(parseDomain('//example.com')).toMatchObject({
|
||||
subdomain: '',
|
||||
domain: 'example',
|
||||
tld: 'com',
|
||||
expect(parseDomain("//example.com")).toMatchObject({
|
||||
subdomain: "",
|
||||
domain: "example",
|
||||
tld: "com",
|
||||
});
|
||||
expect(parseDomain('https://example.com')).toMatchObject({
|
||||
subdomain: '',
|
||||
domain: 'example',
|
||||
tld: 'com',
|
||||
expect(parseDomain("https://example.com")).toMatchObject({
|
||||
subdomain: "",
|
||||
domain: "example",
|
||||
tld: "com",
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove sub-domains', () => {
|
||||
expect(parseDomain('www.example.com')).toMatchObject({
|
||||
subdomain: 'www',
|
||||
domain: 'example',
|
||||
tld: 'com',
|
||||
it("should remove sub-domains", () => {
|
||||
expect(parseDomain("www.example.com")).toMatchObject({
|
||||
subdomain: "www",
|
||||
domain: "example",
|
||||
tld: "com",
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove the path', () => {
|
||||
expect(parseDomain('example.com/some/path?and&query')).toMatchObject({
|
||||
subdomain: '',
|
||||
domain: 'example',
|
||||
tld: 'com',
|
||||
it("should remove the path", () => {
|
||||
expect(parseDomain("example.com/some/path?and&query")).toMatchObject({
|
||||
subdomain: "",
|
||||
domain: "example",
|
||||
tld: "com",
|
||||
});
|
||||
expect(parseDomain('example.com/')).toMatchObject({
|
||||
subdomain: '',
|
||||
domain: 'example',
|
||||
tld: 'com',
|
||||
expect(parseDomain("example.com/")).toMatchObject({
|
||||
subdomain: "",
|
||||
domain: "example",
|
||||
tld: "com",
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove the query string', () => {
|
||||
expect(parseDomain('example.com?and&query')).toMatchObject({
|
||||
subdomain: '',
|
||||
domain: 'example',
|
||||
tld: 'com',
|
||||
it("should remove the query string", () => {
|
||||
expect(parseDomain("example.com?and&query")).toMatchObject({
|
||||
subdomain: "",
|
||||
domain: "example",
|
||||
tld: "com",
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove special characters', () => {
|
||||
expect(parseDomain('http://m.example.com\r')).toMatchObject({
|
||||
subdomain: 'm',
|
||||
domain: 'example',
|
||||
tld: 'com',
|
||||
it("should remove special characters", () => {
|
||||
expect(parseDomain("http://m.example.com\r")).toMatchObject({
|
||||
subdomain: "m",
|
||||
domain: "example",
|
||||
tld: "com",
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove the port', () => {
|
||||
expect(parseDomain('example.com:8080')).toMatchObject({
|
||||
subdomain: '',
|
||||
domain: 'example',
|
||||
tld: 'com',
|
||||
it("should remove the port", () => {
|
||||
expect(parseDomain("example.com:8080")).toMatchObject({
|
||||
subdomain: "",
|
||||
domain: "example",
|
||||
tld: "com",
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow @ characters in the path', () => {
|
||||
expect(parseDomain('https://medium.com/@username/')).toMatchObject({
|
||||
subdomain: '',
|
||||
domain: 'medium',
|
||||
tld: 'com',
|
||||
it("should allow @ characters in the path", () => {
|
||||
expect(parseDomain("https://medium.com/@username/")).toMatchObject({
|
||||
subdomain: "",
|
||||
domain: "medium",
|
||||
tld: "com",
|
||||
});
|
||||
});
|
||||
|
||||
it('should also work with three-level domains like .co.uk', () => {
|
||||
expect(parseDomain('www.example.co.uk')).toMatchObject({
|
||||
subdomain: 'www',
|
||||
domain: 'example',
|
||||
tld: 'co.uk',
|
||||
it("should also work with three-level domains like .co.uk", () => {
|
||||
expect(parseDomain("www.example.co.uk")).toMatchObject({
|
||||
subdomain: "www",
|
||||
domain: "example",
|
||||
tld: "co.uk",
|
||||
});
|
||||
});
|
||||
|
||||
it('should not include private domains like blogspot.com by default', () => {
|
||||
expect(parseDomain('foo.blogspot.com')).toMatchObject({
|
||||
subdomain: 'foo',
|
||||
domain: 'blogspot',
|
||||
tld: 'com',
|
||||
it("should not include private domains like blogspot.com by default", () => {
|
||||
expect(parseDomain("foo.blogspot.com")).toMatchObject({
|
||||
subdomain: "foo",
|
||||
domain: "blogspot",
|
||||
tld: "com",
|
||||
});
|
||||
});
|
||||
|
||||
it('should also work with the minimum', () => {
|
||||
expect(parseDomain('example.com')).toMatchObject({
|
||||
subdomain: '',
|
||||
domain: 'example',
|
||||
tld: 'com',
|
||||
it("should also work with the minimum", () => {
|
||||
expect(parseDomain("example.com")).toMatchObject({
|
||||
subdomain: "",
|
||||
domain: "example",
|
||||
tld: "com",
|
||||
});
|
||||
});
|
||||
|
||||
it('should return null if the given value is not a string', () => {
|
||||
it("should return null if the given value is not a string", () => {
|
||||
expect(parseDomain(undefined)).toBe(null);
|
||||
expect(parseDomain({})).toBe(null);
|
||||
expect(parseDomain('')).toBe(null);
|
||||
expect(parseDomain("")).toBe(null);
|
||||
});
|
||||
|
||||
it('should work with custom top-level domains (eg .local)', () => {
|
||||
expect(parseDomain('mymachine.local')).toMatchObject({
|
||||
subdomain: '',
|
||||
domain: 'mymachine',
|
||||
tld: 'local',
|
||||
it("should work with custom top-level domains (eg .local)", () => {
|
||||
expect(parseDomain("mymachine.local")).toMatchObject({
|
||||
subdomain: "",
|
||||
domain: "mymachine",
|
||||
tld: "local",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#stripSubdomain', () => {
|
||||
test('to work with localhost', () => {
|
||||
expect(stripSubdomain('localhost')).toBe('localhost');
|
||||
describe("#stripSubdomain", () => {
|
||||
test("to work with localhost", () => {
|
||||
expect(stripSubdomain("localhost")).toBe("localhost");
|
||||
});
|
||||
test('to return domains without a subdomain', () => {
|
||||
expect(stripSubdomain('example')).toBe('example');
|
||||
expect(stripSubdomain('example.com')).toBe('example.com');
|
||||
expect(stripSubdomain('example.org:3000')).toBe('example.org');
|
||||
test("to return domains without a subdomain", () => {
|
||||
expect(stripSubdomain("example")).toBe("example");
|
||||
expect(stripSubdomain("example.com")).toBe("example.com");
|
||||
expect(stripSubdomain("example.org:3000")).toBe("example.org");
|
||||
});
|
||||
test('to remove subdomains', () => {
|
||||
expect(stripSubdomain('test.example.com')).toBe('example.com');
|
||||
expect(stripSubdomain('test.example.com:3000')).toBe('example.com');
|
||||
test("to remove subdomains", () => {
|
||||
expect(stripSubdomain("test.example.com")).toBe("example.com");
|
||||
expect(stripSubdomain("test.example.com:3000")).toBe("example.com");
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isCustomSubdomain', () => {
|
||||
test('to work with localhost', () => {
|
||||
expect(isCustomSubdomain('localhost')).toBe(false);
|
||||
describe("#isCustomSubdomain", () => {
|
||||
test("to work with localhost", () => {
|
||||
expect(isCustomSubdomain("localhost")).toBe(false);
|
||||
});
|
||||
test('to return false for domains without a subdomain', () => {
|
||||
expect(isCustomSubdomain('example')).toBe(false);
|
||||
expect(isCustomSubdomain('example.com')).toBe(false);
|
||||
expect(isCustomSubdomain('example.org:3000')).toBe(false);
|
||||
test("to return false for domains without a subdomain", () => {
|
||||
expect(isCustomSubdomain("example")).toBe(false);
|
||||
expect(isCustomSubdomain("example.com")).toBe(false);
|
||||
expect(isCustomSubdomain("example.org:3000")).toBe(false);
|
||||
});
|
||||
test('to return false for www', () => {
|
||||
expect(isCustomSubdomain('www.example.com')).toBe(false);
|
||||
expect(isCustomSubdomain('www.example.com:3000')).toBe(false);
|
||||
test("to return false for www", () => {
|
||||
expect(isCustomSubdomain("www.example.com")).toBe(false);
|
||||
expect(isCustomSubdomain("www.example.com:3000")).toBe(false);
|
||||
});
|
||||
test('to return true for subdomains', () => {
|
||||
expect(isCustomSubdomain('test.example.com')).toBe(true);
|
||||
expect(isCustomSubdomain('test.example.com:3000')).toBe(true);
|
||||
test("to return true for subdomains", () => {
|
||||
expect(isCustomSubdomain("test.example.com")).toBe(true);
|
||||
expect(isCustomSubdomain("test.example.com:3000")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
// @flow
|
||||
|
||||
export default function getQueryVariable(variable: string) {
|
||||
var query = window.location.search.substring(1);
|
||||
var vars = query.split('&');
|
||||
const query = window.location.search.substring(1);
|
||||
const vars = query.split("&");
|
||||
|
||||
for (var i = 0; i < vars.length; i++) {
|
||||
var pair = vars[i].split('=');
|
||||
if (pair[0] == variable) {
|
||||
const pair = vars[i].split("=");
|
||||
|
||||
if (pair[0] === variable) {
|
||||
return pair[1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// @flow
|
||||
import { deburr } from 'lodash';
|
||||
import naturalSort from 'natural-sort';
|
||||
import { deburr } from "lodash";
|
||||
import naturalSort from "natural-sort";
|
||||
|
||||
type NaturalSortOptions = {
|
||||
caseSensitive?: boolean,
|
||||
direction?: 'asc' | 'desc',
|
||||
direction?: "asc" | "desc",
|
||||
};
|
||||
|
||||
const sorter = naturalSort();
|
||||
@@ -13,7 +13,7 @@ function getSortByField<T: Object>(
|
||||
item: T,
|
||||
keyOrCallback: string | (T => string)
|
||||
) {
|
||||
if (typeof keyOrCallback === 'string') {
|
||||
if (typeof keyOrCallback === "string") {
|
||||
return deburr(item[keyOrCallback]);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @flow
|
||||
import { parser } from 'rich-markdown-editor';
|
||||
import { parser } from "rich-markdown-editor";
|
||||
|
||||
export default function parseDocumentIds(text: string): string[] {
|
||||
const value = parser.parse(text);
|
||||
@@ -7,15 +7,15 @@ export default function parseDocumentIds(text: string): string[] {
|
||||
|
||||
function findLinks(node) {
|
||||
// get text nodes
|
||||
if (node.type.name === 'text') {
|
||||
if (node.type.name === "text") {
|
||||
// get marks for text nodes
|
||||
node.marks.forEach(mark => {
|
||||
// any of the marks links?
|
||||
if (mark.type.name === 'link') {
|
||||
if (mark.type.name === "link") {
|
||||
const { href } = mark.attrs;
|
||||
// any of the links to other docs?
|
||||
if (href.startsWith('/doc')) {
|
||||
const tokens = href.replace(/\/$/, '').split('/');
|
||||
if (href.startsWith("/doc")) {
|
||||
const tokens = href.replace(/\/$/, "").split("/");
|
||||
const lastToken = tokens[tokens.length - 1];
|
||||
|
||||
// don't return the same link more than once
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
/* eslint-disable flowtype/require-valid-file-annotation */
|
||||
import parseDocumentIds from './parseDocumentIds';
|
||||
import parseDocumentIds from "./parseDocumentIds";
|
||||
|
||||
it('should not return non links', () => {
|
||||
it("should not return non links", () => {
|
||||
expect(parseDocumentIds(`# Header`).length).toBe(0);
|
||||
});
|
||||
|
||||
it('should return an array of document ids', () => {
|
||||
it("should return an array of document ids", () => {
|
||||
const result = parseDocumentIds(`# Header
|
||||
|
||||
[internal](/doc/test-456733)
|
||||
`);
|
||||
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0]).toBe('test-456733');
|
||||
expect(result[0]).toBe("test-456733");
|
||||
});
|
||||
|
||||
it('should not return duplicate document ids', () => {
|
||||
it("should not return duplicate document ids", () => {
|
||||
expect(parseDocumentIds(`# Header`).length).toBe(0);
|
||||
|
||||
const result = parseDocumentIds(`# Header
|
||||
@@ -26,13 +26,13 @@ it('should not return duplicate document ids', () => {
|
||||
`);
|
||||
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0]).toBe('test-456733');
|
||||
expect(result[0]).toBe("test-456733");
|
||||
});
|
||||
|
||||
it('should not return non document links', () => {
|
||||
it("should not return non document links", () => {
|
||||
expect(parseDocumentIds(`[google](http://www.google.com)`).length).toBe(0);
|
||||
});
|
||||
|
||||
it('should not return non document relative links', () => {
|
||||
it("should not return non document relative links", () => {
|
||||
expect(parseDocumentIds(`[relative](/developers)`).length).toBe(0);
|
||||
});
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// @flow
|
||||
import emojiRegex from 'emoji-regex';
|
||||
import unescape from './unescape';
|
||||
import emojiRegex from "emoji-regex";
|
||||
import unescape from "./unescape";
|
||||
|
||||
export default function parseTitle(text: string = '') {
|
||||
export default function parseTitle(text: string = "") {
|
||||
const regex = emojiRegex();
|
||||
|
||||
// find and extract title
|
||||
const firstLine = text.trim().split(/\r?\n/)[0];
|
||||
const trimmedTitle = firstLine.replace(/^#/, '').trim();
|
||||
const trimmedTitle = firstLine.replace(/^#/, "").trim();
|
||||
|
||||
// remove any escape characters
|
||||
const title = unescape(trimmedTitle);
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
/* eslint-disable flowtype/require-valid-file-annotation */
|
||||
import parseTitle from './parseTitle';
|
||||
import parseTitle from "./parseTitle";
|
||||
|
||||
it('should trim the title', () => {
|
||||
expect(parseTitle(`# Lots of space `).title).toBe('Lots of space');
|
||||
it("should trim the title", () => {
|
||||
expect(parseTitle(`# Lots of space `).title).toBe("Lots of space");
|
||||
});
|
||||
|
||||
it('should extract first title', () => {
|
||||
expect(parseTitle(`# Title one\n# Title two`).title).toBe('Title one');
|
||||
it("should extract first title", () => {
|
||||
expect(parseTitle(`# Title one\n# Title two`).title).toBe("Title one");
|
||||
});
|
||||
|
||||
it('should remove escape characters', () => {
|
||||
expect(parseTitle(`# Thing \\- one`).title).toBe('Thing - one');
|
||||
expect(parseTitle(`# \\[wip\\] Title`).title).toBe('[wip] Title');
|
||||
expect(parseTitle(`# \\> Title`).title).toBe('> Title');
|
||||
it("should remove escape characters", () => {
|
||||
expect(parseTitle(`# Thing \\- one`).title).toBe("Thing - one");
|
||||
expect(parseTitle(`# \\[wip\\] Title`).title).toBe("[wip] Title");
|
||||
expect(parseTitle(`# \\> Title`).title).toBe("> Title");
|
||||
});
|
||||
|
||||
it('should parse emoji if first character', () => {
|
||||
it("should parse emoji if first character", () => {
|
||||
const parsed = parseTitle(`# 😀 Title`);
|
||||
expect(parsed.title).toBe('😀 Title');
|
||||
expect(parsed.emoji).toBe('😀');
|
||||
expect(parsed.title).toBe("😀 Title");
|
||||
expect(parsed.emoji).toBe("😀");
|
||||
});
|
||||
|
||||
it('should not parse emoji if not first character', () => {
|
||||
it("should not parse emoji if not first character", () => {
|
||||
const parsed = parseTitle(`# Title 🌈`);
|
||||
expect(parsed.title).toBe('Title 🌈');
|
||||
expect(parsed.title).toBe("Title 🌈");
|
||||
expect(parsed.emoji).toBe(undefined);
|
||||
});
|
||||
|
||||
@@ -3,54 +3,54 @@
|
||||
export function slackAuth(
|
||||
state: string,
|
||||
scopes: string[] = [
|
||||
'identity.email',
|
||||
'identity.basic',
|
||||
'identity.avatar',
|
||||
'identity.team',
|
||||
"identity.email",
|
||||
"identity.basic",
|
||||
"identity.avatar",
|
||||
"identity.team",
|
||||
],
|
||||
redirectUri: string = `${process.env.URL}/auth/slack.callback`
|
||||
): string {
|
||||
const baseUrl = 'https://slack.com/oauth/authorize';
|
||||
const baseUrl = "https://slack.com/oauth/authorize";
|
||||
const params = {
|
||||
client_id: process.env.SLACK_KEY,
|
||||
scope: scopes ? scopes.join(' ') : '',
|
||||
scope: scopes ? scopes.join(" ") : "",
|
||||
redirect_uri: redirectUri,
|
||||
state,
|
||||
};
|
||||
|
||||
const urlParams = Object.keys(params)
|
||||
.map(key => `${key}=${encodeURIComponent(params[key])}`)
|
||||
.join('&');
|
||||
.join("&");
|
||||
|
||||
return `${baseUrl}?${urlParams}`;
|
||||
}
|
||||
|
||||
export function githubUrl(): string {
|
||||
return 'https://www.github.com/outline';
|
||||
return "https://www.github.com/outline";
|
||||
}
|
||||
|
||||
export function githubIssuesUrl(): string {
|
||||
return 'https://www.github.com/outline/outline/issues';
|
||||
return "https://www.github.com/outline/outline/issues";
|
||||
}
|
||||
|
||||
export function slackAppStoreUrl(): string {
|
||||
return 'https://goabstract.slack.com/apps/A0W3UMKBQ-outline';
|
||||
return "https://goabstract.slack.com/apps/A0W3UMKBQ-outline";
|
||||
}
|
||||
|
||||
export function blogUrl(): string {
|
||||
return 'https://medium.com/getoutline';
|
||||
return "https://medium.com/getoutline";
|
||||
}
|
||||
|
||||
export function twitterUrl(): string {
|
||||
return 'https://twitter.com/outlinewiki';
|
||||
return "https://twitter.com/outlinewiki";
|
||||
}
|
||||
|
||||
export function spectrumUrl(): string {
|
||||
return 'https://spectrum.chat/outline';
|
||||
return "https://spectrum.chat/outline";
|
||||
}
|
||||
|
||||
export function mailToUrl(): string {
|
||||
return 'mailto:hello@getoutline.com';
|
||||
return "mailto:hello@getoutline.com";
|
||||
}
|
||||
|
||||
export function features(): string {
|
||||
@@ -65,7 +65,7 @@ export function changelog(): string {
|
||||
return `https://www.getoutline.com/changelog`;
|
||||
}
|
||||
|
||||
export function signin(service: string = 'slack'): string {
|
||||
export function signin(service: string = "slack"): string {
|
||||
return `${process.env.URL}/auth/${service}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// @flow
|
||||
import slugify from 'slugify';
|
||||
import slugify from "slugify";
|
||||
|
||||
// Slugify, escape, and remove periods from headings so that they are
|
||||
// compatible with url hashes AND dom selectors
|
||||
export default function safeSlugify(text: string) {
|
||||
return `h-${escape(slugify(text, { lower: true }).replace('.', '-'))}`;
|
||||
return `h-${escape(slugify(text, { lower: true }).replace(".", "-"))}`;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
const unescape = (text: string) => {
|
||||
return text
|
||||
.replace(/\\([\\`*{}[\]()#+\-.!_>])/g, '$1')
|
||||
.replace(/\n\\\n/g, '\n\n');
|
||||
.replace(/\\([\\`*{}[\]()#+\-.!_>])/g, "$1")
|
||||
.replace(/\n\\\n/g, "\n\n");
|
||||
};
|
||||
|
||||
export default unescape;
|
||||
|
||||
Reference in New Issue
Block a user