forked from microsoft/roosterjs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge dark mode into master!!!! (microsoft#326)
For more information, please view the roosterjs-darkmode-alpha branch.
- Loading branch information
William Saulnier
authored
Jul 30, 2019
1 parent
edf2355
commit 6049453
Showing
24 changed files
with
1,534 additions
and
1,108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
registry=https://registry.npmjs.com/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
164 changes: 82 additions & 82 deletions
164
packages/roosterjs-editor-api/lib/format/replaceWithNode.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,82 +1,82 @@ | ||
import { Editor } from 'roosterjs-editor-core'; | ||
import { PositionContentSearcher } from 'roosterjs-editor-dom'; | ||
import { ContentPosition } from 'roosterjs-editor-types'; | ||
|
||
/** | ||
* Replace text before current selection with a node, current selection will be kept if possible | ||
* @param editor The editor instance | ||
* @param text The text for matching. We will try to match the text with the text before cursor | ||
* @param node The node to replace the text with | ||
* @param exactMatch True if the text must appear exactly before selection, | ||
* otherwise there can be some text between the tearget text and selection | ||
* @param searcher Optional PositionContentSearcher of current selection to help search text | ||
*/ | ||
export default function replaceWithNode( | ||
editor: Editor, | ||
text: string, | ||
node: Node, | ||
exactMatch: boolean, | ||
searcher?: PositionContentSearcher | ||
): boolean; | ||
|
||
/** | ||
* Replace a given range with a node, current selection will be kept if possible | ||
* @param editor The editor instance | ||
* @param range The range to replace from | ||
* @param node The node to replace the text with | ||
* @param exactMatch True if the text must appear exactly before selection, | ||
* otherwise there can be some text between the tearget text and selection | ||
*/ | ||
export default function replaceWithNode( | ||
editor: Editor, | ||
range: Range, | ||
node: Node, | ||
exactMatch: boolean | ||
): boolean; | ||
|
||
export default function replaceWithNode( | ||
editor: Editor, | ||
textOrRange: string | Range, | ||
node: Node, | ||
exactMatch: boolean, | ||
searcher?: PositionContentSearcher | ||
): boolean { | ||
// Make sure the text and node is valid | ||
if (!textOrRange || !node) { | ||
return false; | ||
} | ||
|
||
let range: Range; | ||
|
||
if (typeof textOrRange == 'string') { | ||
searcher = searcher || editor.getContentSearcherOfCursor(); | ||
range = searcher && searcher.getRangeFromText(textOrRange, exactMatch); | ||
} else { | ||
range = textOrRange; | ||
} | ||
|
||
if (range) { | ||
const backupRange = editor.getSelectionRange(); | ||
|
||
// If the range to replace is right before current cursor, it is actually an exact match | ||
if ( | ||
backupRange.collapsed && | ||
range.endContainer == backupRange.startContainer && | ||
range.endOffset == backupRange.startOffset | ||
) { | ||
exactMatch = true; | ||
} | ||
|
||
editor.insertNode(node, { | ||
position: ContentPosition.Range, | ||
updateCursor: exactMatch, | ||
replaceSelection: true, | ||
insertOnNewLine: false, | ||
range: range, | ||
}); | ||
|
||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
import { ContentPosition } from 'roosterjs-editor-types'; | ||
import { Editor } from 'roosterjs-editor-core'; | ||
import { PositionContentSearcher } from 'roosterjs-editor-dom'; | ||
|
||
/** | ||
* Replace text before current selection with a node, current selection will be kept if possible | ||
* @param editor The editor instance | ||
* @param text The text for matching. We will try to match the text with the text before cursor | ||
* @param node The node to replace the text with | ||
* @param exactMatch True if the text must appear exactly before selection, | ||
* otherwise there can be some text between the tearget text and selection | ||
* @param searcher Optional PositionContentSearcher of current selection to help search text | ||
*/ | ||
export default function replaceWithNode( | ||
editor: Editor, | ||
text: string, | ||
node: Node, | ||
exactMatch: boolean, | ||
searcher?: PositionContentSearcher | ||
): boolean; | ||
|
||
/** | ||
* Replace a given range with a node, current selection will be kept if possible | ||
* @param editor The editor instance | ||
* @param range The range to replace from | ||
* @param node The node to replace the text with | ||
* @param exactMatch True if the text must appear exactly before selection, | ||
* otherwise there can be some text between the tearget text and selection | ||
*/ | ||
export default function replaceWithNode( | ||
editor: Editor, | ||
range: Range, | ||
node: Node, | ||
exactMatch: boolean | ||
): boolean; | ||
|
||
export default function replaceWithNode( | ||
editor: Editor, | ||
textOrRange: string | Range, | ||
node: Node, | ||
exactMatch: boolean, | ||
searcher?: PositionContentSearcher | ||
): boolean { | ||
// Make sure the text and node is valid | ||
if (!textOrRange || !node) { | ||
return false; | ||
} | ||
|
||
let range: Range; | ||
|
||
if (typeof textOrRange == 'string') { | ||
searcher = searcher || editor.getContentSearcherOfCursor(); | ||
range = searcher && searcher.getRangeFromText(textOrRange, exactMatch); | ||
} else { | ||
range = textOrRange; | ||
} | ||
|
||
if (range) { | ||
const backupRange = editor.getSelectionRange(); | ||
|
||
// If the range to replace is right before current cursor, it is actually an exact match | ||
if ( | ||
backupRange.collapsed && | ||
range.endContainer == backupRange.startContainer && | ||
range.endOffset == backupRange.startOffset | ||
) { | ||
exactMatch = true; | ||
} | ||
|
||
editor.insertNode(node, { | ||
position: ContentPosition.Range, | ||
updateCursor: exactMatch, | ||
replaceSelection: true, | ||
insertOnNewLine: false, | ||
range: range, | ||
}); | ||
|
||
return true; | ||
} | ||
|
||
return false; | ||
} |
29 changes: 22 additions & 7 deletions
29
packages/roosterjs-editor-api/lib/format/setBackgroundColor.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,31 @@ | ||
import applyInlineStyle from '../utils/applyInlineStyle'; | ||
import { Editor } from 'roosterjs-editor-core'; | ||
import { ModeIndependentColor } from 'roosterjs-editor-types'; | ||
|
||
/** | ||
* Set background color at current selection | ||
* @param editor The editor instance | ||
* @param color The color string, can be any of the predefined color names (e.g, 'red') | ||
* @param color One of two options: | ||
* The color string, can be any of the predefined color names (e.g, 'red') | ||
* or hexadecimal color string (e.g, '#FF0000') or rgb value (e.g, 'rgb(255, 0, 0)') supported by browser. | ||
* Currently there's no validation to the string, if the passed string is invalid, it won't take affect | ||
*/ | ||
export default function setBackgroundColor(editor: Editor, color: string) { | ||
color = color.trim(); | ||
applyInlineStyle(editor, (element, isInnerNode) => { | ||
element.style.backgroundColor = isInnerNode ? '' : color; | ||
}); | ||
* Alternatively, you can pass a @typedef ModeIndepenentColor. If in light mode, the lightModeColor property will be used. | ||
* If in dark mode, the darkModeColor will be used and the lightModeColor will be used when converting back to light mode. | ||
**/ | ||
export default function setBackgroundColor(editor: Editor, color: string | ModeIndependentColor) { | ||
if (typeof color === 'string') { | ||
const trimmedColor = color.trim(); | ||
applyInlineStyle(editor, (element, isInnerNode) => { | ||
element.style.backgroundColor = isInnerNode ? '' : trimmedColor; | ||
}); | ||
} else { | ||
const darkMode = editor.isDarkMode(); | ||
const appliedColor = darkMode ? color.darkModeColor : color.lightModeColor; | ||
applyInlineStyle(editor, (element, isInnerNode) => { | ||
element.style.backgroundColor = isInnerNode ? '' : appliedColor; | ||
if (darkMode) { | ||
element.dataset.ogsb = color.lightModeColor; | ||
} | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,31 @@ | ||
import applyInlineStyle from '../utils/applyInlineStyle'; | ||
import { Editor } from 'roosterjs-editor-core'; | ||
import { ModeIndependentColor } from 'roosterjs-editor-types'; | ||
|
||
/** | ||
* Set text color at selection | ||
* @param editor The editor instance | ||
* @param color The color string, can be any of the predefined color names (e.g, 'red') | ||
* @param color One of two options: | ||
* The color string, can be any of the predefined color names (e.g, 'red') | ||
* or hexadecimal color string (e.g, '#FF0000') or rgb value (e.g, 'rgb(255, 0, 0)') supported by browser. | ||
* Currently there's no validation to the string, if the passed string is invalid, it won't take affect | ||
* Alternatively, you can pass a @typedef ModeIndepenentColor. If in light mode, the lightModeColor property will be used. | ||
* If in dark mode, the darkModeColor will be used and the lightModeColor will be used when converting back to light mode. | ||
*/ | ||
export default function setTextColor(editor: Editor, color: string) { | ||
color = color.trim(); | ||
applyInlineStyle(editor, (element, isInnerNode) => { | ||
element.style.color = isInnerNode ? '' : color; | ||
}); | ||
export default function setTextColor(editor: Editor, color: string | ModeIndependentColor) { | ||
if (typeof color === 'string') { | ||
const trimmedColor = color.trim(); | ||
applyInlineStyle(editor, (element, isInnerNode) => { | ||
element.style.color = isInnerNode ? '' : trimmedColor; | ||
}); | ||
} else { | ||
const darkMode = editor.isDarkMode(); | ||
const appliedColor = darkMode ? color.darkModeColor : color.lightModeColor; | ||
applyInlineStyle(editor, (element, isInnerNode) => { | ||
element.style.color = isInnerNode ? '' : appliedColor; | ||
if (darkMode) { | ||
element.dataset.ogsc = color.lightModeColor; | ||
} | ||
}); | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
packages/roosterjs-editor-core/lib/coreAPI/calculateDefaultFormat.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { DefaultFormat } from 'roosterjs-editor-types'; | ||
import { getComputedStyles } from 'roosterjs-editor-dom'; | ||
|
||
const DARK_MODE_DEFAULT_FORMAT = { | ||
backgroundColors: { | ||
darkModeColor: 'rgb(51,51,51)', | ||
lightModeColor: 'rgb(255,255,255)', | ||
}, | ||
textColors: { | ||
darkModeColor: 'rgb(255,255,255)', | ||
lightModeColor: 'rgb(0,0,0)', | ||
} | ||
} | ||
|
||
export function calculateDefaultFormat( | ||
node: Node, | ||
baseFormat: DefaultFormat, | ||
inDarkMode: boolean | ||
): DefaultFormat { | ||
if (inDarkMode) { | ||
if (!baseFormat.backgroundColors) { | ||
baseFormat.backgroundColors = DARK_MODE_DEFAULT_FORMAT.backgroundColors; | ||
} | ||
if (!baseFormat.textColors) { | ||
baseFormat.textColors = DARK_MODE_DEFAULT_FORMAT.textColors; | ||
} | ||
} | ||
|
||
if (baseFormat && Object.keys(baseFormat).length === 0) { | ||
return {}; | ||
} | ||
|
||
baseFormat = baseFormat || <DefaultFormat>{}; | ||
let { | ||
fontFamily, | ||
fontSize, | ||
textColor, | ||
textColors, | ||
backgroundColor, | ||
backgroundColors, | ||
bold, | ||
italic, | ||
underline, | ||
} = baseFormat; | ||
let currentStyles = | ||
fontFamily && fontSize && (textColor || textColors) ? null : getComputedStyles(node); | ||
return { | ||
fontFamily: fontFamily || currentStyles[0], | ||
fontSize: fontSize || currentStyles[1], | ||
get textColor() { | ||
return textColors | ||
? inDarkMode | ||
? textColors.darkModeColor | ||
: textColors.lightModeColor | ||
: textColor || currentStyles[2]; | ||
}, | ||
textColors: textColors, | ||
get backgroundColor() { | ||
return backgroundColors | ||
? inDarkMode | ||
? backgroundColors.darkModeColor | ||
: backgroundColors.lightModeColor | ||
: backgroundColor || ''; | ||
}, | ||
backgroundColors: backgroundColors, | ||
bold: bold, | ||
italic: italic, | ||
underline: underline, | ||
}; | ||
} |
Oops, something went wrong.