Fix ci-check by rewriting lint and format under root package.json

This commit is contained in:
Simon Prévost 2019-03-11 06:27:14 -04:00
parent ee39f1a168
commit b9045b5bcd
57 changed files with 1995 additions and 523 deletions

16
.eslintignore Normal file
View File

@ -0,0 +1,16 @@
webapp/node_modules/*
webapp/**/vendor/*.js
webapp/vendor/**/*.js
webapp/bower_components/**/*.js
webapp/dist/**/*.js
webapp/tmp/**/*.js
webapp/app/locales/*/translations.js
webapp/app/utils/phoenix.js
cli/lib
cli/node_modules
cli/bin
jipt/node_modules
jipt/dist
jipt/.cache

View File

@ -1,4 +1,3 @@
{
"globals": {
"JsDiff": true,
@ -16,6 +15,7 @@
"es6": true
},
"rules": {
"no-irregular-whitespace": 0,
"ember/jquery-ember-run": 2,
"ember/use-brace-expansion": 2,
"ember/no-side-effects": 2,

1
.gitignore vendored
View File

@ -6,6 +6,7 @@ doc
deps
*.ez
cover
node_modules
# Generate on crash by the VM
erl_crash.dump

7
.prettierignore Normal file
View File

@ -0,0 +1,7 @@
jipt/dist
jipt/.cache
cli/lib
webapp/dist
webapp/.cache
webapp/node_modules
webapp/tmp

View File

@ -33,7 +33,9 @@ env:
before_install:
- 'echo `curl --verbose http://jsonip.com`'
- npm config set spin false
- npm --prefix webapp install
- npm ci --prefix webapp --no-audit --no-color
- npm ci --prefix cli --no-audit --no-color
- npm ci --prefix jipt --no-audit --no-color
- npm --prefix webapp run build-production
# Create database and prepare the application
@ -42,5 +44,7 @@ before_script:
- mix ecto.setup
script:
- make lint
- ./priv/script/ci-check.sh
- npm --prefix cli run build
- npm --prefix jipt run build-production
- mix coveralls.travis

View File

@ -46,9 +46,24 @@ dependencies-mix:
mix deps.get --force
.PHONY: dependencies-npm
dependencies-npm:
dependencies-npm: dependencies-npm-root dependencies-npm-webapp dependencies-npm-cli dependencies-npm-jipt
.PHONY: dependencies-npm-root
dependencies-npm-root:
npm install
.PHONY: dependencies-npm-webapp
dependencies-npm-webapp:
npm install --prefix webapp
.PHONY: dependencies-npm-cli
dependencies-npm-cli:
npm install --prefix cli
.PHONY: dependencies-npm-jipt
dependencies-npm-jipt:
npm install --prefix jipt
.PHONY: build
build: ## Build the Docker image for the OTP release
docker build --build-arg APP_NAME=$(APP_NAME) --build-arg APP_VERSION=$(APP_VERSION) --rm --tag $(APP_NAME):$(DOCKER_IMAGE_TAG) .
@ -57,7 +72,7 @@ build: ## Build the Docker image for the OTP release
# ----------
.PHONY: lint
lint: lint-compile lint-format lint-credo lint-eslint lint-prettier ## Run lint tools on the code
lint: lint-compile lint-format lint-credo lint-eslint lint-prettier lint-tslint ## Run lint tools on the code
.PHONY: lint-compile
lint-compile:
@ -73,11 +88,15 @@ lint-credo:
.PHONY: lint-eslint
lint-eslint:
./webapp/node_modules/.bin/eslint --ignore-path webapp/.eslintignore webapp
./node_modules/.bin/eslint webapp/. cli/. jipt/.
.PHONY: lint-tslint
lint-tslint:
./node_modules/.bin/tslint -c tslint.json '{cli,jipt}/src/**/*.{js,ts,json}'
.PHONY: lint-prettier
lint-prettier:
./webapp/node_modules/.bin/prettier --single-quote --list-different --no-bracket-spacing --print-width 130 './webapp/app/**/*.{js,gql}'
./node_modules/.bin/prettier --check --single-quote --no-bracket-spacing './{webapp,jipt,cli}/**/*.{js,ts,json,gql}'
.PHONY: test
test: ## Run the test suite
@ -96,7 +115,7 @@ format-elixir:
.PHONY: format-prettier
format-prettier:
./webapp/node_modules/.bin/prettier --single-quote --write --no-bracket-spacing --print-width 130 './webapp/app/**/*.{js,gql}'
./node_modules/.bin/prettier --write --single-quote --no-bracket-spacing './{webapp,jipt,cli}/**/*.{js,ts,json,gql}'
# Development targets
# -------------------

View File

@ -1 +0,0 @@
/lib

View File

@ -1,3 +0,0 @@
{
"extends": "oclif"
}

View File

@ -14,10 +14,7 @@
"beforeAddTranslations": [
"aigu rails-export --locale=fr --output-file=aigu/aigu-is-awesome-fr.json >/dev/null 2>&1"
],
"beforeExport": [
"rm -rf aigu",
"mkdir -p aigu"
],
"beforeExport": ["rm -rf aigu", "mkdir -p aigu"],
"afterExport": [
"aigu rails-import --locale=en --input-file=aigu/aigu-is-awesome-en.json >/dev/null 2>&1",
"aigu rails-import --locale=fr --input-file=aigu/aigu-is-awesome-fr.json >/dev/null 2>&1",

View File

@ -136,10 +136,10 @@
"late_deactivation": "Non désactivées"
},
"statusBadge": {
"activated": "Activée le {{date, DD\/MM\/YYYY HH:mm}}",
"deactivated": "Désactivée le {{date, DD\/MM\/YYYY HH:mm}}",
"lateActivation": "Activation en retard {{date, DD\/MM\/YYYY}}",
"lateDeactivation": "Désactivation en retard {{date, DD\/MM\/YYYY}}",
"activated": "Activée le {{date, DD/MM/YYYY HH:mm}}",
"deactivated": "Désactivée le {{date, DD/MM/YYYY HH:mm}}",
"lateActivation": "Activation en retard {{date, DD/MM/YYYY}}",
"lateDeactivation": "Désactivation en retard {{date, DD/MM/YYYY}}",
"upcoming": "À venir"
}
},

View File

@ -35,7 +35,6 @@
"chai": "4.1.2",
"globby": "8.0.1",
"mocha": "5.0.5",
"prettier": "1.15.3",
"ts-node": "7.0.1",
"tslint": "5.11.0",
"typescript": "3.2.2"
@ -68,10 +67,7 @@
"scripts": {
"build": "rm -rf lib && tsc",
"clean": "rm -f .oclif.manifest.json",
"lint": "tslint --project tsconfig.json 'src/**/*.{ts,tsx}'",
"fix": "tslint --project tsconfig.json --fix 'src/**/*.{ts,tsx}'",
"prepublishOnly": "npm run build && oclif-dev readme && oclif-dev manifest",
"prettier": "prettier --single-quote --no-bracket-spacing --no-semi --write './src/**/*.{js,json,ts,tsx,gql}'"
"prepublishOnly": "npm run build && oclif-dev readme && oclif-dev manifest"
},
"types": "lib/index.d.ts"
}

View File

@ -1,41 +1,41 @@
// Vendor
import Command from '@oclif/command'
import {error} from '@oclif/errors'
import chalk from 'chalk'
import cli from 'cli-ux'
import Command from '@oclif/command';
import {error} from '@oclif/errors';
import chalk from 'chalk';
import cli from 'cli-ux';
// Services
import ConfigFetcher from './services/config'
import ProjectFetcher from './services/project-fetcher'
import ConfigFetcher from './services/config';
import ProjectFetcher from './services/project-fetcher';
// Types
import {Project} from './types/project'
import {Project} from './types/project';
const sleep = (ms: number) =>
new Promise((resolve: () => void) => setTimeout(resolve, ms))
new Promise((resolve: () => void) => setTimeout(resolve, ms));
export default abstract class extends Command {
public projectConfig: ConfigFetcher = new ConfigFetcher()
public project?: Project
projectConfig: ConfigFetcher = new ConfigFetcher();
project?: Project;
public async init() {
const config = this.projectConfig.config
if (!config.apiUrl) error('You must set an API url in your config')
if (!config.apiKey) error('You must set an API key in your config')
async init() {
const config = this.projectConfig.config;
if (!config.apiUrl) error('You must set an API url in your config');
if (!config.apiKey) error('You must set an API key in your config');
// Fetch project from the GraphQL API.
cli.action.start(chalk.white('Fetch config'))
await sleep(1000)
const fetcher = new ProjectFetcher()
this.project = await fetcher.fetch(config)
cli.action.stop(chalk.green('✓'))
console.log('')
cli.action.start(chalk.white('Fetch config'));
await sleep(1000);
const fetcher = new ProjectFetcher();
this.project = await fetcher.fetch(config);
cli.action.stop(chalk.green('✓'));
console.log('');
}
public async refreshProject() {
const config = this.projectConfig.config
async refreshProject() {
const config = this.projectConfig.config;
const fetcher = new ProjectFetcher()
this.project = await fetcher.fetch(config)
const fetcher = new ProjectFetcher();
this.project = await fetcher.fetch(config);
}
}

View File

@ -1,55 +1,56 @@
// Command
import {flags} from '@oclif/command'
import Command from '../base'
import {flags} from '@oclif/command';
import Command from '../base';
// Formatters
import ExportFormatter from '../services/formatters/project-export'
import ExportFormatter from '../services/formatters/project-export';
// Services
import DocumentPathsFetcher from '../services/document-paths-fetcher'
import DocumentExportFormatter from '../services/formatters/document-export'
import HookRunner from '../services/hook-runner'
import DocumentPathsFetcher from '../services/document-paths-fetcher';
import DocumentExportFormatter from '../services/formatters/document-export';
import HookRunner from '../services/hook-runner';
// Types
import {Hooks} from '../types/document-config'
import {Hooks} from '../types/document-config';
export default class Export extends Command {
public static description =
'Export files from Accent and write them to your local filesystem'
static description =
'Export files from Accent and write them to your local filesystem';
public static examples = [`$ accent export`]
static examples = [`$ accent export`];
public static args = []
public static flags = {
static args = [];
static flags = {
'order-by': flags.string({
default: 'index',
description: 'Will be used in the export call as the order of the keys',
options: ['index', 'key-asc']
})
}
};
public async run() {
const {flags} = this.parse(Export)
async run() {
const {flags} = this.parse(Export);
const documents = this.projectConfig.files()
const formatter = new DocumentExportFormatter()
const documents = this.projectConfig.files();
const formatter = new DocumentExportFormatter();
// From all the documentConfigs, do the export, write to local file and log the results.
new ExportFormatter().log()
new ExportFormatter().log();
for (const document of documents) {
await new HookRunner(document).run(Hooks.beforeExport)
await new HookRunner(document).run(Hooks.beforeExport);
const targets = new DocumentPathsFetcher().fetch(this.project!, document)
const targets = new DocumentPathsFetcher().fetch(this.project!, document);
await Promise.all(
targets.map(({path, language, documentPath}) => {
formatter.log(path)
return document.export(path, language, documentPath, flags)
})
)
formatter.log(path);
await new HookRunner(document).run(Hooks.afterExport)
return document.export(path, language, documentPath, flags);
})
);
await new HookRunner(document).run(Hooks.afterExport);
}
}
}

View File

@ -1,57 +1,58 @@
// Command
import Command from '../base'
import Command from '../base';
// Formatters
import ExportFormatter from '../services/formatters/project-export'
import ExportFormatter from '../services/formatters/project-export';
// Services
import DocumentJiptPathsFetcher from '../services/document-jipt-paths-fetcher'
import DocumentExportFormatter from '../services/formatters/document-export'
import HookRunner from '../services/hook-runner'
import DocumentJiptPathsFetcher from '../services/document-jipt-paths-fetcher';
import DocumentExportFormatter from '../services/formatters/document-export';
import HookRunner from '../services/hook-runner';
// Types
import {Hooks} from '../types/document-config'
import {Hooks} from '../types/document-config';
export default class Jipt extends Command {
public static description =
'Export jipt files from Accent and write them to your local filesystem'
static description =
'Export jipt files from Accent and write them to your local filesystem';
public static examples = [`$ accent jipt`]
static examples = [`$ accent jipt`];
public static args = [
static args = [
{
description: 'The pseudo language for in-place-translation-editing',
name: 'pseudoLanguageName',
required: true
}
]
public static flags = {}
];
static flags = {};
public async run() {
const {args} = this.parse(Jipt)
const documents = this.projectConfig.files()
const formatter = new DocumentExportFormatter()
async run() {
const {args} = this.parse(Jipt);
const documents = this.projectConfig.files();
const formatter = new DocumentExportFormatter();
// From all the documentConfigs, do the export, write to local file and log the results.
new ExportFormatter().log()
new ExportFormatter().log();
for (const document of documents) {
await new HookRunner(document).run(Hooks.beforeExport)
await new HookRunner(document).run(Hooks.beforeExport);
const targets = new DocumentJiptPathsFetcher().fetch(
this.project!,
document,
args.pseudoLanguageName
)
);
await Promise.all(
targets.map(({path, documentPath}) => {
formatter.log(path)
return document.exportJipt(path, documentPath)
})
)
formatter.log(path);
await new HookRunner(document).run(Hooks.afterExport)
return document.exportJipt(path, documentPath);
})
);
await new HookRunner(document).run(Hooks.afterExport);
}
}
}

View File

@ -1,18 +1,17 @@
// Command
import Command from '../base'
import Command from '../base';
// Services
import Formatter from '../services/formatters/project-stats'
import Formatter from '../services/formatters/project-stats';
export default class Stats extends Command {
public static description =
'Fetch stats from the API and display it beautifully'
static description = 'Fetch stats from the API and display it beautifully';
public static examples = [`$ accent stats`]
static examples = [`$ accent stats`];
public async run() {
const formatter = new Formatter(this.project!)
async run() {
const formatter = new Formatter(this.project!);
formatter.log()
formatter.log();
}
}

View File

@ -1,34 +1,34 @@
// Vendor
import {flags} from '@oclif/command'
import {existsSync} from 'fs'
import {flags} from '@oclif/command';
import {existsSync} from 'fs';
// Command
import Command from '../base'
import Command from '../base';
// Formatters
import AddTranslationsFormatter from '../services/formatters/project-add-translations'
import ExportFormatter from '../services/formatters/project-export'
import SyncFormatter from '../services/formatters/project-sync'
import AddTranslationsFormatter from '../services/formatters/project-add-translations';
import ExportFormatter from '../services/formatters/project-export';
import SyncFormatter from '../services/formatters/project-sync';
// Services
import Document from '../services/document'
import DocumentPathsFetcher from '../services/document-paths-fetcher'
import CommitOperationFormatter from '../services/formatters/commit-operation'
import DocumentExportFormatter from '../services/formatters/document-export'
import HookRunner from '../services/hook-runner'
import Document from '../services/document';
import DocumentPathsFetcher from '../services/document-paths-fetcher';
import CommitOperationFormatter from '../services/formatters/commit-operation';
import DocumentExportFormatter from '../services/formatters/document-export';
import HookRunner from '../services/hook-runner';
// Types
import {Hooks} from '../types/document-config'
import {Hooks} from '../types/document-config';
export default class Sync extends Command {
public static description =
'Sync files in Accent and write them to your local filesystem'
static description =
'Sync files in Accent and write them to your local filesystem';
public static examples = [`$ accent sync`]
static examples = [`$ accent sync`];
public static args = []
static args = [];
public static flags = {
static flags = {
'add-translations': flags.boolean({
description:
'Add translations in Accent to help translators if you already have translated strings'
@ -52,83 +52,84 @@ export default class Sync extends Command {
write: flags.boolean({
description: 'Write the file from the export _after_ the operation'
})
}
};
public async run() {
const {flags} = this.parse(Sync)
async run() {
const {flags} = this.parse(Sync);
const documents = this.projectConfig.files()
const documents = this.projectConfig.files();
// From all the documentConfigs, do the sync or peek operations and log the results.
new SyncFormatter().log()
new SyncFormatter().log();
for (const document of documents) {
await new HookRunner(document).run(Hooks.beforeSync)
await new HookRunner(document).run(Hooks.beforeSync);
await Promise.all(this.syncDocumentConfig(document))
await Promise.all(this.syncDocumentConfig(document));
await new HookRunner(document).run(Hooks.afterSync)
await new HookRunner(document).run(Hooks.afterSync);
}
if (flags['add-translations']) {
new AddTranslationsFormatter().log()
new AddTranslationsFormatter().log();
for (const document of documents) {
await new HookRunner(document).run(Hooks.beforeAddTranslations)
await new HookRunner(document).run(Hooks.beforeAddTranslations);
await Promise.all(this.addTranslationsDocumentConfig(document))
await Promise.all(this.addTranslationsDocumentConfig(document));
await new HookRunner(document).run(Hooks.afterAddTranslations)
await new HookRunner(document).run(Hooks.afterAddTranslations);
}
}
if (!flags.write) return
if (!flags.write) return;
// After syncing the files in Accent, the list of documents could have changed.
await this.refreshProject()
await this.refreshProject();
const formatter = new DocumentExportFormatter()
const formatter = new DocumentExportFormatter();
// From all the documentConfigs, do the export, write to local file and log the results.
new ExportFormatter().log()
new ExportFormatter().log();
for (const document of documents) {
await new HookRunner(document).run(Hooks.beforeExport)
await new HookRunner(document).run(Hooks.beforeExport);
const targets = new DocumentPathsFetcher().fetch(this.project!, document)
const targets = new DocumentPathsFetcher().fetch(this.project!, document);
await Promise.all(
targets.map(({path, language, documentPath}) => {
formatter.log(path)
return document.export(path, language, documentPath, flags)
})
)
formatter.log(path);
await new HookRunner(document).run(Hooks.afterExport)
return document.export(path, language, documentPath, flags);
})
);
await new HookRunner(document).run(Hooks.afterExport);
}
}
private syncDocumentConfig(document: Document) {
const {flags} = this.parse(Sync)
const formatter = new CommitOperationFormatter()
const {flags} = this.parse(Sync);
const formatter = new CommitOperationFormatter();
return document.paths.map(async path => {
const operations = await document.sync(path, flags)
const operations = await document.sync(path, flags);
if (operations.sync && !operations.peek) formatter.logSync(path)
if (operations.peek) formatter.logPeek(path, operations.peek)
if (operations.sync && !operations.peek) formatter.logSync(path);
if (operations.peek) formatter.logPeek(path, operations.peek);
return operations
})
return operations;
});
}
private addTranslationsDocumentConfig(document: Document) {
const {flags} = this.parse(Sync)
const formatter = new CommitOperationFormatter()
const {flags} = this.parse(Sync);
const formatter = new CommitOperationFormatter();
const targets = new DocumentPathsFetcher()
.fetch(this.project!, document)
.filter(({language}) => language !== document.config.language)
.filter(({path}) => existsSync(path))
.filter(({path}) => existsSync(path));
return targets.map(async ({path, language, documentPath}) => {
const operations = await document.addTranslations(
@ -136,14 +137,14 @@ export default class Sync extends Command {
language,
documentPath,
flags
)
);
if (operations.addTranslations && !operations.peek) {
formatter.logAddTranslations(path)
formatter.logAddTranslations(path);
}
if (operations.peek) formatter.logPeek(path, operations.peek)
if (operations.peek) formatter.logPeek(path, operations.peek);
return operations
})
return operations;
});
}
}

View File

@ -1 +1 @@
export {run} from '@oclif/command'
export {run} from '@oclif/command';

View File

@ -1,41 +1,41 @@
// Vendor
import {error} from '@oclif/errors'
import * as fs from 'fs-extra'
import {error} from '@oclif/errors';
import * as fs from 'fs-extra';
// Services
import Document from './document'
import Document from './document';
// Types
import {Config} from '../types/config'
import {Config} from '../types/config';
export default class ConfigFetcher {
public readonly config: Config
readonly config: Config;
constructor() {
this.config = fs.readJsonSync('accent.json')
this.config.apiKey = this.config.apiKey || process.env.ACCENT_API_KEY!
this.config.apiUrl = this.config.apiUrl || process.env.ACCENT_API_URL!
this.config = fs.readJsonSync('accent.json');
this.config.apiKey = this.config.apiKey || process.env.ACCENT_API_KEY!;
this.config.apiUrl = this.config.apiUrl || process.env.ACCENT_API_URL!;
if (!this.config.apiKey) {
error(
'You must have an apiKey key in the config or the ACCENT_API_KEY environment variable'
)
);
}
if (!this.config.apiUrl) {
error(
'You must have an apiUrl key in the config or the ACCENT_API_URL environment variable'
)
);
}
if (!this.config.files) {
error('You must have at least 1 document set in your config')
error('You must have at least 1 document set in your config');
}
}
public files(): Document[] {
files(): Document[] {
return this.config.files.map(
documentConfig => new Document(documentConfig, this.config)
)
);
}
}

View File

@ -1,10 +1,10 @@
// Types
import {DocumentPath} from '../types/document-path'
import {Project} from '../types/project'
import Document from './document'
import {DocumentPath} from '../types/document-path';
import {Project} from '../types/project';
import Document from './document';
export default class DocumentJiptPathsFetcher {
public fetch(
fetch(
project: Project,
document: Document,
pseudoLanguageName: string
@ -14,13 +14,13 @@ export default class DocumentJiptPathsFetcher {
.map(path => {
const parsedTarget = document.target
.replace('%slug%', pseudoLanguageName)
.replace('%original_file_name%', path)
.replace('%original_file_name%', path);
return {
documentPath: path,
language: pseudoLanguageName,
path: parsedTarget
}
})
};
});
}
}

View File

@ -1,22 +1,23 @@
// Types
import {DocumentPath} from '../types/document-path'
import {Project} from '../types/project'
import Document from './document'
import {DocumentPath} from '../types/document-path';
import {Project} from '../types/project';
import Document from './document';
export default class DocumentPathsFetcher {
public fetch(project: Project, document: Document): DocumentPath[] {
const languageSlugs = project.revisions.map(({language}) => language.slug)
const documentPaths = project.documents.entries.map(({path}) => path)
fetch(project: Project, document: Document): DocumentPath[] {
const languageSlugs = project.revisions.map(({language}) => language.slug);
const documentPaths = project.documents.entries.map(({path}) => path);
return languageSlugs.reduce((memo: DocumentPath[], slug) => {
documentPaths.forEach(path => {
const parsedTarget = document.target
.replace('%slug%', slug)
.replace('%original_file_name%', path)
.replace('%original_file_name%', path);
memo.push({documentPath: path, path: parsedTarget, language: slug})
})
memo.push({documentPath: path, path: parsedTarget, language: slug});
});
return memo
}, [])
return memo;
}, []);
}
}

View File

@ -1,16 +1,16 @@
// Vendor
import * as FormData from 'form-data'
import * as fs from 'fs-extra'
import fetch, {Response} from 'node-fetch'
import * as path from 'path'
import * as FormData from 'form-data';
import * as fs from 'fs-extra';
import fetch, {Response} from 'node-fetch';
import * as path from 'path';
// Services
import Tree from './tree'
import Tree from './tree';
// Types
import {Config} from '../types/config'
import {DocumentConfig} from '../types/document-config'
import {OperationResponse} from '../types/operation-response'
import {Config} from '../types/config';
import {DocumentConfig} from '../types/document-config';
import {OperationResponse} from '../types/operation-response';
const enum OperationName {
Sync = 'sync',
@ -18,128 +18,130 @@ const enum OperationName {
}
export default class Document {
public paths: string[]
public readonly apiKey: string
public readonly apiUrl: string
public readonly config: DocumentConfig
public readonly target: string
paths: string[];
readonly apiKey: string;
readonly apiUrl: string;
readonly config: DocumentConfig;
readonly target: string;
constructor(documentConfig: DocumentConfig, config: Config) {
this.config = documentConfig
this.apiKey = config.apiKey
this.apiUrl = config.apiUrl
this.target = this.config.target
this.paths = new Tree(this.config).list()
this.config = documentConfig;
this.apiKey = config.apiKey;
this.apiUrl = config.apiUrl;
this.target = this.config.target;
this.paths = new Tree(this.config).list();
}
public refreshPaths() {
this.paths = new Tree(this.config).list()
refreshPaths() {
this.paths = new Tree(this.config).list();
}
public async sync(file: string, options: any) {
const formData = new FormData()
formData.append('file', fs.createReadStream(file))
formData.append('document_path', this.parseDocumentName(file))
formData.append('document_format', this.config.format)
formData.append('language', this.config.language)
async sync(file: string, options: any) {
const formData = new FormData();
formData.append('file', fs.createReadStream(file));
formData.append('document_path', this.parseDocumentName(file));
formData.append('document_format', this.config.format);
formData.append('language', this.config.language);
let url = `${this.apiUrl}/sync`
if (!options.write) url = `${url}/peek`
if (options['sync-type']) formData.append('sync_type', options['sync-type'])
const response = await fetch(url, {
body: formData,
headers: this.authorizationHeader(),
method: 'POST'
})
return this.handleResponse(response, options, OperationName.Sync)
}
public async addTranslations(
file: string,
language: string,
documentPath: string,
options: any
) {
const formData = new FormData()
formData.append('file', fs.createReadStream(file))
formData.append('document_path', documentPath)
formData.append('document_format', this.config.format)
formData.append('language', language)
let url = `${this.apiUrl}/add-translations`
if (!options.write) url = `${url}/peek`
if (options['merge-type']) {
formData.append('merge_type', options['merge-type'])
let url = `${this.apiUrl}/sync`;
if (!options.write) url = `${url}/peek`;
if (options['sync-type']) {
formData.append('sync_type', options['sync-type']);
}
const response = await fetch(url, {
body: formData,
headers: this.authorizationHeader(),
method: 'POST'
})
});
return this.handleResponse(response, options, OperationName.AddTranslation)
return this.handleResponse(response, options, OperationName.Sync);
}
public async export(
async addTranslations(
file: string,
language: string,
documentPath: string,
options: any
) {
language = language || this.config.language
const formData = new FormData();
formData.append('file', fs.createReadStream(file));
formData.append('document_path', documentPath);
formData.append('document_format', this.config.format);
formData.append('language', language);
let url = `${this.apiUrl}/add-translations`;
if (!options.write) url = `${url}/peek`;
if (options['merge-type']) {
formData.append('merge_type', options['merge-type']);
}
const response = await fetch(url, {
body: formData,
headers: this.authorizationHeader(),
method: 'POST'
});
return this.handleResponse(response, options, OperationName.AddTranslation);
}
async export(
file: string,
language: string,
documentPath: string,
options: any
) {
const exportLanguage = language || this.config.language;
const query = [
['document_path', documentPath],
['document_format', this.config.format],
['order_by', options['order-by']],
['language', language]
['language', exportLanguage]
]
.map(([name, value]) => `${name}=${value}`)
.join('&')
.join('&');
const url = `${this.apiUrl}/export?${query}`
const url = `${this.apiUrl}/export?${query}`;
const response = await fetch(url, {
headers: this.authorizationHeader()
})
});
return this.writeResponseToFile(response, file)
return this.writeResponseToFile(response, file);
}
public async exportJipt(file: string, documentPath: string) {
async exportJipt(file: string, documentPath: string) {
const query = [
['document_path', documentPath],
['document_format', this.config.format]
]
.map(([name, value]) => `${name}=${value}`)
.join('&')
.join('&');
const url = `${this.apiUrl}/jipt-export?${query}`
const url = `${this.apiUrl}/jipt-export?${query}`;
const response = await fetch(url, {
headers: this.authorizationHeader()
})
});
return this.writeResponseToFile(response, file)
return this.writeResponseToFile(response, file);
}
private authorizationHeader() {
return {authorization: `Bearer ${this.apiKey}`}
return {authorization: `Bearer ${this.apiKey}`};
}
private parseDocumentName(file: string): string {
return path.basename(file).replace(path.extname(file), '')
return path.basename(file).replace(path.extname(file), '');
}
private writeResponseToFile(response: Response, file: string) {
return new Promise((resolve, reject) => {
const fileStream = fs.createWriteStream(file, {autoClose: true})
response.body.pipe(fileStream)
response.body.on('error', reject)
fileStream.on('finish', resolve)
})
const fileStream = fs.createWriteStream(file, {autoClose: true});
response.body.pipe(fileStream);
response.body.on('error', reject);
fileStream.on('finish', resolve);
});
}
private async handleResponse(
@ -149,14 +151,14 @@ export default class Document {
): Promise<OperationResponse> {
if (options.write) {
if (response.status >= 400) {
return {[operationName]: {success: false}, peek: false}
return {[operationName]: {success: false}, peek: false};
}
return {[operationName]: {success: true}, peek: false}
return {[operationName]: {success: true}, peek: false};
} else {
const {data} = await response.json()
const {data} = await response.json();
return {peek: data, [operationName]: {success: true}}
return {peek: data, [operationName]: {success: true}};
}
}
}

View File

@ -1,38 +1,38 @@
// Vendor
import chalk from 'chalk'
import chalk from 'chalk';
// Types
import {PeekOperation} from '../../types/operation'
import {PeekOperation} from '../../types/operation';
// Constants
const MASTER_ONLY_ACTIONS = ['new', 'renew', 'remove']
const MASTER_ONLY_ACTIONS = ['new', 'renew', 'remove'];
export default class CommitOperationFormatter {
public logSync(path: string) {
console.log(' ', chalk.white(path))
console.log(' ', chalk.green('✓ Successfully synced the files in Accent'))
console.log('')
logSync(path: string) {
console.log(' ', chalk.white(path));
console.log(' ', chalk.green('✓ Successfully synced the files in Accent'));
console.log('');
}
public logAddTranslations(path: string) {
console.log(' ', chalk.white(path))
console.log(' ', chalk.green('✓ Successfully add translations in Accent'))
console.log('')
logAddTranslations(path: string) {
console.log(' ', chalk.white(path));
console.log(' ', chalk.green('✓ Successfully add translations in Accent'));
console.log('');
}
public logPeek(path: string, operations: PeekOperation) {
console.log(' ', chalk.white(path))
logPeek(path: string, operations: PeekOperation) {
console.log(' ', chalk.white(path));
if (!Object.keys(operations.stats).length) {
console.log(' ', chalk.gray('~~ No changes for this file ~~'))
console.log(' ', chalk.gray('~~ No changes for this file ~~'));
}
Object.entries(operations.stats).map((stat, index) => {
let actions = Object.entries(stat[1])
let actions = Object.entries(stat[1]);
if (index > 0) {
actions = actions.filter(
([action]) => !MASTER_ONLY_ACTIONS.includes(action)
)
);
}
actions.map(([action, name]) => {
@ -41,15 +41,16 @@ export default class CommitOperationFormatter {
chalk.bold(this.formatAction(action)),
':',
chalk.bold.white(name)
)
})
})
);
});
});
console.log('')
console.log('');
}
private formatAction(action: string) {
const capitalized = action.charAt(0).toUpperCase() + action.slice(1)
return capitalized.replace(/_/g, ' ')
const capitalized = action.charAt(0).toUpperCase() + action.slice(1);
return capitalized.replace(/_/g, ' ');
}
}

View File

@ -1,13 +1,13 @@
// Vendor
import chalk from 'chalk'
import chalk from 'chalk';
export default class DocumentExportFormatter {
public log(path: string) {
console.log(' ', chalk.white(path))
log(path: string) {
console.log(' ', chalk.white(path));
console.log(
' ',
chalk.green('✓ Successfully write the locale files from Accent')
)
console.log('')
);
console.log('');
}
}

View File

@ -1,17 +1,17 @@
// Vendor
import chalk from 'chalk'
import * as decamelize from 'decamelize'
import chalk from 'chalk';
import * as decamelize from 'decamelize';
const capitalizeFirstLetter = (str: string) =>
str.charAt(0).toUpperCase() + str.slice(1)
str.charAt(0).toUpperCase() + str.slice(1);
export default class HookRunnerFomatter {
public log(name: string, commands: string[]) {
const operation = capitalizeFirstLetter(decamelize(name, ' '))
console.log(chalk.yellow('➤ '), chalk.bold(chalk.yellow(`${operation}:`)))
log(name: string, commands: string[]) {
const operation = capitalizeFirstLetter(decamelize(name, ' '));
console.log(chalk.yellow('➤ '), chalk.bold(chalk.yellow(`${operation}:`)));
commands.forEach(command => {
console.log(' ', chalk.yellow(command))
})
console.log('')
console.log(' ', chalk.yellow(command));
});
console.log('');
}
}

View File

