Commit ac95ea7b authored by Christos's avatar Christos

Merge branch 'change-case' into 'master'

Change case

See merge request wax/wax!238
parents 8441e577 084d2df0
......@@ -57,16 +57,15 @@ class AbstractProvider extends EventEmitter {
let currentNodes = clone(nodes)
const containers = this.getAllAvailableSurfaces()
let container = ''
// sort notes by
// the index of the containing block
// their position within that block
currentNodes = map(currentNodes, node => {
const blockId = node.path[0]
forEach(containers, cont => {
let container = containers.find(cont => {
if (includes(cont.nodes, blockId)) {
container = cont
return cont
}
})
// This is actually not correct.
......@@ -205,10 +204,10 @@ class AbstractProvider extends EventEmitter {
getContainerForSelection(selection) {
const containersEls = this.getAllAvailableSurfaces(this.document)
const selectionNodeId = selection.getNodeId()
let container = ''
forEach(containersEls, cont => {
let container = containersEls.find(cont => {
if (includes(cont.nodes, selectionNodeId)) {
container = cont
return cont
}
})
if (container === '') container = containersEls[0]
......
......@@ -47,6 +47,7 @@ import OrnamentPackage from './elements/ornament/OrnamentPackage'
import SpellCheckPackage from './elements/spellCheck/SpellCheckPackage'
import HeadingPackage from './elements/headings/HeadingPackage'
import SpellCheckTogglePackage from './elements/spellcheck_toggle/SpellCheckTogglePackage'
import ChangeCasePackage from './elements/change_case/ChangeCasePackage'
// import InlineNotePackage from './elements/inline_note/InlineNotePackage'
//TODO Need to recreate them?
......@@ -111,6 +112,7 @@ const config = {
config.import(ShortCutsModalPackage)
config.import(SpellCheckTogglePackage)
config.import(QuoteMarksPackage)
config.import(ChangeCasePackage)
// config.import(InlineNotePackage)
},
}
......
import { Command } from 'substance'
class ChangeCaseCommand extends Command {
getCommandState(params) {
let newState = {
active: false,
disabled: false,
}
const selection = params.editorSession.getSelection()
if (selection.isCollapsed() || selection.isContainerSelection()) {
newState.disabled = true
}
if (params.surface) {
const editorProps = params.surface.context.editor.props
if (editorProps.editing === 'selection') newState.disabled = true
}
return newState
}
execute(params) {
return true
}
}
export default ChangeCaseCommand
import { platform } from 'substance'
import WaxAnnotationCommand from '../../commands/WaxAnnotationCommand'
import ChangeCaseTool from './ChangeCaseTool'
import ChangeCaseCommand from './ChangeCaseCommand'
export default {
name: 'change-case',
configure: config => {
config.addCommand('change-case', ChangeCaseCommand, {
commandGroup: 'change-case',
})
config.addTool('change-case', ChangeCaseTool)
},
}
import { forEach } from 'lodash'
import { Tool, FontAwesomeIcon as Icon, documentHelpers } from 'substance'
import toTitleCase from '../../helpers/titleCase'
class ChangeCaseTool extends Tool {
constructor(...args) {
super(...args)
this.DropDownOptions = [
{
name: 'Upper case',
description: 'tranform all leters to upper case',
action: 'uppercase',
},
{
name: 'Lower case',
description: 'tranform all leters to lower case',
action: 'lowerase',
},
{
name: 'Sentence case',
description: 'tranform first letter only capped',
action: 'sentencecase',
},
{
name: 'Title case',
description: 'tranform first letter of all words capped',
action: 'titlecase',
},
]
}
render($$) {
const dropDownCarret = $$(Icon, { icon: 'fa-caret-down' }).addClass(
'icon-down',
)
let el = $$('div')
.addClass('change-case-wrapper')
.attr('id', 'change-case')
.append(
$$('div')
.addClass('choose-case')
.attr('title', `Change Case Action`)
.append('Choose Action')
.append(dropDownCarret)
.on('click', this.toggleDropdown),
)
if (this.props.commandState.disabled) {
el.addClass('sm-disabled')
}
let options = $$('span')
if (this.state.open) {
el.addClass('sm-open')
// dropdown options
options = $$('div')
.addClass('se-options')
.ref('options')
forEach(this.DropDownOptions, (option, index) => {
let button = $$('button')
.addClass('se-option')
.attr('data-type', option)
.append(
$$('div')
.append(option.name)
.addClass('option-box')
.attr('title', option.description),
)
.on('click', () => this.changeCase(option.action))
options.append(button)
})
}
return el.append(options)
}
toggleDropdown() {
this.extendState({
open: !this.state.open,
})
}
changeCase(action) {
this.toggleDropdown()
const text = this.getSelectionText()
const selection = this.context.editorSession.getSelection()
switch (action) {
case 'uppercase':
this.transformToUpper(selection, text)
break
case 'lowerase':
this.transformToLower(selection, text)
break
case 'sentencecase':
this.transformToSentence(selection, text)
break
case 'titlecase':
this.transformToTitle(selection, text)
break
}
}
transformToUpper(selection, text) {
this.context.editorSession.transaction(tx => {
tx.deleteSelection()
tx.insertText(text.toUpperCase())
})
}
transformToLower(selection, text) {
this.context.editorSession.transaction(tx => {
tx.deleteSelection()
tx.insertText(text.toLowerCase())
})
}
transformToSentence(selection, text) {
if (
text.charAt(0).match(/^[a-z]+$/i) !== null &&
text.charAt(0).match(/^[a-z]+$/i)[0]
) {
this.context.editorSession.transaction(tx => {
tx.deleteSelection()
tx.insertText(text.charAt(0).toUpperCase() + text.slice(1))
})
} else {
this.context.editorSession.transaction(tx => {
tx.deleteSelection()
tx.insertText(text.charAt(0))
tx.insertText(text.charAt(1).toUpperCase() + text.slice(2))
})
}
}
transformToTitle(selection, text) {
this.context.editorSession.transaction(tx => {
tx.deleteSelection()
tx.insertText(text.toTitleCase())
})
}
getSelectionText() {
let text = ''
if (window.getSelection) {
text = window.getSelection().toString()
} else if (document.selection && document.selection.type != 'Control') {
text = document.selection.createRange().text
}
return text
}
getInitialState() {
return {
open: false,
}
}
}
export default ChangeCaseTool
import { Command } from 'substance'
class UpperCaseCommand extends Command {}
export default UpperCaseCommand
.change-case-wrapper {
width: 120px;
font-size: 13px;
font-family: 'Fira Sans';
&.sm-disabled {
cursor: default;
opacity: 0.4;
pointer-events: none;
}
.choose-case {
margin-top: 3px;
cursor: pointer;
}
i {
margin-left: 10px;
}
&.sm-open {
div:first-child {
background: #4990e2;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
color: #fff;
padding: 3px;
}
}
.se-options {
width: 120px;
position: fixed;
z-index: 99999;
background-color: #4990e2;
border-top: 1px solid #ccc;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
padding: 2px 0px 5px 0px;
}
button {
font-size: 13px;
display: block;
background: none;
border: none;
color: #fff;
margin-top: 5px;
padding-left: 1px;
cursor: pointer;
&:hover {
font-weight: 600;
}
}
}
......@@ -14,3 +14,4 @@
@import './track_change/trackChange';
@import './notification/notification';
@import './change_case/changecase';
......@@ -28,7 +28,7 @@ class HighLighterTool extends Tool {
.addClass('highlighter-wrapper')
.append(dropDownCarret)
if (this.props.disabled) el.addClass('sm-disabled')
if (this.props.commandState.disabled) el.addClass('sm-disabled')
if (this.state.open) {
el.addClass('sm-open')
......
export default (String.prototype.toTitleCase = function() {
'use strict'
var smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|v.?|vs.?|via)$/i
var alphanumericPattern = /([A-Za-z0-9\u00C0-\u00FF])/
var wordSeparators = /([ :–—-])/
return this.split(wordSeparators)
.map(function(current, index, array) {
if (
/* Check for small words */
current.search(smallWords) > -1 &&
/* Skip first and last word */
index !== 0 &&
index !== array.length - 1 &&
/* Ignore title end and subtitle start */
array[index - 3] !== ':' &&
array[index + 1] !== ':' &&
/* Ignore small words that start a hyphenated phrase */
(array[index + 1] !== '-' ||
(array[index - 1] === '-' && array[index + 1] === '-'))
) {
return current.toLowerCase()
}
/* Ignore intentional capitalization */
if (current.substr(1).search(/[A-Z]|\../) > -1) {
return current
}
/* Ignore URLs */
if (array[index + 1] === ':' && array[index + 2] !== '') {
return current
}
/* Capitalize the first letter */
return current.replace(alphanumericPattern, function(match) {
return match.toUpperCase()
})
})
.join('')
})
......@@ -33,6 +33,13 @@ export default {
style: 'minimal',
commandGroups: ['persistence'],
},
{
name: 'change-case',
type: 'tool-group',
showDisabled: true,
style: 'minimal',
commandGroups: ['change-case'],
},
{
name: 'annotations',
type: 'tool-group',
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment