1
0
Fork 0
mirror of https://github.com/codex-team/codex.docs.git synced 2025-08-08 06:55:26 +02:00

Made uri property of page be optional

This commit is contained in:
DorofeevMark 2019-01-18 21:08:37 +03:00
parent ad6582f0ca
commit 6f3d0a19a5
12 changed files with 79 additions and 44 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -56,12 +56,14 @@ class Pages {
const insertedPage = await page.save(); const insertedPage = await page.save();
const alias = new Alias({ if (insertedPage.uri) {
id: insertedPage._id, const alias = new Alias({
type: aliasTypes.PAGE id: insertedPage._id,
}, insertedPage.uri); type: aliasTypes.PAGE
}, insertedPage.uri);
alias.save(); alias.save();
}
return insertedPage; return insertedPage;
} catch (validationError) { } catch (validationError) {
@ -110,19 +112,17 @@ class Pages {
*/ */
static async update(id, data) { static async update(id, data) {
const page = await Model.get(id); const page = await Model.get(id);
const previousUri = page.uri;
if (!page._id) { if (!page._id) {
throw new Error('Page with given id does not exist'); throw new Error('Page with given id does not exist');
} }
if (!data.uri.match(/^[a-z0-9'-]+$/i)) { if (data.uri && !data.uri.match(/^[a-z0-9'-]+$/i)) {
throw new Error('Uri has unexpected characters'); throw new Error('Uri has unexpected characters');
} }
const previousUri = page.uri;
page.data = data; page.data = data;
const updatedPage = await page.save(); const updatedPage = await page.save();
if (updatedPage.uri !== previousUri) { if (updatedPage.uri !== previousUri) {

View file

@ -88,7 +88,7 @@ export default class Writing {
const title = firstBlock && firstBlock.type === 'header' ? firstBlock.data.text : null; const title = firstBlock && firstBlock.type === 'header' ? firstBlock.data.text : null;
let uri = ''; let uri = '';
if (this.nodes.uriInput) { if (this.nodes.uriInput && this.nodes.uriInput.value) {
if (this.nodes.uriInput.value.match(/^[a-z0-9'-]+$/i)) { if (this.nodes.uriInput.value.match(/^[a-z0-9'-]+$/i)) {
uri = this.nodes.uriInput.value; uri = this.nodes.uriInput.value;
} else { } else {
@ -127,7 +127,7 @@ export default class Writing {
response = await response.json(); response = await response.json();
if (response.success) { if (response.success) {
window.location.pathname = response.result.uri; window.location.pathname = response.result.uri ? response.result.uri : '/page/' + response.result._id;
} else { } else {
alert(response.error); alert(response.error);
console.log('Validation failed:', response.error); console.log('Validation failed:', response.error);

View file

@ -1,9 +1,9 @@
const {aliases: aliasesDb} = require('../utils/database/index'); const {aliases: aliasesDb} = require('../utils/database/index');
const md5 = require('../utils/md5'); const binaryMD5 = require('../utils/crypto');
/** /**
* @typedef {Object} AliasData * @typedef {Object} AliasData
* @property {string} _id - alias id * @property {string} _id - alias id
* @property {string} hash - alias hash * @property {string} hash - alias binary hash
* @property {string} type - entity type * @property {string} type - entity type
* @property {boolean} deprecated - indicate if alias deprecated * @property {boolean} deprecated - indicate if alias deprecated
* @property {string} id - entity id * @property {string} id - entity id
@ -13,7 +13,7 @@ const md5 = require('../utils/md5');
/** /**
* @class Alias * @class Alias
* @property {string} _id - alias id * @property {string} _id - alias id
* @property {string} hash - alias hash * @property {string} hash - alias binary hash
* @property {string} type - entity type * @property {string} type - entity type
* @property {boolean} deprecated - indicate if alias deprecated * @property {boolean} deprecated - indicate if alias deprecated
* @property {string} id - entity title * @property {string} id - entity title
@ -25,7 +25,7 @@ class Alias {
* @returns {Promise<Alias>} * @returns {Promise<Alias>}
*/ */
static async get(aliasName) { static async get(aliasName) {
const hash = md5(aliasName); const hash = binaryMD5(aliasName);
let data = await aliasesDb.findOne({hash: hash, deprecated: false}); let data = await aliasesDb.findOne({hash: hash, deprecated: false});
if (!data) { if (!data) {
@ -49,7 +49,7 @@ class Alias {
this._id = data._id; this._id = data._id;
} }
if (aliasName) { if (aliasName) {
this.hash = md5(aliasName); this.hash = binaryMD5(aliasName);
} }
this.data = data; this.data = data;
} }

View file

@ -83,14 +83,7 @@ class Page {
this.body = body || this.body; this.body = body || this.body;
this.title = this.extractTitleFromBody(); this.title = this.extractTitleFromBody();
this.uri = uri || translateString(this.title this.uri = uri || '';
.replace(/&nbsp;/g, ' ')
.replace(/[^a-zA-Z0-9А-Яа-яЁё ]/g, ' ')
.replace(/ +/g, ' ')
.trim()
.toLowerCase()
.split(' ')
.join('-'));
this._parent = parent || this._parent; this._parent = parent || this._parent;
} }
@ -119,6 +112,21 @@ class Page {
return headerBlock ? headerBlock.data.text : ''; return headerBlock ? headerBlock.data.text : '';
} }
/**
* Transform title for uri
* @return {string}
*/
transformTitleToUri() {
return translateString(this.title
.replace(/&nbsp;/g, ' ')
.replace(/[^a-zA-Z0-9А-Яа-яЁё ]/g, ' ')
.replace(/ +/g, ' ')
.trim()
.toLowerCase()
.split(' ')
.join('-'));
}
/** /**
* Link given page as parent * Link given page as parent
* *
@ -186,12 +194,19 @@ class Page {
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async composeUri(uri) { async composeUri(uri) {
let pageWithSameUri = await Page.getByUri(uri);
let pageWithSameUriCount = 0; let pageWithSameUriCount = 0;
while (pageWithSameUri._id && pageWithSameUri._id !== this._id) { if (!this._id) {
pageWithSameUriCount++; uri = this.transformTitleToUri();
pageWithSameUri = await Page.getByUri(uri + `-${pageWithSameUriCount}`); }
if (uri) {
let pageWithSameUri = await Page.getByUri(uri);
while (pageWithSameUri._id && pageWithSameUri._id !== this._id) {
pageWithSameUriCount++;
pageWithSameUri = await Page.getByUri(uri + `-${pageWithSameUriCount}`);
}
} }
return pageWithSameUriCount ? uri + `-${pageWithSameUriCount}` : uri; return pageWithSameUriCount ? uri + `-${pageWithSameUriCount}` : uri;

View file

@ -5,7 +5,7 @@ const crypto = require('crypto');
* @param stringToHash - string to hash * @param stringToHash - string to hash
* @returns {string} - binary hash of argument * @returns {string} - binary hash of argument
*/ */
module.exports = function md5(stringToHash) { module.exports = function binaryMD5(stringToHash) {
return crypto.createHash('md5') return crypto.createHash('md5')
.update(stringToHash) .update(stringToHash)
.digest('binary'); .digest('binary');

View file

@ -1,14 +1,24 @@
<div class="docs-aside"> <div class="docs-aside">
{% for firstLevelPage in menu %} {% for firstLevelPage in menu %}
<section class="docs-aside__section"> <section class="docs-aside__section">
<a class="docs-aside__section-title" href="/{{ firstLevelPage.uri }}"> <a class="docs-aside__section-title"
{% if firstLevelPage.uri %}
href="/{{ firstLevelPage.uri }}"
{% else %}
href="/page/{{ firstLevelPage._id }}"
{% endif %}>
{{ firstLevelPage.title }} {{ firstLevelPage.title }}
</a> </a>
{% if firstLevelPage.children is not empty %} {% if firstLevelPage.children is not empty %}
<ul class="docs-aside__section-list"> <ul class="docs-aside__section-list">
{% for child in firstLevelPage.children %} {% for child in firstLevelPage.children %}
<li> <li>
<a href="/{{ child.uri }}"> <a
{% if child.uri %}
href="/{{ child.uri }}"
{% else %}
href="/page/{{ child._id }}"
{% endif %}>
{{ child.title }} {{ child.title }}
</a> </a>
</li> </li>

View file

@ -11,7 +11,12 @@
</li> </li>
{% for option in config.menu %} {% for option in config.menu %}
<li> <li>
<a href="{{option.uri}}"> <a
{% if child.uri %}
href="{{ option.uri }}"
{% else %}
href="/page/{{ option._id }}"
{% endif %}>
{{ option.title }} {{ option.title }}
</a> </a>
</li> </li>

View file

@ -7,7 +7,12 @@
Documentation Documentation
</a> </a>
{% if page._parent %} {% if page._parent %}
<a href="{{ pageParent.uri }}" class="page__header-nav"> <a class="page__header-nav"
{% if pageParent.uri %}
href="/{{ pageParent.uri }}"
{% else %}
href="/page/{{ pageParent._id }}"
{% endif %}>
Parent {{ pageParent.title }} Parent {{ pageParent.title }}
</a> </a>
{% endif %} {% endif %}

View file

@ -3,7 +3,7 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const config = require('../../config'); const config = require('../../config');
const Alias = require('../../src/models/alias'); const Alias = require('../../src/models/alias');
const md5 = require('../../src/utils/md5'); const binaryMD5 = require('../../src/utils/crypto');
const aliasTypes = require('../../src/constants/aliasTypes'); const aliasTypes = require('../../src/constants/aliasTypes');
const {aliases} = require('../../src/utils/database'); const {aliases} = require('../../src/utils/database');
@ -50,14 +50,14 @@ describe('Alias model', () => {
data = alias.data; data = alias.data;
expect(data._id).to.equal(initialData._id); expect(data._id).to.equal(initialData._id);
expect(data.hash).to.equal(md5(aliasName)); expect(data.hash).to.equal(binaryMD5(aliasName));
expect(data.type).to.equal(initialData.type); expect(data.type).to.equal(initialData.type);
expect(data.deprecated).to.equal(false); expect(data.deprecated).to.equal(false);
const update = { const update = {
type: aliasTypes.PAGE, type: aliasTypes.PAGE,
id: 'page_id', id: 'page_id',
hash: md5('another test hash'), hash: binaryMD5('another test hash'),
deprecated: true deprecated: true
}; };
@ -87,7 +87,7 @@ describe('Alias model', () => {
const {data} = foundAlias; const {data} = foundAlias;
expect(data._id).to.equal(savedAlias._id); expect(data._id).to.equal(savedAlias._id);
expect(data.hash).to.equal(md5(aliasName)); expect(data.hash).to.equal(binaryMD5(aliasName));
expect(data.type).to.equal(initialData.type); expect(data.type).to.equal(initialData.type);
expect(data.deprecated).to.equal(false); expect(data.deprecated).to.equal(false);
}); });
@ -104,7 +104,7 @@ describe('Alias model', () => {
const savedAlias = await alias.save(); const savedAlias = await alias.save();
expect(savedAlias._id).not.be.undefined; expect(savedAlias._id).not.be.undefined;
expect(savedAlias.hash).to.equal(md5(aliasName)); expect(savedAlias.hash).to.equal(binaryMD5(aliasName));
expect(savedAlias.type).to.equal(initialData.type); expect(savedAlias.type).to.equal(initialData.type);
expect(savedAlias.id).to.equal(initialData.id); expect(savedAlias.id).to.equal(initialData.id);
expect(savedAlias.deprecated).to.equal(false); expect(savedAlias.deprecated).to.equal(false);
@ -120,7 +120,7 @@ describe('Alias model', () => {
const updateData = { const updateData = {
type: aliasTypes.PAGE, type: aliasTypes.PAGE,
id: 'page_id', id: 'page_id',
hash: md5('another test hash'), hash: binaryMD5('another test hash'),
deprecated: true deprecated: true
}; };

View file

@ -72,7 +72,7 @@ describe('Page model', () => {
expect(data._id).to.equal(initialData._id); expect(data._id).to.equal(initialData._id);
expect(data.title).to.equal(initialData.body.blocks[0].data.text); expect(data.title).to.equal(initialData.body.blocks[0].data.text);
expect(data.uri).to.equal(transformToUri(initialData.body.blocks[0].data.text)); expect(data.uri).to.be.empty;
expect(data.body).to.deep.equal(initialData.body); expect(data.body).to.deep.equal(initialData.body);
expect(data.parent).to.be.undefined; expect(data.parent).to.be.undefined;
@ -102,7 +102,7 @@ describe('Page model', () => {
expect(data._id).to.equal(initialData._id); expect(data._id).to.equal(initialData._id);
expect(data.title).to.equal(update.body.blocks[0].data.text); expect(data.title).to.equal(update.body.blocks[0].data.text);
expect(data.uri).to.equal(transformToUri(update.body.blocks[0].data.text)); expect(data.uri).to.be.empty;
expect(data.body).to.equal(update.body); expect(data.body).to.equal(update.body);
expect(data.parent).to.be.undefined; expect(data.parent).to.be.undefined;
}); });