@ -1,10 +1,10 @@
// Vendor
import chalk from 'chalk'
import chalk from 'chalk';
export default class ProjectAddTranslationsFormatter {
public log() {
console.log(chalk.magenta('Adding translations paths'))
log() {
console.log(chalk.magenta('Adding translations paths'));
console.log('')
console.log('');
}
}

View File

@ -1,10 +1,10 @@
// Vendor
import chalk from 'chalk'
import chalk from 'chalk';
export default class ProjectExportFormatter {
public log() {
console.log(chalk.magenta('Writing files'))
log() {
console.log(chalk.magenta('Writing files'));
console.log('')
console.log('');
}
}

View File

@ -1,84 +1,88 @@
// Vendor
import chalk from 'chalk'
import chalk from 'chalk';
// Types
import {Document, Project, Revision} from '../../types/project'
import {Document, Project, Revision} from '../../types/project';
export default class ProjectStatsFormatter {
private readonly project: Project
private readonly project: Project;
constructor(project: Project) {
this.project = project
this.project = project;
}
public log() {
log() {
const translationsCount = this.project.revisions.reduce(
(memo, revision: Revision) => memo + revision.translationsCount,
0
)
);
const conflictsCount = this.project.revisions.reduce(
(memo, revision: Revision) => memo + revision.conflictsCount,
0
)
);
const reviewedCount = this.project.revisions.reduce(
(memo, revision: Revision) => memo + revision.reviewedCount,
0
)
);
console.log(chalk.magenta('Last synced'))
console.log(' ', chalk.white.bold(this.project.lastSyncedAt))
console.log(chalk.magenta('Last synced'));
console.log(' ', chalk.white.bold(this.project.lastSyncedAt));
console.log('')
console.log('');
console.log(chalk.magenta('Master language'))
console.log(chalk.magenta('Master language'));
console.log(
' ',
chalk.white.bold(this.project.language.name) +
' ' +
`${chalk.white.bold(this.project.language.name)} ${
this.project.language.slug
)
}`
);
console.log('')
console.log('');
if (this.project.revisions.length > 1) {
console.log(
chalk.magenta(`Translations (${this.project.revisions.length - 1})`)
)
);
this.project.revisions.forEach((revision: Revision) => {
if (this.project.language.id !== revision.language.id) {
console.log(
' ',
chalk.white.bold(revision.language.name) +
' ' +
`${chalk.white.bold(revision.language.name)} ${
revision.language.slug
)
console.log('')
}`
);
console.log('');
}
})
});
}
console.log(chalk.magenta('Documents'))
console.log(chalk.magenta('Documents'));
this.project.documents.entries.forEach((document: Document) => {
console.log(
' ',
chalk.gray('Format:'),
chalk.white.bold(document.format)
)
console.log(' ', chalk.gray('Path:'), chalk.white.bold(document.path))
console.log('')
})
);
console.log(' ', chalk.gray('Path:'), chalk.white.bold(document.path));
console.log('');
});
console.log(chalk.magenta('Strings'))
console.log(chalk.magenta('Strings'));
console.log(
' ',
chalk.white('# Strings:'),
chalk.white(`${translationsCount}`)
)
);
console.log(
' ',
chalk.green('✓ Reviewed:'),
chalk.green(`${reviewedCount}`)
)
console.log(' ', chalk.red('× In review:'), chalk.red(`${conflictsCount}`))
);
console.log(
' ',
chalk.red('× In review:'),
chalk.red(`${conflictsCount}`)
);
}
}

View File

@ -1,10 +1,10 @@
// Vendor
import chalk from 'chalk'
import chalk from 'chalk';
export default class ProjectSyncFormatter {
public log() {
console.log(chalk.magenta('Syncing sources'))
log() {
console.log(chalk.magenta('Syncing sources'));
console.log('')
console.log('');
}
}

View File

@ -1,32 +1,32 @@
// Vendor
import {execSync} from 'child_process'
import {execSync} from 'child_process';
// Formatters
import Formatter from './formatters/hook-runner'
import Formatter from './formatters/hook-runner';
// Types
import {HookConfig, Hooks} from '../types/document-config'
import Document from './document'
import {HookConfig, Hooks} from '../types/document-config';
import Document from './document';
export default class HookRunner {
public readonly hooks?: HookConfig
private readonly document: Document
readonly hooks?: HookConfig;
private readonly document: Document;
constructor(document: Document) {
this.document = document
this.hooks = document.config.hooks
this.document = document;
this.hooks = document.config.hooks;
}
public async run(name: Hooks) {
if (!this.hooks) return null
const hooks = this.hooks[name]
async run(name: Hooks) {
if (!this.hooks) return null;
const hooks = this.hooks[name];
if (hooks) {
new Formatter().log(name, hooks)
new Formatter().log(name, hooks);
hooks.forEach(execSync)
hooks.forEach(execSync);
}
return this.document.refreshPaths()
return this.document.refreshPaths();
}
}

View File

@ -1,21 +1,21 @@
// Vendor
import {error} from '@oclif/errors'
import fetch from 'node-fetch'
import {error} from '@oclif/errors';
import fetch from 'node-fetch';
// Types
import {Config} from '../types/config'
import {Project} from '../types/project'
import {Config} from '../types/config';
import {Project} from '../types/project';
export default class ProjectFetcher {
public async fetch(config: Config): Promise<Project> {
const response = await this.graphql(config)
const data = await response.json()
async fetch(config: Config): Promise<Project> {
const response = await this.graphql(config);
const data = await response.json();
if (!data.data) {
error(`Can not find the project for the key: ${config.apiKey}`)
error(`Can not find the project for the key: ${config.apiKey}`);
}
return data.data && data.data.viewer.project
return data.data && data.data.viewer.project;
}
private graphql(config: Config) {
@ -51,7 +51,7 @@ export default class ProjectFetcher {
}
}
}
}`
}`;
return fetch(`${config.apiUrl}/graphql`, {
body: JSON.stringify({query}),
@ -60,6 +60,6 @@ export default class ProjectFetcher {
authorization: `Bearer ${config.apiKey}`
},
method: 'POST'
})
});
}
}

View File

