#60 [api] Public API
This commit is contained in:
parent
8fcf96040e
commit
629a12698e
|
@ -182,7 +182,7 @@
|
||||||
if (this.nounsRaw !== undefined) {
|
if (this.nounsRaw !== undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.nounsRaw = await this.$axios.$get(`/nouns/all`);
|
this.nounsRaw = await this.$axios.$get(`/nouns`);
|
||||||
},
|
},
|
||||||
async setFilter(filter) {
|
async setFilter(filter) {
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
|
|
|
@ -37,12 +37,20 @@
|
||||||
<Icon v="gitlab" set="b"/>
|
<Icon v="gitlab" set="b"/>
|
||||||
</SquareButton>
|
</SquareButton>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="config.user.enabled" class="small">
|
<ul v-if="config.user.enabled" class="list-inline small">
|
||||||
<nuxt-link :to="`/${config.user.termsRoute}`">
|
<li class="list-inline-item">
|
||||||
<Icon v="gavel"/>
|
<nuxt-link :to="`/${config.user.termsRoute}`">
|
||||||
<T>terms.header</T>
|
<Icon v="gavel"/>
|
||||||
</nuxt-link>
|
<T>terms.header</T>
|
||||||
</p>
|
</nuxt-link>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<nuxt-link to="/api">
|
||||||
|
<Icon v="laptop-code"/>
|
||||||
|
<T>api.header</T>
|
||||||
|
</nuxt-link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<Share/>
|
<Share/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -87,8 +87,8 @@
|
||||||
|
|
||||||
return jwt.verify(this.token, process.env.PUBLIC_KEY, {
|
return jwt.verify(this.token, process.env.PUBLIC_KEY, {
|
||||||
algorithm: 'RS256',
|
algorithm: 'RS256',
|
||||||
audience: process.env.BASE_URL,
|
audience: this.$base,
|
||||||
issuer: process.env.BASE_URL,
|
issuer: this.$base,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -118,7 +118,6 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { nounTemplates } from '../src/data';
|
import { nounTemplates } from '../src/data';
|
||||||
import config from "../data/config.suml";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
preset: {
|
preset: {
|
||||||
url: process.env.BASE_URL + this.$route.path,
|
url: this.$base + this.$route.path,
|
||||||
title: this.title,
|
title: this.title,
|
||||||
extra: {
|
extra: {
|
||||||
media: '',
|
media: '',
|
||||||
|
|
|
@ -247,3 +247,16 @@ profile:
|
||||||
redirects:
|
redirects:
|
||||||
- { from: '^/neutratywy', to: '/rzeczowniki' }
|
- { from: '^/neutratywy', to: '/rzeczowniki' }
|
||||||
- { from: '^/literatura', to: '/korpus' }
|
- { from: '^/literatura', to: '/korpus' }
|
||||||
|
|
||||||
|
api:
|
||||||
|
examples:
|
||||||
|
pronouns_all: ['/api/pronouns']
|
||||||
|
pronouns_one:
|
||||||
|
- '/api/pronouns/ono/jej'
|
||||||
|
- '/api/pronouns/ono/jej?examples[]=Czy%20chcia%C5%82%7Bverb_end_inter%7Dby%C5%9B%20skorzysta%C4%87%20z%20naszej%20oferty%3F%7CCzy%20chci%7Bverb_middle_inter%7Dby%C5%9Bcie%20skorzysta%C4%87%20z%20naszej%20oferty%3F%7C0'
|
||||||
|
|
||||||
|
sources_all: ['/api/sources']
|
||||||
|
sources_one: ['/api/sources/queerZaimki']
|
||||||
|
|
||||||
|
nouns_all: ['/api/nouns']
|
||||||
|
nouns_search: ['/api/nouns/search/ateis']
|
||||||
|
|
|
@ -805,3 +805,8 @@ table:
|
||||||
count: 'Liczba'
|
count: 'Liczba'
|
||||||
sort: 'Przeciągnij by posortować'
|
sort: 'Przeciągnij by posortować'
|
||||||
scrollUp: 'Przewiń na samą górę'
|
scrollUp: 'Przewiń na samą górę'
|
||||||
|
|
||||||
|
api:
|
||||||
|
header: 'Publiczne API'
|
||||||
|
example: 'Przykład'
|
||||||
|
query: 'Query string parameters'
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import translations from './server/translations';
|
import { loadSuml } from './server/loader';
|
||||||
import config from './server/config';
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import {buildDict} from "./src/helpers";
|
import {buildDict} from "./src/helpers";
|
||||||
|
|
||||||
|
const config = loadSuml('config');
|
||||||
|
const translations = loadSuml('translations');
|
||||||
|
|
||||||
const locale = config.locale;
|
const locale = config.locale;
|
||||||
const title = translations.title;
|
const title = translations.title;
|
||||||
const description = translations.description;
|
const description = translations.description;
|
||||||
|
@ -158,6 +160,8 @@ export default {
|
||||||
routes.push({ path: '/' + config.template.any.route, component: resolve(__dirname, 'routes/any.vue') });
|
routes.push({ path: '/' + config.template.any.route, component: resolve(__dirname, 'routes/any.vue') });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
routes.push({ path: '/api', component: resolve(__dirname, 'routes/api.vue') });
|
||||||
|
|
||||||
routes.push({ name: 'all', path: '*', component: resolve(__dirname, 'routes/template.vue') });
|
routes.push({ name: 'all', path: '*', component: resolve(__dirname, 'routes/template.vue') });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { locales } from '../src/data';
|
||||||
import {buildDict} from "../src/helpers";
|
import {buildDict} from "../src/helpers";
|
||||||
|
|
||||||
export default ({ app }) => {
|
export default ({ app }) => {
|
||||||
|
Vue.prototype.$base = process.env.BASE_URL;
|
||||||
Vue.prototype.$t = t;
|
Vue.prototype.$t = t;
|
||||||
Vue.prototype.config = config;
|
Vue.prototype.config = config;
|
||||||
Vue.prototype.locales = buildDict(function* () {
|
Vue.prototype.locales = buildDict(function* () {
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<h2>
|
||||||
|
<Icon v="laptop-code"/>
|
||||||
|
<T>api.header</T>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<section v-for="group in groups" v-if="group.enabled" class="py-2">
|
||||||
|
<h3>
|
||||||
|
<Icon :v="group.icon"/>
|
||||||
|
<T>{{group.header}}</T>
|
||||||
|
</h3>
|
||||||
|
<ul>
|
||||||
|
<li v-for="([method, path, queryString], endpoint) in group.endpoints" class="my-3">
|
||||||
|
<p>
|
||||||
|
<span class="badge badge-primary">{{method}}</span>
|
||||||
|
<code>{{path}}</code>
|
||||||
|
<a v-for="example in config.api.examples[endpoint]" :href="$base + example" class="badge badge-light border mx-1" target="_blank" rel="noopener">
|
||||||
|
<Icon v="cog"/>
|
||||||
|
<T>api.example</T>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p v-if="queryString" class="mb-0 small">
|
||||||
|
<T>api.query</T>:
|
||||||
|
</p>
|
||||||
|
<ul v-if="queryString" class="small">
|
||||||
|
<li v-for="(description, param) in queryString">
|
||||||
|
<code>{{param}}</code> – <span v-html="description"></span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {head} from "../src/helpers";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
groups: [{
|
||||||
|
enabled: this.config.template.enabled,
|
||||||
|
header: 'home.header',
|
||||||
|
icon: 'tags',
|
||||||
|
endpoints: {
|
||||||
|
pronouns_all: ['GET', '/api/pronouns'],
|
||||||
|
pronouns_one: ['GET', '/api/pronouns/{pronoun}', {
|
||||||
|
'examples[]': 'Overwrite the default example sentences with custom ones. For each of them use the following format: <code>{sentenceSingular}|{sentencePlural}|{isHonorific}</code>. If <code>sentencePlural</code> is missing, if defaults to being the same as <code>sentenceSingular</code>. <code>isHonorific</code> can be <code>0</code> (default) or <code>1</code>.',
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
enabled: this.config.sources.enabled,
|
||||||
|
header: 'sources.header',
|
||||||
|
icon: 'books',
|
||||||
|
endpoints: {
|
||||||
|
sources_all: ['GET', '/api/sources'],
|
||||||
|
sources_one: ['GET', '/api/sources/{key}'],
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
enabled: this.config.nouns.enabled,
|
||||||
|
header: 'nouns.header',
|
||||||
|
icon: 'atom-alt',
|
||||||
|
endpoints: {
|
||||||
|
nouns_all: ['GET', '/api/nouns'],
|
||||||
|
nouns_search: ['GET', '/api/nouns/search/{term}'],
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
head() {
|
||||||
|
return head({
|
||||||
|
title: this.$t('api.header'),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -243,14 +243,14 @@
|
||||||
if (!this.selectedTemplate.pronoun()) {
|
if (!this.selectedTemplate.pronoun()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return this.addSlash(process.env.BASE_URL + '/' + (this.usedBaseEquals ? this.usedBase : this.longLink));
|
return this.addSlash(this.$base + '/' + (this.usedBaseEquals ? this.usedBase : this.longLink));
|
||||||
},
|
},
|
||||||
linkMultiple() {
|
linkMultiple() {
|
||||||
if (!this.multiple.length) {
|
if (!this.multiple.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.addSlash(process.env.BASE_URL + '/' + this.multiple.join('&'));
|
return this.addSlash(this.$base + '/' + this.multiple.join('&'));
|
||||||
},
|
},
|
||||||
sources() {
|
sources() {
|
||||||
return getSources(this.selectedTemplate);
|
return getSources(this.selectedTemplate);
|
||||||
|
|
|
@ -141,7 +141,7 @@
|
||||||
for (let pronoun in this.profile.pronouns) {
|
for (let pronoun in this.profile.pronouns) {
|
||||||
if (!this.profile.pronouns.hasOwnProperty(pronoun)) { continue; }
|
if (!this.profile.pronouns.hasOwnProperty(pronoun)) { continue; }
|
||||||
|
|
||||||
const link = pronoun.replace(new RegExp('^' + process.env.BASE_URL), '').replace(new RegExp('^/'), '');
|
const link = pronoun.replace(new RegExp('^' + this.$base), '').replace(new RegExp('^/'), '');
|
||||||
const template = buildTemplate(templates, link);
|
const template = buildTemplate(templates, link);
|
||||||
|
|
||||||
if (template) {
|
if (template) {
|
||||||
|
|
|
@ -188,7 +188,7 @@
|
||||||
this.$router.push(`/@${this.$user().username}`)
|
this.$router.push(`/@${this.$user().username}`)
|
||||||
},
|
},
|
||||||
validatePronoun(pronoun) {
|
validatePronoun(pronoun) {
|
||||||
const link = pronoun.replace(new RegExp('^' + process.env.BASE_URL), '').replace(new RegExp('^/'), '');
|
const link = pronoun.replace(new RegExp('^' + this.$base), '').replace(new RegExp('^/'), '');
|
||||||
const template = buildTemplate(templates, link);
|
const template = buildTemplate(templates, link);
|
||||||
|
|
||||||
return template ? null : 'profile.pronounsNotFound'
|
return template ? null : 'profile.pronounsNotFound'
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Suml from 'suml';
|
|
||||||
const fs = require('fs');
|
|
||||||
export default new Suml().parse(fs.readFileSync('./data/config.suml').toString());
|
|
|
@ -5,7 +5,7 @@ import session from 'express-session';
|
||||||
import cookieParser from 'cookie-parser';
|
import cookieParser from 'cookie-parser';
|
||||||
import grant from "grant";
|
import grant from "grant";
|
||||||
import router from "./routes/user";
|
import router from "./routes/user";
|
||||||
import config from './config';
|
import { loadSuml } from './loader';
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ app.use(session({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
app.use(async function (req, res, next) {
|
app.use(async function (req, res, next) {
|
||||||
req.config = config;
|
req.config = loadSuml('config');
|
||||||
req.rawUser = authenticate(req);
|
req.rawUser = authenticate(req);
|
||||||
req.user = req.rawUser && req.rawUser.authenticated ? req.rawUser : null;
|
req.user = req.rawUser && req.rawUser.authenticated ? req.rawUser : null;
|
||||||
req.admin = req.user && req.user.roles === 'admin';
|
req.admin = req.user && req.user.roles === 'admin';
|
||||||
|
@ -34,8 +34,9 @@ app.use(require('./routes/user').default);
|
||||||
app.use(require('./routes/profile').default);
|
app.use(require('./routes/profile').default);
|
||||||
app.use(require('./routes/admin').default);
|
app.use(require('./routes/admin').default);
|
||||||
|
|
||||||
app.use(require('./routes/nouns').default);
|
app.use(require('./routes/templates').default);
|
||||||
app.use(require('./routes/sources').default);
|
app.use(require('./routes/sources').default);
|
||||||
|
app.use(require('./routes/nouns').default);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
path: '/api',
|
path: '/api',
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
import Suml from 'suml';
|
||||||
|
import Papa from 'papaparse';
|
||||||
|
|
||||||
|
export const loadSuml = name => new Suml().parse(fs.readFileSync(`./data/${name}.suml`).toString());
|
||||||
|
|
||||||
|
export const loadTsv = name => Papa.parse(fs.readFileSync(`./data/${name}.tsv`).toString(), {
|
||||||
|
dynamicTyping: true,
|
||||||
|
header: true,
|
||||||
|
skipEmptyLines: true,
|
||||||
|
delimiter: '\t',
|
||||||
|
}).data;
|
|
@ -1,11 +1,13 @@
|
||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import SQL from 'sql-template-strings';
|
import SQL from 'sql-template-strings';
|
||||||
import {createCanvas, loadImage, registerFont} from "canvas";
|
import {createCanvas, loadImage, registerFont} from "canvas";
|
||||||
import translations from "../translations";
|
import { loadSuml } from '../loader';
|
||||||
import avatar from '../avatar';
|
import avatar from '../avatar';
|
||||||
import {buildTemplate, parseTemplates} from "../../src/buildTemplate";
|
import {buildTemplate, parseTemplates} from "../../src/buildTemplate";
|
||||||
import {loadTsv} from "../../src/tsv";
|
import {loadTsv} from "../../src/tsv";
|
||||||
|
|
||||||
|
const translations = loadSuml('translations');
|
||||||
|
|
||||||
const drawCircle = (context, image, x, y, size) => {
|
const drawCircle = (context, image, x, y, size) => {
|
||||||
context.save();
|
context.save();
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
|
|
|
@ -23,7 +23,7 @@ const approve = async (db, id) => {
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.get('/nouns/all', async (req, res) => {
|
router.get('/nouns', async (req, res) => {
|
||||||
return res.json(await req.db.all(SQL`
|
return res.json(await req.db.all(SQL`
|
||||||
SELECT * FROM nouns
|
SELECT * FROM nouns
|
||||||
WHERE locale = ${req.config.locale}
|
WHERE locale = ${req.config.locale}
|
||||||
|
@ -32,6 +32,17 @@ router.get('/nouns/all', async (req, res) => {
|
||||||
`));
|
`));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get('/nouns/search/:term', async (req, res) => {
|
||||||
|
const term = '%' + req.params.term + '%';
|
||||||
|
return res.json(await req.db.all(SQL`
|
||||||
|
SELECT * FROM nouns
|
||||||
|
WHERE locale = ${req.config.locale}
|
||||||
|
AND approved >= ${req.admin ? 0 : 1}
|
||||||
|
AND (masc like ${term} OR fem like ${term} OR neutr like ${term} OR mascPl like ${term} OR femPl like ${term} OR neutrPl like ${term})
|
||||||
|
ORDER BY approved, masc
|
||||||
|
`));
|
||||||
|
});
|
||||||
|
|
||||||
router.post('/nouns/submit', async (req, res) => {
|
router.post('/nouns/submit', async (req, res) => {
|
||||||
if (!(req.user && req.user.admin) && isTroll(JSON.stringify(req.body))) {
|
if (!(req.user && req.user.admin) && isTroll(JSON.stringify(req.body))) {
|
||||||
return res.json('ok');
|
return res.json('ok');
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import mailer from "../../src/mailer";
|
import mailer from "../../src/mailer";
|
||||||
import {camelCase, capitalise} from "../../src/helpers";
|
import { camelCase } from "../../src/helpers";
|
||||||
|
import { loadTsv } from '../loader';
|
||||||
|
|
||||||
const generateId = title => {
|
const generateId = title => {
|
||||||
return camelCase(title.split(' ').slice(0, 2));
|
return camelCase(title.split(' ').slice(0, 2));
|
||||||
|
@ -21,8 +22,26 @@ const buildEmail = (data, user) => {
|
||||||
return `<ul>${human.join('')}</ul><pre>${tsv.join('\t')}</pre>`;
|
return `<ul>${human.join('')}</ul><pre>${tsv.join('\t')}</pre>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const loadSources = () => {
|
||||||
|
return loadTsv('sources/sources').map(s => {
|
||||||
|
if (s.author) {
|
||||||
|
s.author = s.author.replace('^', '');
|
||||||
|
}
|
||||||
|
s.fragments = s.fragments.split('@').map(f => f.replace(/\|/g, '\n'));
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
|
router.get('/sources', async (req, res) => {
|
||||||
|
return res.json(loadSources());
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/sources/:key', async (req, res) => {
|
||||||
|
return res.json([...loadSources().filter(s => s.key === req.params.key), null][0]);
|
||||||
|
});
|
||||||
|
|
||||||
router.post('/sources/submit', async (req, res) => {
|
router.post('/sources/submit', async (req, res) => {
|
||||||
const emailBody = buildEmail(req.body, req.user);
|
const emailBody = buildEmail(req.body, req.user);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
import { Router } from 'express';
|
||||||
|
import { loadTsv } from '../loader';
|
||||||
|
import {buildTemplate, parseTemplates} from "../../src/buildTemplate";
|
||||||
|
import {buildList} from "../../src/helpers";
|
||||||
|
import {Example} from "../../src/classes";
|
||||||
|
|
||||||
|
const buildExample = e => new Example(
|
||||||
|
Example.parse(e.singular),
|
||||||
|
Example.parse(e.plural || e.singular),
|
||||||
|
e.isHonorific,
|
||||||
|
)
|
||||||
|
|
||||||
|
const requestExamples = r => {
|
||||||
|
if (!r || !r.length) {
|
||||||
|
return loadTsv('templates/examples');
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildList(function* () {
|
||||||
|
for (let rr of r) {
|
||||||
|
let [singular, plural, isHonorific] = rr.split('|');
|
||||||
|
yield { singular, plural, isHonorific: !!isHonorific};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const addExamples = (pronoun, examples) => {
|
||||||
|
return buildList(function* () {
|
||||||
|
for (let example of examples) {
|
||||||
|
yield buildExample(example).format(pronoun);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
|
||||||
|
router.get('/pronouns', async (req, res) => {
|
||||||
|
const templates = parseTemplates(loadTsv('templates/templates'));
|
||||||
|
for (let template in templates) {
|
||||||
|
if (!templates.hasOwnProperty(template)) { continue; }
|
||||||
|
templates[template].examples = addExamples(templates[template], requestExamples(req.query.examples))
|
||||||
|
}
|
||||||
|
return res.json(templates);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/pronouns/:pronoun*', async (req, res) => {
|
||||||
|
const pronoun = buildTemplate(
|
||||||
|
parseTemplates(loadTsv('templates/templates')),
|
||||||
|
req.params.pronoun + req.params[0],
|
||||||
|
);
|
||||||
|
if (pronoun) {
|
||||||
|
pronoun.examples = addExamples(pronoun, requestExamples(req.query.examples))
|
||||||
|
}
|
||||||
|
return res.json(pronoun);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
|
@ -2,13 +2,15 @@ import { Router } from 'express';
|
||||||
import SQL from 'sql-template-strings';
|
import SQL from 'sql-template-strings';
|
||||||
import {ulid} from "ulid";
|
import {ulid} from "ulid";
|
||||||
import {buildDict, makeId, now} from "../../src/helpers";
|
import {buildDict, makeId, now} from "../../src/helpers";
|
||||||
import translations from "../translations";
|
|
||||||
import jwt from "../../src/jwt";
|
import jwt from "../../src/jwt";
|
||||||
import mailer from "../../src/mailer";
|
import mailer from "../../src/mailer";
|
||||||
import config from '../config';
|
import { loadSuml } from '../loader';
|
||||||
import avatar from '../avatar';
|
import avatar from '../avatar';
|
||||||
import { config as socialLoginConfig, handlers as socialLoginHandlers } from '../social';
|
import { config as socialLoginConfig, handlers as socialLoginHandlers } from '../social';
|
||||||
|
|
||||||
|
const config = loadSuml('config');
|
||||||
|
const translations = loadSuml('translations');
|
||||||
|
|
||||||
const USERNAME_CHARS = 'A-Za-zĄĆĘŁŃÓŚŻŹąćęłńóśżź0-9._-';
|
const USERNAME_CHARS = 'A-Za-zĄĆĘŁŃÓŚŻŹąćęłńóśżź0-9._-';
|
||||||
|
|
||||||
const normalise = s => s.trim().toLowerCase();
|
const normalise = s => s.trim().toLowerCase();
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
import Suml from 'suml';
|
|
||||||
const fs = require('fs');
|
|
||||||
export default new Suml().parse(fs.readFileSync('./data/translations.suml').toString());
|
|
|
@ -6,14 +6,6 @@ export class ExamplePart {
|
||||||
this.variable = variable;
|
this.variable = variable;
|
||||||
this.str = str;
|
this.str = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
format(form) {
|
|
||||||
if (!this.variable) {
|
|
||||||
return this.str[form.plural];
|
|
||||||
}
|
|
||||||
|
|
||||||
return form[this.str[form.plural]];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Example {
|
export class Example {
|
||||||
|
@ -44,12 +36,12 @@ export class Example {
|
||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
format(form) {
|
format(pronoun) {
|
||||||
return Example.ucfirst(this.parts.map(part => part.format(form)).join(''));
|
const plural = this.isHonorific ? pronoun.pluralHonorific[0] : pronoun.plural[0];
|
||||||
}
|
|
||||||
|
|
||||||
static ucfirst(str) {
|
return capitalise(this[plural ? 'pluralParts' : 'singularParts'].map(part => {
|
||||||
return str[0].toUpperCase() + str.slice(1);
|
return part.variable ? pronoun.getMorpheme(part.str) : part.str;
|
||||||
|
}).join(''));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue