问:
Why data variables are persisting the old values in Flutter app?
I am so confused about the data persistence in my app. I am using google drive api to fetch a spreadsheet file(.xlsx) and then read and show the excel cell values in my app using an itemBuilder. The main problem is that when I edit some cells in my google spreadsheet on the browser and fetch the file(which is now updated) from the app, it does not show the new values. I noticed that my app takes some time to fetch file for the first time but after that it fetches immediately. I am going to show about how I am fetching file and updating it.

Initialization of variables:

```<code>//I am using excel dart package
late var excel;
late drive.DriveApi driveApi;
late Sheet sheet;

String fileId = "19jF3lOVW563LU6mEjqAjXVLNQ7poXY1Z"; //xlsx file id
</code>```

Fetching of file from drive:

```<code>drive.Media? response = (await driveApi.files.get(fileId,downloadOptions: drive.DownloadOptions.fullMedia)) as drive.Media?;

List<int> dataStore = [];
response!.stream.listen((data) {
  dataStore.insertAll(dataStore.length, data);
}, onDone: (){
  excel = Excel.decodeBytes(dataStore);            //excel variable declaration
  sheet = excel['Sheet1'];
}, onError: (error) {
  Fluttertoast.showToast(msg: error.toString());
});
</code>```

Showing values of excel using itemBuilder

```<code>Widgets----
............
............
............
............
itemCount: sheet.maxRows - 1,
itemBuilder: (context, index) {
  var cell = sheet.cell(CellIndex.indexByColumnRow(     //taking values from excel sheets
      rowIndex: index + 1, columnIndex: itr));
  String val = cell.value.toString().toLowerCase();
  if (cell.value == null ||
      (val != 'present' && val != 'absent')) {
    cell.value = 'absent';
    cell.cellStyle = absent;
  }

  return ListTile(
    subtitle: Text(cell.value.toString()),
    title: Row(
      children: <Widget>[
        const Icon(Icons.person),
        Expanded(
          child: Text(sheet.rows[index + 1][0]!.value
              .toString()),

............
............
............
............
Widgets----
</code>```

Updating the excel file to google drive:

```<code>//First I am creating a unique pathName, then creating a file and saving the new excel values
//to the newly created file

final String path = (await getApplicationSupportDirectory()).path;
final String fileName = path + cryptoRandom() + '/$fileId.xlsx';
File newFile = File(fileName);

var driveFile = new drive.File();
driveFile.name = basename(newFile.path);
//Saving excel to newFile
File(join(newFile.path))
  ..createSync(recursive: true)
  ..writeAsBytesSync(excel.encode()!);

//Updating the newFile
await driveApi.files.update(driveFile, fileId,
    uploadMedia: drive.Media(newFile.openRead(), newFile.lengthSync()));

//Deleting the created file
newFile.deleteSync(recursive: true);

</code>```

Why the old values persist in my app, even when I am creating new file everytime and deleting them also. Why this is happening, I sthis because of some cache data or what ? Thanks

答: you can set as null or any default value. when first run page vars will be default one. and another place you can get your main datas.</p>

Body:
I am so confused about the data persistence in my app. I am using google drive api to fetch a spreadsheet file(.xlsx) and then read and show the excel cell values in my app using an itemBuilder. The main problem is that when I edit some cells in my google spreadsheet on the browser and fetch the file(which is now updated) from the app, it does not show the new values. I noticed that my app takes some time to fetch file for the first time but after that it fetches immediately. I am going to show about how I am fetching file and updating it.

Initialization of variables:

//I am using excel dart package
late var excel;
late drive.DriveApi driveApi;
late Sheet sheet;

String fileId = "19jF3lOVW563LU6mEjqAjXVLNQ7poXY1Z"; //xlsx file id

Fetching of file from drive:

drive.Media? response = (await driveApi.files.get(fileId,downloadOptions: drive.DownloadOptions.fullMedia)) as drive.Media?;

List<int> dataStore = [];
response!.stream.listen((data) {
  dataStore.insertAll(dataStore.length, data);
}, onDone: (){
  excel = Excel.decodeBytes(dataStore);            //excel variable declaration
  sheet = excel['Sheet1'];
}, onError: (error) {
  Fluttertoast.showToast(msg: error.toString());
});

Showing values of excel using itemBuilder

Widgets----
............
............
............
............
itemCount: sheet.maxRows - 1,
itemBuilder: (context, index) {
  var cell = sheet.cell(CellIndex.indexByColumnRow(     //taking values from excel sheets
      rowIndex: index + 1, columnIndex: itr));
  String val = cell.value.toString().toLowerCase();
  if (cell.value == null ||
      (val != 'present' && val != 'absent')) {
    cell.value = 'absent';
    cell.cellStyle = absent;
  }

  return ListTile(
    subtitle: Text(cell.value.toString()),
    title: Row(
      children: <Widget>[
        const Icon(Icons.person),
        Expanded(
          child: Text(sheet.rows[index + 1][0]!.value
              .toString()),

............
............
............
............
Widgets----

Updating the excel file to google drive:

//First I am creating a unique pathName, then creating a file and saving the new excel values
//to the newly created file

final String path = (await getApplicationSupportDirectory()).path;
final String fileName = path + cryptoRandom() + '/$fileId.xlsx';
File newFile = File(fileName);

var driveFile = new drive.File();
driveFile.name = basename(newFile.path);
//Saving excel to newFile
File(join(newFile.path))
  ..createSync(recursive: true)
  ..writeAsBytesSync(excel.encode()!);

//Updating the newFile
await driveApi.files.update(driveFile, fileId,
    uploadMedia: drive.Media(newFile.openRead(), newFile.lengthSync()));

//Deleting the created file
newFile.deleteSync(recursive: true);

Why the old values persist in my app, even when I am creating new file everytime and deleting them also. Why this is happening, I sthis because of some cache data or what ? Thanks


来源: stackexchange

问:
Set default options for matplot/plot
I would like to set default styles for the plot/matplot functions. For instance, I almost always use

matplot(x, y, type='l', lty='solid', col=rainbow(), lwd=2)

so I would like to set default options of type='l', lty='solid', col=rainbow(), lwd=2 in .Rprofile. Of course, I could just make a new function,

```<code>mplot <- function(x, y, type='l', lty='solid', lwd=2, col=rbow(), log='') {
        matplot(x, y, type=type, lty=lty, col=col, log=log, lwd=lwd)
}
</code>```

but if I want to specify xlim and/or ylim or set xaxt='n' etc. it becomes a lot of work since there are more default options that I want than those I don't want. I also thought something like

```<code>plist <- list(type=type, lty=lty, col=col, log=log, lwd=lwd)
matplot(x, y, plist)
</code>```

should work but it doesn't.

答:
If you do

do.call(matplot, c(list(x, y), plist))
```
<p>it should work.  The other option is to use <code>...</code>:</p>
<pre class="lang-r prettyprint-override"><code>mplot <- function(x, y, type='l', lty='solid', lwd=2, col=rbow(), log='', ...) {
        matplot(x, y, type=type, lty=lty, col=col, log=log, lwd=lwd,
           ...)
}
</code>```

ContentLicense: CC BY-SA 4.0

Title: Set default options for matplot/plot

Body:
I would like to set default styles for the plot/matplot functions. For instance, I almost always use

matplot(x, y, type='l', lty='solid', col=rainbow(), lwd=2)

so I would like to set default options of type='l', lty='solid', col=rainbow(), lwd=2 in .Rprofile. Of course, I could just make a new function,

mplot <- function(x, y, type='l', lty='solid', lwd=2, col=rbow(), log='') {
        matplot(x, y, type=type, lty=lty, col=col, log=log, lwd=lwd)
}

but if I want to specify xlim and/or ylim or set xaxt='n' etc. it becomes a lot of work since there are more default options that I want than those I don't want. I also thought something like

plist <- list(type=type, lty=lty, col=col, log=log, lwd=lwd)
matplot(x, y, plist)

should work but it doesn't.

Body:
If you do

do.call(matplot, c(list(x, y), plist))

it should work.  The other option is to use ...:

mplot <- function(x, y, type='l', lty='solid', lwd=2, col=rbow(), log='', ...) {
        matplot(x, y, type=type, lty=lty, col=col, log=log, lwd=lwd,
           ...)
}


问:
Modify a document with TinyXML
Right now, I save my data by simply rewriting the file requested by the user. The way my xml is structured is like this:

```<code>Skeleons root
    Skeleton with string name attribute
       bone with attributes
       bone with attributes
       bone with attributes
       bone with attributes
    end Skeleton
   Skeleton with string name attribute
       bone with attributes
       bone with attributes
       bone with attributes
       bone with attributes
    end Skeleton
    ....
   end Skeletons root
</code>```

I iterate through to see if the skeleton of desired name exists and if it does I want to completely rewrite it. If not, I want to add it to the bottom of the root element.

Does anyone have an example of this?

Thanks

答:
Basically, this is just a matter of splitting the steps.

First, define a TiXmlElement * and set it to 0. Iterate over all children of Skeletons. If you find the correct Skeleton, point your TiXmlElement * to it.

Secondly, if you haven't found it (TiXmlElement * still 0), create a new Skeleton and point your TiXmlElement * to it.

Finally, create a new bone underneath that TiXmlElement *.

ContentLicense: CC BY-SA 3.0

Title: Modify a document with TinyXML

Body:
Right now, I save my data by simply rewriting the file requested by the user. The way my xml is structured is like this:

Skeleons root
    Skeleton with string name attribute
       bone with attributes
       bone with attributes
       bone with attributes
       bone with attributes
    end Skeleton
   Skeleton with string name attribute
       bone with attributes
       bone with attributes
       bone with attributes
       bone with attributes
    end Skeleton
    ....
   end Skeletons root

I iterate through to see if the skeleton of desired name exists and if it does I want to completely rewrite it. If not, I want to add it to the bottom of the root element.

Does anyone have an example of this?

Thanks


答:
You can always "simulate" a click in a button from another button

just:

```<code>$('.otherButton').click(function () {
$('.hamburger__container').trigger("click"); // behaves like if the user had pressed the original button
});
</code>```

or you could encapsulate your event in a function and use it in both buttons

```<code>let myEventHandler = function() {
    $('.nav').toggleClass('open');
    $('.controls').toggleClass('open2');
    $(this).children().first().toggleClass('open');
    $('html, body').toggleClass('noscroll');
}

$('.hamburger__container').click(myEventHandler );
// somwhere else in your code
$('.otherButton').click(myEventHandler );
</code>```

or if both buttons exist in your code at the same time you can just target them both when initializing the event

```<code>$('.hamburger__container, .otherButton').click(function() {
    $('.nav').toggleClass('open');
    $('.controls').toggleClass('open2');
    $(this).children().first().toggleClass('open');
    $('html, body').toggleClass('noscroll');
});
</code>```

Title: Different buttons for open and close nav menu

Body:
I want to have a different button to open the menu options and a different button placed somewhere else to close the menu options. With the JS code below I can use  only one button to toggle and open the menu with options.

(function($) {

    $(document).ready(function() {

        $('.hamburger__container').click(function() {
            $('.nav').toggleClass('open');
            $('.controls').toggleClass('open2');
            $(this).children().first().toggleClass('open');
            $('html, body').toggleClass('noscroll');
        });

        // Bacon Ipsum
        $.ajax({
            url: 'https://baconipsum.com/api/?type=all-meat&paras=2&start-with-lorem=1&format=html',
            success: function(data) {
                $('#content').html(data);
            }
        });

    });
})(jQuery);

and HTML code:

        <button class="quality">
              <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><path d="M893.8,294.1H655.5c49-32.1,95.4-73.9,100.8-119.5c2.7-22.2-2.5-54.8-42.7-83.9c-22.3-16.1-44.9-24.3-67.2-24.3c-70.9,0-111,79.5-132.7,150.6c-25.8-90.6-75.9-207-161.8-207c-25.1,0-50,9.9-74.3,29.5c-47.8,38.7-52.6,78.9-48.1,105.8c10,60.2,76.3,112,140.1,148.7H106.2c-19.3,0-34.9,15.3-34.9,34.1v186.3c0,18.8,15.6,34.1,34.9,34.1h9.1v407.4c0,18.8,15.6,34.1,34.9,34.1h699.6c19.3,0,35-15.3,35-34.1V548.5h9.1c19.4,0,35-15.3,35-34.1V328.1C928.8,309.3,913.1,294.1,893.8,294.1L893.8,294.1z M858.8,477.2H566.6v-115h292.2V477.2L858.8,477.2z M646.4,134.6c6.9,0,15.7,3.7,25.6,10.9c16,11.6,15.1,18.7,14.9,21.1c-3,24.8-54,63.9-113.4,96.2C591,194.1,619.5,134.6,646.4,134.6L646.4,134.6z M298.5,134.4c-1-5.6-3.4-20.5,23.7-42.4c7.8-6.3,19.3-13.8,29.6-13.8c38.5,0,78,92.3,101.1,182.1C380.3,224.9,305.2,174.6,298.5,134.4L298.5,134.4z M437.1,362.2v115h-296v-115H437.1L437.1,362.2z M185.2,518.1h251.9v403.7H185.2V518.1L185.2,518.1z M566.7,921.8V518.1h248.1v403.7H566.7L566.7,921.8z"/></g>
</svg>

        </button>

There is also the CSS code and other part of HTML code but I though this part would be enough to show my point.
In the HTML code there is only one button that opens and closes the navigation.

Body:
You can always "simulate" a click in a button from another button

just:

$('.otherButton').click(function () {
$('.hamburger__container').trigger("click"); // behaves like if the user had pressed the original button
});

or you could encapsulate your event in a function and use it in both buttons

let myEventHandler = function() {
    $('.nav').toggleClass('open');
    $('.controls').toggleClass('open2');
    $(this).children().first().toggleClass('open');
    $('html, body').toggleClass('noscroll');
}

$('.hamburger__container').click(myEventHandler );
// somwhere else in your code
$('.otherButton').click(myEventHandler );

or if both buttons exist in your code at the same time you can just target them both when initializing the event

$('.hamburger__container, .otherButton').click(function() {
    $('.nav').toggleClass('open');
    $('.controls').toggleClass('open2');
    $(this).children().first().toggleClass('open');
    $('html, body').toggleClass('noscroll');
});


问:
What is the alternative to :dir() in Chrome?
I would like to know how we can implement this code to work in chrome browser,

```<code>/* Selects any element with right-to-left text */
:dir(rtl) {
  background-color: red;
}
</code>```

https://developer.mozilla.org/en-US/docs/Web/CSS/:dir
what is the alternative in Chrome Browser?

答:
:dir() is indeed very useful since it refers to the direction of the element even if inherited from the parent or ancestor, but unfouruntately it's only supported in Firefox as you mentioned.

[dir="rtl"] is supported cross-browser, but it only refers to elements that have this specifically. If the entire document is one direction and it is specified in either the  or  tag, then that's not a big problem since you can simply use the descendant selector. For example

```<code>[dir="rtl"] p {
    background: red;
}
</code>```

However, this becomes complicated in a bidirectional document with nested sections. For example

```<code><body dir="rtl">
  <p>עברית (RTL text)</p>
  <div dir="ltr">
    <p>English (LTR text)</p>
    <div dir="rtl">
      <p>עברית (another RTL text)</p>
    </div>
  </div>
</body>
</code>```

Sure, you can apply style rules to both directions like this

```<code>[dir="ltr"] p {
    background: green;
}

[dir="rtl"] p {
    background: red;
}
</code>```

but CSS does not care which ancestor is closer, so the code above would still apply red to all paragraphs (and even reversing the order of rules wouldn't help for the nested section).

What you can do in this case is using CSS variables, which are inherited. For example

```<code>[dir="ltr"] {
    --p-background: green;
}

[dir="rtl"] {
    --p-background: red;
}

p {
  background: var(--p-background);
}
</code>```

In this case the variable is applied directly to the element with the specified direction, then the variable value is inherited through the element chain the same way the direction itself does, and affects the styling of the element defined to use the variable value - in this example the
 element.

Body:
I would like to know how we can implement this code to work in chrome browser,

/* Selects any element with right-to-left text */
:dir(rtl) {
  background-color: red;
}

https://developer.mozilla.org/en-US/docs/Web/CSS/:dir
what is the alternative in Chrome Browser?

Body:
:dir() is indeed very useful since it refers to the direction of the element even if inherited from the parent or ancestor, but unfouruntately it's only supported in Firefox as you mentioned.

[dir="rtl"] is supported cross-browser, but it only refers to elements that have this specifically. If the entire document is one direction and it is specified in either the <html> or <body> tag, then that's not a big problem since you can simply use the descendant selector. For example

[dir="rtl"] p {
    background: red;
}

However, this becomes complicated in a bidirectional document with nested sections. For example

<body dir="rtl">
  <p>עברית (RTL text)</p>
  <div dir="ltr">
    <p>English (LTR text)</p>
    <div dir="rtl">
      <p>עברית (another RTL text)</p>
    </div>
  </div>
</body>

Sure, you can apply style rules to both directions like this

[dir="ltr"] p {
    background: green;
}

[dir="rtl"] p {
    background: red;
}

but CSS does not care which ancestor is closer, so the code above would still apply red to all paragraphs (and even reversing the order of rules wouldn't help for the nested section).

What you can do in this case is using CSS variables, which are inherited. For example

[dir="ltr"] {
    --p-background: green;
}

[dir="rtl"] {
    --p-background: red;
}

p {
  background: var(--p-background);
}

In this case the variable is applied directly to the element with the specified direction, then the variable value is inherited through the element chain the same way the direction itself does, and affects the styling of the element defined to use the variable value - in this example the <p> element.


问:
How to ensure a minimum recording time in React Native
I am working on a react native app, at this moment I am using EXPO , and I am using expo-av to record the audio.

I would like to know if it is posible to set a minium recording time. I mean, when the user press the recording button, to automatically maintain the recording going for at least 5 seconds.

If this is not posible, maybe, alert the user to record for longer when the audios are too short.

here is the code for recording:

```<code>
async function startRecording() {
    try {
      console.log('Requesting permissions..');
      await Audio.requestPermissionsAsync();
      await Audio.setAudioModeAsync({
        allowsRecordingIOS: true,
        playsInSilentModeIOS: true,
      });
      console.log('Starting recording..');
      const recording = new Audio.Recording();
      await recording.prepareToRecordAsync(Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY);
      await recording.startAsync();
      setRecording(recording);
      console.log('Recording started');
    } catch (err) {
      console.error('Failed to start recording', err);
    }
  }

  async function stopRecording() {
    console.log('Stopping recording..');
    setRecording(undefined);
    await recording.stopAndUnloadAsync();
    const uri = recording.getURI();
    console.log('Recording stopped and stored at', uri);
    setPath(uri);
    uploadAudio(uri);
  }
</code>```

the screen display:

```<code>return (
    <View style={styles.container}>
      <Button
        title={recording ? 'Stop Recording' : 'Start Recording'}
        onPress={recording ? stopRecording : startRecording}
      />
</code>```

答:
We can achieve that by creating a boolean state and use it to either for alert or disabling the stop function for 5 seconds

Method 1

```<code>...
const [disable, setDisable] = useState(false);
...
async function startRecording() {
try {
  ...
  setDisable(true)
  setTimeout(() => {
    setDisable(false)
  }, 5000);
...
...
      <Button
        title={recording ? 'Stop Recording' : 'Start Recording'}
        onPress={recording ? stopRecording : startRecording}
        disabled={disable} // Button will only enabled 5 seconds after recording started
      />
...
</code>```

Method 2

```<code>...
const [disable, setDisable] = useState(false);
...
async function startRecording() {
try {
  ...
  setDisable(true)
  setTimeout(() => {
    setDisable(false)
  }, 5000);
...
...
async function stopRecording() {
  if(disable){
    Alert.alert('Min 5 Sec Required')
    return;
  }//remaining func will only call if disable is false that is after 5 sec
...
...
</code>```

Body:
I am working on a react native app, at this moment I am using EXPO , and I am using expo-av to record the audio.

I would like to know if it is posible to set a minium recording time. I mean, when the user press the recording button, to automatically maintain the recording going for at least 5 seconds.

If this is not posible, maybe, alert the user to record for longer when the audios are too short.

here is the code for recording:

async function startRecording() {
    try {
      console.log('Requesting permissions..');
      await Audio.requestPermissionsAsync();
      await Audio.setAudioModeAsync({
        allowsRecordingIOS: true,
        playsInSilentModeIOS: true,
      });
      console.log('Starting recording..');
      const recording = new Audio.Recording();
      await recording.prepareToRecordAsync(Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY);
      await recording.startAsync();
      setRecording(recording);
      console.log('Recording started');
    } catch (err) {
      console.error('Failed to start recording', err);
    }
  }

  async function stopRecording() {
    console.log('Stopping recording..');
    setRecording(undefined);
    await recording.stopAndUnloadAsync();
    const uri = recording.getURI();
    console.log('Recording stopped and stored at', uri);
    setPath(uri);
    uploadAudio(uri);
  }

the screen display:

return (
    <View style={styles.container}>
      <Button
        title={recording ? 'Stop Recording' : 'Start Recording'}
        onPress={recording ? stopRecording : startRecording}
      />

Body:
We can achieve that by creating a boolean state and use it to either for alert or disabling the stop function for 5 seconds

Method 1

...
const [disable, setDisable] = useState(false);
...
async function startRecording() {
try {
  ...
  setDisable(true)
  setTimeout(() => {
    setDisable(false)
  }, 5000);
...
...
      <Button
        title={recording ? 'Stop Recording' : 'Start Recording'}
        onPress={recording ? stopRecording : startRecording}
        disabled={disable} // Button will only enabled 5 seconds after recording started
      />
...

Method 2

...
const [disable, setDisable] = useState(false);
...
async function startRecording() {
try {
  ...
  setDisable(true)
  setTimeout(() => {
    setDisable(false)
  }, 5000);
...
...
async function stopRecording() {
  if(disable){
    Alert.alert('Min 5 Sec Required')
    return;
  }//remaining func will only call if disable is false that is after 5 sec
...
...


问:
Where does React put the continuous build files when using create-react-app
I'm using create-react-app. When I run npm start (react-scripts start) it continuously builds the changes for me and does it magic. But what is the output folder for that? I know when I build it manually where the files go.

I want to use firebase emulator to serve the current version (the continuous build) of my react all but I don't understand where's the output folder or how to achieve it.

答:
You could try this package https://github.com/Nargonath/cra-build-watch

Install it and add the script to your package.json

```<code>{
  "scripts": {
    "watch": "cra-build-watch"
  }
}
</code>```

and run it

npm run watch

more info here

https://ibraheem.ca/writings/cra-write-to-disk-in-dev/

and if you go to the react repo issue linked in the article you would find more workarounds

Body:
You could try this package https://github.com/Nargonath/cra-build-watch

Install it and add the script to your package.json

{
  "scripts": {
    "watch": "cra-build-watch"
  }
}

and run it

npm run watch

more info here

https://ibraheem.ca/writings/cra-write-to-disk-in-dev/

and if you go to the react repo issue linked in the article you would find more workarounds


问:
Run a GitHub Action Last
I have a bunch of GitHub actions for services that each build a container if something changes in their corresponding directories. Then I have a final GitHub actions that sets up a cloud environment with Terraform and uses the containers created by the other actions to deploy the microservices and API for my project.

Currently I'm running that final action manually after all the other actions complete. However, I was wondering if there is any way to automate this. I realize I can chain actions but I'm unsure how to handle this since any number of actions might be running and might finish in any order.

答:
You can turn each GitHub actions you have into a composite action for more reusability and readability.

But you can just combine all existing actions into 1 workflow - each in separate job if they need different runners.

Then you can set dependencies between those jobs them using needs syntax.
At the end when they all complete, you can have 1 job that has needs for each of those combined and check if they succeeded and based on that execute what you need.

As an example:

```<code>jobs:
  job1:
  job2:
    needs: job1 //if you want to queue jobs then set dependency, if you want to run job1, job2 in parallel, remove this dependency
  final_action:
    needs: [job1, job2]
    if: ${{ needs.job1.result == 'success' && needs.job2.result == 'success' }}
    run: //PUBLISH STUFF
  notify_error:
    needs: [job1, job2]
    if: ${{ always() && !cancelled() && (needs.job1.result != 'success' || needs.job2.result != 'success') }}
    run: //NOTIFY FAILURE
</code>```

Title: Run a GitHub Action Last

Body:
You can turn each GitHub actions you have into a composite action for more reusability and readability.

But you can just combine all existing actions into 1 workflow - each in separate job if they need different runners.

Then you can set dependencies between those jobs them using needs syntax.
At the end when they all complete, you can have 1 job that has needs for each of those combined and check if they succeeded and based on that execute what you need.

As an example:

jobs:
  job1:
  job2:
    needs: job1 //if you want to queue jobs then set dependency, if you want to run job1, job2 in parallel, remove this dependency
  final_action:
    needs: [job1, job2]
    if: ${{ needs.job1.result == 'success' && needs.job2.result == 'success' }}
    run: //PUBLISH STUFF
  notify_error:
    needs: [job1, job2]
    if: ${{ always() && !cancelled() && (needs.job1.result != 'success' || needs.job2.result != 'success') }}
    run: //NOTIFY FAILURE


问:
Easiest way to read from a URL into a string in .NET
Given a URL in a string:

```<code>http://www.example.com/test.xml
</code>```

What's the easiest/most succinct way to download the contents of the file from the server (pointed to by the url) into a string in C#?

The way I'm doing it at the moment is:

```<code>WebRequest request = WebRequest.Create("http://www.example.com/test.xml");
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
</code>```

That's a lot of code that could essentially be one line:

```<code>string responseFromServer = ????.GetStringFromUrl("http://www.example.com/test.xml");
</code>```

Note: I'm not worried about asynchronous calls - this is not production code.

答:
The method in the above answer is now deprecated, the current recommendation is to use HttpClient:</p>
```<code>using (HttpClient client = new HttpClient())
{
    string s = await client.GetStringAsync(url);
}
</code>```

Body:
Given a URL in a string:

http://www.example.com/test.xml

What's the easiest/most succinct way to download the contents of the file from the server (pointed to by the url) into a string in C#?

The way I'm doing it at the moment is:

WebRequest request = WebRequest.Create("http://www.example.com/test.xml");
WebResponse response = request.GetResponse();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();

That's a lot of code that could essentially be one line:

string responseFromServer = ????.GetStringFromUrl("http://www.example.com/test.xml");

Note: I'm not worried about asynchronous calls - this is not production code.

Body:
The method in the above answer is now deprecated, the current recommendation is to use HttpClient:

using (HttpClient client = new HttpClient())
{
    string s = await client.GetStringAsync(url);
}


问:
How to use grepl function to subset rows based on multiple conditions across columns in R
I am trying to subset a dataset using the grepl function.

I want to retain rows where all columns contain '@'

I tried this code but it doesn't work.

```<code>all_nullx <- riv %>% with(riv, riv[ grepl( '@', col1) & grepl( '@', col2) & grepl('@', col3) & grepl('@', left_index) & grepl('@', right_middle) & grepl('@', col4), ])
</code>```

Thanks

答:
one nice option within the tidyverse, specifically dplyr in this case, can be the if_all() function (I will use @andrews data)

```<code>riv <- structure(list(
  a = c("A@r", "B@r", "Rr"),
  b = c("C@r", "D@r", "E@r"),
  c = c("F@r", "G@r", "Hr")
),
class = "data.frame",
row.names = c(NA,-3L))

library(dplyr)

riv %>%
     dplyr::filter(if_all(everything(), ~grepl("@", .x)))

    a   b   c
1 A@r C@r F@r
2 B@r D@r G@r
</code>```

Body:
I am trying to subset a dataset using the grepl function.

I want to retain rows where all columns contain '@'

I tried this code but it doesn't work.

all_nullx <- riv %>% with(riv, riv[ grepl( '@', col1) & grepl( '@', col2) & grepl('@', col3) & grepl('@', left_index) & grepl('@', right_middle) & grepl('@', col4), ])

Thanks

Body:
one nice option within the tidyverse, specifically dplyr in this case, can be the if_all() function (I will use @andrews data)

riv <- structure(list(
  a = c("A@r", "B@r", "Rr"),
  b = c("C@r", "D@r", "E@r"),
  c = c("F@r", "G@r", "Hr")
),
class = "data.frame",
row.names = c(NA,-3L))

library(dplyr)

riv %>%
     dplyr::filter(if_all(everything(), ~grepl("@", .x)))

    a   b   c
1 A@r C@r F@r
2 B@r D@r G@r


问:
What is the best practice for validating parameters in JSP?
I'm implementing a JSP which expects a few parameters which have to be validated before running the jsp.

Suggestion: Validate the parameters inside the JSP using
Taglibraries

Suggestion: Pre-parse the Parameters in a Filter

What do you think?

Edit

Thank you for the good answers, but I was wondering what would be the best practice in case you are offering a service like google chart API where you can't expect that the parameters are checked by a form before they are sent.
example:
https://chart.googleapis.com/chart?cht=&chd=&chs=&...additional_parameters...

答:
None of both are good approaches. Controller/business logic doesn't belong in a JSP (tag). A filter is almost good, but it's not specific enough. This job should be done by a servlet. You're submitting the form to a servlet to postprocess it, right? It sounds like that you're not already doing that, the answer would otherwise have been pretty straightforward.

In our servlets tag wiki page you can find a hello world example of a good approach of using a JSP with a Servlet to postprocess a form submit. Here's an extract of relevance:

<input id="name" name="name" value="${fn:escapeXml(param.name)}">
${messages.name}
```

<p>with</p>

```String name = request.getParameter("name");
if (name == null || name.trim().isEmpty()) {
    messages.put("name", "Please enter name");
}

// ...

request.getRequestDispatcher("/WEB-INF/hello.jsp").forward(request, response);
```

<hr>

<p>Further, there exist MVC frameworks which removes all the boilerplate (duplicated/repeated) servlet code for this kind of use cases, such as JSF, Spring MVC, Wicket, Stripes, Struts2, etc. With for example JSF it look just something like this:</p>

<pre class="lang-xml prettyprint-override"><code><h:inputText id="name" value="#{bean.name}" required="true" requiredMessage="Please enter name" />
<h:message for="name" />
</code>```

That's all. The JSF's FacesServlet controller servlet will validate if it's been filled in and display a (configureable) message at the given location, without any need for custom Java code. You could even move it to the model, JSF has transparent support for JSR303 bean validation as well. E.g.

<h:inputText id="name" value="#{bean.name}" />
<h:message for="name" />
```

<p>with</p>

```@NotNull(message="Please enter name")
private String name;
```

Update as per your edit:

Thank you for the good answers, but I was wondering what would be the best practice in case you are offering a service like google chart API where you can't expect that the parameters are checked by a form before they are sent. example: https://chart.googleapis.com/chart?cht=&chd=&chs=&...additional_parameters...

Just use a servlet the same way. The only difference is that you've to implement the job in doGet() instead of doPost() and if necessary return HTTP 400 on an error :) Once again, check our servlets tag wiki page to understand their purpose better. Or to go a step further, use a webservice framework instead, such as JAX-WS or JAX-RS which do this job transparently like a MVC framework does for HTML pages.

Body:
None of both are good approaches. Controller/business logic doesn't belong in a JSP (tag). A filter is almost good, but it's not specific enough. This job should be done by a servlet. You're submitting the form to a servlet to postprocess it, right? It sounds like that you're not already doing that, the answer would otherwise have been pretty straightforward.

In our servlets tag wiki page you can find a hello world example of a good approach of using a JSP with a Servlet to postprocess a form submit. Here's an extract of relevance:

<input id="name" name="name" value="${fn:escapeXml(param.name)}">
<span class="error">${messages.name}</span>

with

String name = request.getParameter("name");
if (name == null || name.trim().isEmpty()) {
    messages.put("name", "Please enter name");
}

// ...

request.getRequestDispatcher("/WEB-INF/hello.jsp").forward(request, response);

Further, there exist MVC frameworks which removes all the boilerplate (duplicated/repeated) servlet code for this kind of use cases, such as JSF, Spring MVC, Wicket, Stripes, Struts2, etc. With for example JSF it look just something like this:

<h:inputText id="name" value="#{bean.name}" required="true" requiredMessage="Please enter name" />
<h:message for="name" />

That's all. The JSF's FacesServlet controller servlet will validate if it's been filled in and display a (configureable) message at the given location, without any need for custom Java code. You could even move it to the model, JSF has transparent support for JSR303 bean validation as well. E.g.

<h:inputText id="name" value="#{bean.name}" />
<h:message for="name" />

with

@NotNull(message="Please enter name")
private String name;

Update as per your edit:

Thank you for the good answers, but I was wondering what would be the best practice in case you are offering a service like google chart API where you can't expect that the parameters are checked by a form before they are sent. example: https://chart.googleapis.com/chart?cht=&chd=&chs=&...additional_parameters...

Just use a servlet the same way. The only difference is that you've to implement the job in doGet() instead of doPost() and if necessary return HTTP 400 on an error :) Once again, check our servlets tag wiki page to understand their purpose better. Or to go a step further, use a webservice framework instead, such as JAX-WS or JAX-RS which do this job transparently like a MVC framework does for HTML pages.


问:
Django Rest Framework JWT Unit Test
I am using DRF with the JWT package for authentication. Now, I'm trying to write a unit test that authenticates itself with a JWT token. No matter how I try it, I can't get the test API client to authenticate itself via JWT. If I do the same with an API client (in my case, Postman), everything works.

This is the test case:

```<code>from django.urls import reverse
from rest_framework.test import APITestCase
from rest_framework_jwt.settings import api_settings

from backend.factories import member_factory

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

class MemberTests(APITestCase):
    def test_get_member(self):
        member = member_factory()

        payload = jwt_payload_handler(member.user)
        token = jwt_encode_handler(payload)

        self.client.credentials(Authorization='JWT {0}'.format(token))
        response = self.client.get(reverse('member-detail', kwargs={'pk': member.pk}))
        assert response.status_code == 200
</code>```

But I always get a 401 Authentication credentials were not provided.

In response.request I see the token is there, it's just not being applied I guess.

If I rewrite the test to use rest_framework.test.RequestsClient and actually send it to the live_server URL, it works.

Any help on this?

P.S.: I am aware of force_authenticate() and login, but I would like my unit tests to access the API the same as the API client will in production.

答:
I'm using DRF and simple-jwt and I had to use Bearer instead of JWT in the http auth header: HTTP_AUTHORIZATION=f'Bearer {token}'

Full code:

```<code>def setUp(self):
    username = "tim@me.com"
    password = "strongP@assword!"
    self.user = User.objects.create_user(username, username, password)

    jwt_fetch_data = {
        'username':username,
        'password':password
    }

    url = reverse('token_obtain_pair')
    response = self.client.post(url, jwt_fetch_data, format='json')
    token = response.data['access']
    self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}')

def test_post(self):
    response = self.client.get('/some-url/',
                               data={'format': 'json'}
                               )
    self.assertEqual(response.status_code, status.HTTP_200_OK)
</code>```

Title: Django Rest Framework JWT Unit Test

Body:
I am using DRF with the JWT package for authentication. Now, I'm trying to write a unit test that authenticates itself with a JWT token. No matter how I try it, I can't get the test API client to authenticate itself via JWT. If I do the same with an API client (in my case, Postman), everything works.

This is the test case:

from django.urls import reverse
from rest_framework.test import APITestCase
from rest_framework_jwt.settings import api_settings

from backend.factories import member_factory

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

class MemberTests(APITestCase):
    def test_get_member(self):
        member = member_factory()

        payload = jwt_payload_handler(member.user)
        token = jwt_encode_handler(payload)

        self.client.credentials(Authorization='JWT {0}'.format(token))
        response = self.client.get(reverse('member-detail', kwargs={'pk': member.pk}))
        assert response.status_code == 200

But I always get a 401 Authentication credentials were not provided.

In response.request I see the token is there, it's just not being applied I guess.

If I rewrite the test to use rest_framework.test.RequestsClient and actually send it to the live_server URL, it works.

Any help on this?

P.S.: I am aware of force_authenticate() and login, but I would like my unit tests to access the API the same as the API client will in production.

Body:
I'm using DRF and simple-jwt and I had to use Bearer instead of JWT in the http auth header: HTTP_AUTHORIZATION=f'Bearer {token}'

Full code:

def setUp(self):
    username = "tim@me.com"
    password = "strongP@assword!"
    self.user = User.objects.create_user(username, username, password)

    jwt_fetch_data = {
        'username':username,
        'password':password
    }

    url = reverse('token_obtain_pair')
    response = self.client.post(url, jwt_fetch_data, format='json')
    token = response.data['access']
    self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}')

def test_post(self):
    response = self.client.get('/some-url/',
                               data={'format': 'json'}
                               )
    self.assertEqual(response.status_code, status.HTTP_200_OK)


问:
getting last three lines of python output assigned to 3 variables in bash
I have a python script that outputs a long list of files.

The script is ran from bash, and at the end i need to assign the last three files each to a specific variables.

I'm able to capture the output into a bash Variable, but then when I try to pipe it to 'tail' command, it seems to be one line only?

I've tried tips i've seen around, but can't seem to figure out how to work on an individual line basis with output.

it seems that any python output will be interpreted as one line?

echo "TESTING sample multi-line python output"
OUTPUT=$(python -c "for i in range(5): print(i)")

# check output
echo "$OUTPUT"

variable3=$(echo $OUTPUT | tail -1)

echo "VARIABLE CAPTURED"
echo $variable3
```
<p>here is what i get:
<img src="https://i.stack.imgur.com/giove.png" alt="enter image description here" /></p>
<p>But I actually need to capture variable1 as 3rd line from end, variable2 as 2nd line from end and variable3 as first line from the end</p>
<p>So that in the above example at the end the desired result is:</p>
```variable1 = 2
variable2 = 3
variable3 = 4
```

in order to pass these variables to next stage of the script...

答:
One option could be to tail -3 and read those last lines into an array:

#!/bin/bash

echo "TESTING sample multi-line python output"
readarray -t arr <<< "$(python -c "for i in range(5): print(i)" | tail -3)"

echo "VARIABLE CAPTURED"
echo "${arr[0]}"
echo "${arr[1]}"
echo "${arr[2]}"

echo "VIA LOOP"
for var in "${arr[@]}"; do
    echo "$var"
done
```
<p>Output</p>
```TESTING sample multi-line python output
VARIABLE CAPTURED
2
3
4
VIA LOOP
2
3
4
```
<p>If you really need the full output saved before extracting the three last lines:</p>
```OUTPUT="$(python -c "for i in range(5): print(i)")"
readarray -t arr <<< "$(echo "$OUTPUT" | tail -3)"
```

Body:
I have a python script that outputs a long list of files.

The script is ran from bash, and at the end i need to assign the last three files each to a specific variables.

I'm able to capture the output into a bash Variable, but then when I try to pipe it to 'tail' command, it seems to be one line only?

I've tried tips i've seen around, but can't seem to figure out how to work on an individual line basis with output.

it seems that any python output will be interpreted as one line?

echo "TESTING sample multi-line python output"
OUTPUT=$(python -c "for i in range(5): print(i)")

# check output
echo "$OUTPUT"

variable3=$(echo $OUTPUT | tail -1)

echo "VARIABLE CAPTURED"
echo $variable3

here is what i get:

But I actually need to capture variable1 as 3rd line from end, variable2 as 2nd line from end and variable3 as first line from the end

So that in the above example at the end the desired result is:

variable1 = 2
variable2 = 3
variable3 = 4

in order to pass these variables to next stage of the script...

Body:
One option could be to tail -3 and read those last lines into an array:

#!/bin/bash

echo "TESTING sample multi-line python output"
readarray -t arr <<< "$(python -c "for i in range(5): print(i)" | tail -3)"

echo "VARIABLE CAPTURED"
echo "${arr[0]}"
echo "${arr[1]}"
echo "${arr[2]}"

echo "VIA LOOP"
for var in "${arr[@]}"; do
    echo "$var"
done

Output

TESTING sample multi-line python output
VARIABLE CAPTURED
2
3
4
VIA LOOP
2
3
4

If you really need the full output saved before extracting the three last lines:

OUTPUT="$(python -c "for i in range(5): print(i)")"
readarray -t arr <<< "$(echo "$OUTPUT" | tail -3)"


问:
How do I move/copy a symlink to a different folder as a symlink under Solaris?
It is an odd behaviour seen only on Solaris that when I try to copy a symbolic link with the "cp -R -P" command to some other folder with a different name, it copies the entire directory/file it's pointing to.

For example:

```<code>link -> dir

cp -R -P link folder/new_link
</code>```

答: You might consider copying via tar, like tar -cf - srcdir|(cd somedir;tar -xf -)</p>

OwnerDisplayName: kadeshpa

ContentLicense: CC BY-SA 2.5

Body:
It is an odd behaviour seen only on Solaris that when I try to copy a symbolic link with the "cp -R -P" command to some other folder with a different name, it copies the entire directory/file it's pointing to.

For example:

link -> dir

cp -R -P link folder/new_link

LastEditorDisplayName: Eddie

OwnerDisplayName: Brian Mitchell


问:
using pandas two perform Cross tab between one column and two others that share the same enumerated values
I have table with

```<code>|Majors|First Minor|Second Minor|
|Philosophy|English|Null|
|Math|Philosophy|English|
|English|Theology|Political Science
|Philosophy|Theology|English|
</code>```

The possible values of the "First Minor" and "Second Minor" columns are the same (English, Philosophy, Math, etc)

I want to see the correlation between "Major" and the "Minors" belonging to those majors. I don't care if the minor is a first or second minor. So based on the above sample I want an output that looks something like:

```<code>|Major|Philosophy|Math|English
First Minor||||
Philosophy|0|1|0|
|Math|0|0|0|
|English|2|1|0|
Political Science|0|0|1|
Theology|1|0|1|
Null|1|0|0
</code>```

The following code generates the desired result for just the "First Minor" or the "Second Minor":

ct = pd.crosstab(newdf.MajorInterMinor, newdf["First Minor"])

But I want to get the results for both columns ("First Minor" and "Second Minor") and I can't figure out how to get the combined result.

Any help/advice is much appreciated!

答:
pd.melt to collapse FirstMinor, SecondMinor into one column and make new df

```<code> df2 = pd.melt(df,id_vars=['Majors'], value_vars=['FirstMinor','SecondMinor'],var_name='myVarname', value_name='FirstMinor_SecondMinor')
</code>```

Slice new df to  get_dummies on Majors. Join this back to the df. Groupby and sum

```<code>pd.DataFrame(df2.loc[:,'FirstMinor_SecondMinor']).join(pd.get_dummies(df2.loc[:,'Majors'])).groupby('FirstMinor_SecondMinor').agg(sum)

                          English  Math  Philosophy
FirstMinor_SecondMinor
English                       0     1           2
Null                          0     0           1
Philosophy                    0     1           0
PoliticalScience              1     0           0
Theology                      1     0           1
</code>```

Body:
I have table with

|Majors|First Minor|Second Minor|
|Philosophy|English|Null|
|Math|Philosophy|English|
|English|Theology|Political Science
|Philosophy|Theology|English|

The possible values of the "First Minor" and "Second Minor" columns are the same (English, Philosophy, Math, etc)

I want to see the correlation between "Major" and the "Minors" belonging to those majors. I don't care if the minor is a first or second minor. So based on the above sample I want an output that looks something like:

|Major|Philosophy|Math|English
First Minor||||
Philosophy|0|1|0|
|Math|0|0|0|
|English|2|1|0|
Political Science|0|0|1|
Theology|1|0|1|
Null|1|0|0

The following code generates the desired result for just the "First Minor" or the "Second Minor":

ct = pd.crosstab(newdf.MajorInterMinor, newdf["First Minor"])

But I want to get the results for both columns ("First Minor" and "Second Minor") and I can't figure out how to get the combined result.

Any help/advice is much appreciated!

Body:
pd.melt to collapse FirstMinor, SecondMinor into one column and make new df

 df2 = pd.melt(df,id_vars=['Majors'], value_vars=['FirstMinor','SecondMinor'],var_name='myVarname', value_name='FirstMinor_SecondMinor')

Slice new df to  get_dummies on Majors. Join this back to the df. Groupby and sum

pd.DataFrame(df2.loc[:,'FirstMinor_SecondMinor']).join(pd.get_dummies(df2.loc[:,'Majors'])).groupby('FirstMinor_SecondMinor').agg(sum)

                          English  Math  Philosophy
FirstMinor_SecondMinor
English                       0     1           2
Null                          0     0           1
Philosophy                    0     1           0
PoliticalScience              1     0           0
Theology                      1     0           1


问:
Firebase ID token has invalid signature even on jwt
Firebase ID token has invalid signature

Hi all, I'm somehow new to NodeJS and I've only used Google Firebase a few times.
Now, I'm trying to verify an idToken generated using getIdToken() method whenever a user signs up or signs in. The token generation works fine but if I try to use this token to authorize a user admin.auth().verifyIdToken(idToken) on another route, I get this error Firebase ID token has invalid signature on Postman. I tried to verify the token on jwt.io as well, it gave error Invalid Signature.

I tried switching to different algorithms, some eventually made the token valid on jwt, but there is usually a VERIFY SIGNATURE box by the bottom-right which I don't really know what to fill there. Well, I've tried copying different newly generated valid tokens by jwt after changing algorithm, but I still get Firebase ID token has invalid signature from Postman.

Does anyone know what the problem may be? Please help.

答:
To verify the token manually on jwt.io, you need to grab one of the public keys from google: https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com

To choose the correct key, find the one that corresponds to your kid from jwt.io.

Paste in the correct corresponding value and now your token should verify correctly (be sure to clear out any \n characters):

For easier programmatic verification, the "JWK URI" is https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com

Source: https://firebase.google.com/docs/auth/admin/verify-id-tokens


问:
IBM MQ for Apple Silicon
Is there a solution to make this docker image https://hub.docker.com/r/ibmcom/mq run on Apple M1 chips? For Intel chips, I was able to run this image by:

```<code>docker run -e LICENSE=accept -e MQ_QMGR_NAME=QM1 -p 1414:1414 -p 9443:9443 ibmcom/mq
</code>```

Is there a custom build or an official IBM plan to create an Apple M1 compatible version of this image?

答: This has already been requested from IBM, you can view and vote on it here.</p>

Title: IBM MQ for Apple Silicon

Body:
Is there a solution to make this docker image https://hub.docker.com/r/ibmcom/mq run on Apple M1 chips? For Intel chips, I was able to run this image by:

docker run -e LICENSE=accept -e MQ_QMGR_NAME=QM1 -p 1414:1414 -p 9443:9443 ibmcom/mq

Is there a custom build or an official IBM plan to create an Apple M1 compatible version of this image?


问:
Web Scraping with Node JS, Puppeteer and Cheerio
I was trying to do some Web scraping. My goal is to find get find all <H></H> tags and text that are directly following them. Example Would be:

```<code><div>
 <h2>heading 1</h2>
 <p>text 1</p>
 <h3>heading 2></h3>
 <p>text 2</p>
</div>
</code>```

Result for this would be:

```<code>[
 {
        "title": "heading 1",
        "tag": "h2",
        "text": "text 1"
    },
    {
        "title": "heading 2",
        "tag": "h3",
        "text": "text 2"
    },
]
</code>```

My Solution for this :

```<code>let headings = $('h1, h2, h3, h4, h5, h6');
let result = {}
    for (let i = 0; i < headings.length; i++) {
        let newObj = {};
        //preparing title from heading
        newObj.title = this.#cleanText($(headings[i]).text());

        //tag name of the heading
         newObj.tag = $(headings[i])[0].name;
        if($(headings[i]).nextUntil($(headings[i + 1])).find('img')){
          numberOfImage++;
        }
       $(headings[i]).nextUntil($(headings[i + 1])).find('img').remove()
       $(headings[i]).next().find($(headings[i + 1])) && "got new heading"
        //getting html markup as string between current heading and next one
       if (i === headings.length - 1){
           newObj.text = $(headings[i]).nextAll().toString();
       }else{
           newObj.text = $(headings[i]).nextUntil($(headings[i + 1])).toString();
       }
       result.content.push(newObj)
   }
</code>```

As you can see I'm getting it alright if all <h></h> tags are siblings but I'm not being able to handle any nested headings like:

```<code><div>
 <div><h3>heading 1></h3>
 <p>text 1</p>
  <h2>heading 2</h2>
 </div>
 <p>text 2</p>
 <h3>heading 3></h3>
 <p>text 3</p>
<div>
 <h3>heading 2></h3>
 <p>text 2</p>
</div>
</div>
</code>```

I need Result to be like this:

```<code>[
 {
        "title": "heading 1",
        "tag": "h2",
        "text": "text 1"
    },
    {
        "title": "heading 2",
        "tag": "h3",
        "text": "text 2"
    },

    {
        "title": "heading 3",
        "tag": "h3",
        "text": "text 3"
    },
]
</code>```

It would be really helpful if anyone can give me a solution for this

答:
It should look something like:

```<code>$('h1, h2, h3, h4, h5, h6').get().map(h => {
  return {
    title: $(h).text(),
    text: $(h).find('~ p').first().text()
  }
})
</code>```

I'm using ~ which is following sibling selector (newer versions of cheerio only)

Body:
I was trying to do some Web scraping. My goal is to find get find all <H></H> tags and text that are directly following them. Example Would be:

heading 1

text 1

heading 2>

text 2

Result for this would be:

[
 {
        "title": "heading 1",
        "tag": "h2",
        "text": "text 1"
    },
    {
        "title": "heading 2",
        "tag": "h3",
        "text": "text 2"
    },
]

My Solution for this :

let headings = $('h1, h2, h3, h4, h5, h6');
let result = {}
    for (let i = 0; i < headings.length; i++) {
        let newObj = {};
        //preparing title from heading
        newObj.title = this.#cleanText($(headings[i]).text());

        //tag name of the heading
         newObj.tag = $(headings[i])[0].name;
        if($(headings[i]).nextUntil($(headings[i + 1])).find('img')){
          numberOfImage++;
        }
       $(headings[i]).nextUntil($(headings[i + 1])).find('img').remove()
       $(headings[i]).next().find($(headings[i + 1])) && "got new heading"
        //getting html markup as string between current heading and next one
       if (i === headings.length - 1){
           newObj.text = $(headings[i]).nextAll().toString();
       }else{
           newObj.text = $(headings[i]).nextUntil($(headings[i + 1])).toString();
       }
       result.content.push(newObj)
   }

As you can see I'm getting it alright if all <h></h> tags are siblings but I'm not being able to handle any nested headings like:

heading 1>

text 1

heading 2

text 2

heading 3>

text 3

heading 2>

text 2

I need Result to be like this:

[
 {
        "title": "heading 1",
        "tag": "h2",
        "text": "text 1"
    },
    {
        "title": "heading 2",
        "tag": "h3",
        "text": "text 2"
    },

    {
        "title": "heading 3",
        "tag": "h3",
        "text": "text 3"
    },
]

It would be really helpful if anyone can give me a solution for this

Body:
It should look something like:

$('h1, h2, h3, h4, h5, h6').get().map(h => {
  return {
    title: $(h).text(),
    text: $(h).find('~ p').first().text()
  }
})

I'm using ~ which is following sibling selector (newer versions of cheerio only)


问:
Terraform error refreshing state access denied
I'm using gitbucket for both my repository and for pipelines.
I have a terraform config file with a remote state configured which runs fine on my local machine however it fails when running in gitbucket. I keep getting access denied error.
Here's the main.tf:

```<code>terraform {
backend "s3" {
    bucket = "zego-terraform-test"
    key    = "test/terraform.tfstate"
    region = "eu-west-1"
  }
}

data "terraform_remote_state" "remote_state" {
  backend = "s3"

  config {
    bucket = "zego-terraform-test"
    key    = "test/terraform.tfstate"
    region = "eu-west-1"
  }
}

variable "region" {}

provider "aws" {
  region     = "${var.region}"
  access_key = {}
  secret_key = {}
  token      = {}
}

module "vpc" {
  source = "./modules/vpc"
}
</code>```

Here's my gitbucket-pipelines.yml:

```<code>image: python:3.5.1
pipelines:
  default:
    - step:
        caches:
          - pip
        script: # Modify the commands below to build your repository.
          - apt-get update
          - apt-get install unzip
          - wget https://releases.hashicorp.com/terraform/0.11.7/terraform_0.11.7_linux_amd64.zip
          - unzip terraform_0.11.7_linux_amd64.zip
          - rm terraform_0.11.7_linux_amd64.zip
          - export PATH="$PATH:${BITBUCKET_CLONE_DIR}"
          - terraform init
            -backend-config "access_key=$AWS_ACCESS_KEY"
            -backend-config "secret_key=$AWS_SECRET_KEY"
            -backend-config "token=$TOKEN"
</code>```

When I run the .tf file in this pipeline I get this error:

```<code>Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
Error refreshing state: AccessDenied: Access Denied
    status code: 403
</code>```

When I remove remote state config it runs fine.
Why am I getting the access denied error even though I'm using the same creds on my local machine and in gitbucket environment?

答:
In case a solution has not been found for this issue, you can use either "profile=" or "role_arn=" in the config section of your terraform_remote_state stanza.  The same is true for the AWS Provider and the backend configuration.

I chased this issue all day today not realizing that role_arn was available for terraform_backend_state data source.

Body:
I'm using gitbucket for both my repository and for pipelines.
I have a terraform config file with a remote state configured which runs fine on my local machine however it fails when running in gitbucket. I keep getting access denied error.
Here's the main.tf:

terraform {
backend "s3" {
    bucket = "zego-terraform-test"
    key    = "test/terraform.tfstate"
    region = "eu-west-1"
  }
}

data "terraform_remote_state" "remote_state" {
  backend = "s3"

  config {
    bucket = "zego-terraform-test"
    key    = "test/terraform.tfstate"
    region = "eu-west-1"
  }
}

variable "region" {}

provider "aws" {
  region     = "${var.region}"
  access_key = {}
  secret_key = {}
  token      = {}
}

module "vpc" {
  source = "./modules/vpc"
}

Here's my gitbucket-pipelines.yml:

image: python:3.5.1
pipelines:
  default:
    - step:
        caches:
          - pip
        script: # Modify the commands below to build your repository.
          - apt-get update
          - apt-get install unzip
          - wget https://releases.hashicorp.com/terraform/0.11.7/terraform_0.11.7_linux_amd64.zip
          - unzip terraform_0.11.7_linux_amd64.zip
          - rm terraform_0.11.7_linux_amd64.zip
          - export PATH="$PATH:${BITBUCKET_CLONE_DIR}"
          - terraform init
            -backend-config "access_key=$AWS_ACCESS_KEY"
            -backend-config "secret_key=$AWS_SECRET_KEY"
            -backend-config "token=$TOKEN"

When I run the .tf file in this pipeline I get this error:

Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.
Error refreshing state: AccessDenied: Access Denied
    status code: 403

When I remove remote state config it runs fine.
Why am I getting the access denied error even though I'm using the same creds on my local machine and in gitbucket environment?


问:
Best way to uniquely identify a dictionary in Python?
I have a service in Python which processes some dictionaries. I wish to  find and store a unique identifier for one of these dictionaries (when a condition is met).

Then a different service can process a list of dictionaries.  This list contains the unique dictionary. If the unique identifier is found and verified, then the dictionary will be processed accordingly.

What is the best way to do achieve this. I thought maybe adding a new field to the dictionary something like

```<code>my_dict["unique_dict"] = True
</code>```

but is there a better way?

答:
I found another way. One could to hash the dictionary like this for example:

```<code>import hashlib
import json

hasher = hashlib.sha1()
unhashed = {
    "msg": "blablabla",
    "measurements": [23, 567, 90],
    "calculation": 70.34,
}
encoded = json.dumps(unhashed, sort_keys=True).encode()
hasher.update(encoded)
hashed = hasher.hexdigest()
print(hashed)
</code>```

and then store that hashed number in Redis, for example, or in a database or in cache or something.

Then in the second service the list of dictionaries will be hashed one by one. If one is found to have a hashed value that matches the stored value, it will then be processed accordingly.

Body:
I have a service in Python which processes some dictionaries. I wish to  find and store a unique identifier for one of these dictionaries (when a condition is met).

Then a different service can process a list of dictionaries.  This list contains the unique dictionary. If the unique identifier is found and verified, then the dictionary will be processed accordingly.

What is the best way to do achieve this. I thought maybe adding a new field to the dictionary something like

my_dict["unique_dict"] = True

but is there a better way?

Body:
I found another way. One could to hash the dictionary like this for example:

import hashlib
import json

hasher = hashlib.sha1()
unhashed = {
    "msg": "blablabla",
    "measurements": [23, 567, 90],
    "calculation": 70.34,
}
encoded = json.dumps(unhashed, sort_keys=True).encode()
hasher.update(encoded)
hashed = hasher.hexdigest()
print(hashed)

and then store that hashed number in Redis, for example, or in a database or in cache or something.

Then in the second service the list of dictionaries will be hashed one by one. If one is found to have a hashed value that matches the stored value, it will then be processed accordingly.


问:
How can I replace a tab with four spaces in JTextArea?
I'm using a JTextArea in a JFrame. I would like the tab key to insert four spaces instead of a tab.

The method setTabSize does not work, as it puts a tab ('\t') in the contents of the text area.

How can I have JTextArea insert four spaces instead of a tab whenever I press the tab key? That way the getText() method will return indentations of four spaces for every tab.

答:
This is one of those “I wonder if…” moments.

Personally, I’d try a tackle the problem more directly, at the source.  This means “trapping” the Tab event some how and “replacing” it’s functionality.

So, I started by modifying http://www.java2s.com/Tutorial/Java/0260__Swing-Event/ListingtheKeyBindingsinaComponent.htm, which could list the key bindings for component, for this, I found that the JTextArea was using insert-tab as the action map key.

I then created my own Action designed to insert spaces at the current caret position, for example…

```<code>public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
//            insert-tab
            JTextArea ta = new JTextArea(10, 20);
            add(new JScrollPane(ta));

            ActionMap am = ta.getActionMap();
            am.put("insert-tab", new SpacesTabAction());
        }

        public class SpacesTabAction extends AbstractAction {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (!(e.getSource() instanceof JTextArea)) {
                    return;
                }
                JTextArea textArea = (JTextArea) e.getSource();
                int caretPosition = textArea.getCaretPosition();
                Document document = textArea.getDocument();
                try {
                    document.insertString(caretPosition, "  ", null);
                } catch (BadLocationException ex) {
                    ex.printStackTrace();
                }
            }

        }

    }
}
</code>```

Admittable limitations

This will not cover pasting the text into the component, which would otherwise be covered by a DocumentFilter, but, I like to think about scenarios where a DocumentFilter might not be usable (such as having one already installed)

More investigations

The method setTabSize does not work, as it puts a tab ('\t') in the contents of the text area.

Is this one of those “spaces vs tabs” flame wars :P

I did some fiddling and discovered that, most of the inconsistencies with setTabSize came about from not using a fixed width font, for example…

```<code>import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new BorderLayout());
            Font font = Font.decode("Courier New").deriveFont(12);
            JTextArea ta = new JTextArea(10, 40);
            ta.setFont(font);
            ta.setText("---|----|----|----|----|----|----|----|\n\tHello");
            ta.setTabSize(0);
            add(new JScrollPane(ta));

            DefaultComboBoxModel<Integer> model = new DefaultComboBoxModel<>(new Integer[] {0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24});
            JComboBox<Integer> tabSizes = new JComboBox<>(model);
            add(tabSizes, BorderLayout.NORTH);
            tabSizes.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Integer tabSize = (Integer)tabSizes.getSelectedItem();
                    ta.setTabSize(tabSize);
                }
            });
        }

    }
}
</code>```

When I set the font to “Courier New”, I was able to get a consistent indentation which was in align with the set tab size

I'm obviously missing something...

The tab is four spaces. In this "111\t" string, the tab is expands to 1 space; "22\t" — to 2 spaces; "3\t" — to 3 spaces; finally, "\t" expands to four spaces.

Yes, isn't this the expected behaviour?!

JTextArea, tabSize of 4, mono spaced font

Sublime text editor, tabSize of 4, mono spaced font

```<code>import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.util.StringJoiner;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            StringJoiner textJoiner = new StringJoiner("\n");
            for (int row = 0; row < 10; row++) {
                StringJoiner rowJoiner = new StringJoiner("\t");
                for (int col = 0; col < 10; col++) {
                    rowJoiner.add(Integer.toString(col).repeat(row));
                }
                textJoiner.add(rowJoiner.toString());
            }

            setLayout(new BorderLayout());
            JTextArea ta = new JTextArea(10, 40);
            ta.setFont(new Font("Monospaced", Font.PLAIN, 13));
            ta.setText(textJoiner.toString());
            add(new JScrollPane(ta));
        }

        protected String replicate(char value, int times) {
            return new String(new char[times]).replace('\0', value);
        }
    }

}
</code>```

I think you're thinking of "tab stops", rather than "tab size", for example, in which case, even the DocumentFilter won't do what you're expecting.

I assume the use of monospace font is implied in the question

Don't "assume" we know anything.  In my experimentation, the font was NOT monospaced. This is where providing "expected" and "actual" results and a minimal reproducible example, as it removes the ambiguity and doesn't waste everybody's time (especially yours)

It is how it works in any text editor.

I'm obviously using different text editors

Body:
This is one of those “I wonder if…” moments.

Personally, I’d try a tackle the problem more directly, at the source.  This means “trapping” the Tab event some how and “replacing” it’s functionality.

So, I started by modifying http://www.java2s.com/Tutorial/Java/0260__Swing-Event/ListingtheKeyBindingsinaComponent.htm, which could list the key bindings for component, for this, I found that the JTextArea was using insert-tab as the action map key.

I then created my own Action designed to insert spaces at the current caret position, for example…

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
//            insert-tab
            JTextArea ta = new JTextArea(10, 20);
            add(new JScrollPane(ta));

            ActionMap am = ta.getActionMap();
            am.put("insert-tab", new SpacesTabAction());
        }

        public class SpacesTabAction extends AbstractAction {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (!(e.getSource() instanceof JTextArea)) {
                    return;
                }
                JTextArea textArea = (JTextArea) e.getSource();
                int caretPosition = textArea.getCaretPosition();
                Document document = textArea.getDocument();
                try {
                    document.insertString(caretPosition, "  ", null);
                } catch (BadLocationException ex) {
                    ex.printStackTrace();
                }
            }

        }

    }
}

Admittable limitations

This will not cover pasting the text into the component, which would otherwise be covered by a DocumentFilter, but, I like to think about scenarios where a DocumentFilter might not be usable (such as having one already installed)

More investigations

The method setTabSize does not work, as it puts a tab ('\t') in the contents of the text area.

Is this one of those “spaces vs tabs” flame wars :P

I did some fiddling and discovered that, most of the inconsistencies with setTabSize came about from not using a fixed width font, for example…

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new BorderLayout());
            Font font = Font.decode("Courier New").deriveFont(12);
            JTextArea ta = new JTextArea(10, 40);
            ta.setFont(font);
            ta.setText("---|----|----|----|----|----|----|----|\n\tHello");
            ta.setTabSize(0);
            add(new JScrollPane(ta));

            DefaultComboBoxModel<Integer> model = new DefaultComboBoxModel<>(new Integer[] {0, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24});
            JComboBox<Integer> tabSizes = new JComboBox<>(model);
            add(tabSizes, BorderLayout.NORTH);
            tabSizes.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Integer tabSize = (Integer)tabSizes.getSelectedItem();
                    ta.setTabSize(tabSize);
                }
            });
        }

    }
}

When I set the font to “Courier New”, I was able to get a consistent indentation which was in align with the set tab size

I'm obviously missing something...

The tab is four spaces. In this "111\t" string, the tab is expands to 1 space; "22\t" — to 2 spaces; "3\t" — to 3 spaces; finally, "\t" expands to four spaces.

Yes, isn't this the expected behaviour?!

JTextArea, tabSize of 4, mono spaced font

Sublime text editor, tabSize of 4, mono spaced font

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Font;
import java.util.StringJoiner;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            StringJoiner textJoiner = new StringJoiner("\n");
            for (int row = 0; row < 10; row++) {
                StringJoiner rowJoiner = new StringJoiner("\t");
                for (int col = 0; col < 10; col++) {
                    rowJoiner.add(Integer.toString(col).repeat(row));
                }
                textJoiner.add(rowJoiner.toString());
            }

            setLayout(new BorderLayout());
            JTextArea ta = new JTextArea(10, 40);
            ta.setFont(new Font("Monospaced", Font.PLAIN, 13));
            ta.setText(textJoiner.toString());
            add(new JScrollPane(ta));
        }

        protected String replicate(char value, int times) {
            return new String(new char[times]).replace('\0', value);
        }
    }

}

I think you're thinking of "tab stops", rather than "tab size", for example, in which case, even the DocumentFilter won't do what you're expecting.

I assume the use of monospace font is implied in the question

Don't "assume" we know anything.  In my experimentation, the font was NOT monospaced. This is where providing "expected" and "actual" results and a minimal reproducible example, as it removes the ambiguity and doesn't waste everybody's time (especially yours)

It is how it works in any text editor.

I'm obviously using different text editors


问:
Ionic and MSAL Authentication
I have an Ionic app that needs to authenticate in Azure, so I installed MSAL following this tutorial:
https://learn.microsoft.com/en-us/graph/tutorials/angular

It works like a charm with "ionic serve" but when I run it in the device, it crashes when I try to sign in Azure. I think it is because the popup window MSAL shows for login is not allowed in Ionic.

So my first attempt was to change the loginPopup() call for a loginRedirect(). So I removed this code:

```<code>async signIn(): Promise<void> {
  const result = await this.msalService
    .loginPopup(OAuthSettings)
    .toPromise()
    .catch((reason) => {
      this.alertsService.addError('Login failed',
        JSON.stringify(reason, null, 2));
    });

  if (result) {
    this.msalService.instance.setActiveAccount(result.account);
    this.authenticated = true;
    this.user = await this.getUser();
  }
}
</code>```

And I added this new one (based on https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/errors.md):

```<code>async signIn(): Promise<void> {
  await this.msalService.instance.handleRedirectPromise();

  const accounts = this.msalService.instance.getAllAccounts();
  if (accounts.length === 0) {
    // No user signed in
    this.msalService.instance.loginRedirect();
  }
}
</code>```

But this way, the user information is not saved, because I have not a "result" to handle or to call to setActiveAccount(result). It did not work even in "ionic serve", so I discarded this approach.

The second approach, after seaching for a posible solution for two days, was to show the popup in a InAppBrowser (https://ionicframework.com/docs/native/in-app-browser), so I changed the code to:

```<code>async signIn(): Promise<void> {
  const browser = this.iab.create('https://www.microsoft.com/');
  browser.executeScript({ code: "\
    const result = await this.msalService\
      .loginPopup(OAuthSettings)\
      .toPromise()\
      .catch((reason) => {\
        this.alertsService.addError('Login failed',\
          JSON.stringify(reason, null, 2));\
      });\
    if (result) {\
      this.msalService.instance.setActiveAccount(result.account);\
      this.authenticated = true;\
      this.user = await this.getUser();\
    }"
  });
}
</code>```

But it just open a new window and do nothing more, it does not execute loginPopup(), so I also discard this second approach.

Anyone knows how to avoid the popup problem in Ionic?

Thank you

答:
I can confirm Paolo Cuscelas solution is working.
We were using ionic & capacitor with the cordova InAppBrowser, since capacitors browser does not support listening to url changes, which is needed in order to "proxy" the msal route params.

Also, make sure to register the redirection uri in your azure portal.

The rest of the application is more or less setup based on the provided examples from microsoft for msal/angular package.

CustomNavigationClient for Capacitor

Make sure you setup the msal interaction type to "InteractionType.Redirect"

The constructor requires you to pass in a InAppBrowser reference.

Also azure returns the data in the url through #code instead of #state, so make sure to split the url accordingly.

class CustomNavigationClient extends NavigationClient {

  constructor(private iab: InAppBrowser) {
    super();
  }

  async navigateExternal(url: string, options: any) {
    if (Capacitor.isNativePlatform()) {
      const browser = this.iab.create(url, '_blank', {
        location: 'yes',
        clearcache: 'yes',
        clearsessioncache: 'yes',
        hidenavigationbuttons: 'yes',
        hideurlbar: 'yes',
        fullscreen: 'yes'
      });
      browser.on('loadstart').subscribe(event => {
        if (event.url.includes('#code')) {
          // Close the in app browser and redirect to localhost + the state parameter
          browser.close();

          const domain = event.url.split('#')[0];
          const url = event.url.replace(domain, 'http://localhost/home');
          console.log('will redirect to:', url);
          window.location.href = url;
        }
      });
    } else {
      if (options.noHistory) {
        window.location.replace(url);
      } else {
        window.location.assign(url);
      }
    }
    return true;
  }
}

```
<p><strong>app.component.ts</strong>
<br>
Register the navigation client</p>
<pre class="lang-js prettyprint-override"><code>import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { InAppBrowser } from '@awesome-cordova-plugins/in-app-browser/ngx';
import { MsalBroadcastService, MsalService } from '@azure/msal-angular';
import { AuthenticationResult, EventMessage, EventType, NavigationClient } from '@azure/msal-browser';
import { Capacitor } from '@capacitor/core';
import { Subject } from 'rxjs';
import { filter, tap } from 'rxjs/operators';
import { AzureAuthService } from '@core/auth';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {

  constructor(
    private azureAuthService: AzureAuthService,
    private authService: MsalService,
    private msalBroadcastService: MsalBroadcastService,
    private router: Router,
    private iab: InAppBrowser,
    private msalService: MsalService,
  ) {
    this.msalService.instance.setNavigationClient(new CustomNavigationClient(this.iab));
  }

  ngOnInit(): void {

    this.msalBroadcastService.msalSubject$
      .pipe(
        filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS),
      )
      .subscribe((result: EventMessage) => {
        console.log('--> login success 1: ', result);
        const payload = result.payload as AuthenticationResult;
        this.authService.instance.setActiveAccount(payload.account);

        // custom service to handle authentication result within application
        this.azureAuthService.handleAuthentication(payload)
          .pipe(
            tap(() => {
              console.log('--> login success 2: ');
              this.router.navigate(['/home']);
            })
          )
          .subscribe();
      });
  }

}
</code>```

package.json

If you are using angulars monorepo approach, make sure you place the dependencies within you project specific package.json file, otherwise, when syncing plugins (cordova and capacitor) with npx cap sync, the plugins are ignored. Which results in the error "...plugin_not_installed"

"dependencies": {
    ...
    "@capacitor/android": "3.4.1",
    "cordova-plugin-inappbrowser": "^5.0.0",
    "@awesome-cordova-plugins/in-app-browser": "^5.39.1",
    "@azure/msal-angular": "^2.0.1",
    "@azure/msal-browser": "^2.15.0",
    ...
}
```

Title: Ionic and MSAL Authentication

Body:
I have an Ionic app that needs to authenticate in Azure, so I installed MSAL following this tutorial:
https://learn.microsoft.com/en-us/graph/tutorials/angular

It works like a charm with "ionic serve" but when I run it in the device, it crashes when I try to sign in Azure. I think it is because the popup window MSAL shows for login is not allowed in Ionic.

So my first attempt was to change the loginPopup() call for a loginRedirect(). So I removed this code:

async signIn(): Promise<void> {
  const result = await this.msalService
    .loginPopup(OAuthSettings)
    .toPromise()
    .catch((reason) => {
      this.alertsService.addError('Login failed',
        JSON.stringify(reason, null, 2));
    });

  if (result) {
    this.msalService.instance.setActiveAccount(result.account);
    this.authenticated = true;
    this.user = await this.getUser();
  }
}

And I added this new one (based on https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/errors.md):

async signIn(): Promise<void> {
  await this.msalService.instance.handleRedirectPromise();

  const accounts = this.msalService.instance.getAllAccounts();
  if (accounts.length === 0) {
    // No user signed in
    this.msalService.instance.loginRedirect();
  }
}

But this way, the user information is not saved, because I have not a "result" to handle or to call to setActiveAccount(result). It did not work even in "ionic serve", so I discarded this approach.

The second approach, after seaching for a posible solution for two days, was to show the popup in a InAppBrowser (https://ionicframework.com/docs/native/in-app-browser), so I changed the code to:

async signIn(): Promise<void> {
  const browser = this.iab.create('https://www.microsoft.com/');
  browser.executeScript({ code: "\
    const result = await this.msalService\
      .loginPopup(OAuthSettings)\
      .toPromise()\
      .catch((reason) => {\
        this.alertsService.addError('Login failed',\
          JSON.stringify(reason, null, 2));\
      });\
    if (result) {\
      this.msalService.instance.setActiveAccount(result.account);\
      this.authenticated = true;\
      this.user = await this.getUser();\
    }"
  });
}

But it just open a new window and do nothing more, it does not execute loginPopup(), so I also discard this second approach.

Anyone knows how to avoid the popup problem in Ionic?

Thank you

Body:
I can confirm Paolo Cuscelas solution is working.
We were using ionic & capacitor with the cordova InAppBrowser, since capacitors browser does not support listening to url changes, which is needed in order to "proxy" the msal route params.

Also, make sure to register the redirection uri in your azure portal.

The rest of the application is more or less setup based on the provided examples from microsoft for msal/angular package.

CustomNavigationClient for Capacitor

Make sure you setup the msal interaction type to "InteractionType.Redirect"

The constructor requires you to pass in a InAppBrowser reference.

Also azure returns the data in the url through #code instead of #state, so make sure to split the url accordingly.

class CustomNavigationClient extends NavigationClient {

  constructor(private iab: InAppBrowser) {
    super();
  }

  async navigateExternal(url: string, options: any) {
    if (Capacitor.isNativePlatform()) {
      const browser = this.iab.create(url, '_blank', {
        location: 'yes',
        clearcache: 'yes',
        clearsessioncache: 'yes',
        hidenavigationbuttons: 'yes',
        hideurlbar: 'yes',
        fullscreen: 'yes'
      });
      browser.on('loadstart').subscribe(event => {
        if (event.url.includes('#code')) {
          // Close the in app browser and redirect to localhost + the state parameter
          browser.close();

          const domain = event.url.split('#')[0];
          const url = event.url.replace(domain, 'http://localhost/home');
          console.log('will redirect to:', url);
          window.location.href = url;
        }
      });
    } else {
      if (options.noHistory) {
        window.location.replace(url);
      } else {
        window.location.assign(url);
      }
    }
    return true;
  }
}

app.component.ts

Register the navigation client

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { InAppBrowser } from '@awesome-cordova-plugins/in-app-browser/ngx';
import { MsalBroadcastService, MsalService } from '@azure/msal-angular';
import { AuthenticationResult, EventMessage, EventType, NavigationClient } from '@azure/msal-browser';
import { Capacitor } from '@capacitor/core';
import { Subject } from 'rxjs';
import { filter, tap } from 'rxjs/operators';
import { AzureAuthService } from '@core/auth';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {

  constructor(
    private azureAuthService: AzureAuthService,
    private authService: MsalService,
    private msalBroadcastService: MsalBroadcastService,
    private router: Router,
    private iab: InAppBrowser,
    private msalService: MsalService,
  ) {
    this.msalService.instance.setNavigationClient(new CustomNavigationClient(this.iab));
  }

  ngOnInit(): void {

    this.msalBroadcastService.msalSubject$
      .pipe(
        filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS),
      )
      .subscribe((result: EventMessage) => {
        console.log('--> login success 1: ', result);
        const payload = result.payload as AuthenticationResult;
        this.authService.instance.setActiveAccount(payload.account);

        // custom service to handle authentication result within application
        this.azureAuthService.handleAuthentication(payload)
          .pipe(
            tap(() => {
              console.log('--> login success 2: ');
              this.router.navigate(['/home']);
            })
          )
          .subscribe();
      });
  }

}