@ -1,17 +1,17 @@
// Vendor
import * as glob from 'glob'
import * as glob from 'glob';
// Types
import {DocumentConfig} from '../types/document-config'
import {DocumentConfig} from '../types/document-config';
export default class Tree {
private readonly document: DocumentConfig
private readonly document: DocumentConfig;
constructor(document: DocumentConfig) {
this.document = document
this.document = document;
}
public list(): string[] {
return glob.sync(this.document.source, {})
list(): string[] {
return glob.sync(this.document.source, {});
}
}

View File

@ -1,8 +1,8 @@
// Types
import {DocumentConfig} from './document-config'
import {DocumentConfig} from './document-config';
export interface Config {
apiUrl: string
apiKey: string
files: DocumentConfig[]
apiUrl: string;
apiKey: string;
files: DocumentConfig[];
}

View File

@ -8,19 +8,19 @@ export enum Hooks {
}
export interface HookConfig {
[Hooks.beforeAddTranslations]: string[]
[Hooks.afterAddTranslations]: string[]
[Hooks.beforeExport]: string[]
[Hooks.afterExport]: string[]
[Hooks.beforeSync]: string[]
[Hooks.afterSync]: string[]
[Hooks.beforeAddTranslations]: string[];
[Hooks.afterAddTranslations]: string[];
[Hooks.beforeExport]: string[];
[Hooks.afterExport]: string[];
[Hooks.beforeSync]: string[];
[Hooks.afterSync]: string[];
}
export interface DocumentConfig {
name: string
language: string
format: string
source: string
target: string
hooks?: HookConfig
name: string;
language: string;
format: string;
source: string;
target: string;
hooks?: HookConfig;
}

View File

@ -1,5 +1,5 @@
export interface DocumentPath {
path: string
language: string
documentPath: string
path: string;
language: string;
documentPath: string;
}

View File

@ -1,4 +1,4 @@
export interface OperationResponse {
peek: any
[x: string]: any
peek: any;
[x: string]: any;
}

View File

@ -1,4 +1,4 @@
export interface PeekOperation {
operations: any[]
stats: any
operations: any[];
stats: any;
}

View File

@ -1,31 +1,31 @@
export interface Language {
id: string
name: string
slug: string
id: string;
name: string;
slug: string;
}
export interface Revision {
id: string
language: Language
translationsCount: number
conflictsCount: number
reviewedCount: number
id: string;
language: Language;
translationsCount: number;
conflictsCount: number;
reviewedCount: number;
}
export interface Document {
path: string
format: string
path: string;
format: string;
}
export interface PaginatedDocuments {
entries: Document[]
entries: Document[];
}
export interface Project {
id: string
name: string
lastSyncedAt: string
language: Language
revisions: Revision[]
documents: PaginatedDocuments
id: string;
name: string;
lastSyncedAt: string;
language: Language;
revisions: Revision[];
documents: PaginatedDocuments;
}

View File

@ -13,16 +13,10 @@
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"rootDirs": [
"./src"
],
"rootDirs": ["./src"],
"strict": true,
"target": "es2017"
},
"include": [
"./src/**/*"
],
"exclude": [
"node_modules/**/*"
]
"include": ["./src/**/*"],
"exclude": ["node_modules/**/*"]
}

View File

@ -1,21 +0,0 @@
{
"extends": ["@oclif/tslint", "tslint:latest", "tslint-config-prettier"],
"rules": {
"no-implicit-dependencies": false,
"no-submodule-imports": false,
"no-console": false,
"variable-name": [
true,
"ban-keywords",
"check-format",
"allow-leading-underscore",
"allow-pascal-case"
],
"prefer-const": true,
"no-empty-interface": false,
"interface-name": false,
"no-shadowed-variable": false,
"curly": [true, "ignore-same-line"],
"no-empty": false
}
}

View File

@ -1,2 +0,0 @@
dist
.cache

View File

@ -1,5 +0,0 @@
{
"printWidth": 120,
"singleQuote": true,
"bracketSpacing": false
}

12
jipt/package-lock.json generated
View File

@ -5871,12 +5871,6 @@
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
"dev": true
},
"prettier": {
"version": "1.16.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz",
"integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==",
"dev": true
},
"private": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@ -6899,12 +6893,6 @@
"tsutils": "2.29.0"
}
},
"tslint-config-prettier": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz",
"integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==",
"dev": true
},
"tsutils": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",

View File

@ -6,18 +6,13 @@
"scripts": {
"build": "parcel index.html",
"build-production": "parcel build index.ts -d ../priv/static/jipt --target browser --experimental-scope-hoisting",
"prettier": "prettier --write '**/*.{ts,html,json}'",
"test": "echo \"Error: no test specified\" && exit 1",
"lint-scripts": "tslint -c tslint.json 'src/**/*.{js,ts}'"
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"parcel-bundler": "1.11.0",
"prettier": "1.16.4",
"tslint": "^5.12.1",
"tslint-config-prettier": "^1.17.0",
"typescript": "3.3.1"
}
}

View File

