Multiple nots. Complex
firstname != 'Juan' || lastname != 'Cruz'
English-speak:
If your firstname is not Juan or your lastname is not Cruz, therefore you are not Juan Cruz
Don't use the above, it has multiple nots. Use this:
Single not, simple. Translates well to English:
!(firstname == 'Juan' && lastname == 'Cruz')
English-speak (reading from inside out):
If you are Juan Cruz, then don't.
English-speak (reading from left to right):
If you are not Juan Cruz, then do.
Postgres tuple test:
(firstname, lastname) != ('Juan', 'Cruz')
Languages without tuple:
firstname + ' ' + lastname != 'Juan Cruz'
**Schema (PostgreSQL v13)**
create table person(firstname text, lastname text);
insert into person(firstname, lastname) values
('Juan', 'Cruz'),
('Juan', 'Buen'),
('Michael', 'Cruz'),
('Michael', 'Buen');
---
**Query #1**
select
firstname, lastname,
firstname != 'Juan' or lastname != 'Cruz' as test1,
not (firstname = 'Juan' and lastname = 'Cruz') as test2,
(firstname, lastname) != ('Juan', 'Cruz') as test3,
(firstname || ' ' || lastname) != 'Juan Cruz' as test4
from
person;
| firstname | lastname | test1 | test2 | test3 | test4 |
| --------- | -------- | ----- | ----- | ----- | ----- |
| Juan | Cruz | false | false | false | false |
| Juan | Buen | true | true | true | true |
| Michael | Cruz | true | true | true | true |
| Michael | Buen | true | true | true | true |
---
[View on DB Fiddle](https://www.db-fiddle.com/f/nxbuszjT4zgmdj4pGaZeuQ/0)
-------------
Multiple nots. Complex
firstname != 'Juan' && lastname != 'Cruz'
Single not, simple. Translates well to English:
!(firstname == 'Juan' || lastname == 'Cruz')
English-speak:
If your firstname is Juan or lastname is Cruz, then don't.
**Schema (PostgreSQL v13)**
create table person(firstname text, lastname text);
insert into person(firstname, lastname) values
('Juan', 'Cruz'),
('Juan', 'Buen'),
('Michael', 'Cruz'),
('Michael', 'Buen');
---
**Query #1**
select
firstname, lastname,
firstname != 'Juan' and lastname != 'Cruz' as test1,
not (firstname = 'Juan' or lastname = 'Cruz') as test2
from
person;
| firstname | lastname | test1 | test2 |
| --------- | -------- | ----- | ----- |
| Juan | Cruz | false | false |
| Juan | Buen | false | false |
| Michael | Cruz | false | false |
| Michael | Buen | true | true |
---
[View on DB Fiddle](https://www.db-fiddle.com/f/nxbuszjT4zgmdj4pGaZeuQ/1)
Sunday, April 25, 2021
Do not be driven nuts by multiple nots
Thursday, April 22, 2021
Intl.Segmenter
It would be awesome if Intl.Segmenter is perfect. For the meantime, retokenize the words that should not be together
Live: https://jsfiddle.net/rgqen1zc/
Output:
我不是 should be 我 不是
function tokenizeZH(text) {
const segmenter = new Intl.Segmenter('zh', { granularity: 'word' });
const segments = segmenter.segment(text);
const words = [];
for (const { segment /* , index, isWordLike */ } of segments) {
words.push(segment);
}
return words;
}
console.log(tokenizeZH('我不是太清楚'));
Live: https://jsfiddle.net/rgqen1zc/
Output:
["我不是", "太", "清楚"]
我不是 should be 我 不是
Monday, April 19, 2021
Unchecked runtime.lastError: The message port closed before a response was received.
Even if the listener's async code returns true to indicate it is running an async code, the code will still have the error "Unchecked runtime.lastError: The message port closed before a response was received" if the async code is wrongly placed.
The following code produces the error mentioned due to misplaced async
The following code produces the error mentioned due to misplaced async
chrome.runtime.onMessage.addListener(async (message /* , sender, sendResponse */) => {
if (message.action === UPDATE_PAGE) {
await applyStyleFromSettings();
}
// https://stackoverflow.com/questions/53024819/chrome-extension-sendresponse-not-waiting-for-async-function
return true;
});
Returning true is not enough, to fully fix the problem, we must place the async code on the code body itself, not on the callback's declaration. Remove the async declaration from the listener, move it to the code's body instead
chrome.runtime.onMessage.addListener((message /*, sender, sendResponse */) => {
(async () => {
if (message.action === UPDATE_PAGE) {
await applyStyleFromSettings();
}
})();
// https://stackoverflow.com/questions/53024819/chrome-extension-sendresponse-not-waiting-for-async-function
return true;
});
Saturday, April 17, 2021
TypeScript, array map can't be type-checked
Given this interface:
interface IHskLevel {
hanzi: string;
hsk: number;
}
This code does not produce compile error (it should):
function* generateHskLevel(): Iterable<IHskLevel> {
yield* json.map(
({ hanzi, pinyin, HSK: hsk }) => ({ hanzi, pinyin, hsk })
);
}
This produces compile error (it should):
function* generateHskLevel(): Iterable<IHskLevel> {
for (const { hanzi, pinyin, HSK: hsk } of json) {
yield { hanzi, pinyin, hsk };
}
}
Error:
error: TS2322 [ERROR]: Type '{ hanzi: string; pinyin: string; hsk: number; }' is not assignable to type 'IHskLevel'.
Object literal may only specify known properties, and 'pinyin' does not exist in type 'IHskLevel'.
pinyin,
Wednesday, April 14, 2021
Uncaught (in promise) The message port closed before a response was received
// eslint-disable-next-line no-undef
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.dataNeeded === HANZI) {
(async () => {
const hzl = await loadHanziListFile();
sendResponse({data: hzl});
})();
// Need to return true if we are using async code in addListener.
// Without this line..
return true;
// ..we will receive the error:
// Uncaught (in promise) The message port closed before a response was received
}
});
Sunday, April 11, 2021
Service worker registration failed. Cannot read property 'onClicked' of undefined
Given this background.js:
And I received this error:
// eslint-disable-next-line no-undef
chrome.action.onClicked.addListener((tab) => {
console.log("working");
// eslint-disable-next-line no-undef
chrome.tabs.sendMessage(
// tabs[0].id,
tab.id,
{ action: "CHANGE_COLOR" },
// eslint-disable-next-line no-unused-vars
function (response) {}
);
});
I'm using manifest version 3:
{
"name": "Chinese word separator",
"description": "Put spaces between words",
"version": "1.0",
"manifest_version": 3,
"background" : {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"css": [],
"js": ["contentScript.js"]
}
]
}
And I received this error:
To fix the error, add the action property even if it is empty:
{
"name": "Chinese word separator",
"description": "Put spaces between words",
"version": "1.0",
"manifest_version": 3,
"action": {},
"background" : {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"css": [],
"js": ["contentScript.js"]
}
]
}
It is advisable to wrap the background.js via a wrapper so you'll get better error message, so if there's no action property in manifest.json..
{
"name": "Chinese word separator",
"description": "Put spaces between words",
"version": "1.0",
"manifest_version": 3,
"background" : {
"service_worker": "background-wrapper.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"css": [],
"js": ["contentScript.js"]
}
]
}
..and you wrap the background via wrapper (e.g., background-wrapper.js).. try {
// eslint-disable-next-line no-undef
importScripts("./background.js");
} catch (e) {
console.error(e);
}
..you will receive a more descriptive error instead:
background-wrapper.js:5 TypeError: Cannot read property 'onClicked' of undefined
at background.js:1
at background-wrapper.js:3
(anonymous) @ background-wrapper.js:5
To fix the error, add action on manifest.json
Tuesday, March 9, 2021
Centering horizontally and vertically
<div id="parent">
<div id="child">hello world</div>
</div>
Centering with margin, it has to be done at child level:
#parent {
width: 50vw;
height: 50vh;
background-color: gray;
display: flex;
}
#child {
margin: auto;
}
Try it at: https://jsfiddle.net/xd7uwgn8/
It's better if it is done at the parent level, the parent should be able to control the child elements:
#parent {
width: 50vw;
height: 50vh;
background-color: gray;
display: flex;
justify-content: center;
align-items: center;
}
#child {
}
Try it at: https://jsfiddle.net/xd7uwgn8/2/
Another good thing if it is done at parent level, creating unnecessary div+margin:auto for the content could be avoided:
<div id="parent">
hello world
</div>
Try it at: https://jsfiddle.net/xd7uwgn8/3/
Subscribe to:
Posts (Atom)