package.json

If you are using angulars monorepo approach, make sure you place the dependencies within you project specific package.json file, otherwise, when syncing plugins (cordova and capacitor) with npx cap sync, the plugins are ignored. Which results in the error "...plugin_not_installed"

"dependencies": {
    ...
    "@capacitor/android": "3.4.1",
    "cordova-plugin-inappbrowser": "^5.0.0",
    "@awesome-cordova-plugins/in-app-browser": "^5.39.1",
    "@azure/msal-angular": "^2.0.1",
    "@azure/msal-browser": "^2.15.0",
    ...
}


问:
[Flutter]: FAB for only one bottom tab
I have a BottomAppBar that has a FloatingActionButton. However, I only want this button to be seen in one particular screen. In the best case, I'd like to add this button only when the user clicks on that particular screen.

I've found that you can add a FAB like this:

```<code>return Scaffold(
      extendBodyBehindAppBar: true,
      extendBody: true,
      floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          ...
        },
        child:  const Icon(
          Icons.add_sharp,
          color: Color(0xFFFFFFFF),
        ),
      ),
      body: Center(
        child: _widgetOptions.elementAt(_selectedIndex),
      ),
      bottomNavigationBar: buildBottomNavigationBar(),
    );
</code>```

However, as you can see this Scaffold is shared by all the screens that can be selected in the bottomNavigationBar. How do I add a FAB only for a particular screen?