@ -4,7 +4,7 @@ import Mutation from './mutation/mutation';
import State from './state';
import UI from './ui/ui';
enum ACTIONS {
const enum ACTIONS {
listTranslations = 'listTranslations',
redirectIfEmbedded = 'redirectIfEmbedded',
login = 'login',
@ -39,7 +39,11 @@ export default class FrameListener {
}
bindEvents() {
window.addEventListener('message', this.handleAccentMessage.bind(this), false);
window.addEventListener(
'message',
this.handleAccentMessage.bind(this),
false
);
}
private handleAccentMessage({data}) {

View File

@ -32,7 +32,9 @@ export default class LiveNode {
const newAttribute = this.replaceValue(attribute.value, translation.text);
attribute.value = newAttribute;
this.state.addReference(node, translation, {attributeName: attribute.name});
this.state.addReference(node, translation, {
attributeName: attribute.name
});
});
}

View File

@ -57,7 +57,9 @@ export default class Mutation {
handleNodeMutation(node) {
if (node.nodeType === Node.TEXT_NODE) this.liveNode.matchText(node.target);
if (node.type === 'childList') node.addedNodes.forEach((node: Element) => this.liveNode.evaluate(node));
if (node.type === 'childList') {
node.addedNodes.forEach((node: Element) => this.liveNode.evaluate(node));
}
if (node.type === 'attributes') this.liveNode.matchAttributes(node.target);
if (node.type === 'characterData') this.liveNode.matchText(node.target);
}

View File

@ -56,15 +56,22 @@ export default class Pin {
private showFor(target: HTMLElement) {
const {left, top, height} = target.getBoundingClientRect();
const keys: string[] = Array.from(this.state.nodes.get(target).keys.values());
styles.set(this.element, `top: ${top + height - 6}px; left: ${left - 6}px; ${styles.pin}`);
const keys: string[] = Array.from(
this.state.nodes.get(target).keys.values()
);
styles.set(
this.element,
`top: ${top + height - 6}px; left: ${left - 6}px; ${styles.pin}`
);
const ids = keys
.map((key: string) => this.state.projectTranslations[key].id)
.filter(Boolean)
.join(',');
this.element.innerHTML = this.pinContent(`data-id${keys.length > 1 ? 's' : ''}="${ids}"`);
this.element.innerHTML = this.pinContent(
`data-id${keys.length > 1 ? 's' : ''}="${ids}"`
);
}
private pinContent(id) {

View File

@ -1,16 +1,19 @@
/* Inline styles are used everywhere so that it does not conflict with parent window styles */
const set = (element: Element, style: string) => element.setAttribute('style', style);
const set = (element: Element, style: string) =>
element.setAttribute('style', style);
const hide = (element: Element) => set(element, 'display: none;');
// Pin
const pin = 'position: fixed; z-index: 10000; min-width: 150px;';
const pinList =
'color: #fff; cursor: pointer; margin: 0; padding: 5px; list-style: none; background: hsl(158, 74%, 46%); font-family: -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif; line-height: 1.5; font-size: 12px;';
const pinIcon = 'box-sizing: border-box; width: 18px; height: 18px; cursor: pointer;';
const pinIcon =
'box-sizing: border-box; width: 18px; height: 18px; cursor: pointer;';
// Node
const translationNode = 'outline: 1px #1ecc8c solid; outline-offset: -1px;transition: outline-color 0.2s ease-in-out;';
const translationNode =
'outline: 1px #1ecc8c solid; outline-offset: -1px;transition: outline-color 0.2s ease-in-out;';
const translationNodeUpdated =
'outline: 1px #c8f5e4 solid; outline-offset: -1px;transition: outline-color 0.2s ease-in-out;';

View File

@ -45,7 +45,11 @@ export default class UI {
}
bindEvents() {
this.editor.addEventListener('click', this.handleEditorToggle.bind(this), false);
this.editor.addEventListener(
'click',
this.handleEditorToggle.bind(this),
false
);
}
hideOverlay() {
@ -104,7 +108,9 @@ export default class UI {
private buildFrame(config) {
const element = document.createElement('iframe');
const query = this.state.getCurrentRevision() ? `?revisionId=${this.state.getCurrentRevision()}` : '';
const query = this.state.getCurrentRevision()
? `?revisionId=${this.state.getCurrentRevision()}`
: '';
element.src = `${config.h}/app/projects/${config.i}/jipt${query}`;
element.frameBorder = '0';
@ -117,7 +123,9 @@ export default class UI {
const element = document.createElement('div');
element.innerHTML = `
<div class="${EXPAND_CLASS}" style="${styles.frameExpandButton}"></div>
<div class="${COLLAPSE_CLASS}" style="${styles.frameCollapseButton}">×</div>
<div class="${COLLAPSE_CLASS}" style="${
styles.frameCollapseButton
}">×</div>
`;
return element;

1432
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

29
package.json Normal file
View File

@ -0,0 +1,29 @@
{
"name": "accent",
"version": "0.0.1",
"description": "The new new Accent Web app",
"private": true,
"scripts": {
"prettier": "prettier --single-quote --no-bracket-spacing --write './{webapp,jipt,cli}/**/*.{js,ts,json,gql}'",
"prettier-check": "prettier --check --single-quote --no-bracket-spacing './{webapp,jipt,cli}/**/*.{js,ts,json,gql}'",
"lint-scripts": "eslint webapp/. cli/. jipt/.",
"lint-scripts-fix": "eslint --fix webapp/.",
"tslint-scripts": "tslint -c tslint.json '{cli,jipt}/src/**/*.{js,ts,json}'",
"tslint-scripts-fix": "tslint --fix -c tslint.json '{cli,jipt}/src/**/*.{js,ts,json}'"
},
"repository": "https://github.com/mirego/accent",
"engines": {
"node": ">= 8.5.0"
},
"devDependencies": {
"babel-eslint": "8.2.3",
"eslint": "4.19.0",
"eslint-config-prettier": "2.9.0",
"eslint-plugin-ember": "5.1.0",
"eslint-plugin-mirego": "0.0.1",
"prettier": "1.16.4",
"tslint": "5.12.1",
"tslint-config-prettier": "1.17.0",
"typescript": "3.2.2"
}
}

View File

@ -29,19 +29,22 @@ header "API tests…"
run mix test
header "Compilation without warnings…"
run mix compile --warnings-as-errors --force
run make lint-compile
header "API code auto-formatting…"
run mix format --dry-run --check-formatted
run make lint-format
header "API code lint…"
run mix credo --strict
run make lint-credo
header "Webapp code auto-formatting…"
run npm --prefix webapp run prettier-check
header "Prettier auto-formatting…"
run make lint-prettier
header "Webapp code lint…"
run npm --prefix webapp run lint
header "Eslint code lint…"
run make lint-eslint
header "Tslint code lint…"
run make lint-tslint
header "Webapp tests…"
run npm --prefix webapp test

View File

@ -14,7 +14,7 @@
"newline-before-return": true,
"no-arg": true,
"no-conditional-assignment": true,
"no-console": true,
"no-console": false,
"no-consecutive-blank-lines": true,
"no-debugger": true,
"no-duplicate-imports": true,
@ -25,7 +25,7 @@
"no-empty": false,
"no-eval": true,
"no-implicit-dependencies": false,
"no-non-null-assertion": true,
"no-non-null-assertion": false,
"no-parameter-reassignment": true,
"no-return-await": true,
"no-shadowed-variable": false,
@ -66,6 +66,12 @@
],
"unified-signatures": true,
"use-isnan": true,
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"]
"variable-name": [
true,
"ban-keywords",
"check-format",
"allow-leading-underscore",
"allow-pascal-case"
]
}
}

View File

@ -1,8 +0,0 @@
node_modules/*
**/vendor/*.js
vendor/**/*.js
bower_components/**/*.js
dist/**/*.js
tmp/**/*.js
app/locales/*/translations.js
app/utils/phoenix.js

View File

@ -1,4 +0,0 @@
dist
.cache
node_modules
tmp

View File

@ -37,6 +37,8 @@ export default Controller.extend({
emptyDocument: empty('document'),
emptyQuery: equal('query', ''),
showLoading: and('emptyEntries', 'model.loading'),
showSkeleton: and(
'emptyEntries',
'model.loading',
@ -44,8 +46,6 @@ export default Controller.extend({
'emptyReference',
'emptyDocument'
),
showLoading: and('emptyEntries', 'model.loading'),
referenceRevisions: computed('model.revisionId', 'revisions', function() {
if (!this.revisions) return [];

View File

@ -16,8 +16,6 @@
"start": "ember server --port $WEBAPP_PORT",
"build": "ember build",
"build-production": "ember build --prod --output-path=../priv/static/webapp",
"prettier": "prettier --loglevel warn --single-quote --no-bracket-spacing --write './**/*.{js,json,gql}'",
"prettier-check": "prettier --check --single-quote --no-bracket-spacing './**/*.{js,json,gql}'",
"test": "ember test"
},
"repository": "https://github.com/mirego/accent",
@ -73,11 +71,6 @@
"ember-mocha": "0.14.0-beta.1",
"ember-native-dom-helpers": "0.6.2",
"ember-sinon": "2.1.0",
"eslint": "4.19.0",
"eslint-config-prettier": "2.9.0",
"eslint-plugin-ember": "5.1.0",
"eslint-plugin-mirego": "0.0.1",
"prettier": "1.16.4",
"sinon-chai": "3.0.0"
}
}