I'd like the FAB to be embedded into the bottomNavigationBar so I do not want to add a plain button to that particular screen. Thanks.

答:
Turns out the solution was actually quite simple and I was overthinking stuff. I have a variable that keeps track of the currently open screen. So I simply added this little logic to the mother screen that hosts the bottomNavigationBar:

```<code>if (_selectedIndex==1){
  // Other screen that needs the FAB
  return Scaffold(
    ...,
    floatingActionButton: FloatingActionButton(
        ....
    ),
    bottomNavigationBar: buildBottomNavigationBar(),
  );
}

return Scaffold(
  ...,
  bottomNavigationBar: buildBottomNavigationBar(),
);
</code>```

Title: [Flutter]: FAB for only one bottom tab

Body:
I have a BottomAppBar that has a FloatingActionButton. However, I only want this button to be seen in one particular screen. In the best case, I'd like to add this button only when the user clicks on that particular screen.

I've found that you can add a FAB like this:

return Scaffold(
      extendBodyBehindAppBar: true,
      extendBody: true,
      floatingActionButtonLocation: FloatingActionButtonLocation.endDocked,
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          ...
        },
        child:  const Icon(
          Icons.add_sharp,
          color: Color(0xFFFFFFFF),
        ),
      ),
      body: Center(
        child: _widgetOptions.elementAt(_selectedIndex),
      ),
      bottomNavigationBar: buildBottomNavigationBar(),
    );

However, as you can see this Scaffold is shared by all the screens that can be selected in the bottomNavigationBar. How do I add a FAB only for a particular screen?

I'd like the FAB to be embedded into the bottomNavigationBar so I do not want to add a plain button to that particular screen. Thanks.

Body:
Turns out the solution was actually quite simple and I was overthinking stuff. I have a variable that keeps track of the currently open screen. So I simply added this little logic to the mother screen that hosts the bottomNavigationBar:

if (_selectedIndex==1){
  // Other screen that needs the FAB
  return Scaffold(
    ...,
    floatingActionButton: FloatingActionButton(
        ....
    ),
    bottomNavigationBar: buildBottomNavigationBar(),
  );
}

return Scaffold(
  ...,
  bottomNavigationBar: buildBottomNavigationBar(),
);


问:
How to develop for MRP (Mythroad, platform for chinese mobile application)?
Hello dearest community

I just given a task to develop a mobile application for chinese mobile phone, Nexian  NX-G920. At first, I think it can just run the J2ME application. But it didn't, it only support MRP application. Having read about it here : MRP, I think my best case is, if any, convert my *.JAR application into *.MRP. Is there any tool that can do it?

My Plan B is, to develop using specific MRP SDK. But that is just to costly, in term of effort  to be use.

答:
Sky-Mobi SDK is saved this archive on Wayback Machine
The Sky-Mobi is saved this page of site in the Internet Archive</p>


问:
make a code preview for documentation with Reactjs
I'm trying to create a component who display source's code passed as props to write documentation of a library i work on with Docusaurus. Like html  or exactly like this (the blue part) :

https://mui.com/components/radio-buttons/

This is a simplified code

```<code>import React from 'react';

export default function Preview({title, description, component, code, rawComponent}) {
  return (
    <div>
      <div><h1>{title}</h1></div>
      <div>{description}</div>

      <div>{component}</div>

      <details>
        <summary>Source</summary>
        ```
          {code}
        ```
      </details>
    </div>
  );
}
</code>```

PROBLEM : i can't found how to pass code as props ....

```<code><Preview
  title={'Quick start'}
  description={'Yes, this really is all you need to get started, as you can see in this live and interactive demo:'}
  component={<HomepageFeatures />}
  code={
    `
      import * as React from 'react';
      import ReactDOM from 'react-dom';
      import HomepageFeatures from 'newlib';

      function App() {
          return <HomepageFeatures />;
      }
  `}
/>
</code>```

this also doesn't work

```<code><Preview
  title={'Quick start'}
  description={'Yes, this really is all you need to get started, as you can see in this live and interactive demo:'}
  component={<HomepageFeatures />}
  code={
     ```
      import * as React from 'react';
      import ReactDOM from 'react-dom';
      import HomepageFeatures from 'newlib';

      function App() {
          return <HomepageFeatures />;
      }
      ```
  }
/>
</code>```

How to pass the code block ???

EDIT : a jsfildle https://jsfiddle.net/2pnc4htm/

it's work in pure reactJS, so it's Docusaurus who mess up ...

Thank you for reading

答:
I believe the issue is that the curly braces are not required for the props. This only needs to be done for the in-line style of a component.

More information can be found here https://docusaurus.io/docs/next/markdown-features/react (in their examples they don’t use curly braces unless for the style)

Body:
I'm trying to create a component who display source's code passed as props to write documentation of a library i work on with Docusaurus. Like html  or exactly like this (the blue part) :

https://mui.com/components/radio-buttons/

This is a simplified code

import React from 'react';

export default function Preview({title, description, component, code, rawComponent}) {
  return (

{title}

{description}

{component}

        Source

          {code}

  );
}

PROBLEM : i can't found how to pass code as props ....

<Preview
  title={'Quick start'}
  description={'Yes, this really is all you need to get started, as you can see in this live and interactive demo:'}
  component={<HomepageFeatures />}
  code={
    `
      import * as React from 'react';
      import ReactDOM from 'react-dom';
      import HomepageFeatures from 'newlib';

      function App() {
          return <HomepageFeatures />;
      }
  `}
/>

this also doesn't work

<Preview
  title={'Quick start'}
  description={'Yes, this really is all you need to get started, as you can see in this live and interactive demo:'}
  component={<HomepageFeatures />}
  code={
     ```
      import * as React from 'react';
      import ReactDOM from 'react-dom';
      import HomepageFeatures from 'newlib';

      function App() {
          return <HomepageFeatures />;
      }
      ```
  }
/>

How to pass the code block ???

EDIT : a jsfildle https://jsfiddle.net/2pnc4htm/

it's work in pure reactJS, so it's Docusaurus who mess up ...

Thank you for